From 2cf681a11aea459b50d712abc7136f7129e4d57f Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Thu, 18 Jul 2019 11:53:54 +0000 Subject: [PATCH 001/289] Creating release_90 branch off revision 366426 llvm-svn: 366428 From c02ac091705f0be00692cb5772c53a79f166a4c3 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Fri, 19 Jul 2019 09:22:23 +0000 Subject: [PATCH 002/289] Drop svn version suffix. llvm-svn: 366547 --- libcxx/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcxx/CMakeLists.txt b/libcxx/CMakeLists.txt index 5df3f257294e..ddcd478b2139 100644 --- a/libcxx/CMakeLists.txt +++ b/libcxx/CMakeLists.txt @@ -27,7 +27,7 @@ if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR OR LIBCXX_STANDALONE_BUIL project(libcxx CXX C) set(PACKAGE_NAME libcxx) - set(PACKAGE_VERSION 9.0.0svn) + set(PACKAGE_VERSION 9.0.0) set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}") set(PACKAGE_BUGREPORT "llvm-bugs@lists.llvm.org") From 135370e01e84166b1c2ecb712487774df8b67957 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Fri, 19 Jul 2019 09:22:41 +0000 Subject: [PATCH 003/289] Drop svn version suffix. llvm-svn: 366548 --- libcxxabi/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcxxabi/CMakeLists.txt b/libcxxabi/CMakeLists.txt index 8ca169065f48..ce69fff1370a 100644 --- a/libcxxabi/CMakeLists.txt +++ b/libcxxabi/CMakeLists.txt @@ -21,7 +21,7 @@ if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR OR LIBCXXABI_STANDALONE_B project(libcxxabi CXX C) set(PACKAGE_NAME libcxxabi) - set(PACKAGE_VERSION 9.0.0svn) + set(PACKAGE_VERSION 9.0.0) set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}") set(PACKAGE_BUGREPORT "llvm-bugs@lists.llvm.org") From a4f7f7245008d48aeeb4bf9ef317b1c8ea09e40b Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Fri, 19 Jul 2019 09:22:57 +0000 Subject: [PATCH 004/289] Drop svn version suffix. llvm-svn: 366549 --- libunwind/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libunwind/CMakeLists.txt b/libunwind/CMakeLists.txt index b51922a48fe2..836b286523ef 100644 --- a/libunwind/CMakeLists.txt +++ b/libunwind/CMakeLists.txt @@ -83,7 +83,7 @@ if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR OR LIBUNWIND_STANDALONE_B endif() set(PACKAGE_NAME libunwind) - set(PACKAGE_VERSION 9.0.0svn) + set(PACKAGE_VERSION 9.0.0) set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}") set(PACKAGE_BUGREPORT "llvm-bugs@lists.llvm.org") From 24c2e53e770f5fe98d853ff04f035e3696b2cf60 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Fri, 19 Jul 2019 09:23:25 +0000 Subject: [PATCH 005/289] Drop svn version suffix. llvm-svn: 366550 --- llvm/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/CMakeLists.txt b/llvm/CMakeLists.txt index b8eb19848bc5..8d71dee98f48 100644 --- a/llvm/CMakeLists.txt +++ b/llvm/CMakeLists.txt @@ -25,7 +25,7 @@ if(NOT DEFINED LLVM_VERSION_PATCH) set(LLVM_VERSION_PATCH 0) endif() if(NOT DEFINED LLVM_VERSION_SUFFIX) - set(LLVM_VERSION_SUFFIX svn) + set(LLVM_VERSION_SUFFIX "") endif() if (NOT PACKAGE_VERSION) From eb482e5e341fb81b3588a203a27d00b8089c0e05 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Fri, 19 Jul 2019 09:36:22 +0000 Subject: [PATCH 006/289] Merging r366429: ------------------------------------------------------------------------ r366429 | ibiryukov | 2019-07-18 13:55:33 +0200 (Thu, 18 Jul 2019) | 5 lines Revert r366422: [OpenCL] Improve destructor support in C++ for OpenCL Reason: this commit causes crashes in the clang compiler when building LLVM Support with libc++, see https://bugs.llvm.org/show_bug.cgi?id=42665 for details. ------------------------------------------------------------------------ llvm-svn: 366552 --- clang/include/clang/AST/DeclCXX.h | 14 +---- clang/lib/AST/DeclCXX.cpp | 25 +------- clang/lib/CodeGen/CGCXXABI.h | 14 ++--- clang/lib/CodeGen/CGCall.cpp | 2 +- clang/lib/CodeGen/CGClass.cpp | 40 +++++-------- clang/lib/CodeGen/CGDecl.cpp | 21 +++---- clang/lib/CodeGen/CGExprCXX.cpp | 31 +++------- clang/lib/CodeGen/CodeGenFunction.h | 13 ++-- clang/lib/CodeGen/ItaniumCXXABI.cpp | 31 ++++------ clang/lib/CodeGen/MicrosoftCXXABI.cpp | 29 ++++----- clang/lib/Sema/SemaDeclCXX.cpp | 50 ++++++++-------- clang/lib/Sema/SemaOverload.cpp | 4 +- clang/test/CodeGenOpenCLCXX/addrspace-ctor.cl | 14 +++++ .../CodeGenOpenCLCXX/addrspace-with-class.cl | 59 ------------------- 14 files changed, 113 insertions(+), 234 deletions(-) create mode 100644 clang/test/CodeGenOpenCLCXX/addrspace-ctor.cl delete mode 100644 clang/test/CodeGenOpenCLCXX/addrspace-with-class.cl diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index 7add83f89624..cbf4f1397eb1 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -2232,20 +2232,20 @@ class CXXMethodDecl : public FunctionDecl { overridden_method_range overridden_methods() const; - /// Return the parent of this method declaration, which + /// Returns the parent of this method declaration, which /// is the class in which this method is defined. const CXXRecordDecl *getParent() const { return cast(FunctionDecl::getParent()); } - /// Return the parent of this method declaration, which + /// Returns the parent of this method declaration, which /// is the class in which this method is defined. CXXRecordDecl *getParent() { return const_cast( cast(FunctionDecl::getParent())); } - /// Return the type of the \c this pointer. + /// Returns the type of the \c this pointer. /// /// Should only be called for instance (i.e., non-static) methods. Note /// that for the call operator of a lambda closure type, this returns the @@ -2253,17 +2253,9 @@ class CXXMethodDecl : public FunctionDecl { /// 'this' type. QualType getThisType() const; - /// Return the type of the object pointed by \c this. - /// - /// See getThisType() for usage restriction. - QualType getThisObjectType() const; - static QualType getThisType(const FunctionProtoType *FPT, const CXXRecordDecl *Decl); - static QualType getThisObjectType(const FunctionProtoType *FPT, - const CXXRecordDecl *Decl); - Qualifiers getMethodQualifiers() const { return getType()->getAs()->getMethodQuals(); } diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index 59710a55498f..857ac19e6b14 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -2253,23 +2253,12 @@ CXXMethodDecl::overridden_methods() const { return getASTContext().overridden_methods(this); } -static QualType getThisObjectType(ASTContext &C, const FunctionProtoType *FPT, - const CXXRecordDecl *Decl) { - QualType ClassTy = C.getTypeDeclType(Decl); - return C.getQualifiedType(ClassTy, FPT->getMethodQuals()); -} - QualType CXXMethodDecl::getThisType(const FunctionProtoType *FPT, const CXXRecordDecl *Decl) { ASTContext &C = Decl->getASTContext(); - QualType ObjectTy = ::getThisObjectType(C, FPT, Decl); - return C.getPointerType(ObjectTy); -} - -QualType CXXMethodDecl::getThisObjectType(const FunctionProtoType *FPT, - const CXXRecordDecl *Decl) { - ASTContext &C = Decl->getASTContext(); - return ::getThisObjectType(C, FPT, Decl); + QualType ClassTy = C.getTypeDeclType(Decl); + ClassTy = C.getQualifiedType(ClassTy, FPT->getMethodQuals()); + return C.getPointerType(ClassTy); } QualType CXXMethodDecl::getThisType() const { @@ -2284,14 +2273,6 @@ QualType CXXMethodDecl::getThisType() const { getParent()); } -QualType CXXMethodDecl::getThisObjectType() const { - // Ditto getThisType. - assert(isInstance() && "No 'this' for static methods!"); - - return CXXMethodDecl::getThisObjectType(getType()->getAs(), - getParent()); -} - bool CXXMethodDecl::hasInlineBody() const { // If this function is a template instantiation, look at the template from // which it was instantiated. diff --git a/clang/lib/CodeGen/CGCXXABI.h b/clang/lib/CodeGen/CGCXXABI.h index 3a9c3b347439..511bcd00d427 100644 --- a/clang/lib/CodeGen/CGCXXABI.h +++ b/clang/lib/CodeGen/CGCXXABI.h @@ -378,7 +378,7 @@ class CGCXXABI { virtual void EmitDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *DD, CXXDtorType Type, bool ForVirtualBase, bool Delegating, - Address This, QualType ThisTy) = 0; + Address This) = 0; /// Emits the VTable definitions required for the given record type. virtual void emitVTableDefinitions(CodeGenVTables &CGVT, @@ -421,15 +421,11 @@ class CGCXXABI { llvm::Type *Ty, SourceLocation Loc) = 0; - using DeleteOrMemberCallExpr = - llvm::PointerUnion; - /// Emit the ABI-specific virtual destructor call. - virtual llvm::Value *EmitVirtualDestructorCall(CodeGenFunction &CGF, - const CXXDestructorDecl *Dtor, - CXXDtorType DtorType, - Address This, - DeleteOrMemberCallExpr E) = 0; + virtual llvm::Value * + EmitVirtualDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *Dtor, + CXXDtorType DtorType, Address This, + const CXXMemberCallExpr *CE) = 0; virtual void adjustCallArgsForDestructorThunk(CodeGenFunction &CGF, GlobalDecl GD, diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index cf8024550eee..5f1fb1007482 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -3502,7 +3502,7 @@ struct DestroyUnpassedArg final : EHScopeStack::Cleanup { const CXXDestructorDecl *Dtor = Ty->getAsCXXRecordDecl()->getDestructor(); assert(!Dtor->isTrivial()); CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete, /*for vbase*/ false, - /*Delegating=*/false, Addr, Ty); + /*Delegating=*/false, Addr); } else { CGF.callCStructDestructor(CGF.MakeAddrLValue(Addr, Ty)); } diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp index c8bb63c5c4b1..9a9dd88810ed 100644 --- a/clang/lib/CodeGen/CGClass.cpp +++ b/clang/lib/CodeGen/CGClass.cpp @@ -491,15 +491,12 @@ namespace { cast(CGF.CurCodeDecl)->getParent(); const CXXDestructorDecl *D = BaseClass->getDestructor(); - // We are already inside a destructor, so presumably the object being - // destroyed should have the expected type. - QualType ThisTy = D->getThisObjectType(); Address Addr = CGF.GetAddressOfDirectBaseInCompleteClass(CGF.LoadCXXThisAddress(), DerivedClass, BaseClass, BaseIsVirtual); CGF.EmitCXXDestructorCall(D, Dtor_Base, BaseIsVirtual, - /*Delegating=*/false, Addr, ThisTy); + /*Delegating=*/false, Addr); } }; @@ -1443,11 +1440,9 @@ void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) { if (DtorType == Dtor_Deleting) { RunCleanupsScope DtorEpilogue(*this); EnterDtorCleanups(Dtor, Dtor_Deleting); - if (HaveInsertPoint()) { - QualType ThisTy = Dtor->getThisObjectType(); + if (HaveInsertPoint()) EmitCXXDestructorCall(Dtor, Dtor_Complete, /*ForVirtualBase=*/false, - /*Delegating=*/false, LoadCXXThisAddress(), ThisTy); - } + /*Delegating=*/false, LoadCXXThisAddress()); return; } @@ -1478,9 +1473,8 @@ void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) { EnterDtorCleanups(Dtor, Dtor_Complete); if (!isTryBody) { - QualType ThisTy = Dtor->getThisObjectType(); EmitCXXDestructorCall(Dtor, Dtor_Base, /*ForVirtualBase=*/false, - /*Delegating=*/false, LoadCXXThisAddress(), ThisTy); + /*Delegating=*/false, LoadCXXThisAddress()); break; } @@ -2019,7 +2013,7 @@ void CodeGenFunction::destroyCXXObject(CodeGenFunction &CGF, const CXXDestructorDecl *dtor = record->getDestructor(); assert(!dtor->isTrivial()); CGF.EmitCXXDestructorCall(dtor, Dtor_Complete, /*for vbase*/ false, - /*Delegating=*/false, addr, type); + /*Delegating=*/false, addr); } void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D, @@ -2369,11 +2363,8 @@ namespace { : Dtor(D), Addr(Addr), Type(Type) {} void Emit(CodeGenFunction &CGF, Flags flags) override { - // We are calling the destructor from within the constructor. - // Therefore, "this" should have the expected type. - QualType ThisTy = Dtor->getThisObjectType(); CGF.EmitCXXDestructorCall(Dtor, Type, /*ForVirtualBase=*/false, - /*Delegating=*/true, Addr, ThisTy); + /*Delegating=*/true, Addr); } }; } // end anonymous namespace @@ -2411,32 +2402,31 @@ CodeGenFunction::EmitDelegatingCXXConstructorCall(const CXXConstructorDecl *Ctor void CodeGenFunction::EmitCXXDestructorCall(const CXXDestructorDecl *DD, CXXDtorType Type, bool ForVirtualBase, - bool Delegating, Address This, - QualType ThisTy) { + bool Delegating, + Address This) { CGM.getCXXABI().EmitDestructorCall(*this, DD, Type, ForVirtualBase, - Delegating, This, ThisTy); + Delegating, This); } namespace { struct CallLocalDtor final : EHScopeStack::Cleanup { const CXXDestructorDecl *Dtor; Address Addr; - QualType Ty; - CallLocalDtor(const CXXDestructorDecl *D, Address Addr, QualType Ty) - : Dtor(D), Addr(Addr), Ty(Ty) {} + CallLocalDtor(const CXXDestructorDecl *D, Address Addr) + : Dtor(D), Addr(Addr) {} void Emit(CodeGenFunction &CGF, Flags flags) override { CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete, /*ForVirtualBase=*/false, - /*Delegating=*/false, Addr, Ty); + /*Delegating=*/false, Addr); } }; } // end anonymous namespace void CodeGenFunction::PushDestructorCleanup(const CXXDestructorDecl *D, - QualType T, Address Addr) { - EHStack.pushCleanup(NormalAndEHCleanup, D, Addr, T); + Address Addr) { + EHStack.pushCleanup(NormalAndEHCleanup, D, Addr); } void CodeGenFunction::PushDestructorCleanup(QualType T, Address Addr) { @@ -2446,7 +2436,7 @@ void CodeGenFunction::PushDestructorCleanup(QualType T, Address Addr) { const CXXDestructorDecl *D = ClassDecl->getDestructor(); assert(D && D->isUsed() && "destructor not marked as used!"); - PushDestructorCleanup(D, T, Addr); + PushDestructorCleanup(D, Addr); } void CodeGenFunction::InitializeVTablePointer(const VPtr &Vptr) { diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp index 6ad43cefc4d2..19a9e75cc5ac 100644 --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/lib/CodeGen/CGDecl.cpp @@ -480,12 +480,11 @@ namespace { template struct DestroyNRVOVariable : EHScopeStack::Cleanup { - DestroyNRVOVariable(Address addr, QualType type, llvm::Value *NRVOFlag) - : NRVOFlag(NRVOFlag), Loc(addr), Ty(type) {} + DestroyNRVOVariable(Address addr, llvm::Value *NRVOFlag) + : NRVOFlag(NRVOFlag), Loc(addr) {} llvm::Value *NRVOFlag; Address Loc; - QualType Ty; void Emit(CodeGenFunction &CGF, Flags flags) override { // Along the exceptions path we always execute the dtor. @@ -512,24 +511,26 @@ namespace { struct DestroyNRVOVariableCXX final : DestroyNRVOVariable { - DestroyNRVOVariableCXX(Address addr, QualType type, - const CXXDestructorDecl *Dtor, llvm::Value *NRVOFlag) - : DestroyNRVOVariable(addr, type, NRVOFlag), - Dtor(Dtor) {} + DestroyNRVOVariableCXX(Address addr, const CXXDestructorDecl *Dtor, + llvm::Value *NRVOFlag) + : DestroyNRVOVariable(addr, NRVOFlag), + Dtor(Dtor) {} const CXXDestructorDecl *Dtor; void emitDestructorCall(CodeGenFunction &CGF) { CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete, /*ForVirtualBase=*/false, - /*Delegating=*/false, Loc, Ty); + /*Delegating=*/false, Loc); } }; struct DestroyNRVOVariableC final : DestroyNRVOVariable { DestroyNRVOVariableC(Address addr, llvm::Value *NRVOFlag, QualType Ty) - : DestroyNRVOVariable(addr, Ty, NRVOFlag) {} + : DestroyNRVOVariable(addr, NRVOFlag), Ty(Ty) {} + + QualType Ty; void emitDestructorCall(CodeGenFunction &CGF) { CGF.destroyNonTrivialCStruct(CGF, Loc, Ty); @@ -1939,7 +1940,7 @@ void CodeGenFunction::emitAutoVarTypeCleanup( if (emission.NRVOFlag) { assert(!type->isArrayType()); CXXDestructorDecl *dtor = type->getAsCXXRecordDecl()->getDestructor(); - EHStack.pushCleanup(cleanupKind, addr, type, dtor, + EHStack.pushCleanup(cleanupKind, addr, dtor, emission.NRVOFlag); return; } diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp index 5476d13b7c46..8ad229fc0c36 100644 --- a/clang/lib/CodeGen/CGExprCXX.cpp +++ b/clang/lib/CodeGen/CGExprCXX.cpp @@ -10,13 +10,12 @@ // //===----------------------------------------------------------------------===// +#include "CodeGenFunction.h" #include "CGCUDARuntime.h" #include "CGCXXABI.h" #include "CGDebugInfo.h" #include "CGObjCRuntime.h" -#include "CodeGenFunction.h" #include "ConstantEmitter.h" -#include "TargetInfo.h" #include "clang/Basic/CodeGenOptions.h" #include "clang/CodeGen/CGFunctionInfo.h" #include "llvm/IR/Intrinsics.h" @@ -91,26 +90,12 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorCall( } RValue CodeGenFunction::EmitCXXDestructorCall( - GlobalDecl Dtor, const CGCallee &Callee, llvm::Value *This, QualType ThisTy, + GlobalDecl Dtor, const CGCallee &Callee, llvm::Value *This, llvm::Value *ImplicitParam, QualType ImplicitParamTy, const CallExpr *CE) { - const CXXMethodDecl *DtorDecl = cast(Dtor.getDecl()); - - assert(!ThisTy.isNull()); - assert(ThisTy->getAsCXXRecordDecl() == DtorDecl->getParent() && - "Pointer/Object mixup"); - - LangAS SrcAS = ThisTy.getAddressSpace(); - LangAS DstAS = DtorDecl->getMethodQualifiers().getAddressSpace(); - if (SrcAS != DstAS) { - QualType DstTy = DtorDecl->getThisType(); - llvm::Type *NewType = CGM.getTypes().ConvertType(DstTy); - This = getTargetHooks().performAddrSpaceCast(*this, This, SrcAS, DstAS, - NewType); - } - CallArgList Args; - commonEmitCXXMemberOrOperatorCall(*this, DtorDecl, This, ImplicitParam, - ImplicitParamTy, CE, Args, nullptr); + commonEmitCXXMemberOrOperatorCall(*this, cast(Dtor.getDecl()), + This, ImplicitParam, ImplicitParamTy, CE, + Args, nullptr); return EmitCall(CGM.getTypes().arrangeCXXStructorDeclaration(Dtor), Callee, ReturnValueSlot(), Args); } @@ -360,9 +345,7 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr( Callee = CGCallee::forDirect(CGM.GetAddrOfFunction(GD, Ty), GD); } - QualType ThisTy = - IsArrow ? Base->getType()->getPointeeType() : Base->getType(); - EmitCXXDestructorCall(GD, Callee, This.getPointer(), ThisTy, + EmitCXXDestructorCall(GD, Callee, This.getPointer(), /*ImplicitParam=*/nullptr, /*ImplicitParamTy=*/QualType(), nullptr); } @@ -1900,7 +1883,7 @@ static void EmitObjectDelete(CodeGenFunction &CGF, CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete, /*ForVirtualBase=*/false, /*Delegating=*/false, - Ptr, ElementType); + Ptr); else if (auto Lifetime = ElementType.getObjCLifetime()) { switch (Lifetime) { case Qualifiers::OCL_None: diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index c3060d1fb351..06ef2dff7e9f 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -675,8 +675,7 @@ class CodeGenFunction : public CodeGenTypeCache { /// PushDestructorCleanup - Push a cleanup to call the /// complete-object variant of the given destructor on the object at /// the given address. - void PushDestructorCleanup(const CXXDestructorDecl *Dtor, QualType T, - Address Addr); + void PushDestructorCleanup(const CXXDestructorDecl *Dtor, Address Addr); /// PopCleanupBlock - Will pop the cleanup entry on the stack and /// process all branch fixups. @@ -2555,8 +2554,8 @@ class CodeGenFunction : public CodeGenTypeCache { static Destroyer destroyCXXObject; void EmitCXXDestructorCall(const CXXDestructorDecl *D, CXXDtorType Type, - bool ForVirtualBase, bool Delegating, Address This, - QualType ThisTy); + bool ForVirtualBase, bool Delegating, + Address This); void EmitNewArrayInitializer(const CXXNewExpr *E, QualType elementType, llvm::Type *ElementTy, Address NewPtr, @@ -3678,9 +3677,9 @@ class CodeGenFunction : public CodeGenTypeCache { llvm::Value *ImplicitParam, QualType ImplicitParamTy, const CallExpr *E, CallArgList *RtlArgs); - RValue EmitCXXDestructorCall(GlobalDecl Dtor, const CGCallee &Callee, - llvm::Value *This, QualType ThisTy, - llvm::Value *ImplicitParam, + RValue EmitCXXDestructorCall(GlobalDecl Dtor, + const CGCallee &Callee, + llvm::Value *This, llvm::Value *ImplicitParam, QualType ImplicitParamTy, const CallExpr *E); RValue EmitCXXMemberCallExpr(const CXXMemberCallExpr *E, ReturnValueSlot ReturnValue); diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index 3b2413d960d6..7367ff37cf45 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -224,8 +224,7 @@ class ItaniumCXXABI : public CodeGen::CGCXXABI { void EmitDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *DD, CXXDtorType Type, bool ForVirtualBase, - bool Delegating, Address This, - QualType ThisTy) override; + bool Delegating, Address This) override; void emitVTableDefinitions(CodeGenVTables &CGVT, const CXXRecordDecl *RD) override; @@ -262,8 +261,9 @@ class ItaniumCXXABI : public CodeGen::CGCXXABI { llvm::Value *EmitVirtualDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *Dtor, - CXXDtorType DtorType, Address This, - DeleteOrMemberCallExpr E) override; + CXXDtorType DtorType, + Address This, + const CXXMemberCallExpr *CE) override; void emitVirtualInheritanceTables(const CXXRecordDecl *RD) override; @@ -1128,7 +1128,7 @@ void ItaniumCXXABI::emitVirtualObjectDelete(CodeGenFunction &CGF, // FIXME: Provide a source location here even though there's no // CXXMemberCallExpr for dtor call. CXXDtorType DtorType = UseGlobalDelete ? Dtor_Complete : Dtor_Deleting; - EmitVirtualDestructorCall(CGF, Dtor, DtorType, Ptr, DE); + EmitVirtualDestructorCall(CGF, Dtor, DtorType, Ptr, /*CE=*/nullptr); if (UseGlobalDelete) CGF.PopCleanupBlock(); @@ -1539,8 +1539,7 @@ CGCXXABI::AddedStructorArgs ItaniumCXXABI::addImplicitConstructorArgs( void ItaniumCXXABI::EmitDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *DD, CXXDtorType Type, bool ForVirtualBase, - bool Delegating, Address This, - QualType ThisTy) { + bool Delegating, Address This) { GlobalDecl GD(DD, Type); llvm::Value *VTT = CGF.GetVTTParameter(GD, ForVirtualBase, Delegating); QualType VTTTy = getContext().getPointerType(getContext().VoidPtrTy); @@ -1552,8 +1551,7 @@ void ItaniumCXXABI::EmitDestructorCall(CodeGenFunction &CGF, else Callee = CGCallee::forDirect(CGM.getAddrOfCXXStructor(GD), GD); - CGF.EmitCXXDestructorCall(GD, Callee, This.getPointer(), ThisTy, VTT, VTTTy, - nullptr); + CGF.EmitCXXDestructorCall(GD, Callee, This.getPointer(), VTT, VTTTy, nullptr); } void ItaniumCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT, @@ -1741,10 +1739,7 @@ CGCallee ItaniumCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF, llvm::Value *ItaniumCXXABI::EmitVirtualDestructorCall( CodeGenFunction &CGF, const CXXDestructorDecl *Dtor, CXXDtorType DtorType, - Address This, DeleteOrMemberCallExpr E) { - auto *CE = E.dyn_cast(); - auto *D = E.dyn_cast(); - assert((CE != nullptr) ^ (D != nullptr)); + Address This, const CXXMemberCallExpr *CE) { assert(CE == nullptr || CE->arg_begin() == CE->arg_end()); assert(DtorType == Dtor_Deleting || DtorType == Dtor_Complete); @@ -1754,14 +1749,8 @@ llvm::Value *ItaniumCXXABI::EmitVirtualDestructorCall( llvm::FunctionType *Ty = CGF.CGM.getTypes().GetFunctionType(*FInfo); CGCallee Callee = CGCallee::forVirtual(CE, GD, This, Ty); - QualType ThisTy; - if (CE) - ThisTy = CE->getImplicitObjectArgument()->getType()->getPointeeType(); - else - ThisTy = D->getDestroyedType(); - - CGF.EmitCXXDestructorCall(GD, Callee, This.getPointer(), ThisTy, nullptr, - QualType(), nullptr); + CGF.EmitCXXDestructorCall(GD, Callee, This.getPointer(), nullptr, QualType(), + nullptr); return nullptr; } diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp index fa34414de5da..a91a949d024f 100644 --- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp @@ -258,8 +258,7 @@ class MicrosoftCXXABI : public CGCXXABI { void EmitDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *DD, CXXDtorType Type, bool ForVirtualBase, - bool Delegating, Address This, - QualType ThisTy) override; + bool Delegating, Address This) override; void emitVTableTypeMetadata(const VPtrInfo &Info, const CXXRecordDecl *RD, llvm::GlobalVariable *VTable); @@ -297,8 +296,9 @@ class MicrosoftCXXABI : public CGCXXABI { llvm::Value *EmitVirtualDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *Dtor, - CXXDtorType DtorType, Address This, - DeleteOrMemberCallExpr E) override; + CXXDtorType DtorType, + Address This, + const CXXMemberCallExpr *CE) override; void adjustCallArgsForDestructorThunk(CodeGenFunction &CGF, GlobalDecl GD, CallArgList &CallArgs) override { @@ -844,7 +844,8 @@ void MicrosoftCXXABI::emitVirtualObjectDelete(CodeGenFunction &CGF, // CXXMemberCallExpr for dtor call. bool UseGlobalDelete = DE->isGlobalDelete(); CXXDtorType DtorType = UseGlobalDelete ? Dtor_Complete : Dtor_Deleting; - llvm::Value *MDThis = EmitVirtualDestructorCall(CGF, Dtor, DtorType, Ptr, DE); + llvm::Value *MDThis = + EmitVirtualDestructorCall(CGF, Dtor, DtorType, Ptr, /*CE=*/nullptr); if (UseGlobalDelete) CGF.EmitDeleteCall(DE->getOperatorDelete(), MDThis, ElementType); } @@ -1568,8 +1569,7 @@ CGCXXABI::AddedStructorArgs MicrosoftCXXABI::addImplicitConstructorArgs( void MicrosoftCXXABI::EmitDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *DD, CXXDtorType Type, bool ForVirtualBase, - bool Delegating, Address This, - QualType ThisTy) { + bool Delegating, Address This) { // Use the base destructor variant in place of the complete destructor variant // if the class has no virtual bases. This effectively implements some of the // -mconstructor-aliases optimization, but as part of the MS C++ ABI. @@ -1591,7 +1591,7 @@ void MicrosoftCXXABI::EmitDestructorCall(CodeGenFunction &CGF, BaseDtorEndBB = EmitDtorCompleteObjectHandler(CGF); } - CGF.EmitCXXDestructorCall(GD, Callee, This.getPointer(), ThisTy, + CGF.EmitCXXDestructorCall(GD, Callee, This.getPointer(), /*ImplicitParam=*/nullptr, /*ImplicitParamTy=*/QualType(), nullptr); if (BaseDtorEndBB) { @@ -1900,10 +1900,7 @@ CGCallee MicrosoftCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF, llvm::Value *MicrosoftCXXABI::EmitVirtualDestructorCall( CodeGenFunction &CGF, const CXXDestructorDecl *Dtor, CXXDtorType DtorType, - Address This, DeleteOrMemberCallExpr E) { - auto *CE = E.dyn_cast(); - auto *D = E.dyn_cast(); - assert((CE != nullptr) ^ (D != nullptr)); + Address This, const CXXMemberCallExpr *CE) { assert(CE == nullptr || CE->arg_begin() == CE->arg_end()); assert(DtorType == Dtor_Deleting || DtorType == Dtor_Complete); @@ -1920,14 +1917,8 @@ llvm::Value *MicrosoftCXXABI::EmitVirtualDestructorCall( llvm::IntegerType::getInt32Ty(CGF.getLLVMContext()), DtorType == Dtor_Deleting); - QualType ThisTy; - if (CE) - ThisTy = CE->getImplicitObjectArgument()->getType()->getPointeeType(); - else - ThisTy = D->getDestroyedType(); - This = adjustThisArgumentForVirtualFunctionCall(CGF, GD, This, true); - RValue RV = CGF.EmitCXXDestructorCall(GD, Callee, This.getPointer(), ThisTy, + RValue RV = CGF.EmitCXXDestructorCall(GD, Callee, This.getPointer(), ImplicitParam, Context.IntTy, CE); return RV.getScalarVal(); } diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 9a6385f28319..dd77fc55721f 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -8190,27 +8190,6 @@ void Sema::ActOnFinishDelayedCXXMethodDeclaration(Scope *S, Decl *MethodD) { CheckCXXDefaultArguments(Method); } -// Emit the given diagnostic for each non-address-space qualifier. -// Common part of CheckConstructorDeclarator and CheckDestructorDeclarator. -static void checkMethodTypeQualifiers(Sema &S, Declarator &D, unsigned DiagID) { - const DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo(); - if (FTI.hasMethodTypeQualifiers() && !D.isInvalidType()) { - bool DiagOccured = false; - FTI.MethodQualifiers->forEachQualifier( - [DiagID, &S, &DiagOccured](DeclSpec::TQ, StringRef QualName, - SourceLocation SL) { - // This diagnostic should be emitted on any qualifier except an addr - // space qualifier. However, forEachQualifier currently doesn't visit - // addr space qualifiers, so there's no way to write this condition - // right now; we just diagnose on everything. - S.Diag(SL, DiagID) << QualName << SourceRange(SL); - DiagOccured = true; - }); - if (DiagOccured) - D.setInvalidType(); - } -} - /// CheckConstructorDeclarator - Called by ActOnDeclarator to check /// the well-formedness of the constructor declarator @p D with type @p /// R. If there are any errors in the declarator, this routine will @@ -8251,11 +8230,25 @@ QualType Sema::CheckConstructorDeclarator(Declarator &D, QualType R, D.setInvalidType(); } - checkMethodTypeQualifiers(*this, D, diag::err_invalid_qualified_constructor); + DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo(); + if (FTI.hasMethodTypeQualifiers()) { + bool DiagOccured = false; + FTI.MethodQualifiers->forEachQualifier( + [&](DeclSpec::TQ TypeQual, StringRef QualName, SourceLocation SL) { + // This diagnostic should be emitted on any qualifier except an addr + // space qualifier. However, forEachQualifier currently doesn't visit + // addr space qualifiers, so there's no way to write this condition + // right now; we just diagnose on everything. + Diag(SL, diag::err_invalid_qualified_constructor) + << QualName << SourceRange(SL); + DiagOccured = true; + }); + if (DiagOccured) + D.setInvalidType(); + } // C++0x [class.ctor]p4: // A constructor shall not be declared with a ref-qualifier. - DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo(); if (FTI.hasRefQualifier()) { Diag(FTI.getRefQualifierLoc(), diag::err_ref_qualifier_constructor) << FTI.RefQualifierIsLValueRef @@ -8430,11 +8423,18 @@ QualType Sema::CheckDestructorDeclarator(Declarator &D, QualType R, } } - checkMethodTypeQualifiers(*this, D, diag::err_invalid_qualified_destructor); + DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo(); + if (FTI.hasMethodTypeQualifiers() && !D.isInvalidType()) { + FTI.MethodQualifiers->forEachQualifier( + [&](DeclSpec::TQ TypeQual, StringRef QualName, SourceLocation SL) { + Diag(SL, diag::err_invalid_qualified_destructor) + << QualName << SourceRange(SL); + }); + D.setInvalidType(); + } // C++0x [class.dtor]p2: // A destructor shall not be declared with a ref-qualifier. - DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo(); if (FTI.hasRefQualifier()) { Diag(FTI.getRefQualifierLoc(), diag::err_ref_qualifier_destructor) << FTI.RefQualifierIsLValueRef diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index f632a4d3bd1a..d8c4ea48ebce 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -5093,10 +5093,12 @@ TryObjectArgumentInitialization(Sema &S, SourceLocation Loc, QualType FromType, QualType ClassType = S.Context.getTypeDeclType(ActingContext); // [class.dtor]p2: A destructor can be invoked for a const, volatile or // const volatile object. - Qualifiers Quals = Method->getMethodQualifiers(); + Qualifiers Quals; if (isa(Method)) { Quals.addConst(); Quals.addVolatile(); + } else { + Quals = Method->getMethodQualifiers(); } QualType ImplicitParamType = S.Context.getQualifiedType(ClassType, Quals); diff --git a/clang/test/CodeGenOpenCLCXX/addrspace-ctor.cl b/clang/test/CodeGenOpenCLCXX/addrspace-ctor.cl new file mode 100644 index 000000000000..42c2e6e9077a --- /dev/null +++ b/clang/test/CodeGenOpenCLCXX/addrspace-ctor.cl @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=c++ -emit-llvm -O0 -o - | FileCheck %s + +struct MyType { + MyType(int i) : i(i) {} + MyType(int i) __constant : i(i) {} + int i; +}; + +//CHECK: call void @_ZNU3AS26MyTypeC1Ei(%struct.MyType addrspace(2)* @const1, i32 1) +__constant MyType const1 = 1; +//CHECK: call void @_ZNU3AS26MyTypeC1Ei(%struct.MyType addrspace(2)* @const2, i32 2) +__constant MyType const2(2); +//CHECK: call void @_ZNU3AS46MyTypeC1Ei(%struct.MyType addrspace(4)* addrspacecast (%struct.MyType addrspace(1)* @glob to %struct.MyType addrspace(4)*), i32 1) +MyType glob(1); diff --git a/clang/test/CodeGenOpenCLCXX/addrspace-with-class.cl b/clang/test/CodeGenOpenCLCXX/addrspace-with-class.cl deleted file mode 100644 index 21ba1ca251d8..000000000000 --- a/clang/test/CodeGenOpenCLCXX/addrspace-with-class.cl +++ /dev/null @@ -1,59 +0,0 @@ -// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=c++ -emit-llvm -O0 -o - | FileCheck %s -// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=c++ -emit-llvm -O0 -o - | FileCheck %s --check-prefix=CHECK-DEFINITIONS - -// This test ensures the proper address spaces and address space cast are used -// for constructors, member functions and destructors. -// See also atexit.cl and global_init.cl for other specific tests. - -// CHECK: %struct.MyType = type { i32 } -struct MyType { - MyType(int i) : i(i) {} - MyType(int i) __constant : i(i) {} - ~MyType() {} - ~MyType() __constant {} - int bar() { return i + 2; } - int bar() __constant { return i + 1; } - int i; -}; - -// CHECK: @const1 = addrspace(2) global %struct.MyType zeroinitializer -__constant MyType const1 = 1; -// CHECK: @const2 = addrspace(2) global %struct.MyType zeroinitializer -__constant MyType const2(2); -// CHECK: @glob = addrspace(1) global %struct.MyType zeroinitializer -MyType glob(1); - -// CHECK: call void @_ZNU3AS26MyTypeC1Ei(%struct.MyType addrspace(2)* @const1, i32 1) -// CHECK: call void @_ZNU3AS26MyTypeC1Ei(%struct.MyType addrspace(2)* @const2, i32 2) -// CHECK: call void @_ZNU3AS46MyTypeC1Ei(%struct.MyType addrspace(4)* addrspacecast (%struct.MyType addrspace(1)* @glob to %struct.MyType addrspace(4)*), i32 1) - -// CHECK-LABEL: define spir_kernel void @fooGlobal() -kernel void fooGlobal() { - // CHECK: call i32 @_ZNU3AS46MyType3barEv(%struct.MyType addrspace(4)* addrspacecast (%struct.MyType addrspace(1)* @glob to %struct.MyType addrspace(4)*)) - glob.bar(); - // CHECK: call i32 @_ZNU3AS26MyType3barEv(%struct.MyType addrspace(2)* @const1) - const1.bar(); - // CHECK: call void @_ZNU3AS26MyTypeD1Ev(%struct.MyType addrspace(2)* @const1) - const1.~MyType(); -} - -// CHECK-LABEL: define spir_kernel void @fooLocal() -kernel void fooLocal() { - // CHECK: [[VAR:%.*]] = alloca %struct.MyType - // CHECK: [[REG:%.*]] = addrspacecast %struct.MyType* [[VAR]] to %struct.MyType addrspace(4)* - // CHECK: call void @_ZNU3AS46MyTypeC1Ei(%struct.MyType addrspace(4)* [[REG]], i32 3) - MyType myLocal(3); - // CHECK: [[REG:%.*]] = addrspacecast %struct.MyType* [[VAR]] to %struct.MyType addrspace(4)* - // CHECK: call i32 @_ZNU3AS46MyType3barEv(%struct.MyType addrspace(4)* [[REG]]) - myLocal.bar(); - // CHECK: [[REG:%.*]] = addrspacecast %struct.MyType* [[VAR]] to %struct.MyType addrspace(4)* - // CHECK: call void @_ZNU3AS46MyTypeD1Ev(%struct.MyType addrspace(4)* [[REG]]) -} - -// Ensure all members are defined for all the required address spaces. -// CHECK-DEFINITIONS-DAG: define linkonce_odr void @_ZNU3AS26MyTypeC1Ei(%struct.MyType addrspace(2)* %this, i32 %i) -// CHECK-DEFINITIONS-DAG: define linkonce_odr void @_ZNU3AS46MyTypeC1Ei(%struct.MyType addrspace(4)* %this, i32 %i) -// CHECK-DEFINITIONS-DAG: define linkonce_odr void @_ZNU3AS26MyTypeD1Ev(%struct.MyType addrspace(2)* %this) -// CHECK-DEFINITIONS-DAG: define linkonce_odr void @_ZNU3AS46MyTypeD1Ev(%struct.MyType addrspace(4)* %this) -// CHECK-DEFINITIONS-DAG: define linkonce_odr i32 @_ZNU3AS26MyType3barEv(%struct.MyType addrspace(2)* %this) -// CHECK-DEFINITIONS-DAG: define linkonce_odr i32 @_ZNU3AS46MyType3barEv(%struct.MyType addrspace(4)* %this) From 7c86e5b06ae54668c1616aa72a47c1ee490b8677 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Fri, 19 Jul 2019 09:38:24 +0000 Subject: [PATCH 007/289] Merging r366433: ------------------------------------------------------------------------ r366433 | stefan.graenitz | 2019-07-18 15:30:37 +0200 (Thu, 18 Jul 2019) | 19 lines [CMake] Always build debugserver on Darwin and allow tests to use the system's one Summary: We can always build debugserver, but we can't always sign it to be useable for testing. `LLDB_USE_SYSTEM_DEBUGSERVER` should only tell whether or not the system debugserver should be used for testing. The old behavior complicated the logic around debugserver a lot. The new logic sorts out most of it. Please note that this patch is in early stage and needs some more testing. It should not affect platfroms other than Darwin. It builds on Davide's approach to validate the code-signing identity at configuration time. What do you think? Reviewers: xiaobai, JDevlieghere, davide, compnerd, friss, labath, mgorny, jasonmolenda Reviewed By: JDevlieghere Subscribers: lldb-commits, #lldb Tags: #lldb Differential Revision: https://reviews.llvm.org/D64806 ------------------------------------------------------------------------ llvm-svn: 366553 --- lldb/CMakeLists.txt | 4 - lldb/cmake/modules/AddLLDB.cmake | 24 +++ lldb/cmake/modules/LLDBConfig.cmake | 1 + lldb/test/CMakeLists.txt | 35 ++-- lldb/tools/debugserver/source/CMakeLists.txt | 185 ++++++------------ lldb/unittests/CMakeLists.txt | 2 +- .../tools/lldb-server/CMakeLists.txt | 9 +- 7 files changed, 115 insertions(+), 145 deletions(-) diff --git a/lldb/CMakeLists.txt b/lldb/CMakeLists.txt index 6b1b67258b3d..609aa0bd2a60 100644 --- a/lldb/CMakeLists.txt +++ b/lldb/CMakeLists.txt @@ -107,10 +107,6 @@ if(LLDB_INCLUDE_TESTS) list(APPEND LLDB_TEST_DEPS lldb-server) endif() - if(TARGET debugserver) - list(APPEND LLDB_TEST_DEPS debugserver) - endif() - if(TARGET lldb-mi) list(APPEND LLDB_TEST_DEPS lldb-mi) endif() diff --git a/lldb/cmake/modules/AddLLDB.cmake b/lldb/cmake/modules/AddLLDB.cmake index 540d01362f0d..4c99278c583b 100644 --- a/lldb/cmake/modules/AddLLDB.cmake +++ b/lldb/cmake/modules/AddLLDB.cmake @@ -276,3 +276,27 @@ function(lldb_setup_rpaths name) INSTALL_RPATH "${LIST_INSTALL_RPATH}" ) endfunction() + +function(lldb_find_system_debugserver path) + execute_process(COMMAND xcode-select -p + RESULT_VARIABLE exit_code + OUTPUT_VARIABLE xcode_dev_dir + ERROR_VARIABLE error_msg + OUTPUT_STRIP_TRAILING_WHITESPACE) + if(exit_code) + message(WARNING "`xcode-select -p` failed:\n${error_msg}") + else() + set(subpath "LLDB.framework/Resources/debugserver") + set(path_shared "${xcode_dev_dir}/../SharedFrameworks/${subpath}") + set(path_private "${xcode_dev_dir}/Library/PrivateFrameworks/${subpath}") + + if(EXISTS ${path_shared}) + set(${path} ${path_shared} PARENT_SCOPE) + elseif(EXISTS ${path_private}) + set(${path} ${path_private} PARENT_SCOPE) + else() + message(WARNING "System debugserver requested, but not found. " + "Candidates don't exist: ${path_shared}\n${path_private}") + endif() + endif() +endfunction() diff --git a/lldb/cmake/modules/LLDBConfig.cmake b/lldb/cmake/modules/LLDBConfig.cmake index ac71136dd026..b9b1ccec2c67 100644 --- a/lldb/cmake/modules/LLDBConfig.cmake +++ b/lldb/cmake/modules/LLDBConfig.cmake @@ -50,6 +50,7 @@ option(LLDB_USE_SYSTEM_SIX "Use six.py shipped with system and do not install a option(LLDB_USE_ENTITLEMENTS "When codesigning, use entitlements if available" ON) option(LLDB_BUILD_FRAMEWORK "Build LLDB.framework (Darwin only)" OFF) option(LLDB_NO_INSTALL_DEFAULT_RPATH "Disable default RPATH settings in binaries" OFF) +option(LLDB_USE_SYSTEM_DEBUGSERVER "Use the system's debugserver for testing (Darwin only)." OFF) if(LLDB_BUILD_FRAMEWORK) if(NOT APPLE) diff --git a/lldb/test/CMakeLists.txt b/lldb/test/CMakeLists.txt index 037222e04477..00225e791526 100644 --- a/lldb/test/CMakeLists.txt +++ b/lldb/test/CMakeLists.txt @@ -74,15 +74,6 @@ if ( CMAKE_SYSTEM_NAME MATCHES "Windows" ) endif() endif() -if(LLDB_CODESIGN_IDENTITY_USED) - list(APPEND LLDB_TEST_COMMON_ARGS --codesign-identity "${LLDB_CODESIGN_IDENTITY_USED}") -endif() - -if(LLDB_BUILD_FRAMEWORK) - get_target_property(framework_target_dir liblldb LIBRARY_OUTPUT_DIRECTORY) - list(APPEND LLDB_TEST_COMMON_ARGS --framework ${framework_target_dir}/LLDB.framework) -endif() - if (NOT ${CMAKE_SYSTEM_NAME} MATCHES "Windows|Darwin") list(APPEND LLDB_TEST_COMMON_ARGS --env ARCHIVER=${CMAKE_AR} --env OBJCOPY=${CMAKE_OBJCOPY}) @@ -94,12 +85,28 @@ if (NOT "${LLDB_LIT_TOOLS_DIR}" STREQUAL "") endif() endif() -if(CMAKE_HOST_APPLE AND DEBUGSERVER_PATH) - list(APPEND LLDB_TEST_COMMON_ARGS --server ${DEBUGSERVER_PATH}) -endif() +if(CMAKE_HOST_APPLE) + if(LLDB_BUILD_FRAMEWORK) + get_target_property(framework_build_dir liblldb LIBRARY_OUTPUT_DIRECTORY) + list(APPEND LLDB_TEST_COMMON_ARGS --framework ${framework_build_dir}/LLDB.framework) + endif() + + # Use the same identity for testing + get_property(code_sign_identity_used GLOBAL PROPERTY LLDB_DEBUGSERVER_CODESIGN_IDENTITY) + if(code_sign_identity_used) + list(APPEND LLDB_TEST_COMMON_ARGS --codesign-identity "${code_sign_identity_used}") + endif() -if(SKIP_TEST_DEBUGSERVER) - list(APPEND LLDB_TEST_COMMON_ARGS --out-of-tree-debugserver) + if(LLDB_USE_SYSTEM_DEBUGSERVER) + lldb_find_system_debugserver(system_debugserver_path) + message(STATUS "LLDB tests use out-of-tree debugserver: ${system_debugserver_path}") + list(APPEND LLDB_TEST_COMMON_ARGS --out-of-tree-debugserver) + else() + set(debugserver_path ${LLVM_RUNTIME_OUTPUT_INTDIR}/debugserver) + message(STATUS "LLDB Tests use just-built debugserver: ${debugserver_path}") + list(APPEND LLDB_TEST_COMMON_ARGS --server ${debugserver_path}) + add_dependencies(lldb-test-deps debugserver) + endif() endif() set(LLDB_DOTEST_ARGS ${LLDB_TEST_COMMON_ARGS};${LLDB_TEST_USER_ARGS}) diff --git a/lldb/tools/debugserver/source/CMakeLists.txt b/lldb/tools/debugserver/source/CMakeLists.txt index cf305c9d2680..303fd28caf6c 100644 --- a/lldb/tools/debugserver/source/CMakeLists.txt +++ b/lldb/tools/debugserver/source/CMakeLists.txt @@ -6,6 +6,58 @@ include_directories(MacOSX/DarwinLog) include_directories(MacOSX) +function(check_certificate identity result_valid) + execute_process( + COMMAND security find-certificate -Z -p -c ${identity} /Library/Keychains/System.keychain + RESULT_VARIABLE exit_code OUTPUT_QUIET ERROR_QUIET) + if(exit_code) + set(${result_valid} FALSE PARENT_SCOPE) + else() + set(${result_valid} TRUE PARENT_SCOPE) + endif() +endfunction() + +function(get_debugserver_codesign_identity result) + string(CONCAT not_found_help + "This will cause failures in the test suite." + "Pass '-DLLDB_USE_SYSTEM_DEBUGSERVER=ON' to use the system one instead." + "See 'Code Signing on macOS' in the documentation." + ) + + # Explicit override: warn if unavailable + if(LLDB_CODESIGN_IDENTITY) + set(${result} ${LLDB_CODESIGN_IDENTITY} PARENT_SCOPE) + check_certificate(${LLDB_CODESIGN_IDENTITY} available) + if(NOT available AND NOT LLDB_USE_SYSTEM_DEBUGSERVER) + message(WARNING "LLDB_CODESIGN_IDENTITY not found: '${LLDB_CODESIGN_IDENTITY}' ${not_found_help}") + endif() + return() + endif() + + # Development signing identity: use if available + check_certificate(lldb_codesign available) + if(available) + set(${result} lldb_codesign PARENT_SCOPE) + return() + endif() + + if(NOT LLDB_USE_SYSTEM_DEBUGSERVER) + message(WARNING "Development code sign identiy not found: 'lldb_codesign' ${not_found_help}") + endif() + + # LLVM pendant: fallback if available + if(LLVM_CODESIGNING_IDENTITY) + check_certificate(${LLVM_CODESIGNING_IDENTITY} available) + if(available) + set(${result} ${LLVM_CODESIGNING_IDENTITY} PARENT_SCOPE) + return() + endif() + endif() + + # Ad-hoc signing: last resort + set(${result} "-" PARENT_SCOPE) +endfunction() + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -stdlib=libc++ -Wl,-sectcreate,__TEXT,__info_plist,${CMAKE_CURRENT_SOURCE_DIR}/../resources/lldb-debugserver-Info.plist") check_cxx_compiler_flag("-Wno-gnu-zero-variadic-macro-arguments" @@ -30,132 +82,17 @@ check_library_exists(compression compression_encode_buffer "" HAVE_LIBCOMPRESSIO add_subdirectory(MacOSX) -# LLDB-specific identity, currently used for code signing debugserver. set(LLDB_CODESIGN_IDENTITY "" CACHE STRING - "Override code sign identity for debugserver and for use in tests; falls back to LLVM_CODESIGNING_IDENTITY if set or lldb_codesign otherwise (Darwin only)") - -# Determine which identity to use and store it in the separate cache entry. -# We will query it later for LLDB_TEST_COMMON_ARGS. -if(LLDB_CODESIGN_IDENTITY) - set(LLDB_CODESIGN_IDENTITY_USED ${LLDB_CODESIGN_IDENTITY} CACHE INTERNAL "" FORCE) -elseif(LLVM_CODESIGNING_IDENTITY) - set(LLDB_CODESIGN_IDENTITY_USED ${LLVM_CODESIGNING_IDENTITY} CACHE INTERNAL "" FORCE) -else() - set(LLDB_CODESIGN_IDENTITY_USED lldb_codesign CACHE INTERNAL "" FORCE) -endif() + "Identity override for debugserver; see 'Code Signing on macOS' in the documentation (Darwin only)") -# Override locally, so the identity is used for targets created in this scope. -set(LLVM_CODESIGNING_IDENTITY ${LLDB_CODESIGN_IDENTITY_USED}) - -option(LLDB_NO_DEBUGSERVER "Disable the debugserver target" OFF) -option(LLDB_USE_SYSTEM_DEBUGSERVER "Use the system's debugserver instead of building it from source (Darwin only)." OFF) +get_debugserver_codesign_identity(debugserver_codesign_identity) -# Incompatible options -if(LLDB_NO_DEBUGSERVER AND LLDB_USE_SYSTEM_DEBUGSERVER) - message(FATAL_ERROR "Inconsistent options: LLDB_NO_DEBUGSERVER and LLDB_USE_SYSTEM_DEBUGSERVER") -endif() - -# Try to locate the system debugserver. -# Subsequent feasibility checks depend on it. -if(APPLE AND CMAKE_HOST_APPLE) - execute_process( - COMMAND xcode-select -p - OUTPUT_VARIABLE xcode_dev_dir) - string(STRIP ${xcode_dev_dir} xcode_dev_dir) - - set(debugserver_rel_path "LLDB.framework/Resources/debugserver") - set(debugserver_shared "${xcode_dev_dir}/../SharedFrameworks/${debugserver_rel_path}") - set(debugserver_private "${xcode_dev_dir}/Library/PrivateFrameworks/${debugserver_rel_path}") - - if(EXISTS ${debugserver_shared}) - set(system_debugserver ${debugserver_shared}) - elseif(EXISTS ${debugserver_private}) - set(system_debugserver ${debugserver_private}) - endif() -endif() - -# Handle unavailability -if(LLDB_USE_SYSTEM_DEBUGSERVER) - if(system_debugserver) - set(use_system_debugserver ON) - elseif(APPLE AND CMAKE_HOST_APPLE) - # Binary not found on system. Keep cached variable, to try again on reconfigure. - message(SEND_ERROR - "LLDB_USE_SYSTEM_DEBUGSERVER option set, but no debugserver found in:\ - ${debugserver_shared}\ - ${debugserver_private}") - else() - # Non-Apple target platform or non-Darwin host. Reset invalid cached variable. - message(WARNING "Reverting invalid option LLDB_USE_SYSTEM_DEBUGSERVER (Darwin only)") - set(LLDB_USE_SYSTEM_DEBUGSERVER OFF CACHE BOOL "" FORCE) - endif() -elseif(NOT LLDB_NO_DEBUGSERVER) - # Default case: on Darwin we need the right code signing ID. - # See lldb/docs/code-signing.txt for details. - if(CMAKE_HOST_APPLE AND NOT LLVM_CODESIGNING_IDENTITY STREQUAL "lldb_codesign") - message(WARNING "Codesigning debugserver with identity ${LLVM_CODESIGNING_IDENTITY}. " - "The usual setup uses the \"lldb_codesign\" identity created with " - "scripts/macos-setup-codesign.sh. As a result your debugserver might " - "not be able to attach to processes.\n" - "Pass -DLLDB_CODESIGN_IDENTITY=lldb_codesign to use the development " - "signing identity.") - endif() - set(build_and_sign_debugserver ON) -endif() - -# TODO: We don't use the $ generator expression here, -# because the value of DEBUGSERVER_PATH is used to build LLDB_DOTEST_ARGS, -# which is used for configuring lldb-dotest.in, which does not have a generator -# step at the moment. -set(default_debugserver_path "${LLVM_RUNTIME_OUTPUT_INTDIR}/debugserver${CMAKE_EXECUTABLE_SUFFIX}") - -# Remember where debugserver binary goes and whether or not we have to test it. -set(DEBUGSERVER_PATH "" CACHE FILEPATH "Path to debugserver") -set(SKIP_TEST_DEBUGSERVER OFF CACHE BOOL "Building the in-tree debugserver was skipped") - -# Reset values in all cases in order to correctly support reconfigurations. -if(use_system_debugserver) - add_custom_target(debugserver - COMMAND ${CMAKE_COMMAND} -E copy_if_different - ${system_debugserver} ${LLVM_RUNTIME_OUTPUT_INTDIR} - COMMENT "Copying the system debugserver to LLDB's binaries directory.") - - set_target_properties(debugserver PROPERTIES FOLDER "lldb libraries/debugserver") - - # Don't test debugserver itself. - # Tests that require debugserver will use the copy. - set(DEBUGSERVER_PATH ${default_debugserver_path} CACHE FILEPATH "" FORCE) - set(SKIP_TEST_DEBUGSERVER ON CACHE BOOL "" FORCE) - - message(STATUS "Copy system debugserver from: ${system_debugserver}") -elseif(build_and_sign_debugserver) - # Build, sign and test debugserver (below) - set(DEBUGSERVER_PATH ${default_debugserver_path} CACHE FILEPATH "" FORCE) - set(SKIP_TEST_DEBUGSERVER OFF CACHE BOOL "" FORCE) - - message(STATUS "lldb debugserver: ${DEBUGSERVER_PATH}") -else() - # No tests for debugserver, no tests that require it. - set(DEBUGSERVER_PATH "" CACHE FILEPATH "" FORCE) - set(SKIP_TEST_DEBUGSERVER ON CACHE BOOL "" FORCE) - - message(STATUS "lldb debugserver will not be available.") -endif() +# Override locally, so the identity is used for targets created in this scope. +set(LLVM_CODESIGNING_IDENTITY ${debugserver_codesign_identity}) -# On MacOS, debugserver needs to be codesigned when built. Check if we have -# a certificate instead of failing in the middle of the build. -if(build_and_sign_debugserver) - execute_process( - COMMAND security find-certificate -Z -p -c ${LLDB_CODESIGN_IDENTITY_USED} /Library/Keychains/System.keychain - RESULT_VARIABLE cert_return - OUTPUT_QUIET - ERROR_QUIET) - - if (cert_return) - message(FATAL_ERROR "Certificate for debugserver not found. Run scripts/macos-setup-codesign.sh or " - "use the system debugserver passing -DLLDB_USE_SYSTEM_DEBUGSERVER=ON to CMake") - endif() -endif() +# Use the same identity later in the test suite. +set_property(GLOBAL PROPERTY + LLDB_DEBUGSERVER_CODESIGN_IDENTITY ${debugserver_codesign_identity}) if(APPLE) if(IOS) @@ -190,7 +127,7 @@ if(LLDB_USE_ENTITLEMENTS) endif() endif() -if(build_and_sign_debugserver) +#if(build_and_sign_debugserver) set(generated_mach_interfaces ${CMAKE_CURRENT_BINARY_DIR}/mach_exc.h ${CMAKE_CURRENT_BINARY_DIR}/mach_excServer.c @@ -318,4 +255,4 @@ if(build_and_sign_debugserver) ${entitlements} ) endif() -endif() +#endif() diff --git a/lldb/unittests/CMakeLists.txt b/lldb/unittests/CMakeLists.txt index 311f47b1b0ec..8e6b3e7b341a 100644 --- a/lldb/unittests/CMakeLists.txt +++ b/lldb/unittests/CMakeLists.txt @@ -78,6 +78,6 @@ add_subdirectory(tools) add_subdirectory(UnwindAssembly) add_subdirectory(Utility) -if(LLDB_CAN_USE_DEBUGSERVER AND NOT SKIP_TEST_DEBUGSERVER) +if(LLDB_CAN_USE_DEBUGSERVER AND NOT LLDB_USE_SYSTEM_DEBUGSERVER) add_subdirectory(debugserver) endif() diff --git a/lldb/unittests/tools/lldb-server/CMakeLists.txt b/lldb/unittests/tools/lldb-server/CMakeLists.txt index 3bae69bfa4a1..7d52181f44b9 100644 --- a/lldb/unittests/tools/lldb-server/CMakeLists.txt +++ b/lldb/unittests/tools/lldb-server/CMakeLists.txt @@ -13,8 +13,13 @@ endfunction() add_lldb_test_executable(thread_inferior inferior/thread_inferior.cpp) add_lldb_test_executable(environment_check inferior/environment_check.cpp) -if(DEBUGSERVER_PATH) - add_definitions(-DLLDB_SERVER="${DEBUGSERVER_PATH}" -DLLDB_SERVER_IS_DEBUGSERVER=1) +if(LLDB_CAN_USE_DEBUGSERVER) + if(LLDB_USE_SYSTEM_DEBUGSERVER) + lldb_find_system_debugserver(debugserver_path) + else() + set(debugserver_path $) + endif() + add_definitions(-DLLDB_SERVER="${debugserver_path}" -DLLDB_SERVER_IS_DEBUGSERVER=1) else() add_definitions(-DLLDB_SERVER="$" -DLLDB_SERVER_IS_DEBUGSERVER=0) endif() From b51b64e4f4bdac842195621745c0176c2dcd050f Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Fri, 19 Jul 2019 09:43:12 +0000 Subject: [PATCH 008/289] Merging r366480: ------------------------------------------------------------------------ r366480 | asb | 2019-07-18 20:29:59 +0200 (Thu, 18 Jul 2019) | 25 lines [RISCV] Hard float ABI support The RISC-V hard float calling convention requires the frontend to: * Detect cases where, once "flattened", a struct can be passed using int+fp or fp+fp registers under the hard float ABI and coerce to the appropriate type(s) * Track usage of GPRs and FPRs in order to gate the above, and to determine when signext/zeroext attributes must be added to integer scalars This patch attempts to do this in compliance with the documented ABI, and uses ABIArgInfo::CoerceAndExpand in order to do this. @rjmccall, as author of that code I've tagged you as reviewer for initial feedback on my usage. Note that a previous version of the ABI indicated that when passing an int+fp struct using a GPR+FPR, the int would need to be sign or zero-extended appropriately. GCC never did this and the ABI was changed, which makes life easier as ABIArgInfo::CoerceAndExpand can't currently handle sign/zero-extension attributes. Re-landed after backing out 366450 due to missed hunks. Differential Revision: https://reviews.llvm.org/D60456 ------------------------------------------------------------------------ llvm-svn: 366554 --- clang/lib/Basic/Targets/RISCV.cpp | 13 +- clang/lib/Basic/Targets/RISCV.h | 6 +- clang/lib/CodeGen/TargetInfo.cpp | 289 +++++++++++++++++- clang/test/CodeGen/riscv32-ilp32-ilp32f-abi.c | 6 +- .../CodeGen/riscv32-ilp32-ilp32f-ilp32d-abi.c | 4 + clang/test/CodeGen/riscv32-ilp32d-abi.c | 282 +++++++++++++++++ clang/test/CodeGen/riscv32-ilp32f-abi.c | 45 +++ .../test/CodeGen/riscv32-ilp32f-ilp32d-abi.c | 275 +++++++++++++++++ clang/test/CodeGen/riscv64-lp64-lp64f-abi.c | 2 + .../CodeGen/riscv64-lp64-lp64f-lp64d-abi.c | 4 + clang/test/CodeGen/riscv64-lp64d-abi.c | 272 +++++++++++++++++ clang/test/CodeGen/riscv64-lp64f-lp64d-abi.c | 265 ++++++++++++++++ clang/test/Driver/riscv-abi.c | 20 +- .../test/Preprocessor/riscv-target-features.c | 24 ++ 14 files changed, 1474 insertions(+), 33 deletions(-) create mode 100644 clang/test/CodeGen/riscv32-ilp32d-abi.c create mode 100644 clang/test/CodeGen/riscv32-ilp32f-abi.c create mode 100644 clang/test/CodeGen/riscv32-ilp32f-ilp32d-abi.c create mode 100644 clang/test/CodeGen/riscv64-lp64d-abi.c create mode 100644 clang/test/CodeGen/riscv64-lp64f-lp64d-abi.c diff --git a/clang/lib/Basic/Targets/RISCV.cpp b/clang/lib/Basic/Targets/RISCV.cpp index f800bb0b25da..58272d14abd1 100644 --- a/clang/lib/Basic/Targets/RISCV.cpp +++ b/clang/lib/Basic/Targets/RISCV.cpp @@ -65,9 +65,18 @@ void RISCVTargetInfo::getTargetDefines(const LangOptions &Opts, Builder.defineMacro("__riscv"); bool Is64Bit = getTriple().getArch() == llvm::Triple::riscv64; Builder.defineMacro("__riscv_xlen", Is64Bit ? "64" : "32"); - // TODO: modify when more code models and ABIs are supported. + // TODO: modify when more code models are supported. Builder.defineMacro("__riscv_cmodel_medlow"); - Builder.defineMacro("__riscv_float_abi_soft"); + + StringRef ABIName = getABI(); + if (ABIName == "ilp32f" || ABIName == "lp64f") + Builder.defineMacro("__riscv_float_abi_single"); + else if (ABIName == "ilp32d" || ABIName == "lp64d") + Builder.defineMacro("__riscv_float_abi_double"); + else if (ABIName == "ilp32e") + Builder.defineMacro("__riscv_abi_rve"); + else + Builder.defineMacro("__riscv_float_abi_soft"); if (HasM) { Builder.defineMacro("__riscv_mul"); diff --git a/clang/lib/Basic/Targets/RISCV.h b/clang/lib/Basic/Targets/RISCV.h index bc814b79ce51..ce193feaeb98 100644 --- a/clang/lib/Basic/Targets/RISCV.h +++ b/clang/lib/Basic/Targets/RISCV.h @@ -87,8 +87,7 @@ class LLVM_LIBRARY_VISIBILITY RISCV32TargetInfo : public RISCVTargetInfo { } bool setABI(const std::string &Name) override { - // TODO: support ilp32f and ilp32d ABIs. - if (Name == "ilp32") { + if (Name == "ilp32" || Name == "ilp32f" || Name == "ilp32d") { ABI = Name; return true; } @@ -105,8 +104,7 @@ class LLVM_LIBRARY_VISIBILITY RISCV64TargetInfo : public RISCVTargetInfo { } bool setABI(const std::string &Name) override { - // TODO: support lp64f and lp64d ABIs. - if (Name == "lp64") { + if (Name == "lp64" || Name == "lp64f" || Name == "lp64d") { ABI = Name; return true; } diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp index 5da988fb8a3c..1e1038dbfe95 100644 --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -9188,25 +9188,45 @@ static bool getTypeString(SmallStringEnc &Enc, const Decl *D, namespace { class RISCVABIInfo : public DefaultABIInfo { private: - unsigned XLen; // Size of the integer ('x') registers in bits. + // Size of the integer ('x') registers in bits. + unsigned XLen; + // Size of the floating point ('f') registers in bits. Note that the target + // ISA might have a wider FLen than the selected ABI (e.g. an RV32IF target + // with soft float ABI has FLen==0). + unsigned FLen; static const int NumArgGPRs = 8; + static const int NumArgFPRs = 8; + bool detectFPCCEligibleStructHelper(QualType Ty, CharUnits CurOff, + llvm::Type *&Field1Ty, + CharUnits &Field1Off, + llvm::Type *&Field2Ty, + CharUnits &Field2Off) const; public: - RISCVABIInfo(CodeGen::CodeGenTypes &CGT, unsigned XLen) - : DefaultABIInfo(CGT), XLen(XLen) {} + RISCVABIInfo(CodeGen::CodeGenTypes &CGT, unsigned XLen, unsigned FLen) + : DefaultABIInfo(CGT), XLen(XLen), FLen(FLen) {} // DefaultABIInfo's classifyReturnType and classifyArgumentType are // non-virtual, but computeInfo is virtual, so we overload it. void computeInfo(CGFunctionInfo &FI) const override; - ABIArgInfo classifyArgumentType(QualType Ty, bool IsFixed, - int &ArgGPRsLeft) const; + ABIArgInfo classifyArgumentType(QualType Ty, bool IsFixed, int &ArgGPRsLeft, + int &ArgFPRsLeft) const; ABIArgInfo classifyReturnType(QualType RetTy) const; Address EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, QualType Ty) const override; ABIArgInfo extendType(QualType Ty) const; + + bool detectFPCCEligibleStruct(QualType Ty, llvm::Type *&Field1Ty, + CharUnits &Field1Off, llvm::Type *&Field2Ty, + CharUnits &Field2Off, int &NeededArgGPRs, + int &NeededArgFPRs) const; + ABIArgInfo coerceAndExpandFPCCEligibleStruct(llvm::Type *Field1Ty, + CharUnits Field1Off, + llvm::Type *Field2Ty, + CharUnits Field2Off) const; }; } // end anonymous namespace @@ -9228,18 +9248,215 @@ void RISCVABIInfo::computeInfo(CGFunctionInfo &FI) const { // different for variadic arguments, we must also track whether we are // examining a vararg or not. int ArgGPRsLeft = IsRetIndirect ? NumArgGPRs - 1 : NumArgGPRs; + int ArgFPRsLeft = FLen ? NumArgFPRs : 0; int NumFixedArgs = FI.getNumRequiredArgs(); int ArgNum = 0; for (auto &ArgInfo : FI.arguments()) { bool IsFixed = ArgNum < NumFixedArgs; - ArgInfo.info = classifyArgumentType(ArgInfo.type, IsFixed, ArgGPRsLeft); + ArgInfo.info = + classifyArgumentType(ArgInfo.type, IsFixed, ArgGPRsLeft, ArgFPRsLeft); ArgNum++; } } +// Returns true if the struct is a potential candidate for the floating point +// calling convention. If this function returns true, the caller is +// responsible for checking that if there is only a single field then that +// field is a float. +bool RISCVABIInfo::detectFPCCEligibleStructHelper(QualType Ty, CharUnits CurOff, + llvm::Type *&Field1Ty, + CharUnits &Field1Off, + llvm::Type *&Field2Ty, + CharUnits &Field2Off) const { + bool IsInt = Ty->isIntegralOrEnumerationType(); + bool IsFloat = Ty->isRealFloatingType(); + + if (IsInt || IsFloat) { + uint64_t Size = getContext().getTypeSize(Ty); + if (IsInt && Size > XLen) + return false; + // Can't be eligible if larger than the FP registers. Half precision isn't + // currently supported on RISC-V and the ABI hasn't been confirmed, so + // default to the integer ABI in that case. + if (IsFloat && (Size > FLen || Size < 32)) + return false; + // Can't be eligible if an integer type was already found (int+int pairs + // are not eligible). + if (IsInt && Field1Ty && Field1Ty->isIntegerTy()) + return false; + if (!Field1Ty) { + Field1Ty = CGT.ConvertType(Ty); + Field1Off = CurOff; + return true; + } + if (!Field2Ty) { + Field2Ty = CGT.ConvertType(Ty); + Field2Off = CurOff; + return true; + } + return false; + } + + if (auto CTy = Ty->getAs()) { + if (Field1Ty) + return false; + QualType EltTy = CTy->getElementType(); + if (getContext().getTypeSize(EltTy) > FLen) + return false; + Field1Ty = CGT.ConvertType(EltTy); + Field1Off = CurOff; + assert(CurOff.isZero() && "Unexpected offset for first field"); + Field2Ty = Field1Ty; + Field2Off = Field1Off + getContext().getTypeSizeInChars(EltTy); + return true; + } + + if (const ConstantArrayType *ATy = getContext().getAsConstantArrayType(Ty)) { + uint64_t ArraySize = ATy->getSize().getZExtValue(); + QualType EltTy = ATy->getElementType(); + CharUnits EltSize = getContext().getTypeSizeInChars(EltTy); + for (uint64_t i = 0; i < ArraySize; ++i) { + bool Ret = detectFPCCEligibleStructHelper(EltTy, CurOff, Field1Ty, + Field1Off, Field2Ty, Field2Off); + if (!Ret) + return false; + CurOff += EltSize; + } + return true; + } + + if (const auto *RTy = Ty->getAs()) { + // Structures with either a non-trivial destructor or a non-trivial + // copy constructor are not eligible for the FP calling convention. + if (CGCXXABI::RecordArgABI RAA = getRecordArgABI(Ty, CGT.getCXXABI())) + return false; + if (isEmptyRecord(getContext(), Ty, true)) + return true; + const RecordDecl *RD = RTy->getDecl(); + // Unions aren't eligible unless they're empty (which is caught above). + if (RD->isUnion()) + return false; + int ZeroWidthBitFieldCount = 0; + for (const FieldDecl *FD : RD->fields()) { + const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD); + uint64_t FieldOffInBits = Layout.getFieldOffset(FD->getFieldIndex()); + QualType QTy = FD->getType(); + if (FD->isBitField()) { + unsigned BitWidth = FD->getBitWidthValue(getContext()); + // Allow a bitfield with a type greater than XLen as long as the + // bitwidth is XLen or less. + if (getContext().getTypeSize(QTy) > XLen && BitWidth <= XLen) + QTy = getContext().getIntTypeForBitwidth(XLen, false); + if (BitWidth == 0) { + ZeroWidthBitFieldCount++; + continue; + } + } + + bool Ret = detectFPCCEligibleStructHelper( + QTy, CurOff + getContext().toCharUnitsFromBits(FieldOffInBits), + Field1Ty, Field1Off, Field2Ty, Field2Off); + if (!Ret) + return false; + + // As a quirk of the ABI, zero-width bitfields aren't ignored for fp+fp + // or int+fp structs, but are ignored for a struct with an fp field and + // any number of zero-width bitfields. + if (Field2Ty && ZeroWidthBitFieldCount > 0) + return false; + } + return Field1Ty != nullptr; + } + + return false; +} + +// Determine if a struct is eligible for passing according to the floating +// point calling convention (i.e., when flattened it contains a single fp +// value, fp+fp, or int+fp of appropriate size). If so, NeededArgFPRs and +// NeededArgGPRs are incremented appropriately. +bool RISCVABIInfo::detectFPCCEligibleStruct(QualType Ty, llvm::Type *&Field1Ty, + CharUnits &Field1Off, + llvm::Type *&Field2Ty, + CharUnits &Field2Off, + int &NeededArgGPRs, + int &NeededArgFPRs) const { + Field1Ty = nullptr; + Field2Ty = nullptr; + NeededArgGPRs = 0; + NeededArgFPRs = 0; + bool IsCandidate = detectFPCCEligibleStructHelper( + Ty, CharUnits::Zero(), Field1Ty, Field1Off, Field2Ty, Field2Off); + // Not really a candidate if we have a single int but no float. + if (Field1Ty && !Field2Ty && !Field1Ty->isFloatingPointTy()) + return IsCandidate = false; + if (!IsCandidate) + return false; + if (Field1Ty && Field1Ty->isFloatingPointTy()) + NeededArgFPRs++; + else if (Field1Ty) + NeededArgGPRs++; + if (Field2Ty && Field2Ty->isFloatingPointTy()) + NeededArgFPRs++; + else if (Field2Ty) + NeededArgGPRs++; + return IsCandidate; +} + +// Call getCoerceAndExpand for the two-element flattened struct described by +// Field1Ty, Field1Off, Field2Ty, Field2Off. This method will create an +// appropriate coerceToType and unpaddedCoerceToType. +ABIArgInfo RISCVABIInfo::coerceAndExpandFPCCEligibleStruct( + llvm::Type *Field1Ty, CharUnits Field1Off, llvm::Type *Field2Ty, + CharUnits Field2Off) const { + SmallVector CoerceElts; + SmallVector UnpaddedCoerceElts; + if (!Field1Off.isZero()) + CoerceElts.push_back(llvm::ArrayType::get( + llvm::Type::getInt8Ty(getVMContext()), Field1Off.getQuantity())); + + CoerceElts.push_back(Field1Ty); + UnpaddedCoerceElts.push_back(Field1Ty); + + if (!Field2Ty) { + return ABIArgInfo::getCoerceAndExpand( + llvm::StructType::get(getVMContext(), CoerceElts, !Field1Off.isZero()), + UnpaddedCoerceElts[0]); + } + + CharUnits Field2Align = + CharUnits::fromQuantity(getDataLayout().getABITypeAlignment(Field2Ty)); + CharUnits Field1Size = + CharUnits::fromQuantity(getDataLayout().getTypeStoreSize(Field1Ty)); + CharUnits Field2OffNoPadNoPack = Field1Size.alignTo(Field2Align); + + CharUnits Padding = CharUnits::Zero(); + if (Field2Off > Field2OffNoPadNoPack) + Padding = Field2Off - Field2OffNoPadNoPack; + else if (Field2Off != Field2Align && Field2Off > Field1Size) + Padding = Field2Off - Field1Size; + + bool IsPacked = !Field2Off.isMultipleOf(Field2Align); + + if (!Padding.isZero()) + CoerceElts.push_back(llvm::ArrayType::get( + llvm::Type::getInt8Ty(getVMContext()), Padding.getQuantity())); + + CoerceElts.push_back(Field2Ty); + UnpaddedCoerceElts.push_back(Field2Ty); + + auto CoerceToType = + llvm::StructType::get(getVMContext(), CoerceElts, IsPacked); + auto UnpaddedCoerceToType = + llvm::StructType::get(getVMContext(), UnpaddedCoerceElts, IsPacked); + + return ABIArgInfo::getCoerceAndExpand(CoerceToType, UnpaddedCoerceToType); +} + ABIArgInfo RISCVABIInfo::classifyArgumentType(QualType Ty, bool IsFixed, - int &ArgGPRsLeft) const { + int &ArgGPRsLeft, + int &ArgFPRsLeft) const { assert(ArgGPRsLeft <= NumArgGPRs && "Arg GPR tracking underflow"); Ty = useFirstFieldIfTransparentUnion(Ty); @@ -9257,6 +9474,42 @@ ABIArgInfo RISCVABIInfo::classifyArgumentType(QualType Ty, bool IsFixed, return ABIArgInfo::getIgnore(); uint64_t Size = getContext().getTypeSize(Ty); + + // Pass floating point values via FPRs if possible. + if (IsFixed && Ty->isFloatingType() && FLen >= Size && ArgFPRsLeft) { + ArgFPRsLeft--; + return ABIArgInfo::getDirect(); + } + + // Complex types for the hard float ABI must be passed direct rather than + // using CoerceAndExpand. + if (IsFixed && Ty->isComplexType() && FLen && ArgFPRsLeft >= 2) { + QualType EltTy = Ty->getAs()->getElementType(); + if (getContext().getTypeSize(EltTy) <= FLen) { + ArgFPRsLeft -= 2; + return ABIArgInfo::getDirect(); + } + } + + if (IsFixed && FLen && Ty->isStructureOrClassType()) { + llvm::Type *Field1Ty = nullptr; + llvm::Type *Field2Ty = nullptr; + CharUnits Field1Off = CharUnits::Zero(); + CharUnits Field2Off = CharUnits::Zero(); + int NeededArgGPRs; + int NeededArgFPRs; + bool IsCandidate = + detectFPCCEligibleStruct(Ty, Field1Ty, Field1Off, Field2Ty, Field2Off, + NeededArgGPRs, NeededArgFPRs); + if (IsCandidate && NeededArgGPRs <= ArgGPRsLeft && + NeededArgFPRs <= ArgFPRsLeft) { + ArgGPRsLeft -= NeededArgGPRs; + ArgFPRsLeft -= NeededArgFPRs; + return coerceAndExpandFPCCEligibleStruct(Field1Ty, Field1Off, Field2Ty, + Field2Off); + } + } + uint64_t NeededAlign = getContext().getTypeAlign(Ty); bool MustUseStack = false; // Determine the number of GPRs needed to pass the current argument @@ -9315,10 +9568,12 @@ ABIArgInfo RISCVABIInfo::classifyReturnType(QualType RetTy) const { return ABIArgInfo::getIgnore(); int ArgGPRsLeft = 2; + int ArgFPRsLeft = FLen ? 2 : 0; // The rules for return and argument types are the same, so defer to // classifyArgumentType. - return classifyArgumentType(RetTy, /*IsFixed=*/true, ArgGPRsLeft); + return classifyArgumentType(RetTy, /*IsFixed=*/true, ArgGPRsLeft, + ArgFPRsLeft); } Address RISCVABIInfo::EmitVAArg(CodeGenFunction &CGF, Address VAListAddr, @@ -9353,8 +9608,9 @@ ABIArgInfo RISCVABIInfo::extendType(QualType Ty) const { namespace { class RISCVTargetCodeGenInfo : public TargetCodeGenInfo { public: - RISCVTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT, unsigned XLen) - : TargetCodeGenInfo(new RISCVABIInfo(CGT, XLen)) {} + RISCVTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT, unsigned XLen, + unsigned FLen) + : TargetCodeGenInfo(new RISCVABIInfo(CGT, XLen, FLen)) {} void setTargetAttributes(const Decl *D, llvm::GlobalValue *GV, CodeGen::CodeGenModule &CGM) const override { @@ -9493,9 +9749,16 @@ const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() { return SetCGInfo(new MSP430TargetCodeGenInfo(Types)); case llvm::Triple::riscv32: - return SetCGInfo(new RISCVTargetCodeGenInfo(Types, 32)); - case llvm::Triple::riscv64: - return SetCGInfo(new RISCVTargetCodeGenInfo(Types, 64)); + case llvm::Triple::riscv64: { + StringRef ABIStr = getTarget().getABI(); + unsigned XLen = getTarget().getPointerWidth(0); + unsigned ABIFLen = 0; + if (ABIStr.endswith("f")) + ABIFLen = 32; + else if (ABIStr.endswith("d")) + ABIFLen = 64; + return SetCGInfo(new RISCVTargetCodeGenInfo(Types, XLen, ABIFLen)); + } case llvm::Triple::systemz: { bool HasVector = getTarget().getABI() == "vector"; diff --git a/clang/test/CodeGen/riscv32-ilp32-ilp32f-abi.c b/clang/test/CodeGen/riscv32-ilp32-ilp32f-abi.c index 0c2f0791e316..677040626f57 100644 --- a/clang/test/CodeGen/riscv32-ilp32-ilp32f-abi.c +++ b/clang/test/CodeGen/riscv32-ilp32-ilp32f-abi.c @@ -1,4 +1,6 @@ // RUN: %clang_cc1 -triple riscv32 -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple riscv32 -target-feature +f -target-abi ilp32f -emit-llvm %s -o - \ +// RUN: | FileCheck %s // This file contains test cases that will have the same output for the ilp32 // and ilp32f ABIs. @@ -35,8 +37,8 @@ int f_scalar_stack_1(int32_t a, int64_t b, int32_t c, double d, long double e, // the presence of large return values that consume a register due to the need // to pass a pointer. -// CHECK-LABEL: define void @f_scalar_stack_2(%struct.large* noalias sret %agg.result, i32 %a, i64 %b, i64 %c, fp128 %d, i8 zeroext %e, i8 %f, i8 %g) -struct large f_scalar_stack_2(int32_t a, int64_t b, int64_t c, long double d, +// CHECK-LABEL: define void @f_scalar_stack_2(%struct.large* noalias sret %agg.result, i32 %a, i64 %b, double %c, fp128 %d, i8 zeroext %e, i8 %f, i8 %g) +struct large f_scalar_stack_2(int32_t a, int64_t b, double c, long double d, uint8_t e, int8_t f, uint8_t g) { return (struct large){a, e, f, g}; } diff --git a/clang/test/CodeGen/riscv32-ilp32-ilp32f-ilp32d-abi.c b/clang/test/CodeGen/riscv32-ilp32-ilp32f-ilp32d-abi.c index 12837fce9422..fa11c1772d72 100644 --- a/clang/test/CodeGen/riscv32-ilp32-ilp32f-ilp32d-abi.c +++ b/clang/test/CodeGen/riscv32-ilp32-ilp32f-ilp32d-abi.c @@ -1,6 +1,10 @@ // RUN: %clang_cc1 -triple riscv32 -emit-llvm %s -o - | FileCheck %s // RUN: %clang_cc1 -triple riscv32 -emit-llvm -fforce-enable-int128 %s -o - \ // RUN: | FileCheck %s -check-prefixes=CHECK,CHECK-FORCEINT128 +// RUN: %clang_cc1 -triple riscv32 -target-feature +f -target-abi ilp32f -emit-llvm %s -o - \ +// RUN: | FileCheck %s +// RUN: %clang_cc1 -triple riscv32 -target-feature +d -target-abi ilp32d -emit-llvm %s -o - \ +// RUN: | FileCheck %s // This file contains test cases that will have the same output for the ilp32, // ilp32f, and ilp32d ABIs. diff --git a/clang/test/CodeGen/riscv32-ilp32d-abi.c b/clang/test/CodeGen/riscv32-ilp32d-abi.c new file mode 100644 index 000000000000..b10656cf123e --- /dev/null +++ b/clang/test/CodeGen/riscv32-ilp32d-abi.c @@ -0,0 +1,282 @@ +// RUN: %clang_cc1 -triple riscv32 -target-feature +d -target-abi ilp32d -emit-llvm %s -o - \ +// RUN: | FileCheck %s + +#include + +// Verify that the tracking of used GPRs and FPRs works correctly by checking +// that small integers are sign/zero extended when passed in registers. + +// Doubles are passed in FPRs, so argument 'i' will be passed zero-extended +// because it will be passed in a GPR. + +// CHECK: define void @f_fpr_tracking(double %a, double %b, double %c, double %d, double %e, double %f, double %g, double %h, i8 zeroext %i) +void f_fpr_tracking(double a, double b, double c, double d, double e, double f, + double g, double h, uint8_t i) {} + +// Check that fp, fp+fp, and int+fp structs are lowered correctly. These will +// be passed in FPR, FPR+FPR, or GPR+FPR regs if sufficient registers are +// available the widths are <= XLEN and FLEN, and should be expanded to +// separate arguments in IR. They are passed by the same rules for returns, +// but will be lowered to simple two-element structs if necessary (as LLVM IR +// functions cannot return multiple values). + +// A struct containing just one floating-point real is passed as though it +// were a standalone floating-point real. + +struct double_s { double f; }; + +// CHECK: define void @f_double_s_arg(double) +void f_double_s_arg(struct double_s a) {} + +// CHECK: define double @f_ret_double_s() +struct double_s f_ret_double_s() { + return (struct double_s){1.0}; +} + +// A struct containing a double and any number of zero-width bitfields is +// passed as though it were a standalone floating-point real. + +struct zbf_double_s { int : 0; double f; }; +struct zbf_double_zbf_s { int : 0; double f; int : 0; }; + +// CHECK: define void @f_zbf_double_s_arg(double) +void f_zbf_double_s_arg(struct zbf_double_s a) {} + +// CHECK: define double @f_ret_zbf_double_s() +struct zbf_double_s f_ret_zbf_double_s() { + return (struct zbf_double_s){1.0}; +} + +// CHECK: define void @f_zbf_double_zbf_s_arg(double) +void f_zbf_double_zbf_s_arg(struct zbf_double_zbf_s a) {} + +// CHECK: define double @f_ret_zbf_double_zbf_s() +struct zbf_double_zbf_s f_ret_zbf_double_zbf_s() { + return (struct zbf_double_zbf_s){1.0}; +} + +// Check that structs containing two floating point values (FLEN <= width) are +// expanded provided sufficient FPRs are available. + +struct double_double_s { double f; double g; }; +struct double_float_s { double f; float g; }; + +// CHECK: define void @f_double_double_s_arg(double, double) +void f_double_double_s_arg(struct double_double_s a) {} + +// CHECK: define { double, double } @f_ret_double_double_s() +struct double_double_s f_ret_double_double_s() { + return (struct double_double_s){1.0, 2.0}; +} + +// CHECK: define void @f_double_float_s_arg(double, float) +void f_double_float_s_arg(struct double_float_s a) {} + +// CHECK: define { double, float } @f_ret_double_float_s() +struct double_float_s f_ret_double_float_s() { + return (struct double_float_s){1.0, 2.0}; +} + +// CHECK: define void @f_double_double_s_arg_insufficient_fprs(float %a, double %b, double %c, double %d, double %e, double %f, double %g, %struct.double_double_s* %h) +void f_double_double_s_arg_insufficient_fprs(float a, double b, double c, double d, + double e, double f, double g, struct double_double_s h) {} + +// Check that structs containing int+double values are expanded, provided +// sufficient FPRs and GPRs are available. The integer components are neither +// sign or zero-extended. + +struct double_int8_s { double f; int8_t i; }; +struct double_uint8_s { double f; uint8_t i; }; +struct double_int32_s { double f; int32_t i; }; +struct double_int64_s { double f; int64_t i; }; +struct double_int64bf_s { double f; int64_t i : 32; }; +struct double_int8_zbf_s { double f; int8_t i; int : 0; }; + +// CHECK: define void @f_double_int8_s_arg(double, i8) +void f_double_int8_s_arg(struct double_int8_s a) {} + +// CHECK: define { double, i8 } @f_ret_double_int8_s() +struct double_int8_s f_ret_double_int8_s() { + return (struct double_int8_s){1.0, 2}; +} + +// CHECK: define void @f_double_uint8_s_arg(double, i8) +void f_double_uint8_s_arg(struct double_uint8_s a) {} + +// CHECK: define { double, i8 } @f_ret_double_uint8_s() +struct double_uint8_s f_ret_double_uint8_s() { + return (struct double_uint8_s){1.0, 2}; +} + +// CHECK: define void @f_double_int32_s_arg(double, i32) +void f_double_int32_s_arg(struct double_int32_s a) {} + +// CHECK: define { double, i32 } @f_ret_double_int32_s() +struct double_int32_s f_ret_double_int32_s() { + return (struct double_int32_s){1.0, 2}; +} + +// CHECK: define void @f_double_int64_s_arg(%struct.double_int64_s* %a) +void f_double_int64_s_arg(struct double_int64_s a) {} + +// CHECK: define void @f_ret_double_int64_s(%struct.double_int64_s* noalias sret %agg.result) +struct double_int64_s f_ret_double_int64_s() { + return (struct double_int64_s){1.0, 2}; +} + +// CHECK: define void @f_double_int64bf_s_arg(double, i32) +void f_double_int64bf_s_arg(struct double_int64bf_s a) {} + +// CHECK: define { double, i32 } @f_ret_double_int64bf_s() +struct double_int64bf_s f_ret_double_int64bf_s() { + return (struct double_int64bf_s){1.0, 2}; +} + +// The zero-width bitfield means the struct can't be passed according to the +// floating point calling convention. + +// CHECK: define void @f_double_int8_zbf_s(double, i8) +void f_double_int8_zbf_s(struct double_int8_zbf_s a) {} + +// CHECK: define { double, i8 } @f_ret_double_int8_zbf_s() +struct double_int8_zbf_s f_ret_double_int8_zbf_s() { + return (struct double_int8_zbf_s){1.0, 2}; +} + +// CHECK: define void @f_double_int8_s_arg_insufficient_gprs(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, i32 %h, %struct.double_int8_s* %i) +void f_double_int8_s_arg_insufficient_gprs(int a, int b, int c, int d, int e, + int f, int g, int h, struct double_int8_s i) {} + +// CHECK: define void @f_struct_double_int8_insufficient_fprs(float %a, double %b, double %c, double %d, double %e, double %f, double %g, double %h, %struct.double_int8_s* %i) +void f_struct_double_int8_insufficient_fprs(float a, double b, double c, double d, + double e, double f, double g, double h, struct double_int8_s i) {} + +// Complex floating-point values or structs containing a single complex +// floating-point value should be passed as if it were an fp+fp struct. + +// CHECK: define void @f_doublecomplex(double %a.coerce0, double %a.coerce1) +void f_doublecomplex(double __complex__ a) {} + +// CHECK: define { double, double } @f_ret_doublecomplex() +double __complex__ f_ret_doublecomplex() { + return 1.0; +} + +struct doublecomplex_s { double __complex__ c; }; + +// CHECK: define void @f_doublecomplex_s_arg(double, double) +void f_doublecomplex_s_arg(struct doublecomplex_s a) {} + +// CHECK: define { double, double } @f_ret_doublecomplex_s() +struct doublecomplex_s f_ret_doublecomplex_s() { + return (struct doublecomplex_s){1.0}; +} + +// Test single or two-element structs that need flattening. e.g. those +// containing nested structs, doubles in small arrays, zero-length structs etc. + +struct doublearr1_s { double a[1]; }; + +// CHECK: define void @f_doublearr1_s_arg(double) +void f_doublearr1_s_arg(struct doublearr1_s a) {} + +// CHECK: define double @f_ret_doublearr1_s() +struct doublearr1_s f_ret_doublearr1_s() { + return (struct doublearr1_s){{1.0}}; +} + +struct doublearr2_s { double a[2]; }; + +// CHECK: define void @f_doublearr2_s_arg(double, double) +void f_doublearr2_s_arg(struct doublearr2_s a) {} + +// CHECK: define { double, double } @f_ret_doublearr2_s() +struct doublearr2_s f_ret_doublearr2_s() { + return (struct doublearr2_s){{1.0, 2.0}}; +} + +struct doublearr2_tricky1_s { struct { double f[1]; } g[2]; }; + +// CHECK: define void @f_doublearr2_tricky1_s_arg(double, double) +void f_doublearr2_tricky1_s_arg(struct doublearr2_tricky1_s a) {} + +// CHECK: define { double, double } @f_ret_doublearr2_tricky1_s() +struct doublearr2_tricky1_s f_ret_doublearr2_tricky1_s() { + return (struct doublearr2_tricky1_s){{{{1.0}}, {{2.0}}}}; +} + +struct doublearr2_tricky2_s { struct {}; struct { double f[1]; } g[2]; }; + +// CHECK: define void @f_doublearr2_tricky2_s_arg(double, double) +void f_doublearr2_tricky2_s_arg(struct doublearr2_tricky2_s a) {} + +// CHECK: define { double, double } @f_ret_doublearr2_tricky2_s() +struct doublearr2_tricky2_s f_ret_doublearr2_tricky2_s() { + return (struct doublearr2_tricky2_s){{}, {{{1.0}}, {{2.0}}}}; +} + +struct doublearr2_tricky3_s { union {}; struct { double f[1]; } g[2]; }; + +// CHECK: define void @f_doublearr2_tricky3_s_arg(double, double) +void f_doublearr2_tricky3_s_arg(struct doublearr2_tricky3_s a) {} + +// CHECK: define { double, double } @f_ret_doublearr2_tricky3_s() +struct doublearr2_tricky3_s f_ret_doublearr2_tricky3_s() { + return (struct doublearr2_tricky3_s){{}, {{{1.0}}, {{2.0}}}}; +} + +struct doublearr2_tricky4_s { union {}; struct { struct {}; double f[1]; } g[2]; }; + +// CHECK: define void @f_doublearr2_tricky4_s_arg(double, double) +void f_doublearr2_tricky4_s_arg(struct doublearr2_tricky4_s a) {} + +// CHECK: define { double, double } @f_ret_doublearr2_tricky4_s() +struct doublearr2_tricky4_s f_ret_doublearr2_tricky4_s() { + return (struct doublearr2_tricky4_s){{}, {{{}, {1.0}}, {{}, {2.0}}}}; +} + +// Test structs that should be passed according to the normal integer calling +// convention. + +struct int_double_int_s { int a; double b; int c; }; + +// CHECK: define void @f_int_double_int_s_arg(%struct.int_double_int_s* %a) +void f_int_double_int_s_arg(struct int_double_int_s a) {} + +// CHECK: define void @f_ret_int_double_int_s(%struct.int_double_int_s* noalias sret %agg.result) +struct int_double_int_s f_ret_int_double_int_s() { + return (struct int_double_int_s){1, 2.0, 3}; +} + +struct int64_double_s { int64_t a; double b; }; + +// CHECK: define void @f_int64_double_s_arg(%struct.int64_double_s* %a) +void f_int64_double_s_arg(struct int64_double_s a) {} + +// CHECK: define void @f_ret_int64_double_s(%struct.int64_double_s* noalias sret %agg.result) +struct int64_double_s f_ret_int64_double_s() { + return (struct int64_double_s){1, 2.0}; +} + +struct char_char_double_s { char a; char b; double c; }; + +// CHECK-LABEL: define void @f_char_char_double_s_arg(%struct.char_char_double_s* %a) +void f_char_char_double_s_arg(struct char_char_double_s a) {} + +// CHECK: define void @f_ret_char_char_double_s(%struct.char_char_double_s* noalias sret %agg.result) +struct char_char_double_s f_ret_char_char_double_s() { + return (struct char_char_double_s){1, 2, 3.0}; +} + +// Unions are always passed according to the integer calling convention, even +// if they can only contain a double. + +union double_u { double a; }; + +// CHECK: define void @f_double_u_arg(i64 %a.coerce) +void f_double_u_arg(union double_u a) {} + +// CHECK: define i64 @f_ret_double_u() +union double_u f_ret_double_u() { + return (union double_u){1.0}; +} diff --git a/clang/test/CodeGen/riscv32-ilp32f-abi.c b/clang/test/CodeGen/riscv32-ilp32f-abi.c new file mode 100644 index 000000000000..76092958aedd --- /dev/null +++ b/clang/test/CodeGen/riscv32-ilp32f-abi.c @@ -0,0 +1,45 @@ +// RUN: %clang_cc1 -triple riscv32 -target-feature +f -target-abi ilp32f -emit-llvm %s -o - \ +// RUN: | FileCheck %s + +#include + +// Doubles are still passed in GPRs, so the 'e' argument will be anyext as +// GPRs are exhausted. + +// CHECK: define void @f_fpr_tracking(double %a, double %b, double %c, double %d, i8 %e) +void f_fpr_tracking(double a, double b, double c, double d, int8_t e) {} + +// Lowering for doubles is unnmodified, as 64 > FLEN. + +struct double_s { double d; }; + +// CHECK: define void @f_double_s_arg(i64 %a.coerce) +void f_double_s_arg(struct double_s a) {} + +// CHECK: define i64 @f_ret_double_s() +struct double_s f_ret_double_s() { + return (struct double_s){1.0}; +} + +struct double_double_s { double d; double e; }; + +// CHECK: define void @f_double_double_s_arg(%struct.double_double_s* %a) +void f_double_double_s_arg(struct double_double_s a) {} + +// CHECK: define void @f_ret_double_double_s(%struct.double_double_s* noalias sret %agg.result) +struct double_double_s f_ret_double_double_s() { + return (struct double_double_s){1.0, 2.0}; +} + +struct double_int8_s { double d; int64_t i; }; + +struct int_double_s { int a; double b; }; + +// CHECK: define void @f_int_double_s_arg(%struct.int_double_s* %a) +void f_int_double_s_arg(struct int_double_s a) {} + +// CHECK: define void @f_ret_int_double_s(%struct.int_double_s* noalias sret %agg.result) +struct int_double_s f_ret_int_double_s() { + return (struct int_double_s){1, 2.0}; +} + diff --git a/clang/test/CodeGen/riscv32-ilp32f-ilp32d-abi.c b/clang/test/CodeGen/riscv32-ilp32f-ilp32d-abi.c new file mode 100644 index 000000000000..b960513655b1 --- /dev/null +++ b/clang/test/CodeGen/riscv32-ilp32f-ilp32d-abi.c @@ -0,0 +1,275 @@ +// RUN: %clang_cc1 -triple riscv32 -target-feature +f -target-abi ilp32f -emit-llvm %s -o - \ +// RUN: | FileCheck %s +// RUN: %clang_cc1 -triple riscv32 -target-feature +d -target-abi ilp32d -emit-llvm %s -o - \ +// RUN: | FileCheck %s + +#include + +// Verify that the tracking of used GPRs and FPRs works correctly by checking +// that small integers are sign/zero extended when passed in registers. + +// Floats are passed in FPRs, so argument 'i' will be passed zero-extended +// because it will be passed in a GPR. + +// CHECK: define void @f_fpr_tracking(float %a, float %b, float %c, float %d, float %e, float %f, float %g, float %h, i8 zeroext %i) +void f_fpr_tracking(float a, float b, float c, float d, float e, float f, + float g, float h, uint8_t i) {} + +// Check that fp, fp+fp, and int+fp structs are lowered correctly. These will +// be passed in FPR, FPR+FPR, or GPR+FPR regs if sufficient registers are +// available the widths are <= XLEN and FLEN, and should be expanded to +// separate arguments in IR. They are passed by the same rules for returns, +// but will be lowered to simple two-element structs if necessary (as LLVM IR +// functions cannot return multiple values). + +// A struct containing just one floating-point real is passed as though it +// were a standalone floating-point real. + +struct float_s { float f; }; + +// CHECK: define void @f_float_s_arg(float) +void f_float_s_arg(struct float_s a) {} + +// CHECK: define float @f_ret_float_s() +struct float_s f_ret_float_s() { + return (struct float_s){1.0}; +} + +// A struct containing a float and any number of zero-width bitfields is +// passed as though it were a standalone floating-point real. + +struct zbf_float_s { int : 0; float f; }; +struct zbf_float_zbf_s { int : 0; float f; int : 0; }; + +// CHECK: define void @f_zbf_float_s_arg(float) +void f_zbf_float_s_arg(struct zbf_float_s a) {} + +// CHECK: define float @f_ret_zbf_float_s() +struct zbf_float_s f_ret_zbf_float_s() { + return (struct zbf_float_s){1.0}; +} + +// CHECK: define void @f_zbf_float_zbf_s_arg(float) +void f_zbf_float_zbf_s_arg(struct zbf_float_zbf_s a) {} + +// CHECK: define float @f_ret_zbf_float_zbf_s() +struct zbf_float_zbf_s f_ret_zbf_float_zbf_s() { + return (struct zbf_float_zbf_s){1.0}; +} + +// Check that structs containing two float values (FLEN <= width) are expanded +// provided sufficient FPRs are available. + +struct float_float_s { float f; float g; }; + +// CHECK: define void @f_float_float_s_arg(float, float) +void f_float_float_s_arg(struct float_float_s a) {} + +// CHECK: define { float, float } @f_ret_float_float_s() +struct float_float_s f_ret_float_float_s() { + return (struct float_float_s){1.0, 2.0}; +} + +// CHECK: define void @f_float_float_s_arg_insufficient_fprs(float %a, float %b, float %c, float %d, float %e, float %f, float %g, [2 x i32] %h.coerce) +void f_float_float_s_arg_insufficient_fprs(float a, float b, float c, float d, + float e, float f, float g, struct float_float_s h) {} + +// Check that structs containing int+float values are expanded, provided +// sufficient FPRs and GPRs are available. The integer components are neither +// sign or zero-extended. + +struct float_int8_s { float f; int8_t i; }; +struct float_uint8_s { float f; uint8_t i; }; +struct float_int32_s { float f; int32_t i; }; +struct float_int64_s { float f; int64_t i; }; +struct float_int64bf_s { float f; int64_t i : 32; }; +struct float_int8_zbf_s { float f; int8_t i; int : 0; }; + +// CHECK: define void @f_float_int8_s_arg(float, i8) +void f_float_int8_s_arg(struct float_int8_s a) {} + +// CHECK: define { float, i8 } @f_ret_float_int8_s() +struct float_int8_s f_ret_float_int8_s() { + return (struct float_int8_s){1.0, 2}; +} + +// CHECK: define void @f_float_uint8_s_arg(float, i8) +void f_float_uint8_s_arg(struct float_uint8_s a) {} + +// CHECK: define { float, i8 } @f_ret_float_uint8_s() +struct float_uint8_s f_ret_float_uint8_s() { + return (struct float_uint8_s){1.0, 2}; +} + +// CHECK: define void @f_float_int32_s_arg(float, i32) +void f_float_int32_s_arg(struct float_int32_s a) {} + +// CHECK: define { float, i32 } @f_ret_float_int32_s() +struct float_int32_s f_ret_float_int32_s() { + return (struct float_int32_s){1.0, 2}; +} + +// CHECK: define void @f_float_int64_s_arg(%struct.float_int64_s* %a) +void f_float_int64_s_arg(struct float_int64_s a) {} + +// CHECK: define void @f_ret_float_int64_s(%struct.float_int64_s* noalias sret %agg.result) +struct float_int64_s f_ret_float_int64_s() { + return (struct float_int64_s){1.0, 2}; +} + +// CHECK: define void @f_float_int64bf_s_arg(float, i32) +void f_float_int64bf_s_arg(struct float_int64bf_s a) {} + +// CHECK: define { float, i32 } @f_ret_float_int64bf_s() +struct float_int64bf_s f_ret_float_int64bf_s() { + return (struct float_int64bf_s){1.0, 2}; +} + +// The zero-width bitfield means the struct can't be passed according to the +// floating point calling convention. + +// CHECK: define void @f_float_int8_zbf_s(float, i8) +void f_float_int8_zbf_s(struct float_int8_zbf_s a) {} + +// CHECK: define { float, i8 } @f_ret_float_int8_zbf_s() +struct float_int8_zbf_s f_ret_float_int8_zbf_s() { + return (struct float_int8_zbf_s){1.0, 2}; +} + +// CHECK: define void @f_float_int8_s_arg_insufficient_gprs(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e, i32 %f, i32 %g, i32 %h, [2 x i32] %i.coerce) +void f_float_int8_s_arg_insufficient_gprs(int a, int b, int c, int d, int e, + int f, int g, int h, struct float_int8_s i) {} + +// CHECK: define void @f_struct_float_int8_insufficient_fprs(float %a, float %b, float %c, float %d, float %e, float %f, float %g, float %h, [2 x i32] %i.coerce) +void f_struct_float_int8_insufficient_fprs(float a, float b, float c, float d, + float e, float f, float g, float h, struct float_int8_s i) {} + +// Complex floating-point values or structs containing a single complex +// floating-point value should be passed as if it were an fp+fp struct. + +// CHECK: define void @f_floatcomplex(float %a.coerce0, float %a.coerce1) +void f_floatcomplex(float __complex__ a) {} + +// CHECK: define { float, float } @f_ret_floatcomplex() +float __complex__ f_ret_floatcomplex() { + return 1.0; +} + +struct floatcomplex_s { float __complex__ c; }; + +// CHECK: define void @f_floatcomplex_s_arg(float, float) +void f_floatcomplex_s_arg(struct floatcomplex_s a) {} + +// CHECK: define { float, float } @f_ret_floatcomplex_s() +struct floatcomplex_s f_ret_floatcomplex_s() { + return (struct floatcomplex_s){1.0}; +} + +// Test single or two-element structs that need flattening. e.g. those +// containing nested structs, floats in small arrays, zero-length structs etc. + +struct floatarr1_s { float a[1]; }; + +// CHECK: define void @f_floatarr1_s_arg(float) +void f_floatarr1_s_arg(struct floatarr1_s a) {} + +// CHECK: define float @f_ret_floatarr1_s() +struct floatarr1_s f_ret_floatarr1_s() { + return (struct floatarr1_s){{1.0}}; +} + +struct floatarr2_s { float a[2]; }; + +// CHECK: define void @f_floatarr2_s_arg(float, float) +void f_floatarr2_s_arg(struct floatarr2_s a) {} + +// CHECK: define { float, float } @f_ret_floatarr2_s() +struct floatarr2_s f_ret_floatarr2_s() { + return (struct floatarr2_s){{1.0, 2.0}}; +} + +struct floatarr2_tricky1_s { struct { float f[1]; } g[2]; }; + +// CHECK: define void @f_floatarr2_tricky1_s_arg(float, float) +void f_floatarr2_tricky1_s_arg(struct floatarr2_tricky1_s a) {} + +// CHECK: define { float, float } @f_ret_floatarr2_tricky1_s() +struct floatarr2_tricky1_s f_ret_floatarr2_tricky1_s() { + return (struct floatarr2_tricky1_s){{{{1.0}}, {{2.0}}}}; +} + +struct floatarr2_tricky2_s { struct {}; struct { float f[1]; } g[2]; }; + +// CHECK: define void @f_floatarr2_tricky2_s_arg(float, float) +void f_floatarr2_tricky2_s_arg(struct floatarr2_tricky2_s a) {} + +// CHECK: define { float, float } @f_ret_floatarr2_tricky2_s() +struct floatarr2_tricky2_s f_ret_floatarr2_tricky2_s() { + return (struct floatarr2_tricky2_s){{}, {{{1.0}}, {{2.0}}}}; +} + +struct floatarr2_tricky3_s { union {}; struct { float f[1]; } g[2]; }; + +// CHECK: define void @f_floatarr2_tricky3_s_arg(float, float) +void f_floatarr2_tricky3_s_arg(struct floatarr2_tricky3_s a) {} + +// CHECK: define { float, float } @f_ret_floatarr2_tricky3_s() +struct floatarr2_tricky3_s f_ret_floatarr2_tricky3_s() { + return (struct floatarr2_tricky3_s){{}, {{{1.0}}, {{2.0}}}}; +} + +struct floatarr2_tricky4_s { union {}; struct { struct {}; float f[1]; } g[2]; }; + +// CHECK: define void @f_floatarr2_tricky4_s_arg(float, float) +void f_floatarr2_tricky4_s_arg(struct floatarr2_tricky4_s a) {} + +// CHECK: define { float, float } @f_ret_floatarr2_tricky4_s() +struct floatarr2_tricky4_s f_ret_floatarr2_tricky4_s() { + return (struct floatarr2_tricky4_s){{}, {{{}, {1.0}}, {{}, {2.0}}}}; +} + +// Test structs that should be passed according to the normal integer calling +// convention. + +struct int_float_int_s { int a; float b; int c; }; + +// CHECK: define void @f_int_float_int_s_arg(%struct.int_float_int_s* %a) +void f_int_float_int_s_arg(struct int_float_int_s a) {} + +// CHECK: define void @f_ret_int_float_int_s(%struct.int_float_int_s* noalias sret %agg.result) +struct int_float_int_s f_ret_int_float_int_s() { + return (struct int_float_int_s){1, 2.0, 3}; +} + +struct int64_float_s { int64_t a; float b; }; + +// CHECK: define void @f_int64_float_s_arg(%struct.int64_float_s* %a) +void f_int64_float_s_arg(struct int64_float_s a) {} + +// CHECK: define void @f_ret_int64_float_s(%struct.int64_float_s* noalias sret %agg.result) +struct int64_float_s f_ret_int64_float_s() { + return (struct int64_float_s){1, 2.0}; +} + +struct char_char_float_s { char a; char b; float c; }; + +// CHECK-LABEL: define void @f_char_char_float_s_arg([2 x i32] %a.coerce) +void f_char_char_float_s_arg(struct char_char_float_s a) {} + +// CHECK: define [2 x i32] @f_ret_char_char_float_s() +struct char_char_float_s f_ret_char_char_float_s() { + return (struct char_char_float_s){1, 2, 3.0}; +} + +// Unions are always passed according to the integer calling convention, even +// if they can only contain a float. + +union float_u { float a; }; + +// CHECK: define void @f_float_u_arg(i32 %a.coerce) +void f_float_u_arg(union float_u a) {} + +// CHECK: define i32 @f_ret_float_u() +union float_u f_ret_float_u() { + return (union float_u){1.0}; +} diff --git a/clang/test/CodeGen/riscv64-lp64-lp64f-abi.c b/clang/test/CodeGen/riscv64-lp64-lp64f-abi.c index 3b944e716a2a..d457bdf3c64e 100644 --- a/clang/test/CodeGen/riscv64-lp64-lp64f-abi.c +++ b/clang/test/CodeGen/riscv64-lp64-lp64f-abi.c @@ -1,4 +1,6 @@ // RUN: %clang_cc1 -triple riscv64 -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple riscv64 -target-feature +f -target-abi lp64f -emit-llvm %s -o - \ +// RUN: | FileCheck %s // This file contains test cases that will have the same output for the lp64 // and lp64f ABIs. diff --git a/clang/test/CodeGen/riscv64-lp64-lp64f-lp64d-abi.c b/clang/test/CodeGen/riscv64-lp64-lp64f-lp64d-abi.c index f51d8252b8f4..f3523702e9a2 100644 --- a/clang/test/CodeGen/riscv64-lp64-lp64f-lp64d-abi.c +++ b/clang/test/CodeGen/riscv64-lp64-lp64f-lp64d-abi.c @@ -1,4 +1,8 @@ // RUN: %clang_cc1 -triple riscv64 -emit-llvm %s -o - | FileCheck %s +// RUN: %clang_cc1 -triple riscv64 -target-feature +f -target-abi lp64f -emit-llvm %s -o - \ +// RUN: | FileCheck %s +// RUN: %clang_cc1 -triple riscv64 -target-feature +d -target-abi lp64d -emit-llvm %s -o - \ +// RUN: | FileCheck %s // This file contains test cases that will have the same output for the lp64, // lp64f, and lp64d ABIs. diff --git a/clang/test/CodeGen/riscv64-lp64d-abi.c b/clang/test/CodeGen/riscv64-lp64d-abi.c new file mode 100644 index 000000000000..00967b5fca85 --- /dev/null +++ b/clang/test/CodeGen/riscv64-lp64d-abi.c @@ -0,0 +1,272 @@ +// RUN: %clang_cc1 -triple riscv64 -target-feature +d -target-abi lp64d -emit-llvm %s -o - \ +// RUN: | FileCheck %s + +#include + +// Verify that the tracking of used GPRs and FPRs works correctly by checking +// that small integers are sign/zero extended when passed in registers. + +// Doubles are passed in FPRs, so argument 'i' will be passed zero-extended +// because it will be passed in a GPR. + +// CHECK: define void @f_fpr_tracking(double %a, double %b, double %c, double %d, double %e, double %f, double %g, double %h, i8 zeroext %i) +void f_fpr_tracking(double a, double b, double c, double d, double e, double f, + double g, double h, uint8_t i) {} + +// Check that fp, fp+fp, and int+fp structs are lowered correctly. These will +// be passed in FPR, FPR+FPR, or GPR+FPR regs if sufficient registers are +// available the widths are <= XLEN and FLEN, and should be expanded to +// separate arguments in IR. They are passed by the same rules for returns, +// but will be lowered to simple two-element structs if necessary (as LLVM IR +// functions cannot return multiple values). + +// A struct containing just one floating-point real is passed as though it +// were a standalone floating-point real. + +struct double_s { double f; }; + +// CHECK: define void @f_double_s_arg(double) +void f_double_s_arg(struct double_s a) {} + +// CHECK: define double @f_ret_double_s() +struct double_s f_ret_double_s() { + return (struct double_s){1.0}; +} + +// A struct containing a double and any number of zero-width bitfields is +// passed as though it were a standalone floating-point real. + +struct zbf_double_s { int : 0; double f; }; +struct zbf_double_zbf_s { int : 0; double f; int : 0; }; + +// CHECK: define void @f_zbf_double_s_arg(double) +void f_zbf_double_s_arg(struct zbf_double_s a) {} + +// CHECK: define double @f_ret_zbf_double_s() +struct zbf_double_s f_ret_zbf_double_s() { + return (struct zbf_double_s){1.0}; +} + +// CHECK: define void @f_zbf_double_zbf_s_arg(double) +void f_zbf_double_zbf_s_arg(struct zbf_double_zbf_s a) {} + +// CHECK: define double @f_ret_zbf_double_zbf_s() +struct zbf_double_zbf_s f_ret_zbf_double_zbf_s() { + return (struct zbf_double_zbf_s){1.0}; +} + +// Check that structs containing two floating point values (FLEN <= width) are +// expanded provided sufficient FPRs are available. + +struct double_double_s { double f; double g; }; +struct double_float_s { double f; float g; }; + +// CHECK: define void @f_double_double_s_arg(double, double) +void f_double_double_s_arg(struct double_double_s a) {} + +// CHECK: define { double, double } @f_ret_double_double_s() +struct double_double_s f_ret_double_double_s() { + return (struct double_double_s){1.0, 2.0}; +} + +// CHECK: define void @f_double_float_s_arg(double, float) +void f_double_float_s_arg(struct double_float_s a) {} + +// CHECK: define { double, float } @f_ret_double_float_s() +struct double_float_s f_ret_double_float_s() { + return (struct double_float_s){1.0, 2.0}; +} + +// CHECK: define void @f_double_double_s_arg_insufficient_fprs(float %a, double %b, double %c, double %d, double %e, double %f, double %g, [2 x i64] %h.coerce) +void f_double_double_s_arg_insufficient_fprs(float a, double b, double c, double d, + double e, double f, double g, struct double_double_s h) {} + +// Check that structs containing int+double values are expanded, provided +// sufficient FPRs and GPRs are available. The integer components are neither +// sign or zero-extended. + +struct double_int8_s { double f; int8_t i; }; +struct double_uint8_s { double f; uint8_t i; }; +struct double_int32_s { double f; int32_t i; }; +struct double_int64_s { double f; int64_t i; }; +struct double_int128bf_s { double f; __int128_t i : 64; }; +struct double_int8_zbf_s { double f; int8_t i; int : 0; }; + +// CHECK: define void @f_double_int8_s_arg(double, i8) +void f_double_int8_s_arg(struct double_int8_s a) {} + +// CHECK: define { double, i8 } @f_ret_double_int8_s() +struct double_int8_s f_ret_double_int8_s() { + return (struct double_int8_s){1.0, 2}; +} + +// CHECK: define void @f_double_uint8_s_arg(double, i8) +void f_double_uint8_s_arg(struct double_uint8_s a) {} + +// CHECK: define { double, i8 } @f_ret_double_uint8_s() +struct double_uint8_s f_ret_double_uint8_s() { + return (struct double_uint8_s){1.0, 2}; +} + +// CHECK: define void @f_double_int32_s_arg(double, i32) +void f_double_int32_s_arg(struct double_int32_s a) {} + +// CHECK: define { double, i32 } @f_ret_double_int32_s() +struct double_int32_s f_ret_double_int32_s() { + return (struct double_int32_s){1.0, 2}; +} + +// CHECK: define void @f_double_int64_s_arg(double, i64) +void f_double_int64_s_arg(struct double_int64_s a) {} + +// CHECK: define { double, i64 } @f_ret_double_int64_s() +struct double_int64_s f_ret_double_int64_s() { + return (struct double_int64_s){1.0, 2}; +} + +// CHECK: define void @f_double_int128bf_s_arg(double, i64) +void f_double_int128bf_s_arg(struct double_int128bf_s a) {} + +// CHECK: define { double, i64 } @f_ret_double_int128bf_s() +struct double_int128bf_s f_ret_double_int128bf_s() { + return (struct double_int128bf_s){1.0, 2}; +} + +// The zero-width bitfield means the struct can't be passed according to the +// floating point calling convention. + +// CHECK: define void @f_double_int8_zbf_s(double, i8) +void f_double_int8_zbf_s(struct double_int8_zbf_s a) {} + +// CHECK: define { double, i8 } @f_ret_double_int8_zbf_s() +struct double_int8_zbf_s f_ret_double_int8_zbf_s() { + return (struct double_int8_zbf_s){1.0, 2}; +} + +// CHECK: define void @f_double_int8_s_arg_insufficient_gprs(i32 signext %a, i32 signext %b, i32 signext %c, i32 signext %d, i32 signext %e, i32 signext %f, i32 signext %g, i32 signext %h, [2 x i64] %i.coerce) +void f_double_int8_s_arg_insufficient_gprs(int a, int b, int c, int d, int e, + int f, int g, int h, struct double_int8_s i) {} + +// CHECK: define void @f_struct_double_int8_insufficient_fprs(float %a, double %b, double %c, double %d, double %e, double %f, double %g, double %h, [2 x i64] %i.coerce) +void f_struct_double_int8_insufficient_fprs(float a, double b, double c, double d, + double e, double f, double g, double h, struct double_int8_s i) {} + +// Complex floating-point values or structs containing a single complex +// floating-point value should be passed as if it were an fp+fp struct. + +// CHECK: define void @f_doublecomplex(double %a.coerce0, double %a.coerce1) +void f_doublecomplex(double __complex__ a) {} + +// CHECK: define { double, double } @f_ret_doublecomplex() +double __complex__ f_ret_doublecomplex() { + return 1.0; +} + +struct doublecomplex_s { double __complex__ c; }; + +// CHECK: define void @f_doublecomplex_s_arg(double, double) +void f_doublecomplex_s_arg(struct doublecomplex_s a) {} + +// CHECK: define { double, double } @f_ret_doublecomplex_s() +struct doublecomplex_s f_ret_doublecomplex_s() { + return (struct doublecomplex_s){1.0}; +} + +// Test single or two-element structs that need flattening. e.g. those +// containing nested structs, doubles in small arrays, zero-length structs etc. + +struct doublearr1_s { double a[1]; }; + +// CHECK: define void @f_doublearr1_s_arg(double) +void f_doublearr1_s_arg(struct doublearr1_s a) {} + +// CHECK: define double @f_ret_doublearr1_s() +struct doublearr1_s f_ret_doublearr1_s() { + return (struct doublearr1_s){{1.0}}; +} + +struct doublearr2_s { double a[2]; }; + +// CHECK: define void @f_doublearr2_s_arg(double, double) +void f_doublearr2_s_arg(struct doublearr2_s a) {} + +// CHECK: define { double, double } @f_ret_doublearr2_s() +struct doublearr2_s f_ret_doublearr2_s() { + return (struct doublearr2_s){{1.0, 2.0}}; +} + +struct doublearr2_tricky1_s { struct { double f[1]; } g[2]; }; + +// CHECK: define void @f_doublearr2_tricky1_s_arg(double, double) +void f_doublearr2_tricky1_s_arg(struct doublearr2_tricky1_s a) {} + +// CHECK: define { double, double } @f_ret_doublearr2_tricky1_s() +struct doublearr2_tricky1_s f_ret_doublearr2_tricky1_s() { + return (struct doublearr2_tricky1_s){{{{1.0}}, {{2.0}}}}; +} + +struct doublearr2_tricky2_s { struct {}; struct { double f[1]; } g[2]; }; + +// CHECK: define void @f_doublearr2_tricky2_s_arg(double, double) +void f_doublearr2_tricky2_s_arg(struct doublearr2_tricky2_s a) {} + +// CHECK: define { double, double } @f_ret_doublearr2_tricky2_s() +struct doublearr2_tricky2_s f_ret_doublearr2_tricky2_s() { + return (struct doublearr2_tricky2_s){{}, {{{1.0}}, {{2.0}}}}; +} + +struct doublearr2_tricky3_s { union {}; struct { double f[1]; } g[2]; }; + +// CHECK: define void @f_doublearr2_tricky3_s_arg(double, double) +void f_doublearr2_tricky3_s_arg(struct doublearr2_tricky3_s a) {} + +// CHECK: define { double, double } @f_ret_doublearr2_tricky3_s() +struct doublearr2_tricky3_s f_ret_doublearr2_tricky3_s() { + return (struct doublearr2_tricky3_s){{}, {{{1.0}}, {{2.0}}}}; +} + +struct doublearr2_tricky4_s { union {}; struct { struct {}; double f[1]; } g[2]; }; + +// CHECK: define void @f_doublearr2_tricky4_s_arg(double, double) +void f_doublearr2_tricky4_s_arg(struct doublearr2_tricky4_s a) {} + +// CHECK: define { double, double } @f_ret_doublearr2_tricky4_s() +struct doublearr2_tricky4_s f_ret_doublearr2_tricky4_s() { + return (struct doublearr2_tricky4_s){{}, {{{}, {1.0}}, {{}, {2.0}}}}; +} + +// Test structs that should be passed according to the normal integer calling +// convention. + +struct int_double_int_s { int a; double b; int c; }; + +// CHECK: define void @f_int_double_int_s_arg(%struct.int_double_int_s* %a) +void f_int_double_int_s_arg(struct int_double_int_s a) {} + +// CHECK: define void @f_ret_int_double_int_s(%struct.int_double_int_s* noalias sret %agg.result) +struct int_double_int_s f_ret_int_double_int_s() { + return (struct int_double_int_s){1, 2.0, 3}; +} + +struct char_char_double_s { char a; char b; double c; }; + +// CHECK-LABEL: define void @f_char_char_double_s_arg([2 x i64] %a.coerce) +void f_char_char_double_s_arg(struct char_char_double_s a) {} + +// CHECK: define [2 x i64] @f_ret_char_char_double_s() +struct char_char_double_s f_ret_char_char_double_s() { + return (struct char_char_double_s){1, 2, 3.0}; +} + +// Unions are always passed according to the integer calling convention, even +// if they can only contain a double. + +union double_u { double a; }; + +// CHECK: define void @f_double_u_arg(i64 %a.coerce) +void f_double_u_arg(union double_u a) {} + +// CHECK: define i64 @f_ret_double_u() +union double_u f_ret_double_u() { + return (union double_u){1.0}; +} diff --git a/clang/test/CodeGen/riscv64-lp64f-lp64d-abi.c b/clang/test/CodeGen/riscv64-lp64f-lp64d-abi.c new file mode 100644 index 000000000000..eee2bc1bdcc6 --- /dev/null +++ b/clang/test/CodeGen/riscv64-lp64f-lp64d-abi.c @@ -0,0 +1,265 @@ +// RUN: %clang_cc1 -triple riscv64 -target-feature +f -target-abi lp64f -emit-llvm %s -o - \ +// RUN: | FileCheck %s +// RUN: %clang_cc1 -triple riscv64 -target-feature +d -target-abi lp64d -emit-llvm %s -o - \ +// RUN: | FileCheck %s + +#include + +// Verify that the tracking of used GPRs and FPRs works correctly by checking +// that small integers are sign/zero extended when passed in registers. + +// Floats are passed in FPRs, so argument 'i' will be passed zero-extended +// because it will be passed in a GPR. + +// CHECK: define void @f_fpr_tracking(float %a, float %b, float %c, float %d, float %e, float %f, float %g, float %h, i8 zeroext %i) +void f_fpr_tracking(float a, float b, float c, float d, float e, float f, + float g, float h, uint8_t i) {} + +// Check that fp, fp+fp, and int+fp structs are lowered correctly. These will +// be passed in FPR, FPR+FPR, or GPR+FPR regs if sufficient registers are +// available the widths are <= XLEN and FLEN, and should be expanded to +// separate arguments in IR. They are passed by the same rules for returns, +// but will be lowered to simple two-element structs if necessary (as LLVM IR +// functions cannot return multiple values). + +// A struct containing just one floating-point real is passed as though it +// were a standalone floating-point real. + +struct float_s { float f; }; + +// CHECK: define void @f_float_s_arg(float) +void f_float_s_arg(struct float_s a) {} + +// CHECK: define float @f_ret_float_s() +struct float_s f_ret_float_s() { + return (struct float_s){1.0}; +} + +// A struct containing a float and any number of zero-width bitfields is +// passed as though it were a standalone floating-point real. + +struct zbf_float_s { int : 0; float f; }; +struct zbf_float_zbf_s { int : 0; float f; int : 0; }; + +// CHECK: define void @f_zbf_float_s_arg(float) +void f_zbf_float_s_arg(struct zbf_float_s a) {} + +// CHECK: define float @f_ret_zbf_float_s() +struct zbf_float_s f_ret_zbf_float_s() { + return (struct zbf_float_s){1.0}; +} + +// CHECK: define void @f_zbf_float_zbf_s_arg(float) +void f_zbf_float_zbf_s_arg(struct zbf_float_zbf_s a) {} + +// CHECK: define float @f_ret_zbf_float_zbf_s() +struct zbf_float_zbf_s f_ret_zbf_float_zbf_s() { + return (struct zbf_float_zbf_s){1.0}; +} + +// Check that structs containing two float values (FLEN <= width) are expanded +// provided sufficient FPRs are available. + +struct float_float_s { float f; float g; }; + +// CHECK: define void @f_float_float_s_arg(float, float) +void f_float_float_s_arg(struct float_float_s a) {} + +// CHECK: define { float, float } @f_ret_float_float_s() +struct float_float_s f_ret_float_float_s() { + return (struct float_float_s){1.0, 2.0}; +} + +// CHECK: define void @f_float_float_s_arg_insufficient_fprs(float %a, float %b, float %c, float %d, float %e, float %f, float %g, i64 %h.coerce) +void f_float_float_s_arg_insufficient_fprs(float a, float b, float c, float d, + float e, float f, float g, struct float_float_s h) {} + +// Check that structs containing int+float values are expanded, provided +// sufficient FPRs and GPRs are available. The integer components are neither +// sign or zero-extended. + +struct float_int8_s { float f; int8_t i; }; +struct float_uint8_s { float f; uint8_t i; }; +struct float_int32_s { float f; int32_t i; }; +struct float_int64_s { float f; int64_t i; }; +struct float_int128bf_s { float f; __int128_t i : 64; }; +struct float_int8_zbf_s { float f; int8_t i; int : 0; }; + +// CHECK: define void @f_float_int8_s_arg(float, i8) +void f_float_int8_s_arg(struct float_int8_s a) {} + +// CHECK: define { float, i8 } @f_ret_float_int8_s() +struct float_int8_s f_ret_float_int8_s() { + return (struct float_int8_s){1.0, 2}; +} + +// CHECK: define void @f_float_uint8_s_arg(float, i8) +void f_float_uint8_s_arg(struct float_uint8_s a) {} + +// CHECK: define { float, i8 } @f_ret_float_uint8_s() +struct float_uint8_s f_ret_float_uint8_s() { + return (struct float_uint8_s){1.0, 2}; +} + +// CHECK: define void @f_float_int32_s_arg(float, i32) +void f_float_int32_s_arg(struct float_int32_s a) {} + +// CHECK: define { float, i32 } @f_ret_float_int32_s() +struct float_int32_s f_ret_float_int32_s() { + return (struct float_int32_s){1.0, 2}; +} + +// CHECK: define void @f_float_int64_s_arg(float, i64) +void f_float_int64_s_arg(struct float_int64_s a) {} + +// CHECK: define { float, i64 } @f_ret_float_int64_s() +struct float_int64_s f_ret_float_int64_s() { + return (struct float_int64_s){1.0, 2}; +} + +// CHECK: define void @f_float_int128bf_s_arg(float, i64) +void f_float_int128bf_s_arg(struct float_int128bf_s a) {} + +// CHECK: define <{ float, i64 }> @f_ret_float_int128bf_s() +struct float_int128bf_s f_ret_float_int128bf_s() { + return (struct float_int128bf_s){1.0, 2}; +} + +// The zero-width bitfield means the struct can't be passed according to the +// floating point calling convention. + +// CHECK: define void @f_float_int8_zbf_s(float, i8) +void f_float_int8_zbf_s(struct float_int8_zbf_s a) {} + +// CHECK: define { float, i8 } @f_ret_float_int8_zbf_s() +struct float_int8_zbf_s f_ret_float_int8_zbf_s() { + return (struct float_int8_zbf_s){1.0, 2}; +} + +// CHECK: define void @f_float_int8_s_arg_insufficient_gprs(i32 signext %a, i32 signext %b, i32 signext %c, i32 signext %d, i32 signext %e, i32 signext %f, i32 signext %g, i32 signext %h, i64 %i.coerce) +void f_float_int8_s_arg_insufficient_gprs(int a, int b, int c, int d, int e, + int f, int g, int h, struct float_int8_s i) {} + +// CHECK: define void @f_struct_float_int8_insufficient_fprs(float %a, float %b, float %c, float %d, float %e, float %f, float %g, float %h, i64 %i.coerce) +void f_struct_float_int8_insufficient_fprs(float a, float b, float c, float d, + float e, float f, float g, float h, struct float_int8_s i) {} + +// Complex floating-point values or structs containing a single complex +// floating-point value should be passed as if it were an fp+fp struct. + +// CHECK: define void @f_floatcomplex(float %a.coerce0, float %a.coerce1) +void f_floatcomplex(float __complex__ a) {} + +// CHECK: define { float, float } @f_ret_floatcomplex() +float __complex__ f_ret_floatcomplex() { + return 1.0; +} + +struct floatcomplex_s { float __complex__ c; }; + +// CHECK: define void @f_floatcomplex_s_arg(float, float) +void f_floatcomplex_s_arg(struct floatcomplex_s a) {} + +// CHECK: define { float, float } @f_ret_floatcomplex_s() +struct floatcomplex_s f_ret_floatcomplex_s() { + return (struct floatcomplex_s){1.0}; +} + +// Test single or two-element structs that need flattening. e.g. those +// containing nested structs, floats in small arrays, zero-length structs etc. + +struct floatarr1_s { float a[1]; }; + +// CHECK: define void @f_floatarr1_s_arg(float) +void f_floatarr1_s_arg(struct floatarr1_s a) {} + +// CHECK: define float @f_ret_floatarr1_s() +struct floatarr1_s f_ret_floatarr1_s() { + return (struct floatarr1_s){{1.0}}; +} + +struct floatarr2_s { float a[2]; }; + +// CHECK: define void @f_floatarr2_s_arg(float, float) +void f_floatarr2_s_arg(struct floatarr2_s a) {} + +// CHECK: define { float, float } @f_ret_floatarr2_s() +struct floatarr2_s f_ret_floatarr2_s() { + return (struct floatarr2_s){{1.0, 2.0}}; +} + +struct floatarr2_tricky1_s { struct { float f[1]; } g[2]; }; + +// CHECK: define void @f_floatarr2_tricky1_s_arg(float, float) +void f_floatarr2_tricky1_s_arg(struct floatarr2_tricky1_s a) {} + +// CHECK: define { float, float } @f_ret_floatarr2_tricky1_s() +struct floatarr2_tricky1_s f_ret_floatarr2_tricky1_s() { + return (struct floatarr2_tricky1_s){{{{1.0}}, {{2.0}}}}; +} + +struct floatarr2_tricky2_s { struct {}; struct { float f[1]; } g[2]; }; + +// CHECK: define void @f_floatarr2_tricky2_s_arg(float, float) +void f_floatarr2_tricky2_s_arg(struct floatarr2_tricky2_s a) {} + +// CHECK: define { float, float } @f_ret_floatarr2_tricky2_s() +struct floatarr2_tricky2_s f_ret_floatarr2_tricky2_s() { + return (struct floatarr2_tricky2_s){{}, {{{1.0}}, {{2.0}}}}; +} + +struct floatarr2_tricky3_s { union {}; struct { float f[1]; } g[2]; }; + +// CHECK: define void @f_floatarr2_tricky3_s_arg(float, float) +void f_floatarr2_tricky3_s_arg(struct floatarr2_tricky3_s a) {} + +// CHECK: define { float, float } @f_ret_floatarr2_tricky3_s() +struct floatarr2_tricky3_s f_ret_floatarr2_tricky3_s() { + return (struct floatarr2_tricky3_s){{}, {{{1.0}}, {{2.0}}}}; +} + +struct floatarr2_tricky4_s { union {}; struct { struct {}; float f[1]; } g[2]; }; + +// CHECK: define void @f_floatarr2_tricky4_s_arg(float, float) +void f_floatarr2_tricky4_s_arg(struct floatarr2_tricky4_s a) {} + +// CHECK: define { float, float } @f_ret_floatarr2_tricky4_s() +struct floatarr2_tricky4_s f_ret_floatarr2_tricky4_s() { + return (struct floatarr2_tricky4_s){{}, {{{}, {1.0}}, {{}, {2.0}}}}; +} + +// Test structs that should be passed according to the normal integer calling +// convention. + +struct int_float_int_s { int a; float b; int c; }; + +// CHECK: define void @f_int_float_int_s_arg([2 x i64] %a.coerce) +void f_int_float_int_s_arg(struct int_float_int_s a) {} + +// CHECK: define [2 x i64] @f_ret_int_float_int_s() +struct int_float_int_s f_ret_int_float_int_s() { + return (struct int_float_int_s){1, 2.0, 3}; +} + +struct char_char_float_s { char a; char b; float c; }; + +// CHECK-LABEL: define void @f_char_char_float_s_arg(i64 %a.coerce) +void f_char_char_float_s_arg(struct char_char_float_s a) {} + +// CHECK: define i64 @f_ret_char_char_float_s() +struct char_char_float_s f_ret_char_char_float_s() { + return (struct char_char_float_s){1, 2, 3.0}; +} + +// Unions are always passed according to the integer calling convention, even +// if they can only contain a float. + +union float_u { float a; }; + +// CHECK: define void @f_float_u_arg(i64 %a.coerce) +void f_float_u_arg(union float_u a) {} + +// CHECK: define i64 @f_ret_float_u() +union float_u f_ret_float_u() { + return (union float_u){1.0}; +} diff --git a/clang/test/Driver/riscv-abi.c b/clang/test/Driver/riscv-abi.c index 6a97ff671ddb..1a4c7ed477b6 100644 --- a/clang/test/Driver/riscv-abi.c +++ b/clang/test/Driver/riscv-abi.c @@ -9,17 +9,15 @@ // CHECK-ILP32: "-target-abi" "ilp32" -// TODO: ilp32f support. -// RUN: not %clang -target riscv32-unknown-elf %s -o %t.o -mabi=ilp32f 2>&1 \ +// RUN: %clang -target riscv32-unknown-elf %s -### -o %t.o -march=rv32if -mabi=ilp32f 2>&1 \ // RUN: | FileCheck -check-prefix=CHECK-ILP32F %s -// CHECK-ILP32F: error: unknown target ABI 'ilp32f' +// CHECK-ILP32F: "-target-abi" "ilp32f" -// TODO: ilp32d support. -// RUN: not %clang -target riscv32-unknown-elf %s -o %t.o -mabi=ilp32d 2>&1 \ +// RUN: %clang -target riscv32-unknown-elf %s -### -o %t.o -march=rv32ifd -mabi=ilp32d 2>&1 \ // RUN: | FileCheck -check-prefix=CHECK-ILP32D %s -// CHECK-ILP32D: error: unknown target ABI 'ilp32d' +// CHECK-ILP32D: "-target-abi" "ilp32d" // RUN: not %clang -target riscv32-unknown-elf %s -o %t.o -mabi=lp64 2>&1 \ // RUN: | FileCheck -check-prefix=CHECK-RV32-LP64 %s @@ -37,17 +35,15 @@ // CHECK-LP64: "-target-abi" "lp64" -// TODO: lp64f support. -// RUN: not %clang -target riscv64-unknown-elf %s -o %t.o -mabi=lp64f 2>&1 \ +// RUN: %clang -target riscv64-unknown-elf %s -### -o %t.o -march=rv64f -mabi=lp64f 2>&1 \ // RUN: | FileCheck -check-prefix=CHECK-LP64F %s -// CHECK-LP64F: error: unknown target ABI 'lp64f' +// CHECK-LP64F: "-target-abi" "lp64f" -// TODO: lp64d support. -// RUN: not %clang -target riscv64-unknown-elf %s -o %t.o -mabi=lp64d 2>&1 \ +// RUN: %clang -target riscv64-unknown-elf %s -### -o %t.o -march=rv64d -mabi=lp64d 2>&1 \ // RUN: | FileCheck -check-prefix=CHECK-LP64D %s -// CHECK-LP64D: error: unknown target ABI 'lp64d' +// CHECK-LP64D: "-target-abi" "lp64d" // RUN: not %clang -target riscv64-unknown-elf %s -o %t.o -mabi=ilp32 2>&1 \ // RUN: | FileCheck -check-prefix=CHECK-RV64-ILP32 %s diff --git a/clang/test/Preprocessor/riscv-target-features.c b/clang/test/Preprocessor/riscv-target-features.c index 2c63e0fa29df..36e49c36f033 100644 --- a/clang/test/Preprocessor/riscv-target-features.c +++ b/clang/test/Preprocessor/riscv-target-features.c @@ -47,3 +47,27 @@ // RUN: %clang -target riscv64-unknown-linux-gnu -march=rv64ic -x c -E -dM %s \ // RUN: -o - | FileCheck --check-prefix=CHECK-C-EXT %s // CHECK-C-EXT: __riscv_compressed 1 + +// RUN: %clang -target riscv32-unknown-linux-gnu -march=rv32ifd -x c -E -dM %s \ +// RUN: -o - | FileCheck --check-prefix=CHECK-SOFT %s +// RUN: %clang -target riscv64-unknown-linux-gnu -march=rv64ifd -x c -E -dM %s \ +// RUN: -o - | FileCheck --check-prefix=CHECK-SOFT %s +// CHECK-SOFT: __riscv_float_abi_soft 1 +// CHECK-SOFT-NOT: __riscv_float_abi_single +// CHECK-SOFT-NOT: __riscv_float_abi_double + +// RUN: %clang -target riscv32-unknown-linux-gnu -march=rv32ifd -mabi=ilp32f -x c -E -dM %s \ +// RUN: -o - | FileCheck --check-prefix=CHECK-SINGLE %s +// RUN: %clang -target riscv64-unknown-linux-gnu -march=rv64ifd -mabi=lp64f -x c -E -dM %s \ +// RUN: -o - | FileCheck --check-prefix=CHECK-SINGLE %s +// CHECK-SINGLE: __riscv_float_abi_single 1 +// CHECK-SINGLE-NOT: __riscv_float_abi_soft +// CHECK-SINGLE-NOT: __riscv_float_abi_double + +// RUN: %clang -target riscv32-unknown-linux-gnu -march=rv32ifd -mabi=ilp32d -x c -E -dM %s \ +// RUN: -o - | FileCheck --check-prefix=CHECK-DOUBLE %s +// RUN: %clang -target riscv64-unknown-linux-gnu -march=rv64ifd -mabi=lp64d -x c -E -dM %s \ +// RUN: -o - | FileCheck --check-prefix=CHECK-DOUBLE %s +// CHECK-DOUBLE: __riscv_float_abi_double 1 +// CHECK-DOUBLE-NOT: __riscv_float_abi_soft +// CHECK-DOUBLE-NOT: __riscv_float_abi_single From 1931d3cb20a00da732c5210b123656632982fde0 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Fri, 19 Jul 2019 09:55:32 +0000 Subject: [PATCH 009/289] Merging r366511: ------------------------------------------------------------------------ r366511 | lhames | 2019-07-19 00:47:18 +0200 (Fri, 19 Jul 2019) | 3 lines Update the SimpleJIT class in the clang-interpreter example to use ORCv2. This will remove the ORCv1 deprecation warnings. ------------------------------------------------------------------------ llvm-svn: 366556 --- clang/examples/clang-interpreter/main.cpp | 97 +++++++++++++---------- 1 file changed, 53 insertions(+), 44 deletions(-) diff --git a/clang/examples/clang-interpreter/main.cpp b/clang/examples/clang-interpreter/main.cpp index 8fb52700a757..69808428a34d 100644 --- a/clang/examples/clang-interpreter/main.cpp +++ b/clang/examples/clang-interpreter/main.cpp @@ -18,6 +18,7 @@ #include "llvm/ADT/SmallString.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/RTDyldObjectLinkingLayer.h" #include "llvm/ExecutionEngine/SectionMemoryManager.h" @@ -50,65 +51,69 @@ namespace orc { class SimpleJIT { private: ExecutionSession ES; - std::shared_ptr Resolver; std::unique_ptr TM; const DataLayout DL; - LegacyRTDyldObjectLinkingLayer ObjectLayer; - LegacyIRCompileLayer CompileLayer; + MangleAndInterner Mangle{ES, DL}; + RTDyldObjectLinkingLayer ObjectLayer{ES, createMemMgr}; + IRCompileLayer CompileLayer{ES, ObjectLayer, SimpleCompiler(*TM)}; -public: - SimpleJIT() - : Resolver(createLegacyLookupResolver( - ES, - [this](const std::string &Name) -> JITSymbol { - if (auto Sym = CompileLayer.findSymbol(Name, false)) - return Sym; - else if (auto Err = Sym.takeError()) - return std::move(Err); - if (auto SymAddr = - RTDyldMemoryManager::getSymbolAddressInProcess(Name)) - return JITSymbol(SymAddr, JITSymbolFlags::Exported); - return nullptr; - }, - [](Error Err) { cantFail(std::move(Err), "lookupFlags failed"); })), - TM(EngineBuilder().selectTarget()), DL(TM->createDataLayout()), - ObjectLayer(ES, - [this](VModuleKey) { - return LegacyRTDyldObjectLinkingLayer::Resources{ - std::make_shared(), Resolver}; - }), - CompileLayer(ObjectLayer, SimpleCompiler(*TM)) { + static std::unique_ptr createMemMgr() { + return llvm::make_unique(); + } + + SimpleJIT(std::unique_ptr TM, DataLayout DL, + DynamicLibrarySearchGenerator ProcessSymbolsGenerator) + : TM(std::move(TM)), DL(std::move(DL)) { llvm::sys::DynamicLibrary::LoadLibraryPermanently(nullptr); + ES.getMainJITDylib().setGenerator(std::move(ProcessSymbolsGenerator)); } - const TargetMachine &getTargetMachine() const { return *TM; } +public: + static Expected> Create() { + auto JTMB = JITTargetMachineBuilder::detectHost(); + if (!JTMB) + return JTMB.takeError(); + + auto TM = JTMB->createTargetMachine(); + if (!TM) + return TM.takeError(); + + auto DL = (*TM)->createDataLayout(); - VModuleKey addModule(std::unique_ptr M) { - // Add the module to the JIT with a new VModuleKey. - auto K = ES.allocateVModule(); - cantFail(CompileLayer.addModule(K, std::move(M))); - return K; + auto ProcessSymbolsGenerator = + DynamicLibrarySearchGenerator::GetForCurrentProcess( + DL.getGlobalPrefix()); + + if (!ProcessSymbolsGenerator) + return ProcessSymbolsGenerator.takeError(); + + return std::unique_ptr(new SimpleJIT( + std::move(*TM), std::move(DL), std::move(*ProcessSymbolsGenerator))); } - JITSymbol findSymbol(const StringRef &Name) { - std::string MangledName; - raw_string_ostream MangledNameStream(MangledName); - Mangler::getNameWithPrefix(MangledNameStream, Name, DL); - return CompileLayer.findSymbol(MangledNameStream.str(), true); + const TargetMachine &getTargetMachine() const { return *TM; } + + Error addModule(ThreadSafeModule M) { + return CompileLayer.add(ES.getMainJITDylib(), std::move(M)); } - JITTargetAddress getSymbolAddress(const StringRef &Name) { - return cantFail(findSymbol(Name).getAddress()); + Expected findSymbol(const StringRef &Name) { + return ES.lookup({&ES.getMainJITDylib()}, Mangle(Name)); } - void removeModule(VModuleKey K) { - cantFail(CompileLayer.removeModule(K)); + Expected getSymbolAddress(const StringRef &Name) { + auto Sym = findSymbol(Name); + if (!Sym) + return Sym.takeError(); + return Sym->getAddress(); } }; } // end namespace orc } // end namespace llvm +llvm::ExitOnError ExitOnErr; + int main(int argc, const char **argv) { // This just needs to be some symbol in the binary; C++ doesn't // allow taking the address of ::main however. @@ -130,6 +135,8 @@ int main(int argc, const char **argv) { T.setObjectFormat(llvm::Triple::ELF); #endif + ExitOnErr.setBanner("clang interpreter"); + Driver TheDriver(Path, T.str(), Diags); TheDriver.setTitle("clang interpreter"); TheDriver.setCheckInputsExist(false); @@ -204,14 +211,16 @@ int main(int argc, const char **argv) { llvm::InitializeNativeTargetAsmPrinter(); int Res = 255; + std::unique_ptr Ctx(Act->takeLLVMContext()); std::unique_ptr Module = Act->takeModule(); if (Module) { - llvm::orc::SimpleJIT J; - auto H = J.addModule(std::move(Module)); - auto Main = (int(*)(...))J.getSymbolAddress("main"); + auto J = ExitOnErr(llvm::orc::SimpleJIT::Create()); + + ExitOnErr(J->addModule( + llvm::orc::ThreadSafeModule(std::move(Module), std::move(Ctx)))); + auto Main = (int (*)(...))ExitOnErr(J->getSymbolAddress("main")); Res = Main(); - J.removeModule(H); } // Shutdown. From 03f9f945ad3e35d46a8403920d87692c5306d12f Mon Sep 17 00:00:00 2001 From: Ulrich Weigand Date: Mon, 22 Jul 2019 14:07:55 +0000 Subject: [PATCH 010/289] Revert r366413 on LLVM 9 branch This commit caused test suite failures on multiple platforms and has been reverted on mainline as r366472/r366482. llvm-svn: 366690 --- .../lib/interception/interception_linux.cc | 9 +--- .../asan/TestCases/Linux/dlopen-mixed-c-cxx.c | 42 ------------------- 2 files changed, 2 insertions(+), 49 deletions(-) delete mode 100644 compiler-rt/test/asan/TestCases/Linux/dlopen-mixed-c-cxx.c diff --git a/compiler-rt/lib/interception/interception_linux.cc b/compiler-rt/lib/interception/interception_linux.cc index 4b27102a159c..d07f060b5b64 100644 --- a/compiler-rt/lib/interception/interception_linux.cc +++ b/compiler-rt/lib/interception/interception_linux.cc @@ -33,7 +33,7 @@ static int StrCmp(const char *s1, const char *s2) { } #endif -static void *GetFuncAddr(const char *name, uptr wrapper_addr) { +static void *GetFuncAddr(const char *name) { #if SANITIZER_NETBSD // FIXME: Find a better way to handle renames if (StrCmp(name, "sigaction")) @@ -47,18 +47,13 @@ static void *GetFuncAddr(const char *name, uptr wrapper_addr) { // want the address of the real definition, though, so look it up using // RTLD_DEFAULT. addr = dlsym(RTLD_DEFAULT, name); - - // In case `name' is not loaded, dlsym ends up finding the actual wrapper. - // We don't want to intercept the wrapper and have it point to itself. - if ((uptr)addr == wrapper_addr) - addr = nullptr; } return addr; } bool InterceptFunction(const char *name, uptr *ptr_to_real, uptr func, uptr wrapper) { - void *addr = GetFuncAddr(name, wrapper); + void *addr = GetFuncAddr(name); *ptr_to_real = (uptr)addr; return addr && (func == wrapper); } diff --git a/compiler-rt/test/asan/TestCases/Linux/dlopen-mixed-c-cxx.c b/compiler-rt/test/asan/TestCases/Linux/dlopen-mixed-c-cxx.c deleted file mode 100644 index 8bce907ef2e6..000000000000 --- a/compiler-rt/test/asan/TestCases/Linux/dlopen-mixed-c-cxx.c +++ /dev/null @@ -1,42 +0,0 @@ -// RUN: %clangxx_asan -xc++ -shared -fPIC -o %t.so - < %s -// RUN: %clang_asan %s -o %t.out -ldl -// RUN: ASAN_OPTIONS=verbosity=1 not %t.out %t.so 2>&1 | FileCheck %s -// -// CHECK: AddressSanitizer: failed to intercept '__cxa_throw' -// -// dlopen() can not be intercepted on Android -// UNSUPPORTED: android -#ifdef __cplusplus - -static void foo(void) { - int i = 0; - throw(i); -} - -extern "C" { -int bar(void); -}; -int bar(void) { - try { - foo(); - } catch (int i) { - return i; - } - return -1; -} - -#else - -#include -#include - -int main(int argc, char **argv) { - int (*bar)(void); - void *handle = dlopen(argv[1], RTLD_LAZY); - assert(handle); - bar = dlsym(handle, "bar"); - assert(bar); - return bar(); -} - -#endif From 9488d77b44eeeaf540d03c724c3a46de37d4a3df Mon Sep 17 00:00:00 2001 From: Ulrich Weigand Date: Mon, 22 Jul 2019 14:39:02 +0000 Subject: [PATCH 011/289] [SystemZ] Add release notes on the LLVM 9 branch llvm-svn: 366693 --- llvm/docs/ReleaseNotes.rst | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst index ebf2c8db7baf..e1481f9f1389 100644 --- a/llvm/docs/ReleaseNotes.rst +++ b/llvm/docs/ReleaseNotes.rst @@ -103,6 +103,27 @@ Changes to the PowerPC Target During this release ... +Changes to the SystemZ Target +----------------------------- + +* Support for the arch13 architecture has been added. When using the + ``-march=arch13`` option, the compiler will generate code making use of + new instructions introduced with the vector enhancement facility 2 + and the miscellaneous instruction extension facility 2. + The ``-mtune=arch13`` option enables arch13 specific instruction + scheduling and tuning without making use of new instructions. + +* Builtins for the new vector instructions have been added and can be + enabled using the ``-mzvector`` option. Support for these builtins + is indicated by the compiler predefining the ``__VEC__`` macro to + the value ``10303``. + +* The compiler now supports and automatically generates alignment hints + on vector load and store instructions. + +* Various code-gen improvements, in particular related to improved + instruction selection and register allocation. + Changes to the X86 Target ------------------------- From 1f2d26a76eb474f02d10ce92b7ae81940800c729 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Mon, 22 Jul 2019 17:32:32 +0000 Subject: [PATCH 012/289] Merging r366431: ------------------------------------------------------------------------ r366431 | spatel | 2019-07-18 14:48:01 +0200 (Thu, 18 Jul 2019) | 13 lines [x86] try harder to form LEA from ADD to avoid flag conflicts (PR40483) LEA doesn't affect flags, so use it more liberally to replace an ADD when we know that the ADD operands affect flags. In the motivating example from PR40483: https://bugs.llvm.org/show_bug.cgi?id=40483 ...this lets us avoid duplicating a math op just to avoid flag conflict. As mentioned in the TODO comments, this heuristic can be extended to fire more often if that leads to more improvements. Differential Revision: https://reviews.llvm.org/D64707 ------------------------------------------------------------------------ llvm-svn: 366704 --- llvm/lib/Target/X86/X86ISelDAGToDAG.cpp | 31 +++++++++++++++++++++++++ llvm/test/CodeGen/X86/combine-sbb.ll | 30 ++++++++---------------- 2 files changed, 41 insertions(+), 20 deletions(-) diff --git a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp index 95d31e62cafc..fcf9b4148b4d 100644 --- a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp +++ b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp @@ -2464,6 +2464,37 @@ bool X86DAGToDAGISel::selectLEAAddr(SDValue N, Complexity += 2; } + // Heuristic: try harder to form an LEA from ADD if the operands set flags. + // Unlike ADD, LEA does not affect flags, so we will be less likely to require + // duplicating flag-producing instructions later in the pipeline. + if (N.getOpcode() == ISD::ADD) { + auto isMathWithFlags = [](SDValue V) { + switch (V.getOpcode()) { + case X86ISD::ADD: + case X86ISD::SUB: + case X86ISD::ADC: + case X86ISD::SBB: + /* TODO: These opcodes can be added safely, but we may want to justify + their inclusion for different reasons (better for reg-alloc). + case X86ISD::SMUL: + case X86ISD::UMUL: + case X86ISD::OR: + case X86ISD::XOR: + case X86ISD::AND: + */ + // Value 1 is the flag output of the node - verify it's not dead. + return !SDValue(V.getNode(), 1).use_empty(); + default: + return false; + } + }; + // TODO: This could be an 'or' rather than 'and' to make the transform more + // likely to happen. We might want to factor in whether there's a + // load folding opportunity for the math op that disappears with LEA. + if (isMathWithFlags(N.getOperand(0)) && isMathWithFlags(N.getOperand(1))) + Complexity++; + } + if (AM.Disp) Complexity++; diff --git a/llvm/test/CodeGen/X86/combine-sbb.ll b/llvm/test/CodeGen/X86/combine-sbb.ll index bba72c566094..6eb0e1e0f0ce 100644 --- a/llvm/test/CodeGen/X86/combine-sbb.ll +++ b/llvm/test/CodeGen/X86/combine-sbb.ll @@ -309,35 +309,25 @@ define i32 @PR40483_sub5(i32*, i32) nounwind { define i32 @PR40483_sub6(i32*, i32) nounwind { ; X86-LABEL: PR40483_sub6: ; X86: # %bb.0: -; X86-NEXT: pushl %edi -; X86-NEXT: pushl %esi ; X86-NEXT: movl {{[0-9]+}}(%esp), %edx -; X86-NEXT: movl (%edx), %esi -; X86-NEXT: movl {{[0-9]+}}(%esp), %edi -; X86-NEXT: movl %esi, %ecx -; X86-NEXT: subl %edi, %ecx +; X86-NEXT: movl (%edx), %ecx ; X86-NEXT: xorl %eax, %eax -; X86-NEXT: subl %edi, %esi -; X86-NEXT: movl %esi, (%edx) +; X86-NEXT: subl {{[0-9]+}}(%esp), %ecx +; X86-NEXT: movl %ecx, (%edx) ; X86-NEXT: jae .LBB8_2 ; X86-NEXT: # %bb.1: -; X86-NEXT: addl %ecx, %ecx -; X86-NEXT: movl %ecx, %eax +; X86-NEXT: leal (%ecx,%ecx), %eax ; X86-NEXT: .LBB8_2: -; X86-NEXT: popl %esi -; X86-NEXT: popl %edi ; X86-NEXT: retl ; ; X64-LABEL: PR40483_sub6: ; X64: # %bb.0: -; X64-NEXT: movl (%rdi), %ecx -; X64-NEXT: movl %ecx, %edx -; X64-NEXT: subl %esi, %edx -; X64-NEXT: addl %edx, %edx -; X64-NEXT: xorl %eax, %eax -; X64-NEXT: subl %esi, %ecx -; X64-NEXT: movl %ecx, (%rdi) -; X64-NEXT: cmovbl %edx, %eax +; X64-NEXT: movl (%rdi), %eax +; X64-NEXT: xorl %ecx, %ecx +; X64-NEXT: subl %esi, %eax +; X64-NEXT: movl %eax, (%rdi) +; X64-NEXT: leal (%rax,%rax), %eax +; X64-NEXT: cmovael %ecx, %eax ; X64-NEXT: retq %3 = load i32, i32* %0, align 8 %4 = tail call { i8, i32 } @llvm.x86.subborrow.32(i8 0, i32 %3, i32 %1) From f8ed38c52c3ec5c51ca4c83f053fcce13b166e41 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Mon, 22 Jul 2019 17:42:16 +0000 Subject: [PATCH 013/289] Merging r366474: ------------------------------------------------------------------------ r366474 | abataev | 2019-07-18 19:49:13 +0200 (Thu, 18 Jul 2019) | 8 lines [OPENMP]Provide correct data sharing attributes for loop control variables. Loop control variables are private in loop-based constructs and we shall take this into account when generate the code for inner constructs. Currently, those variables are reported as shared in many cases. Moved the analysis of the data-sharing attributes of the loop control variable to an early semantic stage to correctly handle their attributes. ------------------------------------------------------------------------ llvm-svn: 366705 --- clang/lib/Sema/SemaOpenMP.cpp | 100 ++++++++++-------- ...ute_parallel_for_firstprivate_messages.cpp | 8 +- ...arallel_for_simd_firstprivate_messages.cpp | 8 +- .../distribute_simd_firstprivate_messages.cpp | 8 +- .../OpenMP/distribute_simd_misc_messages.c | 4 +- clang/test/OpenMP/for_misc_messages.c | 4 +- clang/test/OpenMP/for_simd_misc_messages.c | 4 +- .../parallel_for_firstprivate_messages.cpp | 8 +- .../test/OpenMP/parallel_for_misc_messages.c | 4 +- ...arallel_for_simd_firstprivate_messages.cpp | 8 +- clang/test/OpenMP/simd_misc_messages.c | 4 +- ...get_parallel_for_firstprivate_messages.cpp | 8 +- .../target_parallel_for_misc_messages.c | 4 +- ...arallel_for_simd_firstprivate_messages.cpp | 8 +- .../target_parallel_for_simd_misc_messages.c | 4 +- .../target_simd_firstprivate_messages.cpp | 8 +- ...stribute_parallel_for_simd_misc_messages.c | 4 +- ...rget_teams_distribute_simd_misc_messages.c | 4 +- clang/test/OpenMP/task_codegen.c | 15 +++ .../OpenMP/taskloop_firstprivate_messages.cpp | 8 +- .../taskloop_simd_firstprivate_messages.cpp | 12 +-- 21 files changed, 130 insertions(+), 105 deletions(-) diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index bd68011c18b2..bec2fd8d3c08 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -139,6 +139,7 @@ class DSAStackTy { /// clause, false otherwise. llvm::Optional> OrderedRegion; unsigned AssociatedLoops = 1; + bool HasMutipleLoops = false; const Decl *PossiblyLoopCounter = nullptr; bool NowaitRegion = false; bool CancelRegion = false; @@ -678,12 +679,19 @@ class DSAStackTy { /// Set collapse value for the region. void setAssociatedLoops(unsigned Val) { getTopOfStack().AssociatedLoops = Val; + if (Val > 1) + getTopOfStack().HasMutipleLoops = true; } /// Return collapse value for region. unsigned getAssociatedLoops() const { const SharingMapTy *Top = getTopOfStackOrNull(); return Top ? Top->AssociatedLoops : 0; } + /// Returns true if the construct is associated with multiple loops. + bool hasMutipleLoops() const { + const SharingMapTy *Top = getTopOfStackOrNull(); + return Top ? Top->HasMutipleLoops : false; + } /// Marks current target region as one with closely nested teams /// region. @@ -5604,13 +5612,14 @@ void Sema::ActOnOpenMPLoopInitialization(SourceLocation ForLoc, Stmt *Init) { if (!ISC.checkAndSetInit(Init, /*EmitDiags=*/false)) { if (ValueDecl *D = ISC.getLoopDecl()) { auto *VD = dyn_cast(D); + DeclRefExpr *PrivateRef = nullptr; if (!VD) { if (VarDecl *Private = isOpenMPCapturedDecl(D)) { VD = Private; } else { - DeclRefExpr *Ref = buildCapture(*this, D, ISC.getLoopDeclRefExpr(), - /*WithInit=*/false); - VD = cast(Ref->getDecl()); + PrivateRef = buildCapture(*this, D, ISC.getLoopDeclRefExpr(), + /*WithInit=*/false); + VD = cast(PrivateRef->getDecl()); } } DSAStack->addLoopControlVariable(D, VD); @@ -5623,6 +5632,49 @@ void Sema::ActOnOpenMPLoopInitialization(SourceLocation ForLoc, Stmt *Init) { Var->getType().getNonLValueExprType(Context), ForLoc, /*RefersToCapture=*/true)); } + OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective(); + // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables + // Referenced in a Construct, C/C++]. The loop iteration variable in the + // associated for-loop of a simd construct with just one associated + // for-loop may be listed in a linear clause with a constant-linear-step + // that is the increment of the associated for-loop. The loop iteration + // variable(s) in the associated for-loop(s) of a for or parallel for + // construct may be listed in a private or lastprivate clause. + DSAStackTy::DSAVarData DVar = + DSAStack->getTopDSA(D, /*FromParent=*/false); + // If LoopVarRefExpr is nullptr it means the corresponding loop variable + // is declared in the loop and it is predetermined as a private. + Expr *LoopDeclRefExpr = ISC.getLoopDeclRefExpr(); + OpenMPClauseKind PredeterminedCKind = + isOpenMPSimdDirective(DKind) + ? (DSAStack->hasMutipleLoops() ? OMPC_lastprivate : OMPC_linear) + : OMPC_private; + if (((isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown && + DVar.CKind != PredeterminedCKind && DVar.RefExpr && + (LangOpts.OpenMP <= 45 || (DVar.CKind != OMPC_lastprivate && + DVar.CKind != OMPC_private))) || + ((isOpenMPWorksharingDirective(DKind) || DKind == OMPD_taskloop || + isOpenMPDistributeDirective(DKind)) && + !isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown && + DVar.CKind != OMPC_private && DVar.CKind != OMPC_lastprivate)) && + (DVar.CKind != OMPC_private || DVar.RefExpr)) { + Diag(Init->getBeginLoc(), diag::err_omp_loop_var_dsa) + << getOpenMPClauseName(DVar.CKind) + << getOpenMPDirectiveName(DKind) + << getOpenMPClauseName(PredeterminedCKind); + if (DVar.RefExpr == nullptr) + DVar.CKind = PredeterminedCKind; + reportOriginalDsa(*this, DSAStack, D, DVar, + /*IsLoopIterVar=*/true); + } else if (LoopDeclRefExpr) { + // Make the loop iteration variable private (for worksharing + // constructs), linear (for simd directives with the only one + // associated loop) or lastprivate (for simd directives with several + // collapsed or ordered loops). + if (DVar.CKind == OMPC_unknown) + DSAStack->addDSA(D, LoopDeclRefExpr, PredeterminedCKind, + PrivateRef); + } } } DSAStack->setAssociatedLoops(AssociatedLoops - 1); @@ -5677,8 +5729,6 @@ static bool checkOpenMPIterationSpace( // Check loop variable's type. if (ValueDecl *LCDecl = ISC.getLoopDecl()) { - Expr *LoopDeclRefExpr = ISC.getLoopDeclRefExpr(); - // OpenMP [2.6, Canonical Loop Form] // Var is one of the following: // A variable of signed or unsigned integer type. @@ -5704,46 +5754,6 @@ static bool checkOpenMPIterationSpace( // sharing attributes. VarsWithImplicitDSA.erase(LCDecl); - // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced - // in a Construct, C/C++]. - // The loop iteration variable in the associated for-loop of a simd - // construct with just one associated for-loop may be listed in a linear - // clause with a constant-linear-step that is the increment of the - // associated for-loop. - // The loop iteration variable(s) in the associated for-loop(s) of a for or - // parallel for construct may be listed in a private or lastprivate clause. - DSAStackTy::DSAVarData DVar = DSA.getTopDSA(LCDecl, false); - // If LoopVarRefExpr is nullptr it means the corresponding loop variable is - // declared in the loop and it is predetermined as a private. - OpenMPClauseKind PredeterminedCKind = - isOpenMPSimdDirective(DKind) - ? ((NestedLoopCount == 1) ? OMPC_linear : OMPC_lastprivate) - : OMPC_private; - if (((isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown && - DVar.CKind != PredeterminedCKind && DVar.RefExpr && - (SemaRef.getLangOpts().OpenMP <= 45 || - (DVar.CKind != OMPC_lastprivate && DVar.CKind != OMPC_private))) || - ((isOpenMPWorksharingDirective(DKind) || DKind == OMPD_taskloop || - isOpenMPDistributeDirective(DKind)) && - !isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown && - DVar.CKind != OMPC_private && DVar.CKind != OMPC_lastprivate)) && - (DVar.CKind != OMPC_private || DVar.RefExpr)) { - SemaRef.Diag(Init->getBeginLoc(), diag::err_omp_loop_var_dsa) - << getOpenMPClauseName(DVar.CKind) << getOpenMPDirectiveName(DKind) - << getOpenMPClauseName(PredeterminedCKind); - if (DVar.RefExpr == nullptr) - DVar.CKind = PredeterminedCKind; - reportOriginalDsa(SemaRef, &DSA, LCDecl, DVar, /*IsLoopIterVar=*/true); - HasErrors = true; - } else if (LoopDeclRefExpr != nullptr) { - // Make the loop iteration variable private (for worksharing constructs), - // linear (for simd directives with the only one associated loop) or - // lastprivate (for simd directives with several collapsed or ordered - // loops). - if (DVar.CKind == OMPC_unknown) - DSA.addDSA(LCDecl, LoopDeclRefExpr, PredeterminedCKind); - } - assert(isOpenMPLoopDirective(DKind) && "DSA for non-loop vars"); // Check test-expr. diff --git a/clang/test/OpenMP/distribute_parallel_for_firstprivate_messages.cpp b/clang/test/OpenMP/distribute_parallel_for_firstprivate_messages.cpp index 1678a27f213b..d283c29c3284 100644 --- a/clang/test/OpenMP/distribute_parallel_for_firstprivate_messages.cpp +++ b/clang/test/OpenMP/distribute_parallel_for_firstprivate_messages.cpp @@ -162,14 +162,14 @@ int foomain(int argc, char **argv) { #pragma omp parallel private(i) #pragma omp target #pragma omp teams -#pragma omp distribute parallel for firstprivate(i) // expected-note {{defined as firstprivate}} - for (i = 0; i < argc; ++i) // expected-error {{loop iteration variable in the associated loop of 'omp distribute parallel for' directive may not be firstprivate, predetermined as private}} +#pragma omp distribute parallel for firstprivate(i) // expected-note 2 {{defined as firstprivate}} + for (i = 0; i < argc; ++i) // expected-error 2 {{loop iteration variable in the associated loop of 'omp distribute parallel for' directive may not be firstprivate, predetermined as private}} foo(); #pragma omp parallel reduction(+ : i) #pragma omp target #pragma omp teams -#pragma omp distribute parallel for firstprivate(i) // expected-note {{defined as firstprivate}} - for (i = 0; i < argc; ++i) // expected-error {{loop iteration variable in the associated loop of 'omp distribute parallel for' directive may not be firstprivate, predetermined as private}} +#pragma omp distribute parallel for firstprivate(i) // expected-note 2 {{defined as firstprivate}} + for (i = 0; i < argc; ++i) // expected-error 2 {{loop iteration variable in the associated loop of 'omp distribute parallel for' directive may not be firstprivate, predetermined as private}} foo(); return 0; } diff --git a/clang/test/OpenMP/distribute_parallel_for_simd_firstprivate_messages.cpp b/clang/test/OpenMP/distribute_parallel_for_simd_firstprivate_messages.cpp index aa33807c424d..953cd2097151 100644 --- a/clang/test/OpenMP/distribute_parallel_for_simd_firstprivate_messages.cpp +++ b/clang/test/OpenMP/distribute_parallel_for_simd_firstprivate_messages.cpp @@ -162,14 +162,14 @@ int foomain(int argc, char **argv) { #pragma omp parallel private(i) #pragma omp target #pragma omp teams -#pragma omp distribute parallel for simd firstprivate(i) // expected-note {{defined as firstprivate}} - for (i = 0; i < argc; ++i) // expected-error {{loop iteration variable in the associated loop of 'omp distribute parallel for simd' directive may not be firstprivate, predetermined as linear}} +#pragma omp distribute parallel for simd firstprivate(i) // expected-note 2 {{defined as firstprivate}} + for (i = 0; i < argc; ++i) // expected-error 2 {{loop iteration variable in the associated loop of 'omp distribute parallel for simd' directive may not be firstprivate, predetermined as linear}} foo(); #pragma omp parallel reduction(+ : i) #pragma omp target #pragma omp teams -#pragma omp distribute parallel for simd firstprivate(i) // expected-note {{defined as firstprivate}} - for (i = 0; i < argc; ++i) // expected-error {{loop iteration variable in the associated loop of 'omp distribute parallel for simd' directive may not be firstprivate, predetermined as linear}} +#pragma omp distribute parallel for simd firstprivate(i) // expected-note 2 {{defined as firstprivate}} + for (i = 0; i < argc; ++i) // expected-error 2 {{loop iteration variable in the associated loop of 'omp distribute parallel for simd' directive may not be firstprivate, predetermined as linear}} foo(); return 0; } diff --git a/clang/test/OpenMP/distribute_simd_firstprivate_messages.cpp b/clang/test/OpenMP/distribute_simd_firstprivate_messages.cpp index b73ecc274d0d..0e00f31c8b32 100644 --- a/clang/test/OpenMP/distribute_simd_firstprivate_messages.cpp +++ b/clang/test/OpenMP/distribute_simd_firstprivate_messages.cpp @@ -162,14 +162,14 @@ int foomain(int argc, char **argv) { #pragma omp parallel private(i) #pragma omp target #pragma omp teams -#pragma omp distribute simd firstprivate(i) // expected-note {{defined as firstprivate}} - for (i = 0; i < argc; ++i) // expected-error {{loop iteration variable in the associated loop of 'omp distribute simd' directive may not be firstprivate, predetermined as linear}} +#pragma omp distribute simd firstprivate(i) // expected-note 2 {{defined as firstprivate}} + for (i = 0; i < argc; ++i) // expected-error 2 {{loop iteration variable in the associated loop of 'omp distribute simd' directive may not be firstprivate, predetermined as linear}} foo(); #pragma omp parallel reduction(+ : i) #pragma omp target #pragma omp teams -#pragma omp distribute simd firstprivate(i) // expected-note {{defined as firstprivate}} - for (i = 0; i < argc; ++i) // expected-error {{loop iteration variable in the associated loop of 'omp distribute simd' directive may not be firstprivate, predetermined as linear}} +#pragma omp distribute simd firstprivate(i) // expected-note 2 {{defined as firstprivate}} + for (i = 0; i < argc; ++i) // expected-error 2 {{loop iteration variable in the associated loop of 'omp distribute simd' directive may not be firstprivate, predetermined as linear}} foo(); return 0; } diff --git a/clang/test/OpenMP/distribute_simd_misc_messages.c b/clang/test/OpenMP/distribute_simd_misc_messages.c index 37dcf8ba7b05..4c82b7a96b03 100644 --- a/clang/test/OpenMP/distribute_simd_misc_messages.c +++ b/clang/test/OpenMP/distribute_simd_misc_messages.c @@ -487,11 +487,11 @@ void test_collapse() { #pragma omp distribute simd collapse(5 - 5) for (i = 0; i < 16; ++i) ; -// expected-note@+3 {{defined as reduction}} +// expected-note@+3 2 {{defined as reduction}} #pragma omp target #pragma omp teams #pragma omp distribute simd collapse(2) reduction(+ : i) - for (i = 0; i < 16; ++i) + for (i = 0; i < 16; ++i) // expected-error {{loop iteration variable in the associated loop of 'omp distribute simd' directive may not be reduction, predetermined as lastprivate}} // expected-note@+1 {{variable with automatic storage duration is predetermined as private; perhaps you forget to enclose 'omp for' directive into a parallel or another task region?}} for (int j = 0; j < 16; ++j) // expected-error@+2 2 {{reduction variable must be shared}} diff --git a/clang/test/OpenMP/for_misc_messages.c b/clang/test/OpenMP/for_misc_messages.c index 324c70bee318..e6559ebcb7bd 100644 --- a/clang/test/OpenMP/for_misc_messages.c +++ b/clang/test/OpenMP/for_misc_messages.c @@ -214,10 +214,10 @@ void test_collapse() { ; #pragma omp parallel #pragma omp for collapse(2) - for (i = 0; i < 16; ++i) + for (i = 0; i < 16; ++i) // expected-note {{defined as private}} // expected-note@+1 {{variable with automatic storage duration is predetermined as private; perhaps you forget to enclose 'omp for' directive into a parallel or another task region?}} for (int j = 0; j < 16; ++j) -// expected-error@+2 {{reduction variable must be shared}} +// expected-error@+2 2 {{reduction variable must be shared}} // expected-error@+1 {{region cannot be closely nested inside 'for' region; perhaps you forget to enclose 'omp for' directive into a parallel region?}} #pragma omp for reduction(+ : i, j) for (int k = 0; k < 16; ++k) diff --git a/clang/test/OpenMP/for_simd_misc_messages.c b/clang/test/OpenMP/for_simd_misc_messages.c index f7c864d135e5..ced5ee50cb59 100644 --- a/clang/test/OpenMP/for_simd_misc_messages.c +++ b/clang/test/OpenMP/for_simd_misc_messages.c @@ -381,10 +381,10 @@ void test_collapse() { ; #pragma omp parallel #pragma omp for simd collapse(2) - for (i = 0; i < 16; ++i) + for (i = 0; i < 16; ++i) // expected-note {{defined as lastprivate}} // expected-note@+1 {{variable with automatic storage duration is predetermined as private; perhaps you forget to enclose 'omp for simd' directive into a parallel or another task region?}} for (int j = 0; j < 16; ++j) -// expected-error@+2 {{reduction variable must be shared}} +// expected-error@+2 2 {{reduction variable must be shared}} // expected-error@+1 {{OpenMP constructs may not be nested inside a simd region}} #pragma omp for simd reduction(+ : i, j) for (int k = 0; k < 16; ++k) diff --git a/clang/test/OpenMP/parallel_for_firstprivate_messages.cpp b/clang/test/OpenMP/parallel_for_firstprivate_messages.cpp index 28a21a49e60e..8a312f47662e 100644 --- a/clang/test/OpenMP/parallel_for_firstprivate_messages.cpp +++ b/clang/test/OpenMP/parallel_for_firstprivate_messages.cpp @@ -127,12 +127,12 @@ int foomain(int argc, char **argv) { for (i = 0; i < argc; ++i) foo(); #pragma omp parallel private(i) -#pragma omp parallel for firstprivate(i) // expected-note {{defined as firstprivate}} - for (i = 0; i < argc; ++i) // expected-error {{loop iteration variable in the associated loop of 'omp parallel for' directive may not be firstprivate, predetermined as private}} +#pragma omp parallel for firstprivate(i) // expected-note 2 {{defined as firstprivate}} + for (i = 0; i < argc; ++i) // expected-error 2 {{loop iteration variable in the associated loop of 'omp parallel for' directive may not be firstprivate, predetermined as private}} foo(); #pragma omp parallel reduction(+ : i) -#pragma omp parallel for firstprivate(i) // expected-note {{defined as firstprivate}} - for (i = 0; i < argc; ++i) // expected-error {{loop iteration variable in the associated loop of 'omp parallel for' directive may not be firstprivate, predetermined as private}} +#pragma omp parallel for firstprivate(i) // expected-note 2 {{defined as firstprivate}} + for (i = 0; i < argc; ++i) // expected-error 2 {{loop iteration variable in the associated loop of 'omp parallel for' directive may not be firstprivate, predetermined as private}} foo(); return 0; } diff --git a/clang/test/OpenMP/parallel_for_misc_messages.c b/clang/test/OpenMP/parallel_for_misc_messages.c index 946f6d58ccea..38e50915ddf5 100644 --- a/clang/test/OpenMP/parallel_for_misc_messages.c +++ b/clang/test/OpenMP/parallel_for_misc_messages.c @@ -162,9 +162,9 @@ void test_collapse() { #pragma omp parallel for collapse(5 - 5) for (i = 0; i < 16; ++i) ; -// expected-note@+1 {{defined as firstprivate}} +// expected-note@+1 2 {{defined as firstprivate}} #pragma omp parallel for collapse(2) firstprivate(i) - for (i = 0; i < 16; ++i) + for (i = 0; i < 16; ++i) // expected-error {{loop iteration variable in the associated loop of 'omp parallel for' directive may not be firstprivate, predetermined as private}} // expected-note@+1 {{variable with automatic storage duration is predetermined as private; perhaps you forget to enclose 'omp for' directive into a parallel or another task region?}} for (int j = 0; j < 16; ++j) // expected-error@+2 2 {{reduction variable must be shared}} diff --git a/clang/test/OpenMP/parallel_for_simd_firstprivate_messages.cpp b/clang/test/OpenMP/parallel_for_simd_firstprivate_messages.cpp index 2cd9c065c63b..5f57c65374a3 100644 --- a/clang/test/OpenMP/parallel_for_simd_firstprivate_messages.cpp +++ b/clang/test/OpenMP/parallel_for_simd_firstprivate_messages.cpp @@ -129,12 +129,12 @@ int foomain(int argc, char **argv) { for (i = 0; i < argc; ++i) foo(); #pragma omp parallel private(i) -#pragma omp parallel for simd firstprivate(i) // expected-note {{defined as firstprivate}} - for (i = 0; i < argc; ++i) // expected-error {{loop iteration variable in the associated loop of 'omp parallel for simd' directive may not be firstprivate, predetermined as linear}} +#pragma omp parallel for simd firstprivate(i) // expected-note 2 {{defined as firstprivate}} + for (i = 0; i < argc; ++i) // expected-error 2 {{loop iteration variable in the associated loop of 'omp parallel for simd' directive may not be firstprivate, predetermined as linear}} foo(); #pragma omp parallel reduction(+ : i) -#pragma omp parallel for simd firstprivate(i) // expected-note {{defined as firstprivate}} - for (i = 0; i < argc; ++i) // expected-error {{loop iteration variable in the associated loop of 'omp parallel for simd' directive may not be firstprivate, predetermined as linear}} +#pragma omp parallel for simd firstprivate(i) // expected-note 2 {{defined as firstprivate}} + for (i = 0; i < argc; ++i) // expected-error 2 {{loop iteration variable in the associated loop of 'omp parallel for simd' directive may not be firstprivate, predetermined as linear}} foo(); return 0; } diff --git a/clang/test/OpenMP/simd_misc_messages.c b/clang/test/OpenMP/simd_misc_messages.c index 88df2535103c..29dbde4da8ac 100644 --- a/clang/test/OpenMP/simd_misc_messages.c +++ b/clang/test/OpenMP/simd_misc_messages.c @@ -359,10 +359,10 @@ void test_collapse() { #pragma omp simd collapse(5 - 5) for (i = 0; i < 16; ++i) ; -// expected-note@+2 {{defined as reduction}} +// expected-note@+2 2 {{defined as reduction}} #pragma omp parallel #pragma omp simd collapse(2) reduction(+ : i) - for (i = 0; i < 16; ++i) + for (i = 0; i < 16; ++i) // expected-error {{loop iteration variable in the associated loop of 'omp simd' directive may not be reduction, predetermined as lastprivate}} // expected-note@+1 {{variable with automatic storage duration is predetermined as private; perhaps you forget to enclose 'omp for' directive into a parallel or another task region?}} for (int j = 0; j < 16; ++j) // expected-error@+2 2 {{reduction variable must be shared}} diff --git a/clang/test/OpenMP/target_parallel_for_firstprivate_messages.cpp b/clang/test/OpenMP/target_parallel_for_firstprivate_messages.cpp index dd05d84cb4ff..d90c02478c5e 100644 --- a/clang/test/OpenMP/target_parallel_for_firstprivate_messages.cpp +++ b/clang/test/OpenMP/target_parallel_for_firstprivate_messages.cpp @@ -136,12 +136,12 @@ int foomain(int argc, char **argv) { for (i = 0; i < argc; ++i) foo(); #pragma omp parallel private(i) -#pragma omp target parallel for firstprivate(i) // expected-note {{defined as firstprivate}} - for (i = 0; i < argc; ++i) // expected-error {{loop iteration variable in the associated loop of 'omp target parallel for' directive may not be firstprivate, predetermined as private}} +#pragma omp target parallel for firstprivate(i) // expected-note 2 {{defined as firstprivate}} + for (i = 0; i < argc; ++i) // expected-error 2 {{loop iteration variable in the associated loop of 'omp target parallel for' directive may not be firstprivate, predetermined as private}} foo(); #pragma omp parallel reduction(+ : i) -#pragma omp target parallel for firstprivate(i) // expected-note {{defined as firstprivate}} - for (i = 0; i < argc; ++i) // expected-error {{loop iteration variable in the associated loop of 'omp target parallel for' directive may not be firstprivate, predetermined as private}} +#pragma omp target parallel for firstprivate(i) // expected-note 2 {{defined as firstprivate}} + for (i = 0; i < argc; ++i) // expected-error 2 {{loop iteration variable in the associated loop of 'omp target parallel for' directive may not be firstprivate, predetermined as private}} foo(); return 0; } diff --git a/clang/test/OpenMP/target_parallel_for_misc_messages.c b/clang/test/OpenMP/target_parallel_for_misc_messages.c index f697cf2e6ca4..789d7e04db26 100644 --- a/clang/test/OpenMP/target_parallel_for_misc_messages.c +++ b/clang/test/OpenMP/target_parallel_for_misc_messages.c @@ -162,9 +162,9 @@ void test_collapse() { #pragma omp target parallel for collapse(5 - 5) for (i = 0; i < 16; ++i) ; -// expected-note@+1 {{defined as firstprivate}} +// expected-note@+1 2 {{defined as firstprivate}} #pragma omp target parallel for collapse(2) firstprivate(i) - for (i = 0; i < 16; ++i) + for (i = 0; i < 16; ++i) // expected-error {{loop iteration variable in the associated loop of 'omp target parallel for' directive may not be firstprivate, predetermined as private}} // expected-note@+1 {{variable with automatic storage duration is predetermined as private; perhaps you forget to enclose 'omp for' directive into a parallel or another task region?}} for (int j = 0; j < 16; ++j) // expected-error@+2 2 {{reduction variable must be shared}} diff --git a/clang/test/OpenMP/target_parallel_for_simd_firstprivate_messages.cpp b/clang/test/OpenMP/target_parallel_for_simd_firstprivate_messages.cpp index d76fedcce836..b2ffe3b3840d 100644 --- a/clang/test/OpenMP/target_parallel_for_simd_firstprivate_messages.cpp +++ b/clang/test/OpenMP/target_parallel_for_simd_firstprivate_messages.cpp @@ -136,12 +136,12 @@ int foomain(int argc, char **argv) { for (i = 0; i < argc; ++i) foo(); #pragma omp parallel private(i) -#pragma omp target parallel for simd firstprivate(i) // expected-note {{defined as firstprivate}} - for (i = 0; i < argc; ++i) // expected-error {{loop iteration variable in the associated loop of 'omp target parallel for simd' directive may not be firstprivate, predetermined as linear}} +#pragma omp target parallel for simd firstprivate(i) // expected-note 2 {{defined as firstprivate}} + for (i = 0; i < argc; ++i) // expected-error 2 {{loop iteration variable in the associated loop of 'omp target parallel for simd' directive may not be firstprivate, predetermined as linear}} foo(); #pragma omp parallel reduction(+ : i) -#pragma omp target parallel for simd firstprivate(i) // expected-note {{defined as firstprivate}} - for (i = 0; i < argc; ++i) // expected-error {{loop iteration variable in the associated loop of 'omp target parallel for simd' directive may not be firstprivate, predetermined as linear}} +#pragma omp target parallel for simd firstprivate(i) // expected-note 2 {{defined as firstprivate}} + for (i = 0; i < argc; ++i) // expected-error 2 {{loop iteration variable in the associated loop of 'omp target parallel for simd' directive may not be firstprivate, predetermined as linear}} foo(); return 0; } diff --git a/clang/test/OpenMP/target_parallel_for_simd_misc_messages.c b/clang/test/OpenMP/target_parallel_for_simd_misc_messages.c index 1459d8322a77..b11f57dc7548 100644 --- a/clang/test/OpenMP/target_parallel_for_simd_misc_messages.c +++ b/clang/test/OpenMP/target_parallel_for_simd_misc_messages.c @@ -163,8 +163,8 @@ void test_collapse() { for (i = 0; i < 16; ++i) ; // expected-note@+1 {{defined as firstprivate}} -#pragma omp target parallel for simd collapse(2) firstprivate(i) - for (i = 0; i < 16; ++i) +#pragma omp target parallel for simd collapse(2) firstprivate(i) // expected-note {{defined as firstprivate}} + for (i = 0; i < 16; ++i) // expected-error {{loop iteration variable in the associated loop of 'omp target parallel for simd' directive may not be firstprivate, predetermined as lastprivate}} // expected-note@+1 {{variable with automatic storage duration is predetermined as private; perhaps you forget to enclose 'omp for' directive into a parallel or another task region?}} for (int j = 0; j < 16; ++j) // expected-error@+2 2 {{reduction variable must be shared}} diff --git a/clang/test/OpenMP/target_simd_firstprivate_messages.cpp b/clang/test/OpenMP/target_simd_firstprivate_messages.cpp index c26ef158f87d..651afdde8ab4 100644 --- a/clang/test/OpenMP/target_simd_firstprivate_messages.cpp +++ b/clang/test/OpenMP/target_simd_firstprivate_messages.cpp @@ -136,12 +136,12 @@ int foomain(int argc, char **argv) { for (i = 0; i < argc; ++i) foo(); #pragma omp parallel private(i) -#pragma omp target simd firstprivate(i) // expected-note {{defined as firstprivate}} - for (i = 0; i < argc; ++i) // expected-error {{loop iteration variable in the associated loop of 'omp target simd' directive may not be firstprivate, predetermined as linear}} +#pragma omp target simd firstprivate(i) // expected-note 2 {{defined as firstprivate}} + for (i = 0; i < argc; ++i) // expected-error 2 {{loop iteration variable in the associated loop of 'omp target simd' directive may not be firstprivate, predetermined as linear}} foo(); #pragma omp parallel reduction(+ : i) -#pragma omp target simd firstprivate(i) // expected-note {{defined as firstprivate}} - for (i = 0; i < argc; ++i) // expected-error {{loop iteration variable in the associated loop of 'omp target simd' directive may not be firstprivate, predetermined as linear}} +#pragma omp target simd firstprivate(i) // expected-note 2 {{defined as firstprivate}} + for (i = 0; i < argc; ++i) // expected-error 2 {{loop iteration variable in the associated loop of 'omp target simd' directive may not be firstprivate, predetermined as linear}} foo(); return 0; } diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_misc_messages.c b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_misc_messages.c index 07db3991bba6..f2a870ecb900 100644 --- a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_misc_messages.c +++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_misc_messages.c @@ -164,8 +164,8 @@ void test_collapse() { ; // expected-error@+4 {{OpenMP constructs may not be nested inside a simd region}} -#pragma omp target teams distribute parallel for simd collapse(2) firstprivate(i) - for (i = 0; i < 16; ++i) +#pragma omp target teams distribute parallel for simd collapse(2) firstprivate(i) // expected-note {{defined as firstprivate}} + for (i = 0; i < 16; ++i) // expected-error {{loop iteration variable in the associated loop of 'omp target teams distribute parallel for simd' directive may not be firstprivate, predetermined as lastprivate}} for (int j = 0; j < 16; ++j) #pragma omp parallel for reduction(+ : i, j) for (int k = 0; k < 16; ++k) diff --git a/clang/test/OpenMP/target_teams_distribute_simd_misc_messages.c b/clang/test/OpenMP/target_teams_distribute_simd_misc_messages.c index 45f310ffdf6c..16f595d679bb 100644 --- a/clang/test/OpenMP/target_teams_distribute_simd_misc_messages.c +++ b/clang/test/OpenMP/target_teams_distribute_simd_misc_messages.c @@ -164,8 +164,8 @@ void test_collapse() { ; // expected-error@+4 {{OpenMP constructs may not be nested inside a simd region}} -#pragma omp target teams distribute simd collapse(2) firstprivate(i) - for (i = 0; i < 16; ++i) +#pragma omp target teams distribute simd collapse(2) firstprivate(i) // expected-note {{defined as firstprivate}} + for (i = 0; i < 16; ++i) // expected-error {{loop iteration variable in the associated loop of 'omp target teams distribute simd' directive may not be firstprivate, predetermined as lastprivate}} for (int j = 0; j < 16; ++j) #pragma omp parallel for reduction(+ : i, j) for (int k = 0; k < 16; ++k) diff --git a/clang/test/OpenMP/task_codegen.c b/clang/test/OpenMP/task_codegen.c index 6669c7e73616..69718cc6f4d3 100644 --- a/clang/test/OpenMP/task_codegen.c +++ b/clang/test/OpenMP/task_codegen.c @@ -32,4 +32,19 @@ int main() { // CHECK: call i8* @__kmpc_omp_task_alloc( // CHECK: call i32 @__kmpc_omp_task( // CHECK: call void @__kmpc_end_taskgroup( + +// CHECK-LINE: @bar +void bar() { + // CHECK: call void @__kmpc_for_static_init_4( +#pragma omp for +for (int i = 0; i < 10; ++i) + // CHECK: [[BUF:%.+]] = call i8* @__kmpc_omp_task_alloc(%struct.ident_t* @{{.+}}, i32 %{{.+}}, i32 1, i64 48, + // CHECK: [[BC_BUF:%.+]] = bitcast i8* [[BUF]] to [[TT_WITH_PRIVS:%.+]]* + // CHECK: [[PRIVS:%.+]] = getelementptr inbounds [[TT_WITH_PRIVS]], [[TT_WITH_PRIVS]]* [[BC_BUF]], i32 0, i32 1 + // CHECK: [[I_PRIV:%.+]] = getelementptr inbounds %{{.+}}, %{{.+}} [[PRIVS]], i32 0, i32 0 + // CHECK: store i32 %{{.+}}, i32* [[I_PRIV]], + // CHECK: = call i32 @__kmpc_omp_task(%struct.ident_t* @{{.+}}, i32 %{{.+}}, i8* [[BUF]]) +#pragma omp task +++i; +} #endif diff --git a/clang/test/OpenMP/taskloop_firstprivate_messages.cpp b/clang/test/OpenMP/taskloop_firstprivate_messages.cpp index 9ef869f50ae2..b5311f5e27f9 100644 --- a/clang/test/OpenMP/taskloop_firstprivate_messages.cpp +++ b/clang/test/OpenMP/taskloop_firstprivate_messages.cpp @@ -150,11 +150,11 @@ int foomain(int argc, char **argv) { for (i = 0; i < argc; ++i) foo(); #pragma omp parallel private(i) -#pragma omp taskloop firstprivate(i) // expected-note {{defined as firstprivate}} - for (i = 0; i < argc; ++i) // expected-error {{loop iteration variable in the associated loop of 'omp taskloop' directive may not be firstprivate, predetermined as private}} +#pragma omp taskloop firstprivate(i) // expected-note 2 {{defined as firstprivate}} + for (i = 0; i < argc; ++i) // expected-error 2 {{loop iteration variable in the associated loop of 'omp taskloop' directive may not be firstprivate, predetermined as private}} foo(); -#pragma omp parallel reduction(+ : i) -#pragma omp taskloop firstprivate(i) // expected-note {{defined as firstprivate}} +#pragma omp parallel reduction(+ : i) // expected-note {{defined as reduction}} +#pragma omp taskloop firstprivate(i) // expected-note {{defined as firstprivate}} expected-error {{argument of a reduction clause of a parallel construct must not appear in a firstprivate clause on a task construct}} for (i = 0; i < argc; ++i) // expected-error {{loop iteration variable in the associated loop of 'omp taskloop' directive may not be firstprivate, predetermined as private}} foo(); return 0; diff --git a/clang/test/OpenMP/taskloop_simd_firstprivate_messages.cpp b/clang/test/OpenMP/taskloop_simd_firstprivate_messages.cpp index 1aea8c02a043..fdedda93a735 100644 --- a/clang/test/OpenMP/taskloop_simd_firstprivate_messages.cpp +++ b/clang/test/OpenMP/taskloop_simd_firstprivate_messages.cpp @@ -150,11 +150,11 @@ int foomain(int argc, char **argv) { for (i = 0; i < argc; ++i) foo(); #pragma omp parallel private(i) -#pragma omp taskloop simd firstprivate(i) // expected-note {{defined as firstprivate}} - for (i = 0; i < argc; ++i) // expected-error {{loop iteration variable in the associated loop of 'omp taskloop simd' directive may not be firstprivate, predetermined as linear}} +#pragma omp taskloop simd firstprivate(i) // expected-note 2 {{defined as firstprivate}} + for (i = 0; i < argc; ++i) // expected-error 2 {{loop iteration variable in the associated loop of 'omp taskloop simd' directive may not be firstprivate, predetermined as linear}} foo(); -#pragma omp parallel reduction(+ : i) -#pragma omp taskloop simd firstprivate(i) // expected-note {{defined as firstprivate}} +#pragma omp parallel reduction(+ : i) // expected-note {{defined as reduction}} +#pragma omp taskloop simd firstprivate(i) // expected-note {{defined as firstprivate}} expected-error {{argument of a reduction clause of a parallel construct must not appear in a firstprivate clause on a task construct}} for (i = 0; i < argc; ++i) // expected-error {{loop iteration variable in the associated loop of 'omp taskloop simd' directive may not be firstprivate, predetermined as linear}} foo(); return 0; @@ -307,9 +307,9 @@ int main(int argc, char **argv) { #pragma omp taskloop simd firstprivate(i) // expected-note {{defined as firstprivate}} for (i = 0; i < argc; ++i) // expected-error {{loop iteration variable in the associated loop of 'omp taskloop simd' directive may not be firstprivate, predetermined as linear}} foo(); -#pragma omp parallel reduction(+ : i) // expected-note 2 {{defined as reduction}} +#pragma omp parallel reduction(+ : i) // expected-note {{defined as reduction}} #pragma omp taskloop simd firstprivate(i) // expected-error {{argument of a reduction clause of a parallel construct must not appear in a firstprivate clause on a task construct}} - for (i = 0; i < argc; ++i) // expected-error {{reduction variables may not be accessed in an explicit task}} + for (i = 0; i < argc; ++i) foo(); #pragma omp taskloop simd firstprivate(i) //expected-note {{defined as firstprivate}} for (i = 0; i < argc; ++i) // expected-error {{loop iteration variable in the associated loop of 'omp taskloop simd' directive may not be firstprivate, predetermined as linear}} From bf93c6e0b194fb1dd17e91ddfefad92a52139879 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Mon, 22 Jul 2019 17:45:30 +0000 Subject: [PATCH 014/289] Merging r366483: ------------------------------------------------------------------------ r366483 | abataev | 2019-07-18 21:40:24 +0200 (Thu, 18 Jul 2019) | 6 lines [OPENMP]Fix sharing of threadprivate variables with TLS support. If the threadprivate variable is used in the copyin clause on inner parallel directive with TLS support, we capture this variable in all outer OpenMP scopes. It leads to the fact that in all scopes we're working with the original variable, not the threadprivate copies. ------------------------------------------------------------------------ llvm-svn: 366706 --- clang/lib/Sema/SemaOpenMP.cpp | 7 +++++ clang/test/OpenMP/parallel_copyin_codegen.cpp | 27 ++++++++++++++++--- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index bec2fd8d3c08..4ac87469bf44 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -1882,6 +1882,13 @@ bool Sema::isOpenMPPrivateDecl(const ValueDecl *D, unsigned Level) const { !isOpenMPSimdDirective(DSAStack->getCurrentDirective())) return true; } + if (const auto *VD = dyn_cast(D)) { + if (DSAStack->isThreadPrivate(const_cast(VD)) && + DSAStack->isForceVarCapturing() && + !DSAStack->hasExplicitDSA( + D, [](OpenMPClauseKind K) { return K == OMPC_copyin; }, Level)) + return true; + } return DSAStack->hasExplicitDSA( D, [](OpenMPClauseKind K) { return K == OMPC_private; }, Level) || (DSAStack->isClauseParsingMode() && diff --git a/clang/test/OpenMP/parallel_copyin_codegen.cpp b/clang/test/OpenMP/parallel_copyin_codegen.cpp index 8fa9edd2c1ac..87c11f040619 100644 --- a/clang/test/OpenMP/parallel_copyin_codegen.cpp +++ b/clang/test/OpenMP/parallel_copyin_codegen.cpp @@ -19,6 +19,7 @@ // RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -DLAMBDA -triple x86_64-linux -emit-llvm %s -o - | FileCheck -check-prefix=TLS-LAMBDA %s // RUN: %clang_cc1 -verify -fopenmp -x c++ -fblocks -DBLOCKS -triple x86_64-linux -emit-llvm %s -o - | FileCheck -check-prefix=TLS-BLOCKS %s // RUN: %clang_cc1 -verify -fopenmp -x c++ -std=c++11 -DARRAY -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck -check-prefix=TLS-ARRAY %s +// RUN: %clang_cc1 -verify -fopenmp -x c++ -DNESTED -triple x86_64-linux -emit-llvm %s -o - | FileCheck %s -check-prefix=NESTED // RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -triple x86_64-linux -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s // RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -triple x86_64-linux -emit-pch -o %t %s @@ -28,7 +29,7 @@ // RUN: %clang_cc1 -verify -fopenmp-simd -x c++ -std=c++11 -DARRAY -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY1 %s // SIMD-ONLY1-NOT: {{__kmpc|__tgt}} // expected-no-diagnostics -#ifndef ARRAY +#if !defined(ARRAY) && !defined(NESTED) #ifndef HEADER #define HEADER @@ -493,7 +494,7 @@ int main() { // TLS-CHECK: ret void #endif -#else +#elif defined(ARRAY) // ARRAY-LABEL: array_func // TLS-ARRAY-LABEL: array_func @@ -522,6 +523,24 @@ void array_func() { #pragma omp parallel copyin(a, s) ; } -#endif - +#elif defined(NESTED) +int t; +#pragma omp threadprivate(t) +// NESTED: foo +void foo() { + // NESTED: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* @{{.+}}, i32 0, void (i32*, i32*, ...)* bitcast (void (i32*, i32*)* [[OUTLINED:@.+]] to void (i32*, i32*, ...)*)) +#pragma omp parallel +#pragma omp parallel copyin(t) + ++t; +} +// NESTED: define {{.*}}void [[OUTLINED]]( +// NESTED: [[T:%.+]] = call i32* [[THRP_T:@.+]]() +// NESTED: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* @{{.+}}, i32 1, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, i32*)* [[OUTLINED1:@.+]] to void (i32*, i32*, ...)*), i32* [[T]]) + +// NESTED: define {{.*}}void [[OUTLINED1]]( +// NESTED: [[T_MASTER:%.+]] = load i32*, i32** % +// NESTED: [[T:%.+]] = call i32* [[THRP_T]]() +// NESTED: [[T_MASTER_VAL:%.+]] = load i32, i32* [[T_MASTER]], +// NESTED: store i32 [[T_MASTER_VAL]], i32* [[T]], +#endif // NESTED From 6de5254ec9f394e3159a7e5644804073776998e2 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Mon, 22 Jul 2019 17:48:03 +0000 Subject: [PATCH 015/289] Merging r366500: ------------------------------------------------------------------------ r366500 | quantum | 2019-07-18 23:18:24 +0200 (Thu, 18 Jul 2019) | 13 lines [WebAssembly] fix bug in finding .tdata segment Summary: Fix bug in `wasm-ld`'s `Writer::createInitTLSFunction` that only finds `.tdata` if it's the first section. Reviewers: tlively, aheejin, sbc100 Reviewed By: sbc100 Subscribers: dschuff, jgravelle-google, sunfish, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D64947 ------------------------------------------------------------------------ llvm-svn: 366707 --- lld/test/wasm/tls.ll | 6 +++--- lld/wasm/Writer.cpp | 5 +++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/lld/test/wasm/tls.ll b/lld/test/wasm/tls.ll index b570d4675687..855180dddbad 100644 --- a/lld/test/wasm/tls.ll +++ b/lld/test/wasm/tls.ll @@ -2,8 +2,8 @@ target triple = "wasm32-unknown-unknown" -@tls1 = thread_local(localexec) global i32 1, align 4 @no_tls = global i32 0, align 4 +@tls1 = thread_local(localexec) global i32 1, align 4 @tls2 = thread_local(localexec) global i32 1, align 4 define i32* @tls1_addr() { @@ -49,7 +49,7 @@ define i32* @tls2_addr() { ; CHECK-NEXT: Body: 0B ; CHECK-NEXT: - Index: 1 ; CHECK-NEXT: Locals: [] -; CHECK-NEXT: Body: 20002401200041004108FC0800000B +; CHECK-NEXT: Body: 20002401200041004108FC0801000B ; Expected body of __wasm_init_tls: ; local.get 0 @@ -57,7 +57,7 @@ define i32* @tls2_addr() { ; local.get 0 ; i32.const 0 ; i32.const 8 -; memory.init 0, 0 +; memory.init 1, 0 ; end ; CHECK-NEXT: - Index: 2 diff --git a/lld/wasm/Writer.cpp b/lld/wasm/Writer.cpp index 4ad91ab11171..68e001ccc800 100644 --- a/lld/wasm/Writer.cpp +++ b/lld/wasm/Writer.cpp @@ -771,9 +771,10 @@ void Writer::createInitTLSFunction() { OutputSegment *tlsSeg = nullptr; for (auto *seg : segments) { - if (seg->name == ".tdata") + if (seg->name == ".tdata") { tlsSeg = seg; - break; + break; + } } writeUleb128(os, 0, "num locals"); From f04c5c0d1a38879b7c7cddfa4e729657de1612dd Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Mon, 22 Jul 2019 17:50:00 +0000 Subject: [PATCH 016/289] Merging r366504: ------------------------------------------------------------------------ r366504 | tlively | 2019-07-18 23:50:24 +0200 (Thu, 18 Jul 2019) | 15 lines [WebAssembly] Use passive segments by default when memory is shared Summary: This change makes it so that passing --shared-memory is all a user needs to do to get proper multithreaded code. This default can still be explicitly overridden for any reason using --passive-segments and --active-segments. Reviewers: sbc100, quantum Subscribers: dschuff, jgravelle-google, aheejin, sunfish, jfb, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D64950 ------------------------------------------------------------------------ llvm-svn: 366709 --- lld/test/wasm/data-layout.ll | 2 +- lld/test/wasm/data-segments.ll | 13 ++++++------- lld/test/wasm/import-memory.test | 4 ++-- lld/test/wasm/shared-memory.yaml | 12 ++++++------ lld/test/wasm/tls.ll | 10 ++++------ lld/wasm/Driver.cpp | 5 ++--- lld/wasm/Options.td | 4 ++-- 7 files changed, 23 insertions(+), 27 deletions(-) diff --git a/lld/test/wasm/data-layout.ll b/lld/test/wasm/data-layout.ll index 20fe30445cb7..6c060f460019 100644 --- a/lld/test/wasm/data-layout.ll +++ b/lld/test/wasm/data-layout.ll @@ -76,7 +76,7 @@ target triple = "wasm32-unknown-unknown" ; RUN: wasm-ld -no-gc-sections --allow-undefined --no-entry --shared-memory \ ; RUN: --initial-memory=131072 --max-memory=131072 -o %t_max.wasm %t.o \ -; RUN: %t.hello.o +; RUN: --active-segments %t.hello.o ; RUN: obj2yaml %t_max.wasm | FileCheck %s -check-prefix=CHECK-SHARED ; CHECK-SHARED: - Type: MEMORY diff --git a/lld/test/wasm/data-segments.ll b/lld/test/wasm/data-segments.ll index 944895a0d39c..32fb6812d3b9 100644 --- a/lld/test/wasm/data-segments.ll +++ b/lld/test/wasm/data-segments.ll @@ -2,9 +2,8 @@ ; RUN: llc -filetype=obj %s -o %t.bulk-mem.o -mattr=+bulk-memory ; RUN: llc -filetype=obj %s -o %t.atomics.bulk-mem.o -mattr=+atomics,+bulk-memory -; atomics => active segments (TODO: error) -; RUN: wasm-ld -no-gc-sections --no-entry --shared-memory --max-memory=131072 %t.atomics.o -o %t.atomics.wasm -; RUN: obj2yaml %t.atomics.wasm | FileCheck %s --check-prefixes ACTIVE,ACTIVE-TLS +; atomics => error +; RUN: not wasm-ld -no-gc-sections --no-entry --shared-memory --max-memory=131072 %t.atomics.o -o %t.atomics.wasm 2>&1 | FileCheck %s --check-prefix ERROR ; atomics, active segments => active segments ; RUN: wasm-ld -no-gc-sections --no-entry --shared-memory --max-memory=131072 --active-segments %t.atomics.o -o %t.atomics.active.wasm @@ -25,15 +24,15 @@ ; RUN: wasm-ld -no-gc-sections --no-entry --passive-segments %t.bulk-mem.o -o %t.bulk-mem.passive.wasm ; RUN: obj2yaml %t.bulk-mem.passive.wasm | FileCheck %s --check-prefix PASSIVE -; atomics, bulk memory => active segments (TODO: passive) +; atomics, bulk memory => passive segments ; RUN: wasm-ld -no-gc-sections --no-entry --shared-memory --max-memory=131072 %t.atomics.bulk-mem.o -o %t.atomics.bulk-mem.wasm -; RUN: obj2yaml %t.atomics.bulk-mem.wasm | FileCheck %s --check-prefixes ACTIVE,ACTIVE-TLS +; RUN: obj2yaml %t.atomics.bulk-mem.wasm | FileCheck %s --check-prefixes PASSIVE,PASSIVE-TLS -; atomics, bulk memory, active segments => active segments +; atomics, bulk memory, active segments => active segments ; RUN: wasm-ld -no-gc-sections --no-entry --shared-memory --max-memory=131072 --active-segments %t.atomics.bulk-mem.o -o %t.atomics.bulk-mem.active.wasm ; RUN: obj2yaml %t.atomics.bulk-mem.active.wasm | FileCheck %s --check-prefixes ACTIVE,ACTIVE-TLS -; atomics, bulk memory, passive segments => passive segments +; atomics, bulk memory, passive segments => passive segments ; RUN: wasm-ld -no-gc-sections --no-entry --shared-memory --max-memory=131072 --passive-segments %t.atomics.bulk-mem.o -o %t.atomics.bulk-mem.passive.wasm ; RUN: obj2yaml %t.atomics.bulk-mem.passive.wasm | FileCheck %s --check-prefixes PASSIVE,PASSIVE-TLS diff --git a/lld/test/wasm/import-memory.test b/lld/test/wasm/import-memory.test index 0a64afd6ce20..e9dd972bc496 100644 --- a/lld/test/wasm/import-memory.test +++ b/lld/test/wasm/import-memory.test @@ -32,8 +32,8 @@ # CHECK-MAX-NEXT: Maximum: 0x00000005 # CHECK-MAX-NEXT: - Type: -# RUN: wasm-ld --import-memory --shared-memory --initial-memory=262144 \ -# RUN: --max-memory=327680 -o %t.max.wasm %t.start.o +# RUN: wasm-ld --import-memory --shared-memory --active-segments \ +# RUN: --initial-memory=262144 --max-memory=327680 -o %t.max.wasm %t.start.o # RUN: obj2yaml %t.max.wasm | FileCheck -check-prefix=CHECK-SHARED %s # Verify the --shared-memory flag works with imports diff --git a/lld/test/wasm/shared-memory.yaml b/lld/test/wasm/shared-memory.yaml index 3538f34a4aca..57eccf152917 100644 --- a/lld/test/wasm/shared-memory.yaml +++ b/lld/test/wasm/shared-memory.yaml @@ -1,18 +1,18 @@ # RUN: yaml2obj %s -o %t1.o -# RUN: not wasm-ld --no-entry --shared-memory %t1.o -o - 2>&1 | FileCheck %s --check-prefix SHARED-NO-MAX +# RUN: not wasm-ld --no-entry --shared-memory --active-segments %t1.o -o - 2>&1 | FileCheck %s --check-prefix SHARED-NO-MAX -# RUN: not wasm-ld --no-entry --shared-memory --max-memory=100000 %t1.o -o - 2>&1 | FileCheck %s --check-prefix SHARED-UNALIGNED +# RUN: not wasm-ld --no-entry --shared-memory --active-segments --max-memory=100000 %t1.o -o - 2>&1 | FileCheck %s --check-prefix SHARED-UNALIGNED -# RUN: wasm-ld --no-entry --shared-memory --max-memory=131072 %t1.o -o - | obj2yaml | FileCheck %s --check-prefix SHARED +# RUN: wasm-ld --no-entry --shared-memory --active-segments --max-memory=131072 %t1.o -o - | obj2yaml | FileCheck %s --check-prefix SHARED # RUN: not wasm-ld --no-entry --features=atomics %t1.o -o - 2>&1 | FileCheck %s --check-prefix ATOMICS-NO-SHARED -# RUN: not wasm-ld --no-entry --features=atomics --shared-memory %t1.o -o - 2>&1 | FileCheck %s --check-prefix ATOMICS-NO-MAX +# RUN: not wasm-ld --no-entry --features=atomics --shared-memory --active-segments %t1.o -o - 2>&1 | FileCheck %s --check-prefix ATOMICS-NO-MAX -# RUN: not wasm-ld --no-entry --features=atomics --shared-memory --max-memory=100000 %t1.o -o - 2>&1 | FileCheck %s --check-prefix ATOMICS-UNALIGNED +# RUN: not wasm-ld --no-entry --features=atomics --shared-memory --active-segments --max-memory=100000 %t1.o -o - 2>&1 | FileCheck %s --check-prefix ATOMICS-UNALIGNED -# RUN: wasm-ld --no-entry --features=atomics --shared-memory --max-memory=131072 %t1.o -o - | obj2yaml | FileCheck %s --check-prefix SHARED +# RUN: wasm-ld --no-entry --features=atomics --shared-memory --active-segments --max-memory=131072 %t1.o -o - | obj2yaml | FileCheck %s --check-prefix SHARED --- !WASM diff --git a/lld/test/wasm/tls.ll b/lld/test/wasm/tls.ll index 855180dddbad..e410e08656a4 100644 --- a/lld/test/wasm/tls.ll +++ b/lld/test/wasm/tls.ll @@ -44,10 +44,8 @@ define i32* @tls2_addr() { ; CHECK: - Type: CODE ; CHECK-NEXT: Functions: -; CHECK-NEXT: - Index: 0 -; CHECK-NEXT: Locals: [] -; CHECK-NEXT: Body: 0B -; CHECK-NEXT: - Index: 1 +; Skip __wasm_call_ctors and __wasm_init_memory +; CHECK: - Index: 2 ; CHECK-NEXT: Locals: [] ; CHECK-NEXT: Body: 20002401200041004108FC0801000B @@ -60,7 +58,7 @@ define i32* @tls2_addr() { ; memory.init 1, 0 ; end -; CHECK-NEXT: - Index: 2 +; CHECK-NEXT: - Index: 3 ; CHECK-NEXT: Locals: [] ; CHECK-NEXT: Body: 2381808080004180808080006A0B @@ -70,7 +68,7 @@ define i32* @tls2_addr() { ; i32.add ; end -; CHECK-NEXT: - Index: 3 +; CHECK-NEXT: - Index: 4 ; CHECK-NEXT: Locals: [] ; CHECK-NEXT: Body: 2381808080004184808080006A0B diff --git a/lld/wasm/Driver.cpp b/lld/wasm/Driver.cpp index 900cd051dcfb..003dd0d30baf 100644 --- a/lld/wasm/Driver.cpp +++ b/lld/wasm/Driver.cpp @@ -320,9 +320,8 @@ static void readConfigs(opt::InputArgList &args) { args.hasFlag(OPT_fatal_warnings, OPT_no_fatal_warnings, false); config->importMemory = args.hasArg(OPT_import_memory); config->sharedMemory = args.hasArg(OPT_shared_memory); - // TODO: Make passive segments the default with shared memory - config->passiveSegments = - args.hasFlag(OPT_passive_segments, OPT_active_segments, false); + config->passiveSegments = args.hasFlag( + OPT_passive_segments, OPT_active_segments, config->sharedMemory); config->importTable = args.hasArg(OPT_import_table); config->ltoo = args::getInteger(args, OPT_lto_O, 2); config->ltoPartitions = args::getInteger(args, OPT_lto_partitions, 1); diff --git a/lld/wasm/Options.td b/lld/wasm/Options.td index 29bd9d9ef3d1..4bce790cd576 100644 --- a/lld/wasm/Options.td +++ b/lld/wasm/Options.td @@ -144,10 +144,10 @@ def shared_memory: F<"shared-memory">, HelpText<"Use shared linear memory">; def active_segments: F<"active-segments">, - HelpText<"Force segments to be active">; + HelpText<"Force segments to be active (default with unshared memory)">; def passive_segments: F<"passive-segments">, - HelpText<"Force segments to be passive">; + HelpText<"Force segments to be passive (default with shared memory)">; def import_table: F<"import-table">, HelpText<"Import function table from the environment">; From 0581d619026df9e0b11f454566223cb10bebb52f Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Mon, 22 Jul 2019 17:51:42 +0000 Subject: [PATCH 017/289] Merging r366687: ------------------------------------------------------------------------ r366687 | aaronballman | 2019-07-22 15:22:08 +0200 (Mon, 22 Jul 2019) | 3 lines Update documentation for all CERT checks that correspond to a recommendation. CERT removed their C++ secure coding recommendations from public view and so the links within that documentation are stale. This updates various pieces of documentation to make this more clear, and to help add substance where our docs deferred to CERT's wiki. ------------------------------------------------------------------------ llvm-svn: 366710 --- .../docs/clang-tidy/checks/cert-dcl21-cpp.rst | 16 ++++++++++++++-- .../docs/clang-tidy/checks/cert-err09-cpp.rst | 5 +++++ .../docs/clang-tidy/checks/cert-oop11-cpp.rst | 6 ++++++ .../misc-throw-by-value-catch-by-reference.rst | 9 ++++++--- 4 files changed, 31 insertions(+), 5 deletions(-) diff --git a/clang-tools-extra/docs/clang-tidy/checks/cert-dcl21-cpp.rst b/clang-tools-extra/docs/clang-tidy/checks/cert-dcl21-cpp.rst index d5c294823626..818ae8fea71c 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cert-dcl21-cpp.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cert-dcl21-cpp.rst @@ -7,6 +7,18 @@ This check flags postfix ``operator++`` and ``operator--`` declarations if the return type is not a const object. This also warns if the return type is a reference type. +The object returned by a postfix increment or decrement operator is supposed +to be a snapshot of the object's value prior to modification. With such an +implementation, any modifications made to the resulting object from calling +operator++(int) would be modifying a temporary object. Thus, such an +implementation of a postfix increment or decrement operator should instead +return a const object, prohibiting accidental mutation of a temporary object. +Similarly, it is unexpected for the postfix operator to return a reference to +its previous state, and any subsequent modifications would be operating on a +stale object. + This check corresponds to the CERT C++ Coding Standard recommendation -`DCL21-CPP. Overloaded postfix increment and decrement operators should return a const object -`_. +DCL21-CPP. Overloaded postfix increment and decrement operators should return a +const object. However, all of the CERT recommendations have been removed from +public view, and so their justification for the behavior of this check requires +an account on their wiki to view. \ No newline at end of file diff --git a/clang-tools-extra/docs/clang-tidy/checks/cert-err09-cpp.rst b/clang-tools-extra/docs/clang-tidy/checks/cert-err09-cpp.rst index 1494bcc07e33..8f5220b425ad 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cert-err09-cpp.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cert-err09-cpp.rst @@ -8,3 +8,8 @@ cert-err09-cpp The cert-err09-cpp check is an alias, please see `misc-throw-by-value-catch-by-reference `_ for more information. + +This check corresponds to the CERT C++ Coding Standard recommendation +ERR09-CPP. Throw anonymous temporaries. However, all of the CERT recommendations +have been removed from public view, and so their justification for the behavior +of this check requires an account on their wiki to view. \ No newline at end of file diff --git a/clang-tools-extra/docs/clang-tidy/checks/cert-oop11-cpp.rst b/clang-tools-extra/docs/clang-tidy/checks/cert-oop11-cpp.rst index dcd0fee8b2d9..df06f75000fa 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/cert-oop11-cpp.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/cert-oop11-cpp.rst @@ -8,3 +8,9 @@ cert-oop11-cpp The cert-oop11-cpp check is an alias, please see `performance-move-constructor-init `_ for more information. + +This check corresponds to the CERT C++ Coding Standard recommendation +OOP11-CPP. Do not copy-initialize members or base classes from a move +constructor. However, all of the CERT recommendations have been removed from +public view, and so their justification for the behavior of this check requires +an account on their wiki to view. \ No newline at end of file diff --git a/clang-tools-extra/docs/clang-tidy/checks/misc-throw-by-value-catch-by-reference.rst b/clang-tools-extra/docs/clang-tidy/checks/misc-throw-by-value-catch-by-reference.rst index bbe681a4fbf1..cc970fe014cc 100644 --- a/clang-tools-extra/docs/clang-tidy/checks/misc-throw-by-value-catch-by-reference.rst +++ b/clang-tools-extra/docs/clang-tidy/checks/misc-throw-by-value-catch-by-reference.rst @@ -7,7 +7,10 @@ misc-throw-by-value-catch-by-reference `cert-err61-cpp` redirects here as an alias for this check. Finds violations of the rule "Throw by value, catch by reference" presented for -example in "C++ Coding Standards" by H. Sutter and A. Alexandrescu. +example in "C++ Coding Standards" by H. Sutter and A. Alexandrescu, as well as +the CERT C++ Coding Standard rule `ERR61-CPP. Catch exceptions by lvalue reference +`_. + Exceptions: * Throwing string literals will not be flagged despite being a pointer. They @@ -28,8 +31,8 @@ Options .. option:: CheckThrowTemporaries - Triggers detection of violations of the rule `Throw anonymous temporaries - `_. + Triggers detection of violations of the CERT recommendation ERR09-CPP. Throw + anonymous temporaries. Default is `1`. .. option:: WarnOnLargeObject From 0382aa15992aa15d672395fe9944c5d4b3568d61 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Mon, 22 Jul 2019 17:56:32 +0000 Subject: [PATCH 018/289] Merging r366699: ------------------------------------------------------------------------ r366699 | probinson | 2019-07-22 18:14:09 +0200 (Mon, 22 Jul 2019) | 1 line [X86] Remove const from some intrinsics that shouldn't have them ------------------------------------------------------------------------ llvm-svn: 366711 --- clang/lib/Headers/emmintrin.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/clang/lib/Headers/emmintrin.h b/clang/lib/Headers/emmintrin.h index 3d55f5f2710f..c8fefdfc792a 100644 --- a/clang/lib/Headers/emmintrin.h +++ b/clang/lib/Headers/emmintrin.h @@ -4029,7 +4029,7 @@ _mm_storeu_si128(__m128i_u *__p, __m128i __b) /// \param __b /// A 128-bit integer vector containing the value to be stored. static __inline__ void __DEFAULT_FN_ATTRS -_mm_storeu_si64(void const *__p, __m128i __b) +_mm_storeu_si64(void *__p, __m128i __b) { struct __storeu_si64 { long long __v; @@ -4050,7 +4050,7 @@ _mm_storeu_si64(void const *__p, __m128i __b) /// \param __b /// A 128-bit integer vector containing the value to be stored. static __inline__ void __DEFAULT_FN_ATTRS -_mm_storeu_si32(void const *__p, __m128i __b) +_mm_storeu_si32(void *__p, __m128i __b) { struct __storeu_si32 { int __v; @@ -4071,7 +4071,7 @@ _mm_storeu_si32(void const *__p, __m128i __b) /// \param __b /// A 128-bit integer vector containing the value to be stored. static __inline__ void __DEFAULT_FN_ATTRS -_mm_storeu_si16(void const *__p, __m128i __b) +_mm_storeu_si16(void *__p, __m128i __b) { struct __storeu_si16 { short __v; From dc586a6cc8b988053b739bcf53f5150cf300262d Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Mon, 22 Jul 2019 18:06:03 +0000 Subject: [PATCH 019/289] Merging r366443: ------------------------------------------------------------------------ r366443 | sammccall | 2019-07-18 17:00:38 +0200 (Thu, 18 Jul 2019) | 1 line [clangd] Disable DumpRecordLayout by default per https://bugs.llvm.org/show_bug.cgi?id=42670 ------------------------------------------------------------------------ llvm-svn: 366713 --- clang-tools-extra/clangd/refactor/tweaks/DumpAST.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/clang-tools-extra/clangd/refactor/tweaks/DumpAST.cpp b/clang-tools-extra/clangd/refactor/tweaks/DumpAST.cpp index 4bba9cec9d5d..985993a3d93b 100644 --- a/clang-tools-extra/clangd/refactor/tweaks/DumpAST.cpp +++ b/clang-tools-extra/clangd/refactor/tweaks/DumpAST.cpp @@ -128,6 +128,11 @@ class DumpRecordLayout : public Tweak { TypeWithKeyword::getTagTypeKindName(Record->getTagKind())); } Intent intent() const override { return Info; } + // FIXME: this is interesting to most users. However: + // - triggering is too broad (e.g. triggers on comments within a class) + // - showMessage has inconsistent UX (e.g. newlines are stripped in VSCode) + // - the output itself is a bit hard to decipher. + bool hidden() const override { return true; } private: const RecordDecl *Record = nullptr; From 5844a5e9303f39a98dd1a86867d4efae4a3534a5 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Mon, 22 Jul 2019 18:07:55 +0000 Subject: [PATCH 020/289] Merging r366451: ------------------------------------------------------------------------ r366451 | sureyeaah | 2019-07-18 17:38:03 +0200 (Thu, 18 Jul 2019) | 13 lines [Clangd] Changed ExtractVariable to only work on non empty selections Summary: - For now, we don't trigger in any case if it's an empty selection - Fixed unittests Reviewers: kadircet, sammccall Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D64912 ------------------------------------------------------------------------ llvm-svn: 366714 --- clang-tools-extra/clangd/refactor/Tweak.cpp | 3 +- clang-tools-extra/clangd/refactor/Tweak.h | 5 ++ .../refactor/tweaks/ExtractVariable.cpp | 3 +- .../clangd/unittests/TweakTests.cpp | 69 ++++++++++--------- 4 files changed, 45 insertions(+), 35 deletions(-) diff --git a/clang-tools-extra/clangd/refactor/Tweak.cpp b/clang-tools-extra/clangd/refactor/Tweak.cpp index a6d70dbd38c9..b80f75300ddc 100644 --- a/clang-tools-extra/clangd/refactor/Tweak.cpp +++ b/clang-tools-extra/clangd/refactor/Tweak.cpp @@ -40,7 +40,8 @@ void validateRegistry() { Tweak::Selection::Selection(ParsedAST &AST, unsigned RangeBegin, unsigned RangeEnd) - : AST(AST), ASTSelection(AST.getASTContext(), RangeBegin, RangeEnd) { + : AST(AST), SelectionBegin(RangeBegin), SelectionEnd(RangeEnd), + ASTSelection(AST.getASTContext(), RangeBegin, RangeEnd) { auto &SM = AST.getSourceManager(); Code = SM.getBufferData(SM.getMainFileID()); Cursor = SM.getComposedLoc(SM.getMainFileID(), RangeBegin); diff --git a/clang-tools-extra/clangd/refactor/Tweak.h b/clang-tools-extra/clangd/refactor/Tweak.h index 79e0f3eceee8..9b20d151589a 100644 --- a/clang-tools-extra/clangd/refactor/Tweak.h +++ b/clang-tools-extra/clangd/refactor/Tweak.h @@ -46,7 +46,12 @@ class Tweak { /// Parsed AST of the active file. ParsedAST &AST; /// A location of the cursor in the editor. + // FIXME: Cursor is redundant and should be removed SourceLocation Cursor; + /// The begin offset of the selection + unsigned SelectionBegin; + /// The end offset of the selection + unsigned SelectionEnd; /// The AST nodes that were selected. SelectionTree ASTSelection; // FIXME: provide a way to get sources and ASTs for other files. diff --git a/clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp b/clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp index 447110d3e90b..525c259b7a5d 100644 --- a/clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp +++ b/clang-tools-extra/clangd/refactor/tweaks/ExtractVariable.cpp @@ -219,7 +219,8 @@ bool ExtractVariable::prepare(const Selection &Inputs) { const ASTContext &Ctx = Inputs.AST.getASTContext(); const SourceManager &SM = Inputs.AST.getSourceManager(); const SelectionTree::Node *N = Inputs.ASTSelection.commonAncestor(); - if (!N) + // we don't trigger on empty selections for now + if (!N || Inputs.SelectionBegin == Inputs.SelectionEnd) return false; Target = llvm::make_unique(N, SM, Ctx); return Target->isExtractable(); diff --git a/clang-tools-extra/clangd/unittests/TweakTests.cpp b/clang-tools-extra/clangd/unittests/TweakTests.cpp index 69f74e9d41b9..1ac5bb16e262 100644 --- a/clang-tools-extra/clangd/unittests/TweakTests.cpp +++ b/clang-tools-extra/clangd/unittests/TweakTests.cpp @@ -296,35 +296,36 @@ TEST(TweakTest, ExtractVariable) { checkAvailable(ID, R"cpp( int xyz() { // return statement - return ^1; + return [[1]]; } void f() { - int a = 5 + [[4 ^* ^xyz^()]]; + int a = [[5 +]] [[4 * [[[[xyz]]()]]]]; // multivariable initialization if(1) - int x = ^1, y = ^a + 1, a = ^1, z = a + 1; + int x = [[1]], y = [[a]] + 1, a = [[1]], z = a + 1; // if without else - if(^1) {} + if([[1]]) + a = [[1]]; // if with else - if(a < ^3) - if(a == ^4) - a = ^5; + if(a < [[3]]) + if(a == [[4]]) + a = [[5]]; else - a = ^6; - else if (a < ^4) - a = ^4; + a = [[5]]; + else if (a < [[4]]) + a = [[4]]; else - a = ^5; + a = [[5]]; // for loop - for(a = ^1; a > ^3^+^4; a++) - a = ^2; + for(a = [[1]]; a > [[[[3]] + [[4]]]]; a++) + a = [[2]]; // while - while(a < ^1) - ^a++; + while(a < [[1]]) + [[a]]++; // do while do - a = ^1; - while(a < ^3); + a = [[1]]; + while(a < [[3]]); } )cpp"); // Should not crash. @@ -336,29 +337,31 @@ TEST(TweakTest, ExtractVariable) { }; )cpp"); checkNotAvailable(ID, R"cpp( - int xyz(int a = ^1) { + int xyz(int a = [[1]]) { return 1; class T { - T(int a = ^1) {}; - int xyz = ^1; + T(int a = [[1]]) {}; + int xyz = [[1]]; }; } // function default argument - void f(int b = ^1) { + void f(int b = [[1]]) { + // empty selection + int a = ^1 ^+ ^2; // void expressions auto i = new int, j = new int; - de^lete i^, del^ete j; + [[[[delete i]], delete j]]; // if if(1) - int x = 1, y = a + 1, a = 1, z = ^a + 1; + int x = 1, y = a + 1, a = 1, z = [[a + 1]]; if(int a = 1) - if(^a == 4) - a = ^a ^+ 1; + if([[a]] == 4) + a = [[[[a]] +]] 1; // for loop - for(int a = 1, b = 2, c = 3; ^a > ^b ^+ ^c; ^a++) - a = ^a ^+ 1; + for(int a = 1, b = 2, c = 3; [[a]] > [[b + c]]; [[a]]++) + a = [[a + 1]]; // lambda - auto lamb = [&^a, &^b](int r = ^1) {return 1;} + auto lamb = [&[[a]], &[[b]]](int r = [[1]]) {return 1;} } )cpp"); // vector of pairs of input and output strings @@ -398,7 +401,7 @@ TEST(TweakTest, ExtractVariable) { {R"cpp(#define LOOP(x) {int a = x + 1;} void f(int a) { if(1) - LOOP(5 + ^3) + LOOP(5 + [[3]]) })cpp", R"cpp(#define LOOP(x) {int a = x + 1;} void f(int a) { @@ -407,7 +410,7 @@ TEST(TweakTest, ExtractVariable) { })cpp"}, // label and attribute testing {R"cpp(void f(int a) { - label: [ [gsl::suppress("type")] ] for (;;) a = ^1; + label: [ [gsl::suppress("type")] ] for (;;) a = [[1]]; })cpp", R"cpp(void f(int a) { auto dummy = 1; label: [ [gsl::suppress("type")] ] for (;;) a = dummy; @@ -415,14 +418,14 @@ TEST(TweakTest, ExtractVariable) { // FIXME: Doesn't work because bug in selection tree /*{R"cpp(#define PLUS(x) x++ void f(int a) { - PLUS(^a); + PLUS([[a]]); })cpp", R"cpp(#define PLUS(x) x++ void f(int a) { auto dummy = a; PLUS(dummy); })cpp"},*/ - // FIXME: Doesn't work correctly for \[\[clang::uninitialized\]\] int b - // = 1; since the attr is inside the DeclStmt and the bounds of + // FIXME: Doesn't work correctly for \[\[clang::uninitialized\]\] int + // b = [[1]]; since the attr is inside the DeclStmt and the bounds of // DeclStmt don't cover the attribute }; for (const auto &IO : InputOutputs) { From f3456bb94159771ce608179a9bd37fb52405ba9f Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Mon, 22 Jul 2019 18:12:26 +0000 Subject: [PATCH 021/289] Merging r366448 and r366457: ------------------------------------------------------------------------ r366448 | ibiryukov | 2019-07-18 17:21:34 +0200 (Thu, 18 Jul 2019) | 24 lines [ASTUnit] Fix a regression in cached completions Summary: After r345152 cached completions started adding namespaces after nested name specifiers, e.g. in `some_name::^` The CCC_Symbol indicates the completed item cannot be a namespace (it is described as being "a type, a function or a variable" in the comments). Therefore, 'nested specifier' completions should only be added from cache when the context is CCC_SymbolOrNewName (which roughly seems to indicate that a nested name specifier is allowed). Fixes https://bugs.llvm.org/show_bug.cgi?id=42646 Reviewers: kadircet, sammccall Reviewed By: kadircet, sammccall Subscribers: arphaman, nik, sammccall, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D64918 ------------------------------------------------------------------------ ------------------------------------------------------------------------ r366457 | ibiryukov | 2019-07-18 18:24:09 +0200 (Thu, 18 Jul 2019) | 1 line [ASTUnit] Attempt to unbreak Windows buildbots after r366448 ------------------------------------------------------------------------ llvm-svn: 366717 --- clang/lib/Frontend/ASTUnit.cpp | 1 - .../test/Index/complete-qualified-cached.cpp | 22 +++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 clang/test/Index/complete-qualified-cached.cpp diff --git a/clang/lib/Frontend/ASTUnit.cpp b/clang/lib/Frontend/ASTUnit.cpp index 7445a94cfe59..783d1f9d0919 100644 --- a/clang/lib/Frontend/ASTUnit.cpp +++ b/clang/lib/Frontend/ASTUnit.cpp @@ -435,7 +435,6 @@ void ASTUnit::CacheCodeCompletionResults() { | (1LL << CodeCompletionContext::CCC_UnionTag) | (1LL << CodeCompletionContext::CCC_ClassOrStructTag) | (1LL << CodeCompletionContext::CCC_Type) - | (1LL << CodeCompletionContext::CCC_Symbol) | (1LL << CodeCompletionContext::CCC_SymbolOrNewName) | (1LL << CodeCompletionContext::CCC_ParenthesizedExpression); diff --git a/clang/test/Index/complete-qualified-cached.cpp b/clang/test/Index/complete-qualified-cached.cpp new file mode 100644 index 000000000000..b866abec9062 --- /dev/null +++ b/clang/test/Index/complete-qualified-cached.cpp @@ -0,0 +1,22 @@ +namespace a_namespace {}; +class Class { static void foo(); }; +Class:: +// Completion for a_namespace should be available at the start of the line. +// START-OF-LINE: a_namespace +// START-OF-LINE: Class +// -- Using cached completions. +// RUN: env CINDEXTEST_EDITING=1 c-index-test -code-completion-at=%s:3:1 %s \ +// RUN: | FileCheck --check-prefix=START-OF-LINE %s +// -- Without cached completions. +// RUN: c-index-test -code-completion-at=%s:3:1 %s \ +// RUN: | FileCheck --check-prefix=START-OF-LINE %s +// +// +// ... and should not be available after 'Class::^' +// AFTER-QUALIFIER: Class +// -- Using cached completions. +// RUN: env CINDEXTEST_EDITING=1 c-index-test -code-completion-at=%s:3:8 %s \ +// RUN: | FileCheck --implicit-check-not=a_namespace --check-prefix=AFTER-QUALIFIER %s +// -- Without cached completions. +// RUN: c-index-test -code-completion-at=%s:3:8 %s \ +// RUN: | FileCheck --implicit-check-not=a_namespace --check-prefix=AFTER-QUALIFIER %s From f042a64d23a1c8e2df9a36c911f9432bf5ea75f7 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Mon, 22 Jul 2019 18:17:23 +0000 Subject: [PATCH 022/289] Merging r366455 and r366559: ------------------------------------------------------------------------ r366455 | kadircet | 2019-07-18 18:13:23 +0200 (Thu, 18 Jul 2019) | 9 lines [clangd] Get rid of dots and dotsdots within GlobalCompilationDatabase Reviewers: sammccall Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D64860 ------------------------------------------------------------------------ ------------------------------------------------------------------------ r366559 | kadircet | 2019-07-19 12:18:52 +0200 (Fri, 19 Jul 2019) | 19 lines Revert "Revert r366458, r366467 and r366468" This reverts commit 9c377105da0be7c2c9a3c70035ce674c71b846af. [clangd][BackgroundIndexLoader] Directly store DependentTU while loading shard Summary: We were deferring the population of DependentTU field in LoadedShard until BackgroundIndexLoader was consumed. This actually triggers a use after free since the shards FileToTU was pointing at could've been moved while consuming the Loader. Reviewers: sammccall Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D64980 ------------------------------------------------------------------------ llvm-svn: 366718 --- clang-tools-extra/clangd/CMakeLists.txt | 1 + clang-tools-extra/clangd/ClangdServer.cpp | 3 +- clang-tools-extra/clangd/FS.cpp | 6 + clang-tools-extra/clangd/FS.h | 8 + .../clangd/GlobalCompilationDatabase.cpp | 34 ++- clang-tools-extra/clangd/index/Background.cpp | 268 ++++++------------ clang-tools-extra/clangd/index/Background.h | 38 +-- .../clangd/index/BackgroundIndexLoader.cpp | 143 ++++++++++ .../clangd/index/BackgroundIndexLoader.h | 54 ++++ .../clangd/index/BackgroundIndexStorage.cpp | 40 ++- .../clangd/index/BackgroundRebuild.cpp | 8 +- .../clangd/index/BackgroundRebuild.h | 5 +- .../background-index/definition.jsonrpc | 2 +- .../test/Inputs/background-index/foo.cpp | 2 +- .../sub_dir/compile_flags.txt | 0 .../background-index/{ => sub_dir}/foo.h | 0 .../clangd/test/background-index.test | 4 +- .../clangd/unittests/BackgroundIndexTests.cpp | 16 +- .../GlobalCompilationDatabaseTests.cpp | 28 +- 19 files changed, 421 insertions(+), 239 deletions(-) create mode 100644 clang-tools-extra/clangd/index/BackgroundIndexLoader.cpp create mode 100644 clang-tools-extra/clangd/index/BackgroundIndexLoader.h create mode 100644 clang-tools-extra/clangd/test/Inputs/background-index/sub_dir/compile_flags.txt rename clang-tools-extra/clangd/test/Inputs/background-index/{ => sub_dir}/foo.h (100%) diff --git a/clang-tools-extra/clangd/CMakeLists.txt b/clang-tools-extra/clangd/CMakeLists.txt index ad50a4be9f26..f617f7931de1 100644 --- a/clang-tools-extra/clangd/CMakeLists.txt +++ b/clang-tools-extra/clangd/CMakeLists.txt @@ -73,6 +73,7 @@ add_clang_library(clangDaemon XRefs.cpp index/Background.cpp + index/BackgroundIndexLoader.cpp index/BackgroundIndexStorage.cpp index/BackgroundQueue.cpp index/BackgroundRebuild.cpp diff --git a/clang-tools-extra/clangd/ClangdServer.cpp b/clang-tools-extra/clangd/ClangdServer.cpp index 10949ef001c0..7e77e18725a6 100644 --- a/clang-tools-extra/clangd/ClangdServer.cpp +++ b/clang-tools-extra/clangd/ClangdServer.cpp @@ -127,7 +127,8 @@ ClangdServer::ClangdServer(const GlobalCompilationDatabase &CDB, if (Opts.BackgroundIndex) { BackgroundIdx = llvm::make_unique( Context::current().clone(), FSProvider, CDB, - BackgroundIndexStorage::createDiskBackedStorageFactory()); + BackgroundIndexStorage::createDiskBackedStorageFactory( + [&CDB](llvm::StringRef File) { return CDB.getProjectInfo(File); })); AddIndex(BackgroundIdx.get()); } if (DynamicIdx) diff --git a/clang-tools-extra/clangd/FS.cpp b/clang-tools-extra/clangd/FS.cpp index aca9061d5c53..4f04fb089ae1 100644 --- a/clang-tools-extra/clangd/FS.cpp +++ b/clang-tools-extra/clangd/FS.cpp @@ -111,5 +111,11 @@ PreambleFileStatusCache::getConsumingFS( return llvm::IntrusiveRefCntPtr(new CacheVFS(std::move(FS), *this)); } +Path removeDots(PathRef File) { + llvm::SmallString<128> CanonPath(File); + llvm::sys::path::remove_dots(CanonPath, /*remove_dot_dot=*/true); + return CanonPath.str().str(); +} + } // namespace clangd } // namespace clang diff --git a/clang-tools-extra/clangd/FS.h b/clang-tools-extra/clangd/FS.h index e23b3ff17d24..d8cc4438ef7f 100644 --- a/clang-tools-extra/clangd/FS.h +++ b/clang-tools-extra/clangd/FS.h @@ -9,6 +9,7 @@ #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_FS_H #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_FS_H +#include "Path.h" #include "clang/Basic/LLVM.h" #include "llvm/ADT/Optional.h" #include "llvm/Support/VirtualFileSystem.h" @@ -65,6 +66,13 @@ class PreambleFileStatusCache { llvm::StringMap StatCache; }; +/// Returns a version of \p File that doesn't contain dots and dot dots. +/// e.g /a/b/../c -> /a/c +/// /a/b/./c -> /a/b/c +/// FIXME: We should avoid encountering such paths in clangd internals by +/// filtering everything we get over LSP, CDB, etc. +Path removeDots(PathRef File); + } // namespace clangd } // namespace clang diff --git a/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp b/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp index 51f0e7d015ed..885bf15c616c 100644 --- a/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp +++ b/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "GlobalCompilationDatabase.h" +#include "FS.h" #include "Logger.h" #include "Path.h" #include "clang/Frontend/CompilerInvocation.h" @@ -15,6 +16,7 @@ #include "llvm/ADT/None.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallString.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" #include @@ -147,12 +149,15 @@ DirectoryBasedGlobalCompilationDatabase::lookupCDB( getCDBInDirLocked(*CompileCommandsDir); Result.PI.SourceRoot = *CompileCommandsDir; } else { - actOnAllParentDirectories( - Request.FileName, [this, &SentBroadcast, &Result](PathRef Path) { - std::tie(Result.CDB, SentBroadcast) = getCDBInDirLocked(Path); - Result.PI.SourceRoot = Path; - return Result.CDB != nullptr; - }); + // Traverse the canonical version to prevent false positives. i.e.: + // src/build/../a.cc can detect a CDB in /src/build if not canonicalized. + actOnAllParentDirectories(removeDots(Request.FileName), + [this, &SentBroadcast, &Result](PathRef Path) { + std::tie(Result.CDB, SentBroadcast) = + getCDBInDirLocked(Path); + Result.PI.SourceRoot = Path; + return Result.CDB != nullptr; + }); } if (!Result.CDB) @@ -209,7 +214,8 @@ void DirectoryBasedGlobalCompilationDatabase::broadcastCDB( actOnAllParentDirectories(File, [&](PathRef Path) { if (DirectoryHasCDB.lookup(Path)) { if (Path == Result.PI.SourceRoot) - GovernedFiles.push_back(File); + // Make sure listeners always get a canonical path for the file. + GovernedFiles.push_back(removeDots(File)); // Stop as soon as we hit a CDB. return true; } @@ -248,7 +254,7 @@ OverlayCDB::getCompileCommand(PathRef File) const { llvm::Optional Cmd; { std::lock_guard Lock(Mutex); - auto It = Commands.find(File); + auto It = Commands.find(removeDots(File)); if (It != Commands.end()) Cmd = It->second; } @@ -272,20 +278,24 @@ tooling::CompileCommand OverlayCDB::getFallbackCommand(PathRef File) const { void OverlayCDB::setCompileCommand( PathRef File, llvm::Optional Cmd) { + // We store a canonical version internally to prevent mismatches between set + // and get compile commands. Also it assures clients listening to broadcasts + // doesn't receive different names for the same file. + std::string CanonPath = removeDots(File); { std::unique_lock Lock(Mutex); if (Cmd) - Commands[File] = std::move(*Cmd); + Commands[CanonPath] = std::move(*Cmd); else - Commands.erase(File); + Commands.erase(CanonPath); } - OnCommandChanged.broadcast({File}); + OnCommandChanged.broadcast({CanonPath}); } llvm::Optional OverlayCDB::getProjectInfo(PathRef File) const { { std::lock_guard Lock(Mutex); - auto It = Commands.find(File); + auto It = Commands.find(removeDots(File)); if (It != Commands.end()) return ProjectInfo{}; } diff --git a/clang-tools-extra/clangd/index/Background.cpp b/clang-tools-extra/clangd/index/Background.cpp index 23445e16b2f3..a9e28f8de99a 100644 --- a/clang-tools-extra/clangd/index/Background.cpp +++ b/clang-tools-extra/clangd/index/Background.cpp @@ -10,6 +10,7 @@ #include "ClangdUnit.h" #include "Compiler.h" #include "Context.h" +#include "FSProvider.h" #include "Headers.h" #include "Logger.h" #include "Path.h" @@ -18,6 +19,7 @@ #include "Threading.h" #include "Trace.h" #include "URI.h" +#include "index/BackgroundIndexLoader.h" #include "index/FileIndex.h" #include "index/IndexAction.h" #include "index/MemIndex.h" @@ -28,6 +30,8 @@ #include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceManager.h" #include "clang/Driver/Types.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/Hashing.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/ScopeExit.h" @@ -42,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -49,6 +54,8 @@ #include #include #include +#include +#include namespace clang { namespace clangd { @@ -119,6 +126,18 @@ llvm::SmallString<128> getAbsolutePath(const tooling::CompileCommand &Cmd) { } return AbsolutePath; } + +bool shardIsStale(const LoadedShard &LS, llvm::vfs::FileSystem *FS) { + auto Buf = FS->getBufferForFile(LS.AbsolutePath); + if (!Buf) { + elog("Background-index: Couldn't read {0} to validate stored index: {1}", + LS.AbsolutePath, Buf.getError().message()); + // There is no point in indexing an unreadable file. + return false; + } + return digest(Buf->get()->getBuffer()) != LS.Digest; +} + } // namespace BackgroundIndex::BackgroundIndex( @@ -156,14 +175,14 @@ BackgroundQueue::Task BackgroundIndex::changedFilesTask( log("Enqueueing {0} commands for indexing", ChangedFiles.size()); SPAN_ATTACH(Tracer, "files", int64_t(ChangedFiles.size())); - auto NeedsReIndexing = loadShards(std::move(ChangedFiles)); + auto NeedsReIndexing = loadProject(std::move(ChangedFiles)); // Run indexing for files that need to be updated. std::shuffle(NeedsReIndexing.begin(), NeedsReIndexing.end(), std::mt19937(std::random_device{}())); std::vector Tasks; Tasks.reserve(NeedsReIndexing.size()); - for (auto &Elem : NeedsReIndexing) - Tasks.push_back(indexFileTask(std::move(Elem.first), Elem.second)); + for (auto &Cmd : NeedsReIndexing) + Tasks.push_back(indexFileTask(std::move(Cmd))); Queue.append(std::move(Tasks)); }); @@ -178,13 +197,12 @@ static llvm::StringRef filenameWithoutExtension(llvm::StringRef Path) { } BackgroundQueue::Task -BackgroundIndex::indexFileTask(tooling::CompileCommand Cmd, - BackgroundIndexStorage *Storage) { - BackgroundQueue::Task T([this, Storage, Cmd] { +BackgroundIndex::indexFileTask(tooling::CompileCommand Cmd) { + BackgroundQueue::Task T([this, Cmd] { // We can't use llvm::StringRef here since we are going to // move from Cmd during the call below. const std::string FileName = Cmd.Filename; - if (auto Error = index(std::move(Cmd), Storage)) + if (auto Error = index(std::move(Cmd))) elog("Indexing {0} failed: {1}", FileName, std::move(Error)); }); T.QueuePri = IndexFile; @@ -207,7 +225,7 @@ void BackgroundIndex::boostRelated(llvm::StringRef Path) { void BackgroundIndex::update( llvm::StringRef MainFile, IndexFileIn Index, const llvm::StringMap &ShardVersionsSnapshot, - BackgroundIndexStorage *IndexStorage, bool HadErrors) { + bool HadErrors) { // Partition symbols/references into files. struct File { llvm::DenseSet Symbols; @@ -291,22 +309,21 @@ void BackgroundIndex::update( // We need to store shards before updating the index, since the latter // consumes slabs. // FIXME: Also skip serializing the shard if it is already up-to-date. - if (IndexStorage) { - IndexFileOut Shard; - Shard.Symbols = SS.get(); - Shard.Refs = RS.get(); - Shard.Relations = RelS.get(); - Shard.Sources = IG.get(); - - // Only store command line hash for main files of the TU, since our - // current model keeps only one version of a header file. - if (Path == MainFile) - Shard.Cmd = Index.Cmd.getPointer(); - - if (auto Error = IndexStorage->storeShard(Path, Shard)) - elog("Failed to write background-index shard for file {0}: {1}", Path, - std::move(Error)); - } + BackgroundIndexStorage *IndexStorage = IndexStorageFactory(Path); + IndexFileOut Shard; + Shard.Symbols = SS.get(); + Shard.Refs = RS.get(); + Shard.Relations = RelS.get(); + Shard.Sources = IG.get(); + + // Only store command line hash for main files of the TU, since our + // current model keeps only one version of a header file. + if (Path == MainFile) + Shard.Cmd = Index.Cmd.getPointer(); + + if (auto Error = IndexStorage->storeShard(Path, Shard)) + elog("Failed to write background-index shard for file {0}: {1}", Path, + std::move(Error)); { std::lock_guard Lock(ShardVersionsMu); @@ -329,8 +346,7 @@ void BackgroundIndex::update( } } -llvm::Error BackgroundIndex::index(tooling::CompileCommand Cmd, - BackgroundIndexStorage *IndexStorage) { +llvm::Error BackgroundIndex::index(tooling::CompileCommand Cmd) { trace::Span Tracer("BackgroundIndex"); SPAN_ATTACH(Tracer, "file", Cmd.Filename); auto AbsolutePath = getAbsolutePath(Cmd); @@ -424,176 +440,78 @@ llvm::Error BackgroundIndex::index(tooling::CompileCommand Cmd, for (auto &It : *Index.Sources) It.second.Flags |= IncludeGraphNode::SourceFlag::HadErrors; } - update(AbsolutePath, std::move(Index), ShardVersionsSnapshot, IndexStorage, - HadErrors); + update(AbsolutePath, std::move(Index), ShardVersionsSnapshot, HadErrors); Rebuilder.indexedTU(); return llvm::Error::success(); } -std::vector -BackgroundIndex::loadShard(const tooling::CompileCommand &Cmd, - BackgroundIndexStorage *IndexStorage, - llvm::StringSet<> &LoadedShards) { - struct ShardInfo { - std::string AbsolutePath; - std::unique_ptr Shard; - FileDigest Digest = {}; - bool CountReferences = false; - bool HadErrors = false; - }; - std::vector IntermediateSymbols; - // Make sure we don't have duplicate elements in the queue. Keys are absolute - // paths. - llvm::StringSet<> InQueue; - auto FS = FSProvider.getFileSystem(); - // Dependencies of this TU, paired with the information about whether they - // need to be re-indexed or not. - std::vector Dependencies; - std::queue ToVisit; - std::string AbsolutePath = getAbsolutePath(Cmd).str(); - // Up until we load the shard related to a dependency it needs to be - // re-indexed. - ToVisit.emplace(AbsolutePath, true); - InQueue.insert(AbsolutePath); - // Goes over each dependency. - while (!ToVisit.empty()) { - Dependencies.push_back(std::move(ToVisit.front())); - // Dependencies is not modified during the rest of the loop, so it is safe - // to keep the reference. - auto &CurDependency = Dependencies.back(); - ToVisit.pop(); - // If we have already seen this shard before(either loaded or failed) don't - // re-try again. Since the information in the shard won't change from one TU - // to another. - if (!LoadedShards.try_emplace(CurDependency.Path).second) { - // If the dependency needs to be re-indexed, first occurence would already - // have detected that, so we don't need to issue it again. - CurDependency.NeedsReIndexing = false; - continue; - } +// Restores shards for \p MainFiles from index storage. Then checks staleness of +// those shards and returns a list of TUs that needs to be indexed to update +// staleness. +std::vector +BackgroundIndex::loadProject(std::vector MainFiles) { + std::vector NeedsReIndexing; - auto Shard = IndexStorage->loadShard(CurDependency.Path); - if (!Shard || !Shard->Sources) { - // File will be returned as requiring re-indexing to caller. - vlog("Failed to load shard: {0}", CurDependency.Path); - continue; - } - // These are the edges in the include graph for current dependency. - for (const auto &I : *Shard->Sources) { - auto U = URI::parse(I.getKey()); - if (!U) - continue; - auto AbsolutePath = URI::resolve(*U, CurDependency.Path); - if (!AbsolutePath) - continue; - // Add file as dependency if haven't seen before. - if (InQueue.try_emplace(*AbsolutePath).second) - ToVisit.emplace(*AbsolutePath, true); - // The node contains symbol information only for current file, the rest is - // just edges. - if (*AbsolutePath != CurDependency.Path) - continue; - - // We found source file info for current dependency. - assert(I.getValue().Digest != FileDigest{{0}} && "Digest is empty?"); - ShardInfo SI; - SI.AbsolutePath = CurDependency.Path; - SI.Shard = std::move(Shard); - SI.Digest = I.getValue().Digest; - SI.CountReferences = - I.getValue().Flags & IncludeGraphNode::SourceFlag::IsTU; - SI.HadErrors = - I.getValue().Flags & IncludeGraphNode::SourceFlag::HadErrors; - IntermediateSymbols.push_back(std::move(SI)); - // Check if the source needs re-indexing. - // Get the digest, skip it if file doesn't exist. - auto Buf = FS->getBufferForFile(CurDependency.Path); - if (!Buf) { - elog("Couldn't get buffer for file: {0}: {1}", CurDependency.Path, - Buf.getError().message()); - continue; - } - // If digests match then dependency doesn't need re-indexing. - // FIXME: Also check for dependencies(sources) of this shard and compile - // commands for cache invalidation. - CurDependency.NeedsReIndexing = - digest(Buf->get()->getBuffer()) != I.getValue().Digest; - } - } - // Load shard information into background-index. + Rebuilder.startLoading(); + // Load shards for all of the mainfiles. + const std::vector Result = + loadIndexShards(MainFiles, IndexStorageFactory, CDB); + size_t LoadedShards = 0; { + // Update in-memory state. std::lock_guard Lock(ShardVersionsMu); - // This can override a newer version that is added in another thread, - // if this thread sees the older version but finishes later. This - // should be rare in practice. - for (const ShardInfo &SI : IntermediateSymbols) { + for (auto &LS : Result) { + if (!LS.Shard) + continue; auto SS = - SI.Shard->Symbols - ? llvm::make_unique(std::move(*SI.Shard->Symbols)) + LS.Shard->Symbols + ? llvm::make_unique(std::move(*LS.Shard->Symbols)) : nullptr; - auto RS = SI.Shard->Refs - ? llvm::make_unique(std::move(*SI.Shard->Refs)) + auto RS = LS.Shard->Refs + ? llvm::make_unique(std::move(*LS.Shard->Refs)) : nullptr; auto RelS = - SI.Shard->Relations - ? llvm::make_unique(std::move(*SI.Shard->Relations)) + LS.Shard->Relations + ? llvm::make_unique(std::move(*LS.Shard->Relations)) : nullptr; - ShardVersion &SV = ShardVersions[SI.AbsolutePath]; - SV.Digest = SI.Digest; - SV.HadErrors = SI.HadErrors; + ShardVersion &SV = ShardVersions[LS.AbsolutePath]; + SV.Digest = LS.Digest; + SV.HadErrors = LS.HadErrors; + ++LoadedShards; - IndexedSymbols.update(SI.AbsolutePath, std::move(SS), std::move(RS), - std::move(RelS), SI.CountReferences); + IndexedSymbols.update(LS.AbsolutePath, std::move(SS), std::move(RS), + std::move(RelS), LS.CountReferences); } } - if (!IntermediateSymbols.empty()) - Rebuilder.loadedTU(); + Rebuilder.loadedShard(LoadedShards); + Rebuilder.doneLoading(); - return Dependencies; -} + auto FS = FSProvider.getFileSystem(); + llvm::DenseSet TUsToIndex; + // We'll accept data from stale shards, but ensure the files get reindexed + // soon. + for (auto &LS : Result) { + if (!shardIsStale(LS, FS.get())) + continue; + PathRef TUForFile = LS.DependentTU; + assert(!TUForFile.empty() && "File without a TU!"); + + // FIXME: Currently, we simply schedule indexing on a TU whenever any of + // its dependencies needs re-indexing. We might do it smarter by figuring + // out a minimal set of TUs that will cover all the stale dependencies. + // FIXME: Try looking at other TUs if no compile commands are available + // for this TU, i.e TU was deleted after we performed indexing. + TUsToIndex.insert(TUForFile); + } -// Goes over each changed file and loads them from index. Returns the list of -// TUs that had out-of-date/no shards. -std::vector> -BackgroundIndex::loadShards(std::vector ChangedFiles) { - std::vector> - NeedsReIndexing; - // Keeps track of the files that will be reindexed, to make sure we won't - // re-index same dependencies more than once. Keys are AbsolutePaths. - llvm::StringSet<> FilesToIndex; - // Keeps track of the loaded shards to make sure we don't perform redundant - // disk IO. Keys are absolute paths. - llvm::StringSet<> LoadedShards; - Rebuilder.startLoading(); - for (const auto &File : ChangedFiles) { - auto Cmd = CDB.getCompileCommand(File); + for (PathRef TU : TUsToIndex) { + auto Cmd = CDB.getCompileCommand(TU); if (!Cmd) continue; - - std::string ProjectRoot; - if (auto PI = CDB.getProjectInfo(File)) - ProjectRoot = std::move(PI->SourceRoot); - - BackgroundIndexStorage *IndexStorage = IndexStorageFactory(ProjectRoot); - auto Dependencies = loadShard(*Cmd, IndexStorage, LoadedShards); - for (const auto &Dependency : Dependencies) { - if (!Dependency.NeedsReIndexing || FilesToIndex.count(Dependency.Path)) - continue; - // FIXME: Currently, we simply schedule indexing on a TU whenever any of - // its dependencies needs re-indexing. We might do it smarter by figuring - // out a minimal set of TUs that will cover all the stale dependencies. - vlog("Enqueueing TU {0} because its dependency {1} needs re-indexing.", - Cmd->Filename, Dependency.Path); - NeedsReIndexing.push_back({std::move(*Cmd), IndexStorage}); - // Mark all of this TU's dependencies as to-be-indexed so that we won't - // try to re-index those. - for (const auto &Dependency : Dependencies) - FilesToIndex.insert(Dependency.Path); - break; - } + NeedsReIndexing.emplace_back(std::move(*Cmd)); } - Rebuilder.doneLoading(); + return NeedsReIndexing; } diff --git a/clang-tools-extra/clangd/index/Background.h b/clang-tools-extra/clangd/index/Background.h index 39fe8daeba8f..7ce9e7bf17be 100644 --- a/clang-tools-extra/clangd/index/Background.h +++ b/clang-tools-extra/clangd/index/Background.h @@ -12,6 +12,7 @@ #include "Context.h" #include "FSProvider.h" #include "GlobalCompilationDatabase.h" +#include "Path.h" #include "SourceCode.h" #include "Threading.h" #include "index/BackgroundRebuild.h" @@ -49,15 +50,17 @@ class BackgroundIndexStorage { virtual std::unique_ptr loadShard(llvm::StringRef ShardIdentifier) const = 0; - // The factory provides storage for each CDB. + // The factory provides storage for each File. // It keeps ownership of the storage instances, and should manage caching // itself. Factory must be threadsafe and never returns nullptr. - using Factory = - llvm::unique_function; + using Factory = llvm::unique_function; // Creates an Index Storage that saves shards into disk. Index storage uses - // CDBDirectory + ".clangd/index/" as the folder to save shards. - static Factory createDiskBackedStorageFactory(); + // CDBDirectory + ".clangd/index/" as the folder to save shards. CDBDirectory + // is the first directory containing a CDB in parent directories of a file, or + // user's home directory if none was found, e.g. standard library headers. + static Factory createDiskBackedStorageFactory( + std::function(PathRef)> GetProjectInfo); }; // A priority queue of tasks which can be run on (external) worker threads. @@ -157,15 +160,14 @@ class BackgroundIndex : public SwapIndex { /// information on IndexStorage. void update(llvm::StringRef MainFile, IndexFileIn Index, const llvm::StringMap &ShardVersionsSnapshot, - BackgroundIndexStorage *IndexStorage, bool HadErrors); + bool HadErrors); // configuration const FileSystemProvider &FSProvider; const GlobalCompilationDatabase &CDB; Context BackgroundContext; - llvm::Error index(tooling::CompileCommand, - BackgroundIndexStorage *IndexStorage); + llvm::Error index(tooling::CompileCommand); FileSymbols IndexedSymbols; BackgroundIndexRebuilder Rebuilder; @@ -173,25 +175,13 @@ class BackgroundIndex : public SwapIndex { std::mutex ShardVersionsMu; BackgroundIndexStorage::Factory IndexStorageFactory; - struct Source { - std::string Path; - bool NeedsReIndexing; - Source(llvm::StringRef Path, bool NeedsReIndexing) - : Path(Path), NeedsReIndexing(NeedsReIndexing) {} - }; - // Loads the shards for a single TU and all of its dependencies. Returns the - // list of sources and whether they need to be re-indexed. - std::vector loadShard(const tooling::CompileCommand &Cmd, - BackgroundIndexStorage *IndexStorage, - llvm::StringSet<> &LoadedShards); - // Tries to load shards for the ChangedFiles. - std::vector> - loadShards(std::vector ChangedFiles); + // Tries to load shards for the MainFiles and their dependencies. + std::vector + loadProject(std::vector MainFiles); BackgroundQueue::Task changedFilesTask(const std::vector &ChangedFiles); - BackgroundQueue::Task indexFileTask(tooling::CompileCommand Cmd, - BackgroundIndexStorage *Storage); + BackgroundQueue::Task indexFileTask(tooling::CompileCommand Cmd); // from lowest to highest priority enum QueuePriority { diff --git a/clang-tools-extra/clangd/index/BackgroundIndexLoader.cpp b/clang-tools-extra/clangd/index/BackgroundIndexLoader.cpp new file mode 100644 index 000000000000..585d36716d29 --- /dev/null +++ b/clang-tools-extra/clangd/index/BackgroundIndexLoader.cpp @@ -0,0 +1,143 @@ +//===-- BackgroundIndexLoader.cpp - ---------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "index/BackgroundIndexLoader.h" +#include "GlobalCompilationDatabase.h" +#include "Logger.h" +#include "Path.h" +#include "index/Background.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/Support/Path.h" +#include +#include +#include + +namespace clang { +namespace clangd { +namespace { + +llvm::Optional uriToAbsolutePath(llvm::StringRef URI, PathRef HintPath) { + auto U = URI::parse(URI); + if (!U) + return llvm::None; + auto AbsolutePath = URI::resolve(*U, HintPath); + if (!AbsolutePath) + return llvm::None; + return *AbsolutePath; +} + +/// A helper class to cache BackgroundIndexStorage operations and keep the +/// inverse dependency mapping. +class BackgroundIndexLoader { +public: + BackgroundIndexLoader(BackgroundIndexStorage::Factory &IndexStorageFactory) + : IndexStorageFactory(IndexStorageFactory) {} + /// Load the shards for \p MainFile and all of its dependencies. + void load(PathRef MainFile); + + /// Consumes the loader and returns all shards. + std::vector takeResult() &&; + +private: + /// Returns the Shard for \p StartSourceFile from cache or loads it from \p + /// Storage. Also returns paths for dependencies of \p StartSourceFile if it + /// wasn't cached yet. + std::pair> + loadShard(PathRef StartSourceFile, PathRef DependentTU); + + /// Cache for Storage lookups. + llvm::StringMap LoadedShards; + + BackgroundIndexStorage::Factory &IndexStorageFactory; +}; + +std::pair> +BackgroundIndexLoader::loadShard(PathRef StartSourceFile, PathRef DependentTU) { + auto It = LoadedShards.try_emplace(StartSourceFile); + LoadedShard &LS = It.first->getValue(); + std::vector Edges = {}; + // Return the cached shard. + if (!It.second) + return {LS, Edges}; + + LS.AbsolutePath = StartSourceFile.str(); + LS.DependentTU = DependentTU; + BackgroundIndexStorage *Storage = IndexStorageFactory(LS.AbsolutePath); + auto Shard = Storage->loadShard(StartSourceFile); + if (!Shard || !Shard->Sources) { + vlog("Failed to load shard: {0}", StartSourceFile); + return {LS, Edges}; + } + + LS.Shard = std::move(Shard); + for (const auto &It : *LS.Shard->Sources) { + auto AbsPath = uriToAbsolutePath(It.getKey(), StartSourceFile); + if (!AbsPath) + continue; + // A shard contains only edges for non main-file sources. + if (*AbsPath != StartSourceFile) { + Edges.push_back(*AbsPath); + continue; + } + + // Fill in shard metadata. + const IncludeGraphNode &IGN = It.getValue(); + LS.Digest = IGN.Digest; + LS.CountReferences = IGN.Flags & IncludeGraphNode::SourceFlag::IsTU; + LS.HadErrors = IGN.Flags & IncludeGraphNode::SourceFlag::HadErrors; + } + assert(LS.Digest != FileDigest{{0}} && "Digest is empty?"); + return {LS, Edges}; +} + +void BackgroundIndexLoader::load(PathRef MainFile) { + llvm::StringSet<> InQueue; + // Following containers points to strings inside InQueue. + std::queue ToVisit; + InQueue.insert(MainFile); + ToVisit.push(MainFile); + + while (!ToVisit.empty()) { + PathRef SourceFile = ToVisit.front(); + ToVisit.pop(); + + auto ShardAndEdges = loadShard(SourceFile, MainFile); + for (PathRef Edge : ShardAndEdges.second) { + auto It = InQueue.insert(Edge); + if (It.second) + ToVisit.push(It.first->getKey()); + } + } +} + +std::vector BackgroundIndexLoader::takeResult() && { + std::vector Result; + Result.reserve(LoadedShards.size()); + for (auto &It : LoadedShards) + Result.push_back(std::move(It.getValue())); + return Result; +} +} // namespace + +std::vector +loadIndexShards(llvm::ArrayRef MainFiles, + BackgroundIndexStorage::Factory &IndexStorageFactory, + const GlobalCompilationDatabase &CDB) { + BackgroundIndexLoader Loader(IndexStorageFactory); + for (llvm::StringRef MainFile : MainFiles) { + assert(llvm::sys::path::is_absolute(MainFile)); + Loader.load(MainFile); + } + return std::move(Loader).takeResult(); +} + +} // namespace clangd +} // namespace clang diff --git a/clang-tools-extra/clangd/index/BackgroundIndexLoader.h b/clang-tools-extra/clangd/index/BackgroundIndexLoader.h new file mode 100644 index 000000000000..0caf1b463525 --- /dev/null +++ b/clang-tools-extra/clangd/index/BackgroundIndexLoader.h @@ -0,0 +1,54 @@ +//===--- BackgroundIndexLoader.h - Load shards from index storage-*- C++-*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_BACKGROUND_INDEX_LOADER_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_BACKGROUND_INDEX_LOADER_H + +#include "Path.h" +#include "index/Background.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/VirtualFileSystem.h" +#include +#include + +namespace clang { +namespace clangd { + +/// Represents a shard loaded from storage, stores contents in \p Shard and +/// metadata about the source file that generated this shard. +struct LoadedShard { + /// Path of the source file that produced this shard. + Path AbsolutePath; + /// Digest of the source file contents that produced this shard. + FileDigest Digest = {}; + /// Whether the RefSlab in Shard should be used for updating symbol reference + /// counts when building an index. + bool CountReferences = false; + /// Whether the indexing action producing that shard had errors. + bool HadErrors = false; + /// Path to a TU that is depending on this shard. + Path DependentTU; + /// Will be nullptr when index storage couldn't provide a valid shard for + /// AbsolutePath. + std::unique_ptr Shard; +}; + +/// Loads all shards for the TU \p MainFile from \p Storage. +std::vector +loadIndexShards(llvm::ArrayRef MainFiles, + BackgroundIndexStorage::Factory &IndexStorageFactory, + const GlobalCompilationDatabase &CDB); + +} // namespace clangd +} // namespace clang + +#endif diff --git a/clang-tools-extra/clangd/index/BackgroundIndexStorage.cpp b/clang-tools-extra/clangd/index/BackgroundIndexStorage.cpp index 80246b9ceea2..8b2c411a1666 100644 --- a/clang-tools-extra/clangd/index/BackgroundIndexStorage.cpp +++ b/clang-tools-extra/clangd/index/BackgroundIndexStorage.cpp @@ -6,13 +6,21 @@ // //===----------------------------------------------------------------------===// +#include "GlobalCompilationDatabase.h" #include "Logger.h" +#include "Path.h" #include "index/Background.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/ScopeExit.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" #include "llvm/Support/Error.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" +#include namespace clang { namespace clangd { @@ -118,12 +126,21 @@ class NullStorage : public BackgroundIndexStorage { // Creates and owns IndexStorages for multiple CDBs. class DiskBackedIndexStorageManager { public: - DiskBackedIndexStorageManager() - : IndexStorageMapMu(llvm::make_unique()) {} + DiskBackedIndexStorageManager( + std::function(PathRef)> GetProjectInfo) + : IndexStorageMapMu(llvm::make_unique()), + GetProjectInfo(std::move(GetProjectInfo)) { + llvm::SmallString<128> HomeDir; + llvm::sys::path::home_directory(HomeDir); + this->HomeDir = HomeDir.str().str(); + } - // Creates or fetches to storage from cache for the specified CDB. - BackgroundIndexStorage *operator()(llvm::StringRef CDBDirectory) { + // Creates or fetches to storage from cache for the specified project. + BackgroundIndexStorage *operator()(PathRef File) { std::lock_guard Lock(*IndexStorageMapMu); + Path CDBDirectory = HomeDir; + if (auto PI = GetProjectInfo(File)) + CDBDirectory = PI->SourceRoot; auto &IndexStorage = IndexStorageMap[CDBDirectory]; if (!IndexStorage) IndexStorage = create(CDBDirectory); @@ -131,21 +148,28 @@ class DiskBackedIndexStorageManager { } private: - std::unique_ptr create(llvm::StringRef CDBDirectory) { - if (CDBDirectory.empty()) + std::unique_ptr create(PathRef CDBDirectory) { + if (CDBDirectory.empty()) { + elog("Tried to create storage for empty directory!"); return llvm::make_unique(); + } return llvm::make_unique(CDBDirectory); } + Path HomeDir; + llvm::StringMap> IndexStorageMap; std::unique_ptr IndexStorageMapMu; + + std::function(PathRef)> GetProjectInfo; }; } // namespace BackgroundIndexStorage::Factory -BackgroundIndexStorage::createDiskBackedStorageFactory() { - return DiskBackedIndexStorageManager(); +BackgroundIndexStorage::createDiskBackedStorageFactory( + std::function(PathRef)> GetProjectInfo) { + return DiskBackedIndexStorageManager(std::move(GetProjectInfo)); } } // namespace clangd diff --git a/clang-tools-extra/clangd/index/BackgroundRebuild.cpp b/clang-tools-extra/clangd/index/BackgroundRebuild.cpp index 4233e5c92a04..cb6ac0fc8bf7 100644 --- a/clang-tools-extra/clangd/index/BackgroundRebuild.cpp +++ b/clang-tools-extra/clangd/index/BackgroundRebuild.cpp @@ -78,13 +78,13 @@ void BackgroundIndexRebuilder::idle() { void BackgroundIndexRebuilder::startLoading() { std::lock_guard Lock(Mu); if (!Loading) - LoadedTUs = 0; + LoadedShards = 0; ++Loading; } -void BackgroundIndexRebuilder::loadedTU() { +void BackgroundIndexRebuilder::loadedShard(size_t ShardCount) { std::lock_guard Lock(Mu); assert(Loading); - ++LoadedTUs; + LoadedShards += ShardCount; } void BackgroundIndexRebuilder::doneLoading() { maybeRebuild("after loading index from disk", [this] { @@ -93,7 +93,7 @@ void BackgroundIndexRebuilder::doneLoading() { if (Loading) // was loading multiple batches concurrently return false; // rebuild once the last batch is done. // Rebuild if we loaded any shards, or if we stopped an indexedTU rebuild. - return LoadedTUs > 0 || enoughTUsToRebuild(); + return LoadedShards > 0 || enoughTUsToRebuild(); }); } diff --git a/clang-tools-extra/clangd/index/BackgroundRebuild.h b/clang-tools-extra/clangd/index/BackgroundRebuild.h index f660957f6241..d74c28be5cfb 100644 --- a/clang-tools-extra/clangd/index/BackgroundRebuild.h +++ b/clang-tools-extra/clangd/index/BackgroundRebuild.h @@ -17,6 +17,7 @@ #include "index/FileIndex.h" #include "index/Index.h" #include "llvm/Support/Threading.h" +#include namespace clang { namespace clangd { @@ -61,7 +62,7 @@ class BackgroundIndexRebuilder { // sessions may happen concurrently. void startLoading(); // Called to indicate some shards were actually loaded from disk. - void loadedTU(); + void loadedShard(size_t ShardCount); // Called to indicate we're finished loading shards from disk. // May rebuild (if any were loaded). void doneLoading(); @@ -89,7 +90,7 @@ class BackgroundIndexRebuilder { unsigned IndexedTUsAtLastRebuild = 0; // Are we loading shards? May be multiple concurrent sessions. unsigned Loading = 0; - unsigned LoadedTUs; // In the current loading session. + unsigned LoadedShards; // In the current loading session. SwapIndex *Target; FileSymbols *Source; diff --git a/clang-tools-extra/clangd/test/Inputs/background-index/definition.jsonrpc b/clang-tools-extra/clangd/test/Inputs/background-index/definition.jsonrpc index 933e7791320e..de99072b6a4c 100644 --- a/clang-tools-extra/clangd/test/Inputs/background-index/definition.jsonrpc +++ b/clang-tools-extra/clangd/test/Inputs/background-index/definition.jsonrpc @@ -18,7 +18,7 @@ "uri": "file://DIRECTORY/bar.cpp", "languageId": "cpp", "version": 1, - "text": "#include \"foo.h\"\nint main(){\nreturn foo();\n}" + "text": "#include \"sub_dir/foo.h\"\nint main(){\nreturn foo();\n}" } } } diff --git a/clang-tools-extra/clangd/test/Inputs/background-index/foo.cpp b/clang-tools-extra/clangd/test/Inputs/background-index/foo.cpp index c42ca4d07374..21fc589166a4 100644 --- a/clang-tools-extra/clangd/test/Inputs/background-index/foo.cpp +++ b/clang-tools-extra/clangd/test/Inputs/background-index/foo.cpp @@ -1,2 +1,2 @@ -#include "foo.h" +#include "sub_dir/foo.h" int foo() { return 42; } diff --git a/clang-tools-extra/clangd/test/Inputs/background-index/sub_dir/compile_flags.txt b/clang-tools-extra/clangd/test/Inputs/background-index/sub_dir/compile_flags.txt new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/clang-tools-extra/clangd/test/Inputs/background-index/foo.h b/clang-tools-extra/clangd/test/Inputs/background-index/sub_dir/foo.h similarity index 100% rename from clang-tools-extra/clangd/test/Inputs/background-index/foo.h rename to clang-tools-extra/clangd/test/Inputs/background-index/sub_dir/foo.h diff --git a/clang-tools-extra/clangd/test/background-index.test b/clang-tools-extra/clangd/test/background-index.test index eabca2bcaf76..57118f2159a6 100644 --- a/clang-tools-extra/clangd/test/background-index.test +++ b/clang-tools-extra/clangd/test/background-index.test @@ -5,7 +5,8 @@ # RUN: rm -rf %t # RUN: cp -r %S/Inputs/background-index %t # Need to embed the correct temp path in the actual JSON-RPC requests. -# RUN: sed -i -e "s|DIRECTORY|%t|" %t/* +# RUN: sed -i -e "s|DIRECTORY|%t|" %t/definition.jsonrpc +# RUN: sed -i -e "s|DIRECTORY|%t|" %t/compile_commands.json # We're editing bar.cpp, which includes foo.h. # foo() is declared in foo.h and defined in foo.cpp. @@ -14,6 +15,7 @@ # Test that the index is writing files in the expected location. # RUN: ls %t/.clangd/index/foo.cpp.*.idx +# RUN: ls %t/sub_dir/.clangd/index/foo.h.*.idx # Test the index is read from disk: delete code and restart clangd. # RUN: rm %t/foo.cpp diff --git a/clang-tools-extra/clangd/unittests/BackgroundIndexTests.cpp b/clang-tools-extra/clangd/unittests/BackgroundIndexTests.cpp index 79e081bd6789..0401aeb19231 100644 --- a/clang-tools-extra/clangd/unittests/BackgroundIndexTests.cpp +++ b/clang-tools-extra/clangd/unittests/BackgroundIndexTests.cpp @@ -211,7 +211,7 @@ TEST_F(BackgroundIndexTest, ShardStorageTest) { OverlayCDB CDB(/*Base=*/nullptr); BackgroundIndex Idx(Context::empty(), FS, CDB, [&](llvm::StringRef) { return &MSS; }); - CDB.setCompileCommand(testPath("root"), Cmd); + CDB.setCompileCommand(testPath("root/A.cc"), Cmd); ASSERT_TRUE(Idx.blockUntilIdleForTest()); } EXPECT_EQ(CacheHits, 2U); // Check both A.cc and A.h loaded from cache. @@ -335,7 +335,7 @@ TEST_F(BackgroundIndexTest, ShardStorageLoad) { OverlayCDB CDB(/*Base=*/nullptr); BackgroundIndex Idx(Context::empty(), FS, CDB, [&](llvm::StringRef) { return &MSS; }); - CDB.setCompileCommand(testPath("root"), Cmd); + CDB.setCompileCommand(testPath("root/A.cc"), Cmd); ASSERT_TRUE(Idx.blockUntilIdleForTest()); } EXPECT_EQ(CacheHits, 2U); // Check both A.cc and A.h loaded from cache. @@ -353,7 +353,7 @@ TEST_F(BackgroundIndexTest, ShardStorageLoad) { OverlayCDB CDB(/*Base=*/nullptr); BackgroundIndex Idx(Context::empty(), FS, CDB, [&](llvm::StringRef) { return &MSS; }); - CDB.setCompileCommand(testPath("root"), Cmd); + CDB.setCompileCommand(testPath("root/A.cc"), Cmd); ASSERT_TRUE(Idx.blockUntilIdleForTest()); } EXPECT_EQ(CacheHits, 2U); // Check both A.cc and A.h loaded from cache. @@ -621,8 +621,8 @@ TEST_F(BackgroundIndexRebuilderTest, IndexingTUs) { TEST_F(BackgroundIndexRebuilderTest, LoadingShards) { Rebuilder.startLoading(); - Rebuilder.loadedTU(); - Rebuilder.loadedTU(); + Rebuilder.loadedShard(10); + Rebuilder.loadedShard(20); EXPECT_TRUE(checkRebuild([&] { Rebuilder.doneLoading(); })); // No rebuild for no shards. @@ -631,11 +631,11 @@ TEST_F(BackgroundIndexRebuilderTest, LoadingShards) { // Loads can overlap. Rebuilder.startLoading(); - Rebuilder.loadedTU(); + Rebuilder.loadedShard(1); Rebuilder.startLoading(); - Rebuilder.loadedTU(); + Rebuilder.loadedShard(1); EXPECT_FALSE(checkRebuild([&] { Rebuilder.doneLoading(); })); - Rebuilder.loadedTU(); + Rebuilder.loadedShard(1); EXPECT_TRUE(checkRebuild([&] { Rebuilder.doneLoading(); })); // No rebuilding for indexed files while loading. diff --git a/clang-tools-extra/clangd/unittests/GlobalCompilationDatabaseTests.cpp b/clang-tools-extra/clangd/unittests/GlobalCompilationDatabaseTests.cpp index 3436e63e3032..d535532ada71 100644 --- a/clang-tools-extra/clangd/unittests/GlobalCompilationDatabaseTests.cpp +++ b/clang-tools-extra/clangd/unittests/GlobalCompilationDatabaseTests.cpp @@ -10,6 +10,7 @@ #include "Path.h" #include "TestFS.h" +#include "clang/Tooling/CompilationDatabase.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" @@ -31,6 +32,7 @@ using ::testing::AllOf; using ::testing::Contains; using ::testing::ElementsAre; using ::testing::EndsWith; +using ::testing::HasSubstr; using ::testing::IsEmpty; using ::testing::Not; using ::testing::StartsWith; @@ -247,9 +249,10 @@ TEST(GlobalCompilationDatabaseTest, DiscoveryWithNestedCDBs) { }); File = FS.Root; - llvm::sys::path::append(File, "a.cc"); + llvm::sys::path::append(File, "build", "..", "a.cc"); DB.getCompileCommand(File.str()); - EXPECT_THAT(DiscoveredFiles, UnorderedElementsAre(EndsWith("a.cc"))); + EXPECT_THAT(DiscoveredFiles, UnorderedElementsAre(AllOf( + EndsWith("a.cc"), Not(HasSubstr(".."))))); DiscoveredFiles.clear(); File = FS.Root; @@ -282,6 +285,27 @@ TEST(GlobalCompilationDatabaseTest, DiscoveryWithNestedCDBs) { } } +TEST(GlobalCompilationDatabaseTest, NonCanonicalFilenames) { + OverlayCDB DB(nullptr); + std::vector DiscoveredFiles; + auto Sub = + DB.watch([&DiscoveredFiles](const std::vector Changes) { + DiscoveredFiles = Changes; + }); + + llvm::SmallString<128> Root(testRoot()); + llvm::sys::path::append(Root, "build", "..", "a.cc"); + DB.setCompileCommand(Root.str(), tooling::CompileCommand()); + EXPECT_THAT(DiscoveredFiles, UnorderedElementsAre(testPath("a.cc"))); + DiscoveredFiles.clear(); + + llvm::SmallString<128> File(testRoot()); + llvm::sys::path::append(File, "blabla", "..", "a.cc"); + + EXPECT_TRUE(DB.getCompileCommand(File)); + EXPECT_TRUE(DB.getProjectInfo(File)); +} + } // namespace } // namespace clangd } // namespace clang From 19e5da4edc9665ba9119196f8b3b20cca53e4c24 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Mon, 22 Jul 2019 19:54:33 +0000 Subject: [PATCH 023/289] Merging r366570: ------------------------------------------------------------------------ r366570 | lkail | 2019-07-19 14:58:16 +0200 (Fri, 19 Jul 2019) | 9 lines [MachineCSE][MachinePRE] Avoid hoisting code from code regions into hot BBs. Summary: Current PRE hoists common computations into CMBB = DT->findNearestCommonDominator(MBB, MBB1). However, if CMBB is in a hot loop body, we might get performance degradation. Differential Revision: https://reviews.llvm.org/D64394 ------------------------------------------------------------------------ llvm-svn: 366729 --- llvm/lib/CodeGen/MachineCSE.cpp | 25 ++++++++ llvm/test/CodeGen/AArch64/O3-pipeline.ll | 2 +- llvm/test/CodeGen/ARM/O3-pipeline.ll | 2 +- llvm/test/CodeGen/PowerPC/machine-pre.ll | 82 ++++++++++++------------ llvm/test/CodeGen/X86/O3-pipeline.ll | 2 +- 5 files changed, 70 insertions(+), 43 deletions(-) diff --git a/llvm/lib/CodeGen/MachineCSE.cpp b/llvm/lib/CodeGen/MachineCSE.cpp index 2df6d40d9293..a5af5cb72df9 100644 --- a/llvm/lib/CodeGen/MachineCSE.cpp +++ b/llvm/lib/CodeGen/MachineCSE.cpp @@ -21,6 +21,7 @@ #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Analysis/CFG.h" #include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineBlockFrequencyInfo.h" #include "llvm/CodeGen/MachineDominators.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineFunctionPass.h" @@ -66,6 +67,7 @@ namespace { AliasAnalysis *AA; MachineDominatorTree *DT; MachineRegisterInfo *MRI; + MachineBlockFrequencyInfo *MBFI; public: static char ID; // Pass identification @@ -83,6 +85,8 @@ namespace { AU.addPreservedID(MachineLoopInfoID); AU.addRequired(); AU.addPreserved(); + AU.addRequired(); + AU.addPreserved(); } void releaseMemory() override { @@ -133,6 +137,11 @@ namespace { bool isPRECandidate(MachineInstr *MI); bool ProcessBlockPRE(MachineDominatorTree *MDT, MachineBasicBlock *MBB); bool PerformSimplePRE(MachineDominatorTree *DT); + /// Heuristics to see if it's beneficial to move common computations of MBB + /// and MBB1 to CandidateBB. + bool isBeneficalToHoistInto(MachineBasicBlock *CandidateBB, + MachineBasicBlock *MBB, + MachineBasicBlock *MBB1); }; } // end anonymous namespace @@ -802,6 +811,9 @@ bool MachineCSE::ProcessBlockPRE(MachineDominatorTree *DT, if (!CMBB->isLegalToHoistInto()) continue; + if (!isBeneficalToHoistInto(CMBB, MBB, MBB1)) + continue; + // Two instrs are partial redundant if their basic blocks are reachable // from one to another but one doesn't dominate another. if (CMBB != MBB1) { @@ -854,6 +866,18 @@ bool MachineCSE::PerformSimplePRE(MachineDominatorTree *DT) { return Changed; } +bool MachineCSE::isBeneficalToHoistInto(MachineBasicBlock *CandidateBB, + MachineBasicBlock *MBB, + MachineBasicBlock *MBB1) { + if (CandidateBB->getParent()->getFunction().hasMinSize()) + return true; + assert(DT->dominates(CandidateBB, MBB) && "CandidateBB should dominate MBB"); + assert(DT->dominates(CandidateBB, MBB1) && + "CandidateBB should dominate MBB1"); + return MBFI->getBlockFreq(CandidateBB) <= + MBFI->getBlockFreq(MBB) + MBFI->getBlockFreq(MBB1); +} + bool MachineCSE::runOnMachineFunction(MachineFunction &MF) { if (skipFunction(MF.getFunction())) return false; @@ -863,6 +887,7 @@ bool MachineCSE::runOnMachineFunction(MachineFunction &MF) { MRI = &MF.getRegInfo(); AA = &getAnalysis().getAAResults(); DT = &getAnalysis(); + MBFI = &getAnalysis(); LookAheadLimit = TII->getMachineCSELookAheadLimit(); bool ChangedPRE, ChangedCSE; ChangedPRE = PerformSimplePRE(DT); diff --git a/llvm/test/CodeGen/AArch64/O3-pipeline.ll b/llvm/test/CodeGen/AArch64/O3-pipeline.ll index a331ac87f8f4..4aabcf3c7982 100644 --- a/llvm/test/CodeGen/AArch64/O3-pipeline.ll +++ b/llvm/test/CodeGen/AArch64/O3-pipeline.ll @@ -98,9 +98,9 @@ ; CHECK-NEXT: MachineDominator Tree Construction ; CHECK-NEXT: Machine Natural Loop Construction ; CHECK-NEXT: Early Machine Loop Invariant Code Motion +; CHECK-NEXT: Machine Block Frequency Analysis ; CHECK-NEXT: Machine Common Subexpression Elimination ; CHECK-NEXT: MachinePostDominator Tree Construction -; CHECK-NEXT: Machine Block Frequency Analysis ; CHECK-NEXT: Machine code sinking ; CHECK-NEXT: Peephole Optimizations ; CHECK-NEXT: Remove dead machine instructions diff --git a/llvm/test/CodeGen/ARM/O3-pipeline.ll b/llvm/test/CodeGen/ARM/O3-pipeline.ll index f81f8ce51d18..ec96f055a056 100644 --- a/llvm/test/CodeGen/ARM/O3-pipeline.ll +++ b/llvm/test/CodeGen/ARM/O3-pipeline.ll @@ -72,9 +72,9 @@ ; CHECK-NEXT: MachineDominator Tree Construction ; CHECK-NEXT: Machine Natural Loop Construction ; CHECK-NEXT: Early Machine Loop Invariant Code Motion +; CHECK-NEXT: Machine Block Frequency Analysis ; CHECK-NEXT: Machine Common Subexpression Elimination ; CHECK-NEXT: MachinePostDominator Tree Construction -; CHECK-NEXT: Machine Block Frequency Analysis ; CHECK-NEXT: Machine code sinking ; CHECK-NEXT: Peephole Optimizations ; CHECK-NEXT: Remove dead machine instructions diff --git a/llvm/test/CodeGen/PowerPC/machine-pre.ll b/llvm/test/CodeGen/PowerPC/machine-pre.ll index 39dd3c53bf7a..596c0a4624c4 100644 --- a/llvm/test/CodeGen/PowerPC/machine-pre.ll +++ b/llvm/test/CodeGen/PowerPC/machine-pre.ll @@ -8,25 +8,25 @@ define i32 @t(i32 %n, i32 %delta, i32 %a) { ; CHECK-P9: # %bb.0: # %entry ; CHECK-P9-NEXT: lis r7, 0 ; CHECK-P9-NEXT: li r6, 0 +; CHECK-P9-NEXT: li r8, 0 ; CHECK-P9-NEXT: li r9, 0 -; CHECK-P9-NEXT: li r10, 0 ; CHECK-P9-NEXT: ori r7, r7, 65535 ; CHECK-P9-NEXT: .p2align 5 ; CHECK-P9-NEXT: .LBB0_1: # %header ; CHECK-P9-NEXT: # -; CHECK-P9-NEXT: addi r10, r10, 1 -; CHECK-P9-NEXT: cmpw r10, r3 -; CHECK-P9-NEXT: addi r8, r5, 1024 +; CHECK-P9-NEXT: addi r9, r9, 1 +; CHECK-P9-NEXT: cmpw r9, r3 ; CHECK-P9-NEXT: blt cr0, .LBB0_4 ; CHECK-P9-NEXT: # %bb.2: # %cont ; CHECK-P9-NEXT: # -; CHECK-P9-NEXT: add r9, r9, r4 -; CHECK-P9-NEXT: cmpw r9, r7 +; CHECK-P9-NEXT: add r8, r8, r4 +; CHECK-P9-NEXT: cmpw r8, r7 ; CHECK-P9-NEXT: bgt cr0, .LBB0_1 ; CHECK-P9-NEXT: # %bb.3: # %cont.1 -; CHECK-P9-NEXT: mr r6, r8 +; CHECK-P9-NEXT: addi r6, r5, 1024 ; CHECK-P9-NEXT: .LBB0_4: # %return -; CHECK-P9-NEXT: mullw r3, r6, r8 +; CHECK-P9-NEXT: addi r3, r5, 1024 +; CHECK-P9-NEXT: mullw r3, r6, r3 ; CHECK-P9-NEXT: blr entry: br label %header @@ -75,16 +75,19 @@ define dso_local signext i32 @foo(i32 signext %x, i32 signext %y) local_unnamed_ ; CHECK-P9-NEXT: lis r3, 21845 ; CHECK-P9-NEXT: add r28, r30, r29 ; CHECK-P9-NEXT: ori r27, r3, 21846 -; CHECK-P9-NEXT: b .LBB1_3 +; CHECK-P9-NEXT: b .LBB1_4 ; CHECK-P9-NEXT: .p2align 4 ; CHECK-P9-NEXT: .LBB1_1: # %sw.bb3 ; CHECK-P9-NEXT: # -; CHECK-P9-NEXT: add r28, r3, r28 +; CHECK-P9-NEXT: mulli r3, r30, 23 ; CHECK-P9-NEXT: .LBB1_2: # %sw.epilog ; CHECK-P9-NEXT: # +; CHECK-P9-NEXT: add r28, r3, r28 +; CHECK-P9-NEXT: .LBB1_3: # %sw.epilog +; CHECK-P9-NEXT: # ; CHECK-P9-NEXT: cmpwi r28, 1025 -; CHECK-P9-NEXT: bge cr0, .LBB1_6 -; CHECK-P9-NEXT: .LBB1_3: # %while.cond +; CHECK-P9-NEXT: bge cr0, .LBB1_7 +; CHECK-P9-NEXT: .LBB1_4: # %while.cond ; CHECK-P9-NEXT: # ; CHECK-P9-NEXT: extsw r3, r29 ; CHECK-P9-NEXT: bl bar @@ -101,41 +104,40 @@ define dso_local signext i32 @foo(i32 signext %x, i32 signext %y) local_unnamed_ ; CHECK-P9-NEXT: add r4, r4, r5 ; CHECK-P9-NEXT: slwi r5, r4, 1 ; CHECK-P9-NEXT: add r4, r4, r5 -; CHECK-P9-NEXT: subf r5, r4, r3 -; CHECK-P9-NEXT: mulli r4, r29, 13 -; CHECK-P9-NEXT: mulli r3, r30, 23 -; CHECK-P9-NEXT: cmplwi r5, 1 +; CHECK-P9-NEXT: subf r3, r4, r3 +; CHECK-P9-NEXT: cmplwi r3, 1 ; CHECK-P9-NEXT: beq cr0, .LBB1_1 -; CHECK-P9-NEXT: # %bb.4: # %while.cond +; CHECK-P9-NEXT: # %bb.5: # %while.cond ; CHECK-P9-NEXT: # -; CHECK-P9-NEXT: cmplwi r5, 0 -; CHECK-P9-NEXT: bne cr0, .LBB1_2 -; CHECK-P9-NEXT: # %bb.5: # %sw.bb +; CHECK-P9-NEXT: cmplwi r3, 0 +; CHECK-P9-NEXT: bne cr0, .LBB1_3 +; CHECK-P9-NEXT: # %bb.6: # %sw.bb ; CHECK-P9-NEXT: # -; CHECK-P9-NEXT: add r28, r4, r28 -; CHECK-P9-NEXT: cmpwi r28, 1025 -; CHECK-P9-NEXT: blt cr0, .LBB1_3 -; CHECK-P9-NEXT: .LBB1_6: # %while.end -; CHECK-P9-NEXT: lis r5, -13108 -; CHECK-P9-NEXT: ori r5, r5, 52429 -; CHECK-P9-NEXT: mullw r5, r28, r5 -; CHECK-P9-NEXT: lis r6, 13107 -; CHECK-P9-NEXT: ori r6, r6, 13108 -; CHECK-P9-NEXT: cmplw r5, r6 -; CHECK-P9-NEXT: blt cr0, .LBB1_8 -; CHECK-P9-NEXT: # %bb.7: # %if.then8 -; CHECK-P9-NEXT: extsw r4, r4 -; CHECK-P9-NEXT: extsw r5, r28 +; CHECK-P9-NEXT: mulli r3, r29, 13 +; CHECK-P9-NEXT: b .LBB1_2 +; CHECK-P9-NEXT: .LBB1_7: # %while.end +; CHECK-P9-NEXT: lis r3, -13108 +; CHECK-P9-NEXT: ori r3, r3, 52429 +; CHECK-P9-NEXT: mullw r3, r28, r3 +; CHECK-P9-NEXT: lis r4, 13107 +; CHECK-P9-NEXT: ori r4, r4, 13108 +; CHECK-P9-NEXT: cmplw r3, r4 +; CHECK-P9-NEXT: blt cr0, .LBB1_9 +; CHECK-P9-NEXT: # %bb.8: # %if.then8 +; CHECK-P9-NEXT: mulli r3, r29, 13 +; CHECK-P9-NEXT: mulli r5, r30, 23 +; CHECK-P9-NEXT: extsw r4, r28 ; CHECK-P9-NEXT: extsw r3, r3 +; CHECK-P9-NEXT: extsw r5, r5 +; CHECK-P9-NEXT: sub r3, r4, r3 ; CHECK-P9-NEXT: sub r4, r5, r4 -; CHECK-P9-NEXT: sub r3, r3, r5 -; CHECK-P9-NEXT: rldicl r4, r4, 1, 63 ; CHECK-P9-NEXT: rldicl r3, r3, 1, 63 -; CHECK-P9-NEXT: or r3, r4, r3 -; CHECK-P9-NEXT: b .LBB1_9 -; CHECK-P9-NEXT: .LBB1_8: # %cleanup20 -; CHECK-P9-NEXT: li r3, 0 +; CHECK-P9-NEXT: rldicl r4, r4, 1, 63 +; CHECK-P9-NEXT: or r3, r3, r4 +; CHECK-P9-NEXT: b .LBB1_10 ; CHECK-P9-NEXT: .LBB1_9: # %cleanup20 +; CHECK-P9-NEXT: li r3, 0 +; CHECK-P9-NEXT: .LBB1_10: # %cleanup20 ; CHECK-P9-NEXT: addi r1, r1, 80 ; CHECK-P9-NEXT: ld r0, 16(r1) ; CHECK-P9-NEXT: mtlr r0 diff --git a/llvm/test/CodeGen/X86/O3-pipeline.ll b/llvm/test/CodeGen/X86/O3-pipeline.ll index 7364d950f458..48bc2992a7ed 100644 --- a/llvm/test/CodeGen/X86/O3-pipeline.ll +++ b/llvm/test/CodeGen/X86/O3-pipeline.ll @@ -84,9 +84,9 @@ ; CHECK-NEXT: MachineDominator Tree Construction ; CHECK-NEXT: Machine Natural Loop Construction ; CHECK-NEXT: Early Machine Loop Invariant Code Motion +; CHECK-NEXT: Machine Block Frequency Analysis ; CHECK-NEXT: Machine Common Subexpression Elimination ; CHECK-NEXT: MachinePostDominator Tree Construction -; CHECK-NEXT: Machine Block Frequency Analysis ; CHECK-NEXT: Machine code sinking ; CHECK-NEXT: Peephole Optimizations ; CHECK-NEXT: Remove dead machine instructions From 2493af8f1aecccf1963f4c6f6aafe97050d1feaa Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Mon, 22 Jul 2019 22:27:18 +0000 Subject: [PATCH 024/289] Merging r366445: ------------------------------------------------------------------------ r366445 | maskray | 2019-07-18 17:07:42 +0200 (Thu, 18 Jul 2019) | 3 lines [ELF][PPC] Delete ppc64-dynamic-relocations.s I forgot to delete it in r366424. ------------------------------------------------------------------------ llvm-svn: 366756 --- lld/test/ELF/ppc64-dynamic-relocations.s | 50 ------------------------ 1 file changed, 50 deletions(-) delete mode 100644 lld/test/ELF/ppc64-dynamic-relocations.s diff --git a/lld/test/ELF/ppc64-dynamic-relocations.s b/lld/test/ELF/ppc64-dynamic-relocations.s deleted file mode 100644 index 71a26137a779..000000000000 --- a/lld/test/ELF/ppc64-dynamic-relocations.s +++ /dev/null @@ -1,50 +0,0 @@ -// REQUIRES: ppc - -// RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o -// RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %p/Inputs/shared-ppc64.s -o %t2.o -// RUN: ld.lld -shared %t2.o -o %t2.so -// RUN: ld.lld %t.o %t2.so -o %t -// RUN: llvm-readobj --dyn-relocations %t | FileCheck %s -// RUN: llvm-objdump --section-headers %t | FileCheck --check-prefix=DIS %s -// RUN: llvm-readelf -dynamic-table %t | FileCheck --check-prefix=DT %s - -// RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o -// RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %p/Inputs/shared-ppc64.s -o %t2.o -// RUN: ld.lld -shared %t2.o -o %t2.so -// RUN: ld.lld %t.o %t2.so -o %t -// RUN: llvm-readobj --dyn-relocations %t | FileCheck %s -// RUN: llvm-objdump --section-headers %t | FileCheck --check-prefix=DIS %s -// RUN: llvm-readelf -dynamic-table %t | FileCheck --check-prefix=DT %s - - -// The dynamic relocation for foo should point to 16 bytes past the start of -// the .plt section. -// CHECK: Dynamic Relocations { -// CHECK-NEXT: 0x10030010 R_PPC64_JMP_SLOT foo 0x0 - -// There should be 2 reserved doublewords before the first entry. The dynamic -// linker will fill those in with the address of the resolver entry point and -// the dynamic object identifier. -// DIS: Idx Name Size VMA Type -// DIS: .plt 00000018 0000000010030000 BSS - -// DT_PLTGOT should point to the start of the .plt section. -// DT: 0x0000000000000003 (PLTGOT) 0x10030000 - - .text - .abiversion 2 - .globl _start - .p2align 4 - .type _start,@function -_start: -.Lfunc_begin0: -.Lfunc_gep0: - addis 2, 12, .TOC.-.Lfunc_gep0@ha - addi 2, 2, .TOC.-.Lfunc_gep0@l -.Lfunc_lep0: - .localentry _start, .Lfunc_lep0-.Lfunc_gep0 - bl foo - nop - li 0, 1 - sc - .size _start, .-.Lfunc_begin0 From 9e74d6cb90cfa045778df1c990c3f268a41ae95f Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Mon, 22 Jul 2019 22:30:21 +0000 Subject: [PATCH 025/289] Merging r366481: ------------------------------------------------------------------------ r366481 | teemperor | 2019-07-18 20:33:40 +0200 (Thu, 18 Jul 2019) | 4 lines Fix C++ modules build llvm-svn: 366344 missed an include that broke the LLVM_ENABLE_MODULES build. ------------------------------------------------------------------------ llvm-svn: 366757 --- llvm/include/llvm/ExecutionEngine/Orc/LambdaResolver.h | 1 + 1 file changed, 1 insertion(+) diff --git a/llvm/include/llvm/ExecutionEngine/Orc/LambdaResolver.h b/llvm/include/llvm/ExecutionEngine/Orc/LambdaResolver.h index 855e31b33549..84cbc53b73a5 100644 --- a/llvm/include/llvm/ExecutionEngine/Orc/LambdaResolver.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/LambdaResolver.h @@ -16,6 +16,7 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ExecutionEngine/JITSymbol.h" +#include "llvm/ExecutionEngine/OrcV1Deprecation.h" #include namespace llvm { From 72deb0476d4a1e531b648c8126d9b4bd8f454436 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Mon, 22 Jul 2019 22:33:29 +0000 Subject: [PATCH 026/289] Merging r366527: ------------------------------------------------------------------------ r366527 | abrachet | 2019-07-19 04:31:21 +0200 (Fri, 19 Jul 2019) | 13 lines [test] [llvm-objcopy] Fix broken test case Summary: The test case added in D62718 did not work unless the user was root because write bits were not set for the output file. This change uses only permissions with user write (0200) to ensure tests pass regardless of the users permissions. Reviewers: jhenderson, rupprecht, MaskRay, espindola, alexshap Reviewed By: MaskRay Subscribers: emaste, arichardson, jakehehrlich, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D64302 ------------------------------------------------------------------------ llvm-svn: 366758 --- .../tools/llvm-objcopy/ELF/respect-umask.test | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/llvm/test/tools/llvm-objcopy/ELF/respect-umask.test b/llvm/test/tools/llvm-objcopy/ELF/respect-umask.test index 03f97cdae9b9..f4d309905616 100644 --- a/llvm/test/tools/llvm-objcopy/ELF/respect-umask.test +++ b/llvm/test/tools/llvm-objcopy/ELF/respect-umask.test @@ -9,18 +9,25 @@ # RUN: touch %t # RUN: chmod 0755 %t # RUN: ls -l %t | cut -f 1 -d ' ' > %t.0755 -# RUN: chmod 0500 %t -# RUN: ls -l %t | cut -f 1 -d ' ' > %t.0500 -# RUN: chmod 0555 %t -# RUN: ls -l %t | cut -f 1 -d ' ' > %t.0555 +# RUN: chmod 0600 %t +# RUN: ls -l %t | cut -f 1 -d ' ' > %t.0600 +# RUN: chmod 0655 %t +# RUN: ls -l %t | cut -f 1 -d ' ' > %t.0655 -# RUN: rm -f %t; yaml2obj %s -o %t +# RUN: yaml2obj %s -o %t # RUN: umask 0022 # RUN: chmod 0777 %t -# RUN: rm -f %t1; llvm-objcopy %t %t1 -# RUN: ls -l %t1 | cut -f 1 -d ' ' > %t1.perms -# RUN: cmp %t1.perms %t.0755 +# RUN: llvm-objcopy %t %t1 +# RUN: ls -l %t1 | cut -f 1 -d ' ' | cmp - %t.0755 + +# RUN: umask 0177 +# RUN: llvm-objcopy %t %t2 +# RUN: ls -l %t2 | cut -f 1 -d ' ' | cmp - %t.0600 + +# RUN: umask 0122 +# RUN: llvm-objcopy %t %t3 +# RUN: ls -l %t3 | cut -f 1 -d ' ' | cmp - %t.0655 --- !ELF FileHeader: From a57a03795df93aab990430b38da3c75e03b3bb16 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Mon, 22 Jul 2019 23:37:34 +0000 Subject: [PATCH 027/289] Merging r366510: ------------------------------------------------------------------------ r366510 | efriedma | 2019-07-19 00:35:45 +0200 (Fri, 19 Jul 2019) | 6 lines Update polly test for SCEV change. r366419 adds nsw to more SCEV expressions, which allows polly to make more aggressive assumptions about the input expressions. ------------------------------------------------------------------------ llvm-svn: 366767 --- polly/test/DeLICM/reduction_looprotate_hoisted.ll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/polly/test/DeLICM/reduction_looprotate_hoisted.ll b/polly/test/DeLICM/reduction_looprotate_hoisted.ll index 47f449564508..3a96ff6138b9 100644 --- a/polly/test/DeLICM/reduction_looprotate_hoisted.ll +++ b/polly/test/DeLICM/reduction_looprotate_hoisted.ll @@ -70,7 +70,7 @@ return: ; CHECK-NEXT: Stmt_reduction_preheader ; CHECK-NEXT: MustWriteAccess := [Reduction Type: NONE] [Scalar: 1] ; CHECK-NEXT: [Start] -> { Stmt_reduction_preheader[i0] -> MemRef_phi__phi[] }; -; CHECK-NEXT: new: [Start] -> { Stmt_reduction_preheader[i0] -> MemRef_A[i0] : Start >= 2147483648 or Start <= 2147483646 }; +; CHECK-NEXT: new: [Start] -> { Stmt_reduction_preheader[i0] -> MemRef_A[i0] }; ; CHECK-NEXT: Stmt_reduction_for ; CHECK-NEXT: ReadAccess := [Reduction Type: NONE] [Scalar: 1] ; CHECK-NEXT: [Start] -> { Stmt_reduction_for[i0, i1] -> MemRef_phi__phi[] }; From 70adacb13b2ce32173180059bcc14764b5f4e973 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Tue, 23 Jul 2019 14:58:27 +0000 Subject: [PATCH 028/289] Merging r366670 and r366694: ------------------------------------------------------------------------ r366670 | mantognini | 2019-07-22 11:39:13 +0200 (Mon, 22 Jul 2019) | 4 lines [OpenCL] Improve destructor support in C++ for OpenCL This re-applies r366422 with a fix for Bug PR42665 and a new regression test. ------------------------------------------------------------------------ ------------------------------------------------------------------------ r366694 | mantognini | 2019-07-22 16:47:36 +0200 (Mon, 22 Jul 2019) | 5 lines [NFC] Relaxed regression tests for PR42665 Following up on the buildbot failures, this commits relaxes some tests: instead of checking for specific IR output, it now ensures that the underlying issue (the crash), and only that, doesn't happen. ------------------------------------------------------------------------ llvm-svn: 366814 --- clang/include/clang/AST/DeclCXX.h | 14 ++++- clang/include/clang/AST/ExprCXX.h | 11 +++- clang/lib/AST/DeclCXX.cpp | 25 +++++++- clang/lib/AST/ExprCXX.cpp | 7 +++ clang/lib/CodeGen/CGCXXABI.h | 14 +++-- clang/lib/CodeGen/CGCall.cpp | 2 +- clang/lib/CodeGen/CGClass.cpp | 40 ++++++++----- clang/lib/CodeGen/CGDecl.cpp | 21 ++++--- clang/lib/CodeGen/CGExprCXX.cpp | 31 +++++++--- clang/lib/CodeGen/CodeGenFunction.h | 13 ++-- clang/lib/CodeGen/ItaniumCXXABI.cpp | 32 ++++++---- clang/lib/CodeGen/MicrosoftCXXABI.cpp | 30 ++++++---- clang/lib/Sema/SemaDeclCXX.cpp | 50 ++++++++-------- clang/lib/Sema/SemaOverload.cpp | 4 +- clang/test/CodeGenCXX/PR42665.cpp | 34 +++++++++++ clang/test/CodeGenOpenCLCXX/addrspace-ctor.cl | 14 ----- .../CodeGenOpenCLCXX/addrspace-with-class.cl | 59 +++++++++++++++++++ 17 files changed, 285 insertions(+), 116 deletions(-) create mode 100644 clang/test/CodeGenCXX/PR42665.cpp delete mode 100644 clang/test/CodeGenOpenCLCXX/addrspace-ctor.cl create mode 100644 clang/test/CodeGenOpenCLCXX/addrspace-with-class.cl diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index cbf4f1397eb1..7add83f89624 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -2232,20 +2232,20 @@ class CXXMethodDecl : public FunctionDecl { overridden_method_range overridden_methods() const; - /// Returns the parent of this method declaration, which + /// Return the parent of this method declaration, which /// is the class in which this method is defined. const CXXRecordDecl *getParent() const { return cast(FunctionDecl::getParent()); } - /// Returns the parent of this method declaration, which + /// Return the parent of this method declaration, which /// is the class in which this method is defined. CXXRecordDecl *getParent() { return const_cast( cast(FunctionDecl::getParent())); } - /// Returns the type of the \c this pointer. + /// Return the type of the \c this pointer. /// /// Should only be called for instance (i.e., non-static) methods. Note /// that for the call operator of a lambda closure type, this returns the @@ -2253,9 +2253,17 @@ class CXXMethodDecl : public FunctionDecl { /// 'this' type. QualType getThisType() const; + /// Return the type of the object pointed by \c this. + /// + /// See getThisType() for usage restriction. + QualType getThisObjectType() const; + static QualType getThisType(const FunctionProtoType *FPT, const CXXRecordDecl *Decl); + static QualType getThisObjectType(const FunctionProtoType *FPT, + const CXXRecordDecl *Decl); + Qualifiers getMethodQualifiers() const { return getType()->getAs()->getMethodQuals(); } diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h index 28ed6cdfde14..faddbc6d9675 100644 --- a/clang/include/clang/AST/ExprCXX.h +++ b/clang/include/clang/AST/ExprCXX.h @@ -185,15 +185,20 @@ class CXXMemberCallExpr final : public CallExpr { static CXXMemberCallExpr *CreateEmpty(const ASTContext &Ctx, unsigned NumArgs, EmptyShell Empty); - /// Retrieves the implicit object argument for the member call. + /// Retrieve the implicit object argument for the member call. /// /// For example, in "x.f(5)", this returns the sub-expression "x". Expr *getImplicitObjectArgument() const; - /// Retrieves the declaration of the called method. + /// Retrieve the type of the object argument. + /// + /// Note that this always returns a non-pointer type. + QualType getObjectType() const; + + /// Retrieve the declaration of the called method. CXXMethodDecl *getMethodDecl() const; - /// Retrieves the CXXRecordDecl for the underlying type of + /// Retrieve the CXXRecordDecl for the underlying type of /// the implicit object argument. /// /// Note that this is may not be the same declaration as that of the class diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index 857ac19e6b14..59710a55498f 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -2253,12 +2253,23 @@ CXXMethodDecl::overridden_methods() const { return getASTContext().overridden_methods(this); } +static QualType getThisObjectType(ASTContext &C, const FunctionProtoType *FPT, + const CXXRecordDecl *Decl) { + QualType ClassTy = C.getTypeDeclType(Decl); + return C.getQualifiedType(ClassTy, FPT->getMethodQuals()); +} + QualType CXXMethodDecl::getThisType(const FunctionProtoType *FPT, const CXXRecordDecl *Decl) { ASTContext &C = Decl->getASTContext(); - QualType ClassTy = C.getTypeDeclType(Decl); - ClassTy = C.getQualifiedType(ClassTy, FPT->getMethodQuals()); - return C.getPointerType(ClassTy); + QualType ObjectTy = ::getThisObjectType(C, FPT, Decl); + return C.getPointerType(ObjectTy); +} + +QualType CXXMethodDecl::getThisObjectType(const FunctionProtoType *FPT, + const CXXRecordDecl *Decl) { + ASTContext &C = Decl->getASTContext(); + return ::getThisObjectType(C, FPT, Decl); } QualType CXXMethodDecl::getThisType() const { @@ -2273,6 +2284,14 @@ QualType CXXMethodDecl::getThisType() const { getParent()); } +QualType CXXMethodDecl::getThisObjectType() const { + // Ditto getThisType. + assert(isInstance() && "No 'this' for static methods!"); + + return CXXMethodDecl::getThisObjectType(getType()->getAs(), + getParent()); +} + bool CXXMethodDecl::hasInlineBody() const { // If this function is a template instantiation, look at the template from // which it was instantiated. diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp index b30f785ba8f5..c5f86a4cc12b 100644 --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/lib/AST/ExprCXX.cpp @@ -651,6 +651,13 @@ Expr *CXXMemberCallExpr::getImplicitObjectArgument() const { return nullptr; } +QualType CXXMemberCallExpr::getObjectType() const { + QualType Ty = getImplicitObjectArgument()->getType(); + if (Ty->isPointerType()) + Ty = Ty->getPointeeType(); + return Ty; +} + CXXMethodDecl *CXXMemberCallExpr::getMethodDecl() const { if (const auto *MemExpr = dyn_cast(getCallee()->IgnoreParens())) return cast(MemExpr->getMemberDecl()); diff --git a/clang/lib/CodeGen/CGCXXABI.h b/clang/lib/CodeGen/CGCXXABI.h index 511bcd00d427..3a9c3b347439 100644 --- a/clang/lib/CodeGen/CGCXXABI.h +++ b/clang/lib/CodeGen/CGCXXABI.h @@ -378,7 +378,7 @@ class CGCXXABI { virtual void EmitDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *DD, CXXDtorType Type, bool ForVirtualBase, bool Delegating, - Address This) = 0; + Address This, QualType ThisTy) = 0; /// Emits the VTable definitions required for the given record type. virtual void emitVTableDefinitions(CodeGenVTables &CGVT, @@ -421,11 +421,15 @@ class CGCXXABI { llvm::Type *Ty, SourceLocation Loc) = 0; + using DeleteOrMemberCallExpr = + llvm::PointerUnion; + /// Emit the ABI-specific virtual destructor call. - virtual llvm::Value * - EmitVirtualDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *Dtor, - CXXDtorType DtorType, Address This, - const CXXMemberCallExpr *CE) = 0; + virtual llvm::Value *EmitVirtualDestructorCall(CodeGenFunction &CGF, + const CXXDestructorDecl *Dtor, + CXXDtorType DtorType, + Address This, + DeleteOrMemberCallExpr E) = 0; virtual void adjustCallArgsForDestructorThunk(CodeGenFunction &CGF, GlobalDecl GD, diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 5f1fb1007482..cf8024550eee 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -3502,7 +3502,7 @@ struct DestroyUnpassedArg final : EHScopeStack::Cleanup { const CXXDestructorDecl *Dtor = Ty->getAsCXXRecordDecl()->getDestructor(); assert(!Dtor->isTrivial()); CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete, /*for vbase*/ false, - /*Delegating=*/false, Addr); + /*Delegating=*/false, Addr, Ty); } else { CGF.callCStructDestructor(CGF.MakeAddrLValue(Addr, Ty)); } diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp index 9a9dd88810ed..c8bb63c5c4b1 100644 --- a/clang/lib/CodeGen/CGClass.cpp +++ b/clang/lib/CodeGen/CGClass.cpp @@ -491,12 +491,15 @@ namespace { cast(CGF.CurCodeDecl)->getParent(); const CXXDestructorDecl *D = BaseClass->getDestructor(); + // We are already inside a destructor, so presumably the object being + // destroyed should have the expected type. + QualType ThisTy = D->getThisObjectType(); Address Addr = CGF.GetAddressOfDirectBaseInCompleteClass(CGF.LoadCXXThisAddress(), DerivedClass, BaseClass, BaseIsVirtual); CGF.EmitCXXDestructorCall(D, Dtor_Base, BaseIsVirtual, - /*Delegating=*/false, Addr); + /*Delegating=*/false, Addr, ThisTy); } }; @@ -1440,9 +1443,11 @@ void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) { if (DtorType == Dtor_Deleting) { RunCleanupsScope DtorEpilogue(*this); EnterDtorCleanups(Dtor, Dtor_Deleting); - if (HaveInsertPoint()) + if (HaveInsertPoint()) { + QualType ThisTy = Dtor->getThisObjectType(); EmitCXXDestructorCall(Dtor, Dtor_Complete, /*ForVirtualBase=*/false, - /*Delegating=*/false, LoadCXXThisAddress()); + /*Delegating=*/false, LoadCXXThisAddress(), ThisTy); + } return; } @@ -1473,8 +1478,9 @@ void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) { EnterDtorCleanups(Dtor, Dtor_Complete); if (!isTryBody) { + QualType ThisTy = Dtor->getThisObjectType(); EmitCXXDestructorCall(Dtor, Dtor_Base, /*ForVirtualBase=*/false, - /*Delegating=*/false, LoadCXXThisAddress()); + /*Delegating=*/false, LoadCXXThisAddress(), ThisTy); break; } @@ -2013,7 +2019,7 @@ void CodeGenFunction::destroyCXXObject(CodeGenFunction &CGF, const CXXDestructorDecl *dtor = record->getDestructor(); assert(!dtor->isTrivial()); CGF.EmitCXXDestructorCall(dtor, Dtor_Complete, /*for vbase*/ false, - /*Delegating=*/false, addr); + /*Delegating=*/false, addr, type); } void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D, @@ -2363,8 +2369,11 @@ namespace { : Dtor(D), Addr(Addr), Type(Type) {} void Emit(CodeGenFunction &CGF, Flags flags) override { + // We are calling the destructor from within the constructor. + // Therefore, "this" should have the expected type. + QualType ThisTy = Dtor->getThisObjectType(); CGF.EmitCXXDestructorCall(Dtor, Type, /*ForVirtualBase=*/false, - /*Delegating=*/true, Addr); + /*Delegating=*/true, Addr, ThisTy); } }; } // end anonymous namespace @@ -2402,31 +2411,32 @@ CodeGenFunction::EmitDelegatingCXXConstructorCall(const CXXConstructorDecl *Ctor void CodeGenFunction::EmitCXXDestructorCall(const CXXDestructorDecl *DD, CXXDtorType Type, bool ForVirtualBase, - bool Delegating, - Address This) { + bool Delegating, Address This, + QualType ThisTy) { CGM.getCXXABI().EmitDestructorCall(*this, DD, Type, ForVirtualBase, - Delegating, This); + Delegating, This, ThisTy); } namespace { struct CallLocalDtor final : EHScopeStack::Cleanup { const CXXDestructorDecl *Dtor; Address Addr; + QualType Ty; - CallLocalDtor(const CXXDestructorDecl *D, Address Addr) - : Dtor(D), Addr(Addr) {} + CallLocalDtor(const CXXDestructorDecl *D, Address Addr, QualType Ty) + : Dtor(D), Addr(Addr), Ty(Ty) {} void Emit(CodeGenFunction &CGF, Flags flags) override { CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete, /*ForVirtualBase=*/false, - /*Delegating=*/false, Addr); + /*Delegating=*/false, Addr, Ty); } }; } // end anonymous namespace void CodeGenFunction::PushDestructorCleanup(const CXXDestructorDecl *D, - Address Addr) { - EHStack.pushCleanup(NormalAndEHCleanup, D, Addr); + QualType T, Address Addr) { + EHStack.pushCleanup(NormalAndEHCleanup, D, Addr, T); } void CodeGenFunction::PushDestructorCleanup(QualType T, Address Addr) { @@ -2436,7 +2446,7 @@ void CodeGenFunction::PushDestructorCleanup(QualType T, Address Addr) { const CXXDestructorDecl *D = ClassDecl->getDestructor(); assert(D && D->isUsed() && "destructor not marked as used!"); - PushDestructorCleanup(D, Addr); + PushDestructorCleanup(D, T, Addr); } void CodeGenFunction::InitializeVTablePointer(const VPtr &Vptr) { diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp index 19a9e75cc5ac..6ad43cefc4d2 100644 --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/lib/CodeGen/CGDecl.cpp @@ -480,11 +480,12 @@ namespace { template struct DestroyNRVOVariable : EHScopeStack::Cleanup { - DestroyNRVOVariable(Address addr, llvm::Value *NRVOFlag) - : NRVOFlag(NRVOFlag), Loc(addr) {} + DestroyNRVOVariable(Address addr, QualType type, llvm::Value *NRVOFlag) + : NRVOFlag(NRVOFlag), Loc(addr), Ty(type) {} llvm::Value *NRVOFlag; Address Loc; + QualType Ty; void Emit(CodeGenFunction &CGF, Flags flags) override { // Along the exceptions path we always execute the dtor. @@ -511,26 +512,24 @@ namespace { struct DestroyNRVOVariableCXX final : DestroyNRVOVariable { - DestroyNRVOVariableCXX(Address addr, const CXXDestructorDecl *Dtor, - llvm::Value *NRVOFlag) - : DestroyNRVOVariable(addr, NRVOFlag), - Dtor(Dtor) {} + DestroyNRVOVariableCXX(Address addr, QualType type, + const CXXDestructorDecl *Dtor, llvm::Value *NRVOFlag) + : DestroyNRVOVariable(addr, type, NRVOFlag), + Dtor(Dtor) {} const CXXDestructorDecl *Dtor; void emitDestructorCall(CodeGenFunction &CGF) { CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete, /*ForVirtualBase=*/false, - /*Delegating=*/false, Loc); + /*Delegating=*/false, Loc, Ty); } }; struct DestroyNRVOVariableC final : DestroyNRVOVariable { DestroyNRVOVariableC(Address addr, llvm::Value *NRVOFlag, QualType Ty) - : DestroyNRVOVariable(addr, NRVOFlag), Ty(Ty) {} - - QualType Ty; + : DestroyNRVOVariable(addr, Ty, NRVOFlag) {} void emitDestructorCall(CodeGenFunction &CGF) { CGF.destroyNonTrivialCStruct(CGF, Loc, Ty); @@ -1940,7 +1939,7 @@ void CodeGenFunction::emitAutoVarTypeCleanup( if (emission.NRVOFlag) { assert(!type->isArrayType()); CXXDestructorDecl *dtor = type->getAsCXXRecordDecl()->getDestructor(); - EHStack.pushCleanup(cleanupKind, addr, dtor, + EHStack.pushCleanup(cleanupKind, addr, type, dtor, emission.NRVOFlag); return; } diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp index 8ad229fc0c36..5476d13b7c46 100644 --- a/clang/lib/CodeGen/CGExprCXX.cpp +++ b/clang/lib/CodeGen/CGExprCXX.cpp @@ -10,12 +10,13 @@ // //===----------------------------------------------------------------------===// -#include "CodeGenFunction.h" #include "CGCUDARuntime.h" #include "CGCXXABI.h" #include "CGDebugInfo.h" #include "CGObjCRuntime.h" +#include "CodeGenFunction.h" #include "ConstantEmitter.h" +#include "TargetInfo.h" #include "clang/Basic/CodeGenOptions.h" #include "clang/CodeGen/CGFunctionInfo.h" #include "llvm/IR/Intrinsics.h" @@ -90,12 +91,26 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorCall( } RValue CodeGenFunction::EmitCXXDestructorCall( - GlobalDecl Dtor, const CGCallee &Callee, llvm::Value *This, + GlobalDecl Dtor, const CGCallee &Callee, llvm::Value *This, QualType ThisTy, llvm::Value *ImplicitParam, QualType ImplicitParamTy, const CallExpr *CE) { + const CXXMethodDecl *DtorDecl = cast(Dtor.getDecl()); + + assert(!ThisTy.isNull()); + assert(ThisTy->getAsCXXRecordDecl() == DtorDecl->getParent() && + "Pointer/Object mixup"); + + LangAS SrcAS = ThisTy.getAddressSpace(); + LangAS DstAS = DtorDecl->getMethodQualifiers().getAddressSpace(); + if (SrcAS != DstAS) { + QualType DstTy = DtorDecl->getThisType(); + llvm::Type *NewType = CGM.getTypes().ConvertType(DstTy); + This = getTargetHooks().performAddrSpaceCast(*this, This, SrcAS, DstAS, + NewType); + } + CallArgList Args; - commonEmitCXXMemberOrOperatorCall(*this, cast(Dtor.getDecl()), - This, ImplicitParam, ImplicitParamTy, CE, - Args, nullptr); + commonEmitCXXMemberOrOperatorCall(*this, DtorDecl, This, ImplicitParam, + ImplicitParamTy, CE, Args, nullptr); return EmitCall(CGM.getTypes().arrangeCXXStructorDeclaration(Dtor), Callee, ReturnValueSlot(), Args); } @@ -345,7 +360,9 @@ RValue CodeGenFunction::EmitCXXMemberOrOperatorMemberCallExpr( Callee = CGCallee::forDirect(CGM.GetAddrOfFunction(GD, Ty), GD); } - EmitCXXDestructorCall(GD, Callee, This.getPointer(), + QualType ThisTy = + IsArrow ? Base->getType()->getPointeeType() : Base->getType(); + EmitCXXDestructorCall(GD, Callee, This.getPointer(), ThisTy, /*ImplicitParam=*/nullptr, /*ImplicitParamTy=*/QualType(), nullptr); } @@ -1883,7 +1900,7 @@ static void EmitObjectDelete(CodeGenFunction &CGF, CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete, /*ForVirtualBase=*/false, /*Delegating=*/false, - Ptr); + Ptr, ElementType); else if (auto Lifetime = ElementType.getObjCLifetime()) { switch (Lifetime) { case Qualifiers::OCL_None: diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 06ef2dff7e9f..c3060d1fb351 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -675,7 +675,8 @@ class CodeGenFunction : public CodeGenTypeCache { /// PushDestructorCleanup - Push a cleanup to call the /// complete-object variant of the given destructor on the object at /// the given address. - void PushDestructorCleanup(const CXXDestructorDecl *Dtor, Address Addr); + void PushDestructorCleanup(const CXXDestructorDecl *Dtor, QualType T, + Address Addr); /// PopCleanupBlock - Will pop the cleanup entry on the stack and /// process all branch fixups. @@ -2554,8 +2555,8 @@ class CodeGenFunction : public CodeGenTypeCache { static Destroyer destroyCXXObject; void EmitCXXDestructorCall(const CXXDestructorDecl *D, CXXDtorType Type, - bool ForVirtualBase, bool Delegating, - Address This); + bool ForVirtualBase, bool Delegating, Address This, + QualType ThisTy); void EmitNewArrayInitializer(const CXXNewExpr *E, QualType elementType, llvm::Type *ElementTy, Address NewPtr, @@ -3677,9 +3678,9 @@ class CodeGenFunction : public CodeGenTypeCache { llvm::Value *ImplicitParam, QualType ImplicitParamTy, const CallExpr *E, CallArgList *RtlArgs); - RValue EmitCXXDestructorCall(GlobalDecl Dtor, - const CGCallee &Callee, - llvm::Value *This, llvm::Value *ImplicitParam, + RValue EmitCXXDestructorCall(GlobalDecl Dtor, const CGCallee &Callee, + llvm::Value *This, QualType ThisTy, + llvm::Value *ImplicitParam, QualType ImplicitParamTy, const CallExpr *E); RValue EmitCXXMemberCallExpr(const CXXMemberCallExpr *E, ReturnValueSlot ReturnValue); diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index 7367ff37cf45..51a2561a4552 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -224,7 +224,8 @@ class ItaniumCXXABI : public CodeGen::CGCXXABI { void EmitDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *DD, CXXDtorType Type, bool ForVirtualBase, - bool Delegating, Address This) override; + bool Delegating, Address This, + QualType ThisTy) override; void emitVTableDefinitions(CodeGenVTables &CGVT, const CXXRecordDecl *RD) override; @@ -261,9 +262,8 @@ class ItaniumCXXABI : public CodeGen::CGCXXABI { llvm::Value *EmitVirtualDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *Dtor, - CXXDtorType DtorType, - Address This, - const CXXMemberCallExpr *CE) override; + CXXDtorType DtorType, Address This, + DeleteOrMemberCallExpr E) override; void emitVirtualInheritanceTables(const CXXRecordDecl *RD) override; @@ -1128,7 +1128,7 @@ void ItaniumCXXABI::emitVirtualObjectDelete(CodeGenFunction &CGF, // FIXME: Provide a source location here even though there's no // CXXMemberCallExpr for dtor call. CXXDtorType DtorType = UseGlobalDelete ? Dtor_Complete : Dtor_Deleting; - EmitVirtualDestructorCall(CGF, Dtor, DtorType, Ptr, /*CE=*/nullptr); + EmitVirtualDestructorCall(CGF, Dtor, DtorType, Ptr, DE); if (UseGlobalDelete) CGF.PopCleanupBlock(); @@ -1539,7 +1539,8 @@ CGCXXABI::AddedStructorArgs ItaniumCXXABI::addImplicitConstructorArgs( void ItaniumCXXABI::EmitDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *DD, CXXDtorType Type, bool ForVirtualBase, - bool Delegating, Address This) { + bool Delegating, Address This, + QualType ThisTy) { GlobalDecl GD(DD, Type); llvm::Value *VTT = CGF.GetVTTParameter(GD, ForVirtualBase, Delegating); QualType VTTTy = getContext().getPointerType(getContext().VoidPtrTy); @@ -1551,7 +1552,8 @@ void ItaniumCXXABI::EmitDestructorCall(CodeGenFunction &CGF, else Callee = CGCallee::forDirect(CGM.getAddrOfCXXStructor(GD), GD); - CGF.EmitCXXDestructorCall(GD, Callee, This.getPointer(), VTT, VTTTy, nullptr); + CGF.EmitCXXDestructorCall(GD, Callee, This.getPointer(), ThisTy, VTT, VTTTy, + nullptr); } void ItaniumCXXABI::emitVTableDefinitions(CodeGenVTables &CGVT, @@ -1739,7 +1741,10 @@ CGCallee ItaniumCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF, llvm::Value *ItaniumCXXABI::EmitVirtualDestructorCall( CodeGenFunction &CGF, const CXXDestructorDecl *Dtor, CXXDtorType DtorType, - Address This, const CXXMemberCallExpr *CE) { + Address This, DeleteOrMemberCallExpr E) { + auto *CE = E.dyn_cast(); + auto *D = E.dyn_cast(); + assert((CE != nullptr) ^ (D != nullptr)); assert(CE == nullptr || CE->arg_begin() == CE->arg_end()); assert(DtorType == Dtor_Deleting || DtorType == Dtor_Complete); @@ -1749,8 +1754,15 @@ llvm::Value *ItaniumCXXABI::EmitVirtualDestructorCall( llvm::FunctionType *Ty = CGF.CGM.getTypes().GetFunctionType(*FInfo); CGCallee Callee = CGCallee::forVirtual(CE, GD, This, Ty); - CGF.EmitCXXDestructorCall(GD, Callee, This.getPointer(), nullptr, QualType(), - nullptr); + QualType ThisTy; + if (CE) { + ThisTy = CE->getObjectType(); + } else { + ThisTy = D->getDestroyedType(); + } + + CGF.EmitCXXDestructorCall(GD, Callee, This.getPointer(), ThisTy, nullptr, + QualType(), nullptr); return nullptr; } diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp index a91a949d024f..ca06ad3f042b 100644 --- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp @@ -258,7 +258,8 @@ class MicrosoftCXXABI : public CGCXXABI { void EmitDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *DD, CXXDtorType Type, bool ForVirtualBase, - bool Delegating, Address This) override; + bool Delegating, Address This, + QualType ThisTy) override; void emitVTableTypeMetadata(const VPtrInfo &Info, const CXXRecordDecl *RD, llvm::GlobalVariable *VTable); @@ -296,9 +297,8 @@ class MicrosoftCXXABI : public CGCXXABI { llvm::Value *EmitVirtualDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *Dtor, - CXXDtorType DtorType, - Address This, - const CXXMemberCallExpr *CE) override; + CXXDtorType DtorType, Address This, + DeleteOrMemberCallExpr E) override; void adjustCallArgsForDestructorThunk(CodeGenFunction &CGF, GlobalDecl GD, CallArgList &CallArgs) override { @@ -844,8 +844,7 @@ void MicrosoftCXXABI::emitVirtualObjectDelete(CodeGenFunction &CGF, // CXXMemberCallExpr for dtor call. bool UseGlobalDelete = DE->isGlobalDelete(); CXXDtorType DtorType = UseGlobalDelete ? Dtor_Complete : Dtor_Deleting; - llvm::Value *MDThis = - EmitVirtualDestructorCall(CGF, Dtor, DtorType, Ptr, /*CE=*/nullptr); + llvm::Value *MDThis = EmitVirtualDestructorCall(CGF, Dtor, DtorType, Ptr, DE); if (UseGlobalDelete) CGF.EmitDeleteCall(DE->getOperatorDelete(), MDThis, ElementType); } @@ -1569,7 +1568,8 @@ CGCXXABI::AddedStructorArgs MicrosoftCXXABI::addImplicitConstructorArgs( void MicrosoftCXXABI::EmitDestructorCall(CodeGenFunction &CGF, const CXXDestructorDecl *DD, CXXDtorType Type, bool ForVirtualBase, - bool Delegating, Address This) { + bool Delegating, Address This, + QualType ThisTy) { // Use the base destructor variant in place of the complete destructor variant // if the class has no virtual bases. This effectively implements some of the // -mconstructor-aliases optimization, but as part of the MS C++ ABI. @@ -1591,7 +1591,7 @@ void MicrosoftCXXABI::EmitDestructorCall(CodeGenFunction &CGF, BaseDtorEndBB = EmitDtorCompleteObjectHandler(CGF); } - CGF.EmitCXXDestructorCall(GD, Callee, This.getPointer(), + CGF.EmitCXXDestructorCall(GD, Callee, This.getPointer(), ThisTy, /*ImplicitParam=*/nullptr, /*ImplicitParamTy=*/QualType(), nullptr); if (BaseDtorEndBB) { @@ -1900,7 +1900,10 @@ CGCallee MicrosoftCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF, llvm::Value *MicrosoftCXXABI::EmitVirtualDestructorCall( CodeGenFunction &CGF, const CXXDestructorDecl *Dtor, CXXDtorType DtorType, - Address This, const CXXMemberCallExpr *CE) { + Address This, DeleteOrMemberCallExpr E) { + auto *CE = E.dyn_cast(); + auto *D = E.dyn_cast(); + assert((CE != nullptr) ^ (D != nullptr)); assert(CE == nullptr || CE->arg_begin() == CE->arg_end()); assert(DtorType == Dtor_Deleting || DtorType == Dtor_Complete); @@ -1917,8 +1920,15 @@ llvm::Value *MicrosoftCXXABI::EmitVirtualDestructorCall( llvm::IntegerType::getInt32Ty(CGF.getLLVMContext()), DtorType == Dtor_Deleting); + QualType ThisTy; + if (CE) { + ThisTy = CE->getObjectType(); + } else { + ThisTy = D->getDestroyedType(); + } + This = adjustThisArgumentForVirtualFunctionCall(CGF, GD, This, true); - RValue RV = CGF.EmitCXXDestructorCall(GD, Callee, This.getPointer(), + RValue RV = CGF.EmitCXXDestructorCall(GD, Callee, This.getPointer(), ThisTy, ImplicitParam, Context.IntTy, CE); return RV.getScalarVal(); } diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index dd77fc55721f..9a6385f28319 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -8190,6 +8190,27 @@ void Sema::ActOnFinishDelayedCXXMethodDeclaration(Scope *S, Decl *MethodD) { CheckCXXDefaultArguments(Method); } +// Emit the given diagnostic for each non-address-space qualifier. +// Common part of CheckConstructorDeclarator and CheckDestructorDeclarator. +static void checkMethodTypeQualifiers(Sema &S, Declarator &D, unsigned DiagID) { + const DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo(); + if (FTI.hasMethodTypeQualifiers() && !D.isInvalidType()) { + bool DiagOccured = false; + FTI.MethodQualifiers->forEachQualifier( + [DiagID, &S, &DiagOccured](DeclSpec::TQ, StringRef QualName, + SourceLocation SL) { + // This diagnostic should be emitted on any qualifier except an addr + // space qualifier. However, forEachQualifier currently doesn't visit + // addr space qualifiers, so there's no way to write this condition + // right now; we just diagnose on everything. + S.Diag(SL, DiagID) << QualName << SourceRange(SL); + DiagOccured = true; + }); + if (DiagOccured) + D.setInvalidType(); + } +} + /// CheckConstructorDeclarator - Called by ActOnDeclarator to check /// the well-formedness of the constructor declarator @p D with type @p /// R. If there are any errors in the declarator, this routine will @@ -8230,25 +8251,11 @@ QualType Sema::CheckConstructorDeclarator(Declarator &D, QualType R, D.setInvalidType(); } - DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo(); - if (FTI.hasMethodTypeQualifiers()) { - bool DiagOccured = false; - FTI.MethodQualifiers->forEachQualifier( - [&](DeclSpec::TQ TypeQual, StringRef QualName, SourceLocation SL) { - // This diagnostic should be emitted on any qualifier except an addr - // space qualifier. However, forEachQualifier currently doesn't visit - // addr space qualifiers, so there's no way to write this condition - // right now; we just diagnose on everything. - Diag(SL, diag::err_invalid_qualified_constructor) - << QualName << SourceRange(SL); - DiagOccured = true; - }); - if (DiagOccured) - D.setInvalidType(); - } + checkMethodTypeQualifiers(*this, D, diag::err_invalid_qualified_constructor); // C++0x [class.ctor]p4: // A constructor shall not be declared with a ref-qualifier. + DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo(); if (FTI.hasRefQualifier()) { Diag(FTI.getRefQualifierLoc(), diag::err_ref_qualifier_constructor) << FTI.RefQualifierIsLValueRef @@ -8423,18 +8430,11 @@ QualType Sema::CheckDestructorDeclarator(Declarator &D, QualType R, } } - DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo(); - if (FTI.hasMethodTypeQualifiers() && !D.isInvalidType()) { - FTI.MethodQualifiers->forEachQualifier( - [&](DeclSpec::TQ TypeQual, StringRef QualName, SourceLocation SL) { - Diag(SL, diag::err_invalid_qualified_destructor) - << QualName << SourceRange(SL); - }); - D.setInvalidType(); - } + checkMethodTypeQualifiers(*this, D, diag::err_invalid_qualified_destructor); // C++0x [class.dtor]p2: // A destructor shall not be declared with a ref-qualifier. + DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo(); if (FTI.hasRefQualifier()) { Diag(FTI.getRefQualifierLoc(), diag::err_ref_qualifier_destructor) << FTI.RefQualifierIsLValueRef diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index d8c4ea48ebce..f632a4d3bd1a 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -5093,12 +5093,10 @@ TryObjectArgumentInitialization(Sema &S, SourceLocation Loc, QualType FromType, QualType ClassType = S.Context.getTypeDeclType(ActingContext); // [class.dtor]p2: A destructor can be invoked for a const, volatile or // const volatile object. - Qualifiers Quals; + Qualifiers Quals = Method->getMethodQualifiers(); if (isa(Method)) { Quals.addConst(); Quals.addVolatile(); - } else { - Quals = Method->getMethodQualifiers(); } QualType ImplicitParamType = S.Context.getQualifiedType(ClassType, Quals); diff --git a/clang/test/CodeGenCXX/PR42665.cpp b/clang/test/CodeGenCXX/PR42665.cpp new file mode 100644 index 000000000000..99e180171a3e --- /dev/null +++ b/clang/test/CodeGenCXX/PR42665.cpp @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -std=c++17 -O0 %s -emit-llvm -o /dev/null -verify -triple %itanium_abi_triple +// RUN: %clang_cc1 -std=c++17 -O0 %s -emit-llvm -o /dev/null -verify -triple %ms_abi_triple + +// Minimal reproducer for PR42665. +// expected-no-diagnostics + +struct Foo { + Foo() = default; + virtual ~Foo() = default; +}; + +template +struct Pair { + Foo first; + Deleter second; +}; + +template +Pair(Foo, Deleter) -> Pair; + +template +void deleter(T& t) { t.~T(); } + +auto make_pair() { + return Pair{ Foo(), deleter }; +} + +void foobar() { + auto p = make_pair(); + auto& f = p.first; + auto& d = p.second; + d(f); // Invoke virtual destructor of Foo through d. +} // p's destructor is invoked. + diff --git a/clang/test/CodeGenOpenCLCXX/addrspace-ctor.cl b/clang/test/CodeGenOpenCLCXX/addrspace-ctor.cl deleted file mode 100644 index 42c2e6e9077a..000000000000 --- a/clang/test/CodeGenOpenCLCXX/addrspace-ctor.cl +++ /dev/null @@ -1,14 +0,0 @@ -// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=c++ -emit-llvm -O0 -o - | FileCheck %s - -struct MyType { - MyType(int i) : i(i) {} - MyType(int i) __constant : i(i) {} - int i; -}; - -//CHECK: call void @_ZNU3AS26MyTypeC1Ei(%struct.MyType addrspace(2)* @const1, i32 1) -__constant MyType const1 = 1; -//CHECK: call void @_ZNU3AS26MyTypeC1Ei(%struct.MyType addrspace(2)* @const2, i32 2) -__constant MyType const2(2); -//CHECK: call void @_ZNU3AS46MyTypeC1Ei(%struct.MyType addrspace(4)* addrspacecast (%struct.MyType addrspace(1)* @glob to %struct.MyType addrspace(4)*), i32 1) -MyType glob(1); diff --git a/clang/test/CodeGenOpenCLCXX/addrspace-with-class.cl b/clang/test/CodeGenOpenCLCXX/addrspace-with-class.cl new file mode 100644 index 000000000000..21ba1ca251d8 --- /dev/null +++ b/clang/test/CodeGenOpenCLCXX/addrspace-with-class.cl @@ -0,0 +1,59 @@ +// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=c++ -emit-llvm -O0 -o - | FileCheck %s +// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=c++ -emit-llvm -O0 -o - | FileCheck %s --check-prefix=CHECK-DEFINITIONS + +// This test ensures the proper address spaces and address space cast are used +// for constructors, member functions and destructors. +// See also atexit.cl and global_init.cl for other specific tests. + +// CHECK: %struct.MyType = type { i32 } +struct MyType { + MyType(int i) : i(i) {} + MyType(int i) __constant : i(i) {} + ~MyType() {} + ~MyType() __constant {} + int bar() { return i + 2; } + int bar() __constant { return i + 1; } + int i; +}; + +// CHECK: @const1 = addrspace(2) global %struct.MyType zeroinitializer +__constant MyType const1 = 1; +// CHECK: @const2 = addrspace(2) global %struct.MyType zeroinitializer +__constant MyType const2(2); +// CHECK: @glob = addrspace(1) global %struct.MyType zeroinitializer +MyType glob(1); + +// CHECK: call void @_ZNU3AS26MyTypeC1Ei(%struct.MyType addrspace(2)* @const1, i32 1) +// CHECK: call void @_ZNU3AS26MyTypeC1Ei(%struct.MyType addrspace(2)* @const2, i32 2) +// CHECK: call void @_ZNU3AS46MyTypeC1Ei(%struct.MyType addrspace(4)* addrspacecast (%struct.MyType addrspace(1)* @glob to %struct.MyType addrspace(4)*), i32 1) + +// CHECK-LABEL: define spir_kernel void @fooGlobal() +kernel void fooGlobal() { + // CHECK: call i32 @_ZNU3AS46MyType3barEv(%struct.MyType addrspace(4)* addrspacecast (%struct.MyType addrspace(1)* @glob to %struct.MyType addrspace(4)*)) + glob.bar(); + // CHECK: call i32 @_ZNU3AS26MyType3barEv(%struct.MyType addrspace(2)* @const1) + const1.bar(); + // CHECK: call void @_ZNU3AS26MyTypeD1Ev(%struct.MyType addrspace(2)* @const1) + const1.~MyType(); +} + +// CHECK-LABEL: define spir_kernel void @fooLocal() +kernel void fooLocal() { + // CHECK: [[VAR:%.*]] = alloca %struct.MyType + // CHECK: [[REG:%.*]] = addrspacecast %struct.MyType* [[VAR]] to %struct.MyType addrspace(4)* + // CHECK: call void @_ZNU3AS46MyTypeC1Ei(%struct.MyType addrspace(4)* [[REG]], i32 3) + MyType myLocal(3); + // CHECK: [[REG:%.*]] = addrspacecast %struct.MyType* [[VAR]] to %struct.MyType addrspace(4)* + // CHECK: call i32 @_ZNU3AS46MyType3barEv(%struct.MyType addrspace(4)* [[REG]]) + myLocal.bar(); + // CHECK: [[REG:%.*]] = addrspacecast %struct.MyType* [[VAR]] to %struct.MyType addrspace(4)* + // CHECK: call void @_ZNU3AS46MyTypeD1Ev(%struct.MyType addrspace(4)* [[REG]]) +} + +// Ensure all members are defined for all the required address spaces. +// CHECK-DEFINITIONS-DAG: define linkonce_odr void @_ZNU3AS26MyTypeC1Ei(%struct.MyType addrspace(2)* %this, i32 %i) +// CHECK-DEFINITIONS-DAG: define linkonce_odr void @_ZNU3AS46MyTypeC1Ei(%struct.MyType addrspace(4)* %this, i32 %i) +// CHECK-DEFINITIONS-DAG: define linkonce_odr void @_ZNU3AS26MyTypeD1Ev(%struct.MyType addrspace(2)* %this) +// CHECK-DEFINITIONS-DAG: define linkonce_odr void @_ZNU3AS46MyTypeD1Ev(%struct.MyType addrspace(4)* %this) +// CHECK-DEFINITIONS-DAG: define linkonce_odr i32 @_ZNU3AS26MyType3barEv(%struct.MyType addrspace(2)* %this) +// CHECK-DEFINITIONS-DAG: define linkonce_odr i32 @_ZNU3AS46MyType3barEv(%struct.MyType addrspace(4)* %this) From 1e6b12dd3158a554c63d332df6b25f407eed9556 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Tue, 23 Jul 2019 15:22:25 +0000 Subject: [PATCH 029/289] Merging r366780 and r366784: ------------------------------------------------------------------------ r366780 | mstorsjo | 2019-07-23 08:38:04 +0200 (Tue, 23 Jul 2019) | 21 lines [COFF] Unbreak sorting of mingw comdat .tls sections after SVN r363457 Code built for mingw with -fdata-sections will store each TLS variable in a comdat section, named .tls$$. Normal TLS variables are stored in sections named .tls$ with a trailing dollar, which are sorted after a starter marker (in a later linked object file) in a section named ".tls" (with no dollar suffix), before an ending marker in a section named ".tls$ZZZ". The mingw comdat section suffix stripping introduced in SVN r363457 broke sorting of such tls sections, ending up sorting the stripped .tls$$ sections (stripped to ".tls") before the start marker in the section named ".tls". We could add exceptions to the section name suffix stripping for .tls (and .CRT, where suffixes always should be honored), but the more conservative option is probably the reverse; to only apply the stripping for the normal sections where sorting shouldn't have any effect. Differential Revision: https://reviews.llvm.org/D65018 ------------------------------------------------------------------------ ------------------------------------------------------------------------ r366784 | mstorsjo | 2019-07-23 09:28:23 +0200 (Tue, 23 Jul 2019) | 4 lines [test] Fix the test from the previous commit when run on windows. NFC. Apparently the escaped dollar sign didn't work the same way in "echo -e" on windows buildbots. ------------------------------------------------------------------------ llvm-svn: 366816 --- lld/COFF/Writer.cpp | 27 +++++++++++++++++++++++---- lld/test/COFF/Inputs/tlssup.s | 10 ++++++++++ lld/test/COFF/tls_suffix_sorting.s | 27 +++++++++++++++++++++++++++ 3 files changed, 60 insertions(+), 4 deletions(-) create mode 100644 lld/test/COFF/Inputs/tlssup.s create mode 100644 lld/test/COFF/tls_suffix_sorting.s diff --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp index 36ef87de4263..3da8b98d3d22 100644 --- a/lld/COFF/Writer.cpp +++ b/lld/COFF/Writer.cpp @@ -762,6 +762,28 @@ void Writer::locateImportTables() { } } +// Return whether a SectionChunk's suffix (the dollar and any trailing +// suffix) should be removed and sorted into the main suffixless +// PartialSection. +static bool shouldStripSectionSuffix(SectionChunk *sc, StringRef name) { + // On MinGW, comdat groups are formed by putting the comdat group name + // after the '$' in the section name. For .eh_frame$, that must + // still be sorted before the .eh_frame trailer from crtend.o, thus just + // strip the section name trailer. For other sections, such as + // .tls$$ (where non-comdat .tls symbols are otherwise stored in + // ".tls$"), they must be strictly sorted after .tls. And for the + // hypothetical case of comdat .CRT$XCU, we definitely need to keep the + // suffix for sorting. Thus, to play it safe, only strip the suffix for + // the standard sections. + if (!config->mingw) + return false; + if (!sc || !sc->isCOMDAT()) + return false; + return name.startswith(".text$") || name.startswith(".data$") || + name.startswith(".rdata$") || name.startswith(".pdata$") || + name.startswith(".xdata$") || name.startswith(".eh_frame$"); +} + // Create output section objects and add them to OutputSections. void Writer::createSections() { // First, create the builtin sections. @@ -807,10 +829,7 @@ void Writer::createSections() { continue; } StringRef name = c->getSectionName(); - // On MinGW, comdat groups are formed by putting the comdat group name - // after the '$' in the section name. Such a section name suffix shouldn't - // imply separate alphabetical sorting of those section chunks though. - if (config->mingw && sc && sc->isCOMDAT()) + if (shouldStripSectionSuffix(sc, name)) name = name.split('$').first; PartialSection *pSec = createPartialSection(name, c->getOutputCharacteristics()); diff --git a/lld/test/COFF/Inputs/tlssup.s b/lld/test/COFF/Inputs/tlssup.s new file mode 100644 index 000000000000..ca61c9dda3e9 --- /dev/null +++ b/lld/test/COFF/Inputs/tlssup.s @@ -0,0 +1,10 @@ + .section .tls,"dw" + .byte 0xaa + + .section .tls$ZZZ,"dw" + .byte 0xff + + .globl _tls_index + .data +_tls_index: + .int 0 diff --git a/lld/test/COFF/tls_suffix_sorting.s b/lld/test/COFF/tls_suffix_sorting.s new file mode 100644 index 000000000000..d426ac1fe1cd --- /dev/null +++ b/lld/test/COFF/tls_suffix_sorting.s @@ -0,0 +1,27 @@ +# REQUIRES: x86 + +# RUN: llvm-mc -triple=x86_64-windows-gnu %S/Inputs/tlssup.s -filetype=obj -o %t.tlssup.o +# RUN: llvm-mc -triple=x86_64-windows-gnu %s -filetype=obj -o %t.main.o + +# RUN: lld-link -lldmingw -entry:main %t.main.o %t.tlssup.o -out:%t.exe +# RUN: llvm-objdump -s %t.exe | FileCheck %s + +# Check that .tls$$foo is sorted after the start marker (aa) and before the +# end marker (ff). + +# CHECK: Contents of section .tls: +# CHECK: 140004000 aabbff + + .text + .globl main +main: + movl _tls_index(%rip), %eax + movq %gs:88, %rcx + movq (%rcx,%rax,8), %rax + movb foo@SECREL32(%rax), %al + ret + + .section .tls$$foo,"dw" + .linkonce discard +foo: + .byte 0xbb From 1014eef04815718704829f811ec8e348530a67a4 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Wed, 24 Jul 2019 20:03:13 +0000 Subject: [PATCH 030/289] Merging r366925: ------------------------------------------------------------------------ r366925 | xbolva00 | 2019-07-24 19:01:20 +0200 (Wed, 24 Jul 2019) | 13 lines [InstCombine] Adjusted pow-exp tests for Windows [NFC] Summary: https://bugs.llvm.org/show_bug.cgi?id=42740 Reviewers: efriedma, hans Reviewed By: hans Subscribers: spatel, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D65220 ------------------------------------------------------------------------ llvm-svn: 366940 --- llvm/test/Transforms/InstCombine/pow-exp.ll | 18 +++++++++--------- llvm/test/Transforms/InstCombine/pow_fp_int.ll | 6 +++--- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/llvm/test/Transforms/InstCombine/pow-exp.ll b/llvm/test/Transforms/InstCombine/pow-exp.ll index d5ed51117812..f352c3a88138 100644 --- a/llvm/test/Transforms/InstCombine/pow-exp.ll +++ b/llvm/test/Transforms/InstCombine/pow-exp.ll @@ -212,7 +212,7 @@ declare void @use_f(float) define double @pow_ok_base(double %e) { ; CHECK-LABEL: @pow_ok_base( -; CHECK-NEXT: [[MUL:%.*]] = fmul nnan ninf afn double [[E:%.*]], 0xBFE0776228967D13 +; CHECK-NEXT: [[MUL:%.*]] = fmul nnan ninf afn double [[E:%.*]], 0xBFE0776{{.*}} ; CHECK-NEXT: [[EXP2:%.*]] = call nnan ninf afn double @exp2(double [[MUL]]) ; CHECK-NEXT: ret double [[EXP2]] ; @@ -222,7 +222,7 @@ define double @pow_ok_base(double %e) { define double @pow_ok_base_fast(double %e) { ; CHECK-LABEL: @pow_ok_base_fast( -; CHECK-NEXT: [[MUL:%.*]] = fmul fast double [[E:%.*]], 0xBFE0776228967D13 +; CHECK-NEXT: [[MUL:%.*]] = fmul fast double [[E:%.*]], 0xBFE0776{{.*}} ; CHECK-NEXT: [[EXP2:%.*]] = call fast double @exp2(double [[MUL]]) ; CHECK-NEXT: ret double [[EXP2]] ; @@ -232,7 +232,7 @@ define double @pow_ok_base_fast(double %e) { define double @pow_ok_base2(double %e) { ; CHECK-LABEL: @pow_ok_base2( -; CHECK-NEXT: [[MUL:%.*]] = fmul nnan ninf afn double [[E:%.*]], 0x4010952C788751AC +; CHECK-NEXT: [[MUL:%.*]] = fmul nnan ninf afn double [[E:%.*]], 0x4010952{{.*}} ; CHECK-NEXT: [[EXP2:%.*]] = call nnan ninf afn double @exp2(double [[MUL]]) ; CHECK-NEXT: ret double [[EXP2]] ; @@ -242,7 +242,7 @@ define double @pow_ok_base2(double %e) { define double @pow_ok_base3(double %e) { ; CHECK-LABEL: @pow_ok_base3( -; CHECK-NEXT: [[MUL:%.*]] = fmul nnan ninf afn double [[E:%.*]], 0x400AB0B5584886CD +; CHECK-NEXT: [[MUL:%.*]] = fmul nnan ninf afn double [[E:%.*]], 0x400AB0B5{{.*}} ; CHECK-NEXT: [[EXP2:%.*]] = call nnan ninf afn double @exp2(double [[MUL]]) ; CHECK-NEXT: ret double [[EXP2]] ; @@ -252,7 +252,7 @@ define double @pow_ok_base3(double %e) { define double @pow_ok_ten_base(double %e) { ; CHECK-LABEL: @pow_ok_ten_base( -; CHECK-NEXT: [[MUL:%.*]] = fmul nnan ninf afn double [[E:%.*]], 0x400A934F0979A371 +; CHECK-NEXT: [[MUL:%.*]] = fmul nnan ninf afn double [[E:%.*]], 0x400A934F{{.*}} ; CHECK-NEXT: [[EXP2:%.*]] = call nnan ninf afn double @exp2(double [[MUL]]) ; CHECK-NEXT: ret double [[EXP2]] ; @@ -262,7 +262,7 @@ define double @pow_ok_ten_base(double %e) { define float @powf_ok_base(float %e) { ; CHECK-LABEL: @powf_ok_base( -; CHECK-NEXT: [[MUL:%.*]] = fmul nnan ninf afn float [[E:%.*]], 0xBFE0776240000000 +; CHECK-NEXT: [[MUL:%.*]] = fmul nnan ninf afn float [[E:%.*]], 0xBFE07762{{.*}} ; CHECK-NEXT: [[EXP2F:%.*]] = call nnan ninf afn float @exp2f(float [[MUL]]) ; CHECK-NEXT: ret float [[EXP2F]] ; @@ -272,7 +272,7 @@ define float @powf_ok_base(float %e) { define float @powf_ok_base2(float %e) { ; CHECK-LABEL: @powf_ok_base2( -; CHECK-NEXT: [[MUL:%.*]] = fmul nnan ninf afn float [[E:%.*]], 0x4010952C80000000 +; CHECK-NEXT: [[MUL:%.*]] = fmul nnan ninf afn float [[E:%.*]], 0x4010952{{.*}} ; CHECK-NEXT: [[EXP2F:%.*]] = call nnan ninf afn float @exp2f(float [[MUL]]) ; CHECK-NEXT: ret float [[EXP2F]] ; @@ -282,7 +282,7 @@ define float @powf_ok_base2(float %e) { define float @powf_ok_base3(float %e) { ; CHECK-LABEL: @powf_ok_base3( -; CHECK-NEXT: [[MUL:%.*]] = fmul nnan ninf afn float [[E:%.*]], 0x400AB0B560000000 +; CHECK-NEXT: [[MUL:%.*]] = fmul nnan ninf afn float [[E:%.*]], 0x400AB0B5{{.*}} ; CHECK-NEXT: [[EXP2F:%.*]] = call nnan ninf afn float @exp2f(float [[MUL]]) ; CHECK-NEXT: ret float [[EXP2F]] ; @@ -292,7 +292,7 @@ define float @powf_ok_base3(float %e) { define float @powf_ok_ten_base(float %e) { ; CHECK-LABEL: @powf_ok_ten_base( -; CHECK-NEXT: [[MUL:%.*]] = fmul nnan ninf afn float [[E:%.*]], 0x400A934F00000000 +; CHECK-NEXT: [[MUL:%.*]] = fmul nnan ninf afn float [[E:%.*]], 0x400A934{{.*}} ; CHECK-NEXT: [[EXP2F:%.*]] = call nnan ninf afn float @exp2f(float [[MUL]]) ; CHECK-NEXT: ret float [[EXP2F]] ; diff --git a/llvm/test/Transforms/InstCombine/pow_fp_int.ll b/llvm/test/Transforms/InstCombine/pow_fp_int.ll index 372a9e11c1eb..b0cb836da942 100644 --- a/llvm/test/Transforms/InstCombine/pow_fp_int.ll +++ b/llvm/test/Transforms/InstCombine/pow_fp_int.ll @@ -199,7 +199,7 @@ define double @powf_exp_const2_int_fast(double %base) { define double @pow_uitofp_const_base_fast_i32(i32 %x) { ; CHECK-LABEL: @pow_uitofp_const_base_fast_i32( ; CHECK-NEXT: [[SUBFP:%.*]] = uitofp i32 [[X:%.*]] to float -; CHECK-NEXT: [[MUL:%.*]] = fmul fast float [[SUBFP]], 0x4006757680000000 +; CHECK-NEXT: [[MUL:%.*]] = fmul fast float [[SUBFP]], 0x4006757{{.*}} ; CHECK-NEXT: [[EXP2:%.*]] = call fast float @llvm.exp2.f32(float [[MUL]]) ; CHECK-NEXT: [[RES:%.*]] = fpext float [[EXP2]] to double ; CHECK-NEXT: ret double [[RES]] @@ -251,7 +251,7 @@ define double @pow_uitofp_double_base_fast_i32(double %base, i32 %x) { define double @pow_sitofp_const_base_fast_i64(i64 %x) { ; CHECK-LABEL: @pow_sitofp_const_base_fast_i64( ; CHECK-NEXT: [[SUBFP:%.*]] = sitofp i64 [[X:%.*]] to float -; CHECK-NEXT: [[MUL:%.*]] = fmul fast float [[SUBFP]], 0x4006757680000000 +; CHECK-NEXT: [[MUL:%.*]] = fmul fast float [[SUBFP]], 0x400675{{.*}} ; CHECK-NEXT: [[EXP2:%.*]] = call fast float @llvm.exp2.f32(float [[MUL]]) ; CHECK-NEXT: [[RES:%.*]] = fpext float [[EXP2]] to double ; CHECK-NEXT: ret double [[RES]] @@ -265,7 +265,7 @@ define double @pow_sitofp_const_base_fast_i64(i64 %x) { define double @pow_uitofp_const_base_fast_i64(i64 %x) { ; CHECK-LABEL: @pow_uitofp_const_base_fast_i64( ; CHECK-NEXT: [[SUBFP:%.*]] = uitofp i64 [[X:%.*]] to float -; CHECK-NEXT: [[MUL:%.*]] = fmul fast float [[SUBFP]], 0x4006757680000000 +; CHECK-NEXT: [[MUL:%.*]] = fmul fast float [[SUBFP]], 0x400675{{.*}} ; CHECK-NEXT: [[EXP2:%.*]] = call fast float @llvm.exp2.f32(float [[MUL]]) ; CHECK-NEXT: [[RES:%.*]] = fpext float [[EXP2]] to double ; CHECK-NEXT: ret double [[RES]] From 7b4b8dc63658caef2eb68b50db41235554de736b Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Thu, 25 Jul 2019 00:29:40 +0000 Subject: [PATCH 031/289] Generate {Attribute,ClangCommandLine,Diagnostics}Reference.rst $ bin/clang-tblgen -gen-diag-docs -I../cfe.src/include \ -I../cfe.src/include/clang/Basic/ \ ../cfe.src/include/clang/Basic/Diagnostic.td -o \ ../cfe.src/docs/DiagnosticsReference.rst && \ bin/clang-tblgen -gen-attr-docs -I../cfe.src/include \ ../cfe.src/include/clang/Basic/Attr.td -o \ ../cfe.src/docs/AttributeReference.rst && \ bin/clang-tblgen -gen-opt-docs -I../cfe.src/include \ -I../cfe.src/include/clang/Driver -I../llvm.src/include \ ../cfe.src/include/clang/Driver/ClangOptionDocs.td -o \ ../cfe.src/docs/ClangCommandLineReference.rst llvm-svn: 366971 --- clang/docs/AttributeReference.rst | 5545 +++++++++++++++++++++- clang/docs/ClangCommandLineReference.rst | 355 +- clang/docs/DiagnosticsReference.rst | 2596 +++++++--- 3 files changed, 7690 insertions(+), 806 deletions(-) diff --git a/clang/docs/AttributeReference.rst b/clang/docs/AttributeReference.rst index a763ddeaeb10..8163b47185b3 100644 --- a/clang/docs/AttributeReference.rst +++ b/clang/docs/AttributeReference.rst @@ -1,13 +1,5546 @@ .. ------------------------------------------------------------------- NOTE: This file is automatically generated by running clang-tblgen - -gen-attr-docs. Do not edit this file by hand!! The contents for - this file are automatically generated by a server-side process. - - Please do not commit this file. The file exists for local testing - purposes only. + -gen-attr-docs. Do not edit this file by hand!! ------------------------------------------------------------------- =================== Attributes in Clang -=================== \ No newline at end of file +=================== +.. contents:: + :local: + +.. |br| raw:: html + +
+ +Introduction +============ + +This page lists the attributes currently supported by Clang. + +Function Attributes +=================== + + +#pragma omp declare simd +------------------------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "","","","","","``omp declare simd``","" + +The `declare simd` construct can be applied to a function to enable the creation +of one or more versions that can process multiple arguments using SIMD +instructions from a single invocation in a SIMD loop. The `declare simd` +directive is a declarative directive. There may be multiple `declare simd` +directives for a function. The use of a `declare simd` construct on a function +enables the creation of SIMD versions of the associated function that can be +used to process multiple arguments from a single invocation from a SIMD loop +concurrently. +The syntax of the `declare simd` construct is as follows: + + .. code-block:: none + + #pragma omp declare simd [clause[[,] clause] ...] new-line + [#pragma omp declare simd [clause[[,] clause] ...] new-line] + [...] + function definition or declaration + +where clause is one of the following: + + .. code-block:: none + + simdlen(length) + linear(argument-list[:constant-linear-step]) + aligned(argument-list[:alignment]) + uniform(argument-list) + inbranch + notinbranch + + +#pragma omp declare target +-------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "","","","","","``omp declare target``","" + +The `declare target` directive specifies that variables and functions are mapped +to a device for OpenMP offload mechanism. + +The syntax of the declare target directive is as follows: + + .. code-block:: c + + #pragma omp declare target new-line + declarations-definition-seq + #pragma omp end declare target new-line + + +_Noreturn +--------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "","","","","``_Noreturn``","","" + +A function declared as ``_Noreturn`` shall not return to its caller. The +compiler will generate a diagnostic for a function declared as ``_Noreturn`` +that appears to be capable of returning to its caller. + + +abi_tag +------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``abi_tag``","``gnu::abi_tag``","","","","","Yes" + +The ``abi_tag`` attribute can be applied to a function, variable, class or +inline namespace declaration to modify the mangled name of the entity. It gives +the ability to distinguish between different versions of the same entity but +with different ABI versions supported. For example, a newer version of a class +could have a different set of data members and thus have a different size. Using +the ``abi_tag`` attribute, it is possible to have different mangled names for +a global variable of the class type. Therefore, the old code could keep using +the old manged name and the new code will use the new mangled name with tags. + + +acquire_capability, acquire_shared_capability +--------------------------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``acquire_capability`` |br| ``acquire_shared_capability`` |br| ``exclusive_lock_function`` |br| ``shared_lock_function``","``clang::acquire_capability`` |br| ``clang::acquire_shared_capability``","","","","","" + +Marks a function as acquiring a capability. + + +alloc_align +----------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``alloc_align``","``gnu::alloc_align``","","","","","" + +Use ``__attribute__((alloc_align())`` on a function +declaration to specify that the return value of the function (which must be a +pointer type) is at least as aligned as the value of the indicated parameter. The +parameter is given by its index in the list of formal parameters; the first +parameter has index 1 unless the function is a C++ non-static member function, +in which case the first parameter has index 2 to account for the implicit ``this`` +parameter. + +.. code-block:: c++ + + // The returned pointer has the alignment specified by the first parameter. + void *a(size_t align) __attribute__((alloc_align(1))); + + // The returned pointer has the alignment specified by the second parameter. + void *b(void *v, size_t align) __attribute__((alloc_align(2))); + + // The returned pointer has the alignment specified by the second visible + // parameter, however it must be adjusted for the implicit 'this' parameter. + void *Foo::b(void *v, size_t align) __attribute__((alloc_align(3))); + +Note that this attribute merely informs the compiler that a function always +returns a sufficiently aligned pointer. It does not cause the compiler to +emit code to enforce that alignment. The behavior is undefined if the returned +poitner is not sufficiently aligned. + + +alloc_size +---------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``alloc_size``","``gnu::alloc_size``","","","","","Yes" + +The ``alloc_size`` attribute can be placed on functions that return pointers in +order to hint to the compiler how many bytes of memory will be available at the +returned pointer. ``alloc_size`` takes one or two arguments. + +- ``alloc_size(N)`` implies that argument number N equals the number of + available bytes at the returned pointer. +- ``alloc_size(N, M)`` implies that the product of argument number N and + argument number M equals the number of available bytes at the returned + pointer. + +Argument numbers are 1-based. + +An example of how to use ``alloc_size`` + +.. code-block:: c + + void *my_malloc(int a) __attribute__((alloc_size(1))); + void *my_calloc(int a, int b) __attribute__((alloc_size(1, 2))); + + int main() { + void *const p = my_malloc(100); + assert(__builtin_object_size(p, 0) == 100); + void *const a = my_calloc(20, 5); + assert(__builtin_object_size(a, 0) == 100); + } + +.. Note:: This attribute works differently in clang than it does in GCC. + Specifically, clang will only trace ``const`` pointers (as above); we give up + on pointers that are not marked as ``const``. In the vast majority of cases, + this is unimportant, because LLVM has support for the ``alloc_size`` + attribute. However, this may cause mildly unintuitive behavior when used with + other attributes, such as ``enable_if``. + + +allocator +--------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "","","","``allocator``","","","" + +The ``__declspec(allocator)`` attribute is applied to functions that allocate +memory, such as operator new in C++. When CodeView debug information is emitted +(enabled by ``clang -gcodeview`` or ``clang-cl /Z7``), Clang will attempt to +record the code offset of heap allocation call sites in the debug info. It will +also record the type being allocated using some local heuristics. The Visual +Studio debugger uses this information to `profile memory usage`_. + +.. _profile memory usage: https://docs.microsoft.com/en-us/visualstudio/profiling/memory-usage + +This attribute does not affect optimizations in any way, unlike GCC's +``__attribute__((malloc))``. + + +artificial +---------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``artificial``","``gnu::artificial``","","","","","" + +The ``artificial`` attribute can be applied to an inline function. If such a +function is inlined, the attribute indicates that debuggers should associate +the resulting instructions with the call site, rather than with the +corresponding line within the inlined callee. + + +assert_capability, assert_shared_capability +------------------------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``assert_capability`` |br| ``assert_shared_capability``","``clang::assert_capability`` |br| ``clang::assert_shared_capability``","","","","","" + +Marks a function that dynamically tests whether a capability is held, and halts +the program if it is not held. + + +assume_aligned +-------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``assume_aligned``","``gnu::assume_aligned``","","","","","Yes" + +Use ``__attribute__((assume_aligned([,]))`` on a function +declaration to specify that the return value of the function (which must be a +pointer type) has the specified offset, in bytes, from an address with the +specified alignment. The offset is taken to be zero if omitted. + +.. code-block:: c++ + + // The returned pointer value has 32-byte alignment. + void *a() __attribute__((assume_aligned (32))); + + // The returned pointer value is 4 bytes greater than an address having + // 32-byte alignment. + void *b() __attribute__((assume_aligned (32, 4))); + +Note that this attribute provides information to the compiler regarding a +condition that the code already ensures is true. It does not cause the compiler +to enforce the provided alignment assumption. + + +availability +------------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``availability``","``clang::availability``","``clang::availability``","","","","Yes" + +The ``availability`` attribute can be placed on declarations to describe the +lifecycle of that declaration relative to operating system versions. Consider +the function declaration for a hypothetical function ``f``: + +.. code-block:: c++ + + void f(void) __attribute__((availability(macos,introduced=10.4,deprecated=10.6,obsoleted=10.7))); + +The availability attribute states that ``f`` was introduced in macOS 10.4, +deprecated in macOS 10.6, and obsoleted in macOS 10.7. This information +is used by Clang to determine when it is safe to use ``f``: for example, if +Clang is instructed to compile code for macOS 10.5, a call to ``f()`` +succeeds. If Clang is instructed to compile code for macOS 10.6, the call +succeeds but Clang emits a warning specifying that the function is deprecated. +Finally, if Clang is instructed to compile code for macOS 10.7, the call +fails because ``f()`` is no longer available. + +The availability attribute is a comma-separated list starting with the +platform name and then including clauses specifying important milestones in the +declaration's lifetime (in any order) along with additional information. Those +clauses can be: + +introduced=\ *version* + The first version in which this declaration was introduced. + +deprecated=\ *version* + The first version in which this declaration was deprecated, meaning that + users should migrate away from this API. + +obsoleted=\ *version* + The first version in which this declaration was obsoleted, meaning that it + was removed completely and can no longer be used. + +unavailable + This declaration is never available on this platform. + +message=\ *string-literal* + Additional message text that Clang will provide when emitting a warning or + error about use of a deprecated or obsoleted declaration. Useful to direct + users to replacement APIs. + +replacement=\ *string-literal* + Additional message text that Clang will use to provide Fix-It when emitting + a warning about use of a deprecated declaration. The Fix-It will replace + the deprecated declaration with the new declaration specified. + +Multiple availability attributes can be placed on a declaration, which may +correspond to different platforms. For most platforms, the availability +attribute with the platform corresponding to the target platform will be used; +any others will be ignored. However, the availability for ``watchOS`` and +``tvOS`` can be implicitly inferred from an ``iOS`` availability attribute. +Any explicit availability attributes for those platforms are still prefered over +the implicitly inferred availability attributes. If no availability attribute +specifies availability for the current target platform, the availability +attributes are ignored. Supported platforms are: + +``ios`` + Apple's iOS operating system. The minimum deployment target is specified by + the ``-mios-version-min=*version*`` or ``-miphoneos-version-min=*version*`` + command-line arguments. + +``macos`` + Apple's macOS operating system. The minimum deployment target is + specified by the ``-mmacosx-version-min=*version*`` command-line argument. + ``macosx`` is supported for backward-compatibility reasons, but it is + deprecated. + +``tvos`` + Apple's tvOS operating system. The minimum deployment target is specified by + the ``-mtvos-version-min=*version*`` command-line argument. + +``watchos`` + Apple's watchOS operating system. The minimum deployment target is specified by + the ``-mwatchos-version-min=*version*`` command-line argument. + +A declaration can typically be used even when deploying back to a platform +version prior to when the declaration was introduced. When this happens, the +declaration is `weakly linked +`_, +as if the ``weak_import`` attribute were added to the declaration. A +weakly-linked declaration may or may not be present a run-time, and a program +can determine whether the declaration is present by checking whether the +address of that declaration is non-NULL. + +The flag ``strict`` disallows using API when deploying back to a +platform version prior to when the declaration was introduced. An +attempt to use such API before its introduction causes a hard error. +Weakly-linking is almost always a better API choice, since it allows +users to query availability at runtime. + +If there are multiple declarations of the same entity, the availability +attributes must either match on a per-platform basis or later +declarations must not have availability attributes for that +platform. For example: + +.. code-block:: c + + void g(void) __attribute__((availability(macos,introduced=10.4))); + void g(void) __attribute__((availability(macos,introduced=10.4))); // okay, matches + void g(void) __attribute__((availability(ios,introduced=4.0))); // okay, adds a new platform + void g(void); // okay, inherits both macos and ios availability from above. + void g(void) __attribute__((availability(macos,introduced=10.5))); // error: mismatch + +When one method overrides another, the overriding method can be more widely available than the overridden method, e.g.,: + +.. code-block:: objc + + @interface A + - (id)method __attribute__((availability(macos,introduced=10.4))); + - (id)method2 __attribute__((availability(macos,introduced=10.4))); + @end + + @interface B : A + - (id)method __attribute__((availability(macos,introduced=10.3))); // okay: method moved into base class later + - (id)method __attribute__((availability(macos,introduced=10.5))); // error: this method was available via the base class in 10.4 + @end + +Starting with the macOS 10.12 SDK, the ``API_AVAILABLE`` macro from +```` can simplify the spelling: + +.. code-block:: objc + + @interface A + - (id)method API_AVAILABLE(macos(10.11))); + - (id)otherMethod API_AVAILABLE(macos(10.11), ios(11.0)); + @end + +Availability attributes can also be applied using a ``#pragma clang attribute``. +Any explicit availability attribute whose platform corresponds to the target +platform is applied to a declaration regardless of the availability attributes +specified in the pragma. For example, in the code below, +``hasExplicitAvailabilityAttribute`` will use the ``macOS`` availability +attribute that is specified with the declaration, whereas +``getsThePragmaAvailabilityAttribute`` will use the ``macOS`` availability +attribute that is applied by the pragma. + +.. code-block:: c + + #pragma clang attribute push (__attribute__((availability(macOS, introduced=10.12))), apply_to=function) + void getsThePragmaAvailabilityAttribute(void); + void hasExplicitAvailabilityAttribute(void) __attribute__((availability(macos,introduced=10.4))); + #pragma clang attribute pop + +For platforms like ``watchOS`` and ``tvOS``, whose availability attributes can +be implicitly inferred from an ``iOS`` availability attribute, the logic is +slightly more complex. The explicit and the pragma-applied availability +attributes whose platform corresponds to the target platform are applied as +described in the previous paragraph. However, the implicitly inferred attributes +are applied to a declaration only when there is no explicit or pragma-applied +availability attribute whose platform corresponds to the target platform. For +example, the function below will receive the ``tvOS`` availability from the +pragma rather than using the inferred ``iOS`` availability from the declaration: + +.. code-block:: c + + #pragma clang attribute push (__attribute__((availability(tvOS, introduced=12.0))), apply_to=function) + void getsThePragmaTVOSAvailabilityAttribute(void) __attribute__((availability(iOS,introduced=11.0))); + #pragma clang attribute pop + +The compiler is also able to apply implicly inferred attributes from a pragma +as well. For example, when targeting ``tvOS``, the function below will receive +a ``tvOS`` availability attribute that is implicitly inferred from the ``iOS`` +availability attribute applied by the pragma: + +.. code-block:: c + + #pragma clang attribute push (__attribute__((availability(iOS, introduced=12.0))), apply_to=function) + void infersTVOSAvailabilityFromPragma(void); + #pragma clang attribute pop + +The implicit attributes that are inferred from explicitly specified attributes +whose platform corresponds to the target platform are applied to the declaration +even if there is an availability attribute that can be inferred from a pragma. +For example, the function below will receive the ``tvOS, introduced=11.0`` +availability that is inferred from the attribute on the declaration rather than +inferring availability from the pragma: + +.. code-block:: c + + #pragma clang attribute push (__attribute__((availability(iOS, unavailable))), apply_to=function) + void infersTVOSAvailabilityFromAttributeNextToDeclaration(void) + __attribute__((availability(iOS,introduced=11.0))); + #pragma clang attribute pop + +Also see the documentation for `@available +`_ + + +callback +-------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``callback``","``clang::callback``","``clang::callback``","","","","Yes" + +The ``callback`` attribute specifies that the annotated function may invoke the +specified callback zero or more times. The callback, as well as the passed +arguments, are identified by their parameter name or position (starting with +1!) in the annotated function. The first position in the attribute identifies +the callback callee, the following positions declare describe its arguments. +The callback callee is required to be callable with the number, and order, of +the specified arguments. The index `0`, or the identifier `this`, is used to +represent an implicit "this" pointer in class methods. If there is no implicit +"this" pointer it shall not be referenced. The index '-1', or the name "__", +represents an unknown callback callee argument. This can be a value which is +not present in the declared parameter list, or one that is, but is potentially +inspected, captured, or modified. Parameter names and indices can be mixed in +the callback attribute. + +The ``callback`` attribute, which is directly translated to ``callback`` +metadata , make the +connection between the call to the annotated function and the callback callee. +This can enable interprocedural optimizations which were otherwise impossible. +If a function parameter is mentioned in the ``callback`` attribute, through its +position, it is undefined if that parameter is used for anything other than the +actual callback. Inspected, captured, or modified parameters shall not be +listed in the ``callback`` metadata. + +Example encodings for the callback performed by `pthread_create` are shown +below. The explicit attribute annotation indicates that the third parameter +(`start_routine`) is called zero or more times by the `pthread_create` function, +and that the fourth parameter (`arg`) is passed along. Note that the callback +behavior of `pthread_create` is automatically recognized by Clang. In addition, +the declarations of `__kmpc_fork_teams` and `__kmpc_fork_call`, generated for +`#pragma omp target teams` and `#pragma omp parallel`, respectively, are also +automatically recognized as broker functions. Further functions might be added +in the future. + + .. code-block:: c + + __attribute__((callback (start_routine, arg))) + int pthread_create(pthread_t *thread, const pthread_attr_t *attr, + void *(*start_routine) (void *), void *arg); + + __attribute__((callback (3, 4))) + int pthread_create(pthread_t *thread, const pthread_attr_t *attr, + void *(*start_routine) (void *), void *arg); + + +carries_dependency +------------------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``carries_dependency``","``carries_dependency``","","","","","Yes" + +The ``carries_dependency`` attribute specifies dependency propagation into and +out of functions. + +When specified on a function or Objective-C method, the ``carries_dependency`` +attribute means that the return value carries a dependency out of the function, +so that the implementation need not constrain ordering upon return from that +function. Implementations of the function and its caller may choose to preserve +dependencies instead of emitting memory ordering instructions such as fences. + +Note, this attribute does not change the meaning of the program, but may result +in generation of more efficient code. + + +cf_consumed +----------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``cf_consumed``","``clang::cf_consumed``","``clang::cf_consumed``","","","","Yes" + +The behavior of a function with respect to reference counting for Foundation +(Objective-C), CoreFoundation (C) and OSObject (C++) is determined by a naming +convention (e.g. functions starting with "get" are assumed to return at +``+0``). + +It can be overriden using a family of the following attributes. In +Objective-C, the annotation ``__attribute__((ns_returns_retained))`` applied to +a function communicates that the object is returned at ``+1``, and the caller +is responsible for freeing it. +Similiarly, the annotation ``__attribute__((ns_returns_not_retained))`` +specifies that the object is returned at ``+0`` and the ownership remains with +the callee. +The annotation ``__attribute__((ns_consumes_self))`` specifies that +the Objective-C method call consumes the reference to ``self``, e.g. by +attaching it to a supplied parameter. +Additionally, parameters can have an annotation +``__attribute__((ns_consumed))``, which specifies that passing an owned object +as that parameter effectively transfers the ownership, and the caller is no +longer responsible for it. +These attributes affect code generation when interacting with ARC code, and +they are used by the Clang Static Analyzer. + +In C programs using CoreFoundation, a similar set of attributes: +``__attribute__((cf_returns_not_retained))``, +``__attribute__((cf_returns_retained))`` and ``__attribute__((cf_consumed))`` +have the same respective semantics when applied to CoreFoundation objects. +These attributes affect code generation when interacting with ARC code, and +they are used by the Clang Static Analyzer. + +Finally, in C++ interacting with XNU kernel (objects inheriting from OSObject), +the same attribute family is present: +``__attribute__((os_returns_not_retained))``, +``__attribute__((os_returns_retained))`` and ``__attribute__((os_consumed))``, +with the same respective semantics. +Similar to ``__attribute__((ns_consumes_self))``, +``__attribute__((os_consumes_this))`` specifies that the method call consumes +the reference to "this" (e.g., when attaching it to a different object supplied +as a parameter). +Out parameters (parameters the function is meant to write into, +either via pointers-to-pointers or references-to-pointers) +may be annotated with ``__attribute__((os_returns_retained))`` +or ``__attribute__((os_returns_not_retained))`` which specifies that the object +written into the out parameter should (or respectively should not) be released +after use. +Since often out parameters may or may not be written depending on the exit +code of the function, +annotations ``__attribute__((os_returns_retained_on_zero))`` +and ``__attribute__((os_returns_retained_on_non_zero))`` specify that +an out parameter at ``+1`` is written if and only if the function returns a zero +(respectively non-zero) error code. +Observe that return-code-dependent out parameter annotations are only +available for retained out parameters, as non-retained object do not have to be +released by the callee. +These attributes are only used by the Clang Static Analyzer. + +The family of attributes ``X_returns_X_retained`` can be added to functions, +C++ methods, and Objective-C methods and properties. +Attributes ``X_consumed`` can be added to parameters of methods, functions, +and Objective-C methods. + + +cf_returns_not_retained +----------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``cf_returns_not_retained``","``clang::cf_returns_not_retained``","``clang::cf_returns_not_retained``","","","","" + +The behavior of a function with respect to reference counting for Foundation +(Objective-C), CoreFoundation (C) and OSObject (C++) is determined by a naming +convention (e.g. functions starting with "get" are assumed to return at +``+0``). + +It can be overriden using a family of the following attributes. In +Objective-C, the annotation ``__attribute__((ns_returns_retained))`` applied to +a function communicates that the object is returned at ``+1``, and the caller +is responsible for freeing it. +Similiarly, the annotation ``__attribute__((ns_returns_not_retained))`` +specifies that the object is returned at ``+0`` and the ownership remains with +the callee. +The annotation ``__attribute__((ns_consumes_self))`` specifies that +the Objective-C method call consumes the reference to ``self``, e.g. by +attaching it to a supplied parameter. +Additionally, parameters can have an annotation +``__attribute__((ns_consumed))``, which specifies that passing an owned object +as that parameter effectively transfers the ownership, and the caller is no +longer responsible for it. +These attributes affect code generation when interacting with ARC code, and +they are used by the Clang Static Analyzer. + +In C programs using CoreFoundation, a similar set of attributes: +``__attribute__((cf_returns_not_retained))``, +``__attribute__((cf_returns_retained))`` and ``__attribute__((cf_consumed))`` +have the same respective semantics when applied to CoreFoundation objects. +These attributes affect code generation when interacting with ARC code, and +they are used by the Clang Static Analyzer. + +Finally, in C++ interacting with XNU kernel (objects inheriting from OSObject), +the same attribute family is present: +``__attribute__((os_returns_not_retained))``, +``__attribute__((os_returns_retained))`` and ``__attribute__((os_consumed))``, +with the same respective semantics. +Similar to ``__attribute__((ns_consumes_self))``, +``__attribute__((os_consumes_this))`` specifies that the method call consumes +the reference to "this" (e.g., when attaching it to a different object supplied +as a parameter). +Out parameters (parameters the function is meant to write into, +either via pointers-to-pointers or references-to-pointers) +may be annotated with ``__attribute__((os_returns_retained))`` +or ``__attribute__((os_returns_not_retained))`` which specifies that the object +written into the out parameter should (or respectively should not) be released +after use. +Since often out parameters may or may not be written depending on the exit +code of the function, +annotations ``__attribute__((os_returns_retained_on_zero))`` +and ``__attribute__((os_returns_retained_on_non_zero))`` specify that +an out parameter at ``+1`` is written if and only if the function returns a zero +(respectively non-zero) error code. +Observe that return-code-dependent out parameter annotations are only +available for retained out parameters, as non-retained object do not have to be +released by the callee. +These attributes are only used by the Clang Static Analyzer. + +The family of attributes ``X_returns_X_retained`` can be added to functions, +C++ methods, and Objective-C methods and properties. +Attributes ``X_consumed`` can be added to parameters of methods, functions, +and Objective-C methods. + + +cf_returns_retained +------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``cf_returns_retained``","``clang::cf_returns_retained``","``clang::cf_returns_retained``","","","","" + +The behavior of a function with respect to reference counting for Foundation +(Objective-C), CoreFoundation (C) and OSObject (C++) is determined by a naming +convention (e.g. functions starting with "get" are assumed to return at +``+0``). + +It can be overriden using a family of the following attributes. In +Objective-C, the annotation ``__attribute__((ns_returns_retained))`` applied to +a function communicates that the object is returned at ``+1``, and the caller +is responsible for freeing it. +Similiarly, the annotation ``__attribute__((ns_returns_not_retained))`` +specifies that the object is returned at ``+0`` and the ownership remains with +the callee. +The annotation ``__attribute__((ns_consumes_self))`` specifies that +the Objective-C method call consumes the reference to ``self``, e.g. by +attaching it to a supplied parameter. +Additionally, parameters can have an annotation +``__attribute__((ns_consumed))``, which specifies that passing an owned object +as that parameter effectively transfers the ownership, and the caller is no +longer responsible for it. +These attributes affect code generation when interacting with ARC code, and +they are used by the Clang Static Analyzer. + +In C programs using CoreFoundation, a similar set of attributes: +``__attribute__((cf_returns_not_retained))``, +``__attribute__((cf_returns_retained))`` and ``__attribute__((cf_consumed))`` +have the same respective semantics when applied to CoreFoundation objects. +These attributes affect code generation when interacting with ARC code, and +they are used by the Clang Static Analyzer. + +Finally, in C++ interacting with XNU kernel (objects inheriting from OSObject), +the same attribute family is present: +``__attribute__((os_returns_not_retained))``, +``__attribute__((os_returns_retained))`` and ``__attribute__((os_consumed))``, +with the same respective semantics. +Similar to ``__attribute__((ns_consumes_self))``, +``__attribute__((os_consumes_this))`` specifies that the method call consumes +the reference to "this" (e.g., when attaching it to a different object supplied +as a parameter). +Out parameters (parameters the function is meant to write into, +either via pointers-to-pointers or references-to-pointers) +may be annotated with ``__attribute__((os_returns_retained))`` +or ``__attribute__((os_returns_not_retained))`` which specifies that the object +written into the out parameter should (or respectively should not) be released +after use. +Since often out parameters may or may not be written depending on the exit +code of the function, +annotations ``__attribute__((os_returns_retained_on_zero))`` +and ``__attribute__((os_returns_retained_on_non_zero))`` specify that +an out parameter at ``+1`` is written if and only if the function returns a zero +(respectively non-zero) error code. +Observe that return-code-dependent out parameter annotations are only +available for retained out parameters, as non-retained object do not have to be +released by the callee. +These attributes are only used by the Clang Static Analyzer. + +The family of attributes ``X_returns_X_retained`` can be added to functions, +C++ methods, and Objective-C methods and properties. +Attributes ``X_consumed`` can be added to parameters of methods, functions, +and Objective-C methods. + + +code_seg +-------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "","","","``code_seg``","","","" + +The ``__declspec(code_seg)`` attribute enables the placement of code into separate +named segments that can be paged or locked in memory individually. This attribute +is used to control the placement of instantiated templates and compiler-generated +code. See the documentation for `__declspec(code_seg)`_ on MSDN. + +.. _`__declspec(code_seg)`: http://msdn.microsoft.com/en-us/library/dn636922.aspx + + +convergent +---------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``convergent``","``clang::convergent``","``clang::convergent``","","","","Yes" + +The ``convergent`` attribute can be placed on a function declaration. It is +translated into the LLVM ``convergent`` attribute, which indicates that the call +instructions of a function with this attribute cannot be made control-dependent +on any additional values. + +In languages designed for SPMD/SIMT programming model, e.g. OpenCL or CUDA, +the call instructions of a function with this attribute must be executed by +all work items or threads in a work group or sub group. + +This attribute is different from ``noduplicate`` because it allows duplicating +function calls if it can be proved that the duplicated function calls are +not made control-dependent on any additional values, e.g., unrolling a loop +executed by all work items. + +Sample usage: +.. code-block:: c + + void convfunc(void) __attribute__((convergent)); + // Setting it as a C++11 attribute is also valid in a C++ program. + // void convfunc(void) [[clang::convergent]]; + + +cpu_dispatch +------------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``cpu_dispatch``","``clang::cpu_dispatch``","``clang::cpu_dispatch``","``cpu_dispatch``","","","Yes" + +The ``cpu_specific`` and ``cpu_dispatch`` attributes are used to define and +resolve multiversioned functions. This form of multiversioning provides a +mechanism for declaring versions across translation units and manually +specifying the resolved function list. A specified CPU defines a set of minimum +features that are required for the function to be called. The result of this is +that future processors execute the most restrictive version of the function the +new processor can execute. + +Function versions are defined with ``cpu_specific``, which takes one or more CPU +names as a parameter. For example: + +.. code-block:: c + + // Declares and defines the ivybridge version of single_cpu. + __attribute__((cpu_specific(ivybridge))) + void single_cpu(void){} + + // Declares and defines the atom version of single_cpu. + __attribute__((cpu_specific(atom))) + void single_cpu(void){} + + // Declares and defines both the ivybridge and atom version of multi_cpu. + __attribute__((cpu_specific(ivybridge, atom))) + void multi_cpu(void){} + +A dispatching (or resolving) function can be declared anywhere in a project's +source code with ``cpu_dispatch``. This attribute takes one or more CPU names +as a parameter (like ``cpu_specific``). Functions marked with ``cpu_dispatch`` +are not expected to be defined, only declared. If such a marked function has a +definition, any side effects of the function are ignored; trivial function +bodies are permissible for ICC compatibility. + +.. code-block:: c + + // Creates a resolver for single_cpu above. + __attribute__((cpu_dispatch(ivybridge, atom))) + void single_cpu(void){} + + // Creates a resolver for multi_cpu, but adds a 3rd version defined in another + // translation unit. + __attribute__((cpu_dispatch(ivybridge, atom, sandybridge))) + void multi_cpu(void){} + +Note that it is possible to have a resolving function that dispatches based on +more or fewer options than are present in the program. Specifying fewer will +result in the omitted options not being considered during resolution. Specifying +a version for resolution that isn't defined in the program will result in a +linking failure. + +It is also possible to specify a CPU name of ``generic`` which will be resolved +if the executing processor doesn't satisfy the features required in the CPU +name. The behavior of a program executing on a processor that doesn't satisfy +any option of a multiversioned function is undefined. + + +cpu_specific +------------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``cpu_specific``","``clang::cpu_specific``","``clang::cpu_specific``","``cpu_specific``","","","Yes" + +The ``cpu_specific`` and ``cpu_dispatch`` attributes are used to define and +resolve multiversioned functions. This form of multiversioning provides a +mechanism for declaring versions across translation units and manually +specifying the resolved function list. A specified CPU defines a set of minimum +features that are required for the function to be called. The result of this is +that future processors execute the most restrictive version of the function the +new processor can execute. + +Function versions are defined with ``cpu_specific``, which takes one or more CPU +names as a parameter. For example: + +.. code-block:: c + + // Declares and defines the ivybridge version of single_cpu. + __attribute__((cpu_specific(ivybridge))) + void single_cpu(void){} + + // Declares and defines the atom version of single_cpu. + __attribute__((cpu_specific(atom))) + void single_cpu(void){} + + // Declares and defines both the ivybridge and atom version of multi_cpu. + __attribute__((cpu_specific(ivybridge, atom))) + void multi_cpu(void){} + +A dispatching (or resolving) function can be declared anywhere in a project's +source code with ``cpu_dispatch``. This attribute takes one or more CPU names +as a parameter (like ``cpu_specific``). Functions marked with ``cpu_dispatch`` +are not expected to be defined, only declared. If such a marked function has a +definition, any side effects of the function are ignored; trivial function +bodies are permissible for ICC compatibility. + +.. code-block:: c + + // Creates a resolver for single_cpu above. + __attribute__((cpu_dispatch(ivybridge, atom))) + void single_cpu(void){} + + // Creates a resolver for multi_cpu, but adds a 3rd version defined in another + // translation unit. + __attribute__((cpu_dispatch(ivybridge, atom, sandybridge))) + void multi_cpu(void){} + +Note that it is possible to have a resolving function that dispatches based on +more or fewer options than are present in the program. Specifying fewer will +result in the omitted options not being considered during resolution. Specifying +a version for resolution that isn't defined in the program will result in a +linking failure. + +It is also possible to specify a CPU name of ``generic`` which will be resolved +if the executing processor doesn't satisfy the features required in the CPU +name. The behavior of a program executing on a processor that doesn't satisfy +any option of a multiversioned function is undefined. + + +diagnose_if +----------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``diagnose_if``","","","","","","" + +The ``diagnose_if`` attribute can be placed on function declarations to emit +warnings or errors at compile-time if calls to the attributed function meet +certain user-defined criteria. For example: + +.. code-block:: c + + int abs(int a) + __attribute__((diagnose_if(a >= 0, "Redundant abs call", "warning"))); + int must_abs(int a) + __attribute__((diagnose_if(a >= 0, "Redundant abs call", "error"))); + + int val = abs(1); // warning: Redundant abs call + int val2 = must_abs(1); // error: Redundant abs call + int val3 = abs(val); + int val4 = must_abs(val); // Because run-time checks are not emitted for + // diagnose_if attributes, this executes without + // issue. + + +``diagnose_if`` is closely related to ``enable_if``, with a few key differences: + +* Overload resolution is not aware of ``diagnose_if`` attributes: they're + considered only after we select the best candidate from a given candidate set. +* Function declarations that differ only in their ``diagnose_if`` attributes are + considered to be redeclarations of the same function (not overloads). +* If the condition provided to ``diagnose_if`` cannot be evaluated, no + diagnostic will be emitted. + +Otherwise, ``diagnose_if`` is essentially the logical negation of ``enable_if``. + +As a result of bullet number two, ``diagnose_if`` attributes will stack on the +same function. For example: + +.. code-block:: c + + int foo() __attribute__((diagnose_if(1, "diag1", "warning"))); + int foo() __attribute__((diagnose_if(1, "diag2", "warning"))); + + int bar = foo(); // warning: diag1 + // warning: diag2 + int (*fooptr)(void) = foo; // warning: diag1 + // warning: diag2 + + constexpr int supportsAPILevel(int N) { return N < 5; } + int baz(int a) + __attribute__((diagnose_if(!supportsAPILevel(10), + "Upgrade to API level 10 to use baz", "error"))); + int baz(int a) + __attribute__((diagnose_if(!a, "0 is not recommended.", "warning"))); + + int (*bazptr)(int) = baz; // error: Upgrade to API level 10 to use baz + int v = baz(0); // error: Upgrade to API level 10 to use baz + +Query for this feature with ``__has_attribute(diagnose_if)``. + + +disable_tail_calls +------------------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``disable_tail_calls``","``clang::disable_tail_calls``","``clang::disable_tail_calls``","","","","Yes" + +The ``disable_tail_calls`` attribute instructs the backend to not perform tail call optimization inside the marked function. + +For example: + + .. code-block:: c + + int callee(int); + + int foo(int a) __attribute__((disable_tail_calls)) { + return callee(a); // This call is not tail-call optimized. + } + +Marking virtual functions as ``disable_tail_calls`` is legal. + + .. code-block:: c++ + + int callee(int); + + class Base { + public: + [[clang::disable_tail_calls]] virtual int foo1() { + return callee(); // This call is not tail-call optimized. + } + }; + + class Derived1 : public Base { + public: + int foo1() override { + return callee(); // This call is tail-call optimized. + } + }; + + +enable_if +--------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``enable_if``","","","","","","Yes" + +.. Note:: Some features of this attribute are experimental. The meaning of + multiple enable_if attributes on a single declaration is subject to change in + a future version of clang. Also, the ABI is not standardized and the name + mangling may change in future versions. To avoid that, use asm labels. + +The ``enable_if`` attribute can be placed on function declarations to control +which overload is selected based on the values of the function's arguments. +When combined with the ``overloadable`` attribute, this feature is also +available in C. + +.. code-block:: c++ + + int isdigit(int c); + int isdigit(int c) __attribute__((enable_if(c <= -1 || c > 255, "chosen when 'c' is out of range"))) __attribute__((unavailable("'c' must have the value of an unsigned char or EOF"))); + + void foo(char c) { + isdigit(c); + isdigit(10); + isdigit(-10); // results in a compile-time error. + } + +The enable_if attribute takes two arguments, the first is an expression written +in terms of the function parameters, the second is a string explaining why this +overload candidate could not be selected to be displayed in diagnostics. The +expression is part of the function signature for the purposes of determining +whether it is a redeclaration (following the rules used when determining +whether a C++ template specialization is ODR-equivalent), but is not part of +the type. + +The enable_if expression is evaluated as if it were the body of a +bool-returning constexpr function declared with the arguments of the function +it is being applied to, then called with the parameters at the call site. If the +result is false or could not be determined through constant expression +evaluation, then this overload will not be chosen and the provided string may +be used in a diagnostic if the compile fails as a result. + +Because the enable_if expression is an unevaluated context, there are no global +state changes, nor the ability to pass information from the enable_if +expression to the function body. For example, suppose we want calls to +strnlen(strbuf, maxlen) to resolve to strnlen_chk(strbuf, maxlen, size of +strbuf) only if the size of strbuf can be determined: + +.. code-block:: c++ + + __attribute__((always_inline)) + static inline size_t strnlen(const char *s, size_t maxlen) + __attribute__((overloadable)) + __attribute__((enable_if(__builtin_object_size(s, 0) != -1))), + "chosen when the buffer size is known but 'maxlen' is not"))) + { + return strnlen_chk(s, maxlen, __builtin_object_size(s, 0)); + } + +Multiple enable_if attributes may be applied to a single declaration. In this +case, the enable_if expressions are evaluated from left to right in the +following manner. First, the candidates whose enable_if expressions evaluate to +false or cannot be evaluated are discarded. If the remaining candidates do not +share ODR-equivalent enable_if expressions, the overload resolution is +ambiguous. Otherwise, enable_if overload resolution continues with the next +enable_if attribute on the candidates that have not been discarded and have +remaining enable_if attributes. In this way, we pick the most specific +overload out of a number of viable overloads using enable_if. + +.. code-block:: c++ + + void f() __attribute__((enable_if(true, ""))); // #1 + void f() __attribute__((enable_if(true, ""))) __attribute__((enable_if(true, ""))); // #2 + + void g(int i, int j) __attribute__((enable_if(i, ""))); // #1 + void g(int i, int j) __attribute__((enable_if(j, ""))) __attribute__((enable_if(true))); // #2 + +In this example, a call to f() is always resolved to #2, as the first enable_if +expression is ODR-equivalent for both declarations, but #1 does not have another +enable_if expression to continue evaluating, so the next round of evaluation has +only a single candidate. In a call to g(1, 1), the call is ambiguous even though +#2 has more enable_if attributes, because the first enable_if expressions are +not ODR-equivalent. + +Query for this feature with ``__has_attribute(enable_if)``. + +Note that functions with one or more ``enable_if`` attributes may not have +their address taken, unless all of the conditions specified by said +``enable_if`` are constants that evaluate to ``true``. For example: + +.. code-block:: c + + const int TrueConstant = 1; + const int FalseConstant = 0; + int f(int a) __attribute__((enable_if(a > 0, ""))); + int g(int a) __attribute__((enable_if(a == 0 || a != 0, ""))); + int h(int a) __attribute__((enable_if(1, ""))); + int i(int a) __attribute__((enable_if(TrueConstant, ""))); + int j(int a) __attribute__((enable_if(FalseConstant, ""))); + + void fn() { + int (*ptr)(int); + ptr = &f; // error: 'a > 0' is not always true + ptr = &g; // error: 'a == 0 || a != 0' is not a truthy constant + ptr = &h; // OK: 1 is a truthy constant + ptr = &i; // OK: 'TrueConstant' is a truthy constant + ptr = &j; // error: 'FalseConstant' is a constant, but not truthy + } + +Because ``enable_if`` evaluation happens during overload resolution, +``enable_if`` may give unintuitive results when used with templates, depending +on when overloads are resolved. In the example below, clang will emit a +diagnostic about no viable overloads for ``foo`` in ``bar``, but not in ``baz``: + +.. code-block:: c++ + + double foo(int i) __attribute__((enable_if(i > 0, ""))); + void *foo(int i) __attribute__((enable_if(i <= 0, ""))); + template + auto bar() { return foo(I); } + + template + auto baz() { return foo(T::number); } + + struct WithNumber { constexpr static int number = 1; }; + void callThem() { + bar(); + baz(); + } + +This is because, in ``bar``, ``foo`` is resolved prior to template +instantiation, so the value for ``I`` isn't known (thus, both ``enable_if`` +conditions for ``foo`` fail). However, in ``baz``, ``foo`` is resolved during +template instantiation, so the value for ``T::number`` is known. + + +exclude_from_explicit_instantiation +----------------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``exclude_from_explicit_instantiation``","``clang::exclude_from_explicit_instantiation``","``clang::exclude_from_explicit_instantiation``","","","","Yes" + +The ``exclude_from_explicit_instantiation`` attribute opts-out a member of a +class template from being part of explicit template instantiations of that +class template. This means that an explicit instantiation will not instantiate +members of the class template marked with the attribute, but also that code +where an extern template declaration of the enclosing class template is visible +will not take for granted that an external instantiation of the class template +would provide those members (which would otherwise be a link error, since the +explicit instantiation won't provide those members). For example, let's say we +don't want the ``data()`` method to be part of libc++'s ABI. To make sure it +is not exported from the dylib, we give it hidden visibility: + + .. code-block:: c++ + + // in + template + class basic_string { + public: + __attribute__((__visibility__("hidden"))) + const value_type* data() const noexcept { ... } + }; + + template class basic_string; + +Since an explicit template instantiation declaration for ``basic_string`` +is provided, the compiler is free to assume that ``basic_string::data()`` +will be provided by another translation unit, and it is free to produce an +external call to this function. However, since ``data()`` has hidden visibility +and the explicit template instantiation is provided in a shared library (as +opposed to simply another translation unit), ``basic_string::data()`` +won't be found and a link error will ensue. This happens because the compiler +assumes that ``basic_string::data()`` is part of the explicit template +instantiation declaration, when it really isn't. To tell the compiler that +``data()`` is not part of the explicit template instantiation declaration, the +``exclude_from_explicit_instantiation`` attribute can be used: + + .. code-block:: c++ + + // in + template + class basic_string { + public: + __attribute__((__visibility__("hidden"))) + __attribute__((exclude_from_explicit_instantiation)) + const value_type* data() const noexcept { ... } + }; + + template class basic_string; + +Now, the compiler won't assume that ``basic_string::data()`` is provided +externally despite there being an explicit template instantiation declaration: +the compiler will implicitly instantiate ``basic_string::data()`` in the +TUs where it is used. + +This attribute can be used on static and non-static member functions of class +templates, static data members of class templates and member classes of class +templates. + + +flatten +------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``flatten``","``gnu::flatten``","","","","","Yes" + +The ``flatten`` attribute causes calls within the attributed function to +be inlined unless it is impossible to do so, for example if the body of the +callee is unavailable or if the callee has the ``noinline`` attribute. + + +force_align_arg_pointer +----------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``force_align_arg_pointer``","``gnu::force_align_arg_pointer``","","","","","" + +Use this attribute to force stack alignment. + +Legacy x86 code uses 4-byte stack alignment. Newer aligned SSE instructions +(like 'movaps') that work with the stack require operands to be 16-byte aligned. +This attribute realigns the stack in the function prologue to make sure the +stack can be used with SSE instructions. + +Note that the x86_64 ABI forces 16-byte stack alignment at the call site. +Because of this, 'force_align_arg_pointer' is not needed on x86_64, except in +rare cases where the caller does not align the stack properly (e.g. flow +jumps from i386 arch code). + + .. code-block:: c + + __attribute__ ((force_align_arg_pointer)) + void f () { + ... + } + + +format +------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``format``","``gnu::format``","","","","","" + +Clang supports the ``format`` attribute, which indicates that the function +accepts a ``printf`` or ``scanf``-like format string and corresponding +arguments or a ``va_list`` that contains these arguments. + +Please see `GCC documentation about format attribute +`_ to find details +about attribute syntax. + +Clang implements two kinds of checks with this attribute. + +#. Clang checks that the function with the ``format`` attribute is called with + a format string that uses format specifiers that are allowed, and that + arguments match the format string. This is the ``-Wformat`` warning, it is + on by default. + +#. Clang checks that the format string argument is a literal string. This is + the ``-Wformat-nonliteral`` warning, it is off by default. + + Clang implements this mostly the same way as GCC, but there is a difference + for functions that accept a ``va_list`` argument (for example, ``vprintf``). + GCC does not emit ``-Wformat-nonliteral`` warning for calls to such + functions. Clang does not warn if the format string comes from a function + parameter, where the function is annotated with a compatible attribute, + otherwise it warns. For example: + + .. code-block:: c + + __attribute__((__format__ (__scanf__, 1, 3))) + void foo(const char* s, char *buf, ...) { + va_list ap; + va_start(ap, buf); + + vprintf(s, ap); // warning: format string is not a string literal + } + + In this case we warn because ``s`` contains a format string for a + ``scanf``-like function, but it is passed to a ``printf``-like function. + + If the attribute is removed, clang still warns, because the format string is + not a string literal. + + Another example: + + .. code-block:: c + + __attribute__((__format__ (__printf__, 1, 3))) + void foo(const char* s, char *buf, ...) { + va_list ap; + va_start(ap, buf); + + vprintf(s, ap); // warning + } + + In this case Clang does not warn because the format string ``s`` and + the corresponding arguments are annotated. If the arguments are + incorrect, the caller of ``foo`` will receive a warning. + + +gnu_inline +---------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``gnu_inline``","``gnu::gnu_inline``","","","","","Yes" + +The ``gnu_inline`` changes the meaning of ``extern inline`` to use GNU inline +semantics, meaning: + +* If any declaration that is declared ``inline`` is not declared ``extern``, + then the ``inline`` keyword is just a hint. In particular, an out-of-line + definition is still emitted for a function with external linkage, even if all + call sites are inlined, unlike in C99 and C++ inline semantics. + +* If all declarations that are declared ``inline`` are also declared + ``extern``, then the function body is present only for inlining and no + out-of-line version is emitted. + +Some important consequences: ``static inline`` emits an out-of-line +version if needed, a plain ``inline`` definition emits an out-of-line version +always, and an ``extern inline`` definition (in a header) followed by a +(non-``extern``) ``inline`` declaration in a source file emits an out-of-line +version of the function in that source file but provides the function body for +inlining to all includers of the header. + +Either ``__GNUC_GNU_INLINE__`` (GNU inline semantics) or +``__GNUC_STDC_INLINE__`` (C99 semantics) will be defined (they are mutually +exclusive). If ``__GNUC_STDC_INLINE__`` is defined, then the ``gnu_inline`` +function attribute can be used to get GNU inline semantics on a per function +basis. If ``__GNUC_GNU_INLINE__`` is defined, then the translation unit is +already being compiled with GNU inline semantics as the implied default. It is +unspecified which macro is defined in a C++ compilation. + +GNU inline semantics are the default behavior with ``-std=gnu89``, +``-std=c89``, ``-std=c94``, or ``-fgnu89-inline``. + + +ifunc +----- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``ifunc``","``gnu::ifunc``","","","","","Yes" + +``__attribute__((ifunc("resolver")))`` is used to mark that the address of a declaration should be resolved at runtime by calling a resolver function. + +The symbol name of the resolver function is given in quotes. A function with this name (after mangling) must be defined in the current translation unit; it may be ``static``. The resolver function should return a pointer. + +The ``ifunc`` attribute may only be used on a function declaration. A function declaration with an ``ifunc`` attribute is considered to be a definition of the declared entity. The entity must not have weak linkage; for example, in C++, it cannot be applied to a declaration if a definition at that location would be considered inline. + +Not all targets support this attribute. ELF target support depends on both the linker and runtime linker, and is available in at least lld 4.0 and later, binutils 2.20.1 and later, glibc v2.11.1 and later, and FreeBSD 9.1 and later. Non-ELF targets currently do not support this attribute. + + +import_module +------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``import_module``","``clang::import_module``","``clang::import_module``","","","","Yes" + +Clang supports the ``__attribute__((import_module()))`` +attribute for the WebAssembly target. This attribute may be attached to a +function declaration, where it modifies how the symbol is to be imported +within the WebAssembly linking environment. + +WebAssembly imports use a two-level namespace scheme, consisting of a module +name, which typically identifies a module from which to import, and a field +name, which typically identifies a field from that module to import. By +default, module names for C/C++ symbols are assigned automatically by the +linker. This attribute can be used to override the default behavior, and +reuqest a specific module name be used instead. + + +import_name +----------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``import_name``","``clang::import_name``","``clang::import_name``","","","","Yes" + +Clang supports the ``__attribute__((import_name()))`` +attribute for the WebAssembly target. This attribute may be attached to a +function declaration, where it modifies how the symbol is to be imported +within the WebAssembly linking environment. + +WebAssembly imports use a two-level namespace scheme, consisting of a module +name, which typically identifies a module from which to import, and a field +name, which typically identifies a field from that module to import. By +default, field names for C/C++ symbols are the same as their C/C++ symbol +names. This attribute can be used to override the default behavior, and +reuqest a specific field name be used instead. + + +internal_linkage +---------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``internal_linkage``","``clang::internal_linkage``","``clang::internal_linkage``","","","","Yes" + +The ``internal_linkage`` attribute changes the linkage type of the declaration to internal. +This is similar to C-style ``static``, but can be used on classes and class methods. When applied to a class definition, +this attribute affects all methods and static data members of that class. +This can be used to contain the ABI of a C++ library by excluding unwanted class methods from the export tables. + + +interrupt (ARM) +--------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``interrupt``","``gnu::interrupt``","","","","","" + +Clang supports the GNU style ``__attribute__((interrupt("TYPE")))`` attribute on +ARM targets. This attribute may be attached to a function definition and +instructs the backend to generate appropriate function entry/exit code so that +it can be used directly as an interrupt service routine. + +The parameter passed to the interrupt attribute is optional, but if +provided it must be a string literal with one of the following values: "IRQ", +"FIQ", "SWI", "ABORT", "UNDEF". + +The semantics are as follows: + +- If the function is AAPCS, Clang instructs the backend to realign the stack to + 8 bytes on entry. This is a general requirement of the AAPCS at public + interfaces, but may not hold when an exception is taken. Doing this allows + other AAPCS functions to be called. +- If the CPU is M-class this is all that needs to be done since the architecture + itself is designed in such a way that functions obeying the normal AAPCS ABI + constraints are valid exception handlers. +- If the CPU is not M-class, the prologue and epilogue are modified to save all + non-banked registers that are used, so that upon return the user-mode state + will not be corrupted. Note that to avoid unnecessary overhead, only + general-purpose (integer) registers are saved in this way. If VFP operations + are needed, that state must be saved manually. + + Specifically, interrupt kinds other than "FIQ" will save all core registers + except "lr" and "sp". "FIQ" interrupts will save r0-r7. +- If the CPU is not M-class, the return instruction is changed to one of the + canonical sequences permitted by the architecture for exception return. Where + possible the function itself will make the necessary "lr" adjustments so that + the "preferred return address" is selected. + + Unfortunately the compiler is unable to make this guarantee for an "UNDEF" + handler, where the offset from "lr" to the preferred return address depends on + the execution state of the code which generated the exception. In this case + a sequence equivalent to "movs pc, lr" will be used. + + +interrupt (AVR) +--------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``interrupt``","``gnu::interrupt``","","","","","Yes" + +Clang supports the GNU style ``__attribute__((interrupt))`` attribute on +AVR targets. This attribute may be attached to a function definition and instructs +the backend to generate appropriate function entry/exit code so that it can be used +directly as an interrupt service routine. + +On the AVR, the hardware globally disables interrupts when an interrupt is executed. +The first instruction of an interrupt handler declared with this attribute is a SEI +instruction to re-enable interrupts. See also the signal attribute that +does not insert a SEI instruction. + + +interrupt (MIPS) +---------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``interrupt``","``gnu::interrupt``","","","","","Yes" + +Clang supports the GNU style ``__attribute__((interrupt("ARGUMENT")))`` attribute on +MIPS targets. This attribute may be attached to a function definition and instructs +the backend to generate appropriate function entry/exit code so that it can be used +directly as an interrupt service routine. + +By default, the compiler will produce a function prologue and epilogue suitable for +an interrupt service routine that handles an External Interrupt Controller (eic) +generated interrupt. This behaviour can be explicitly requested with the "eic" +argument. + +Otherwise, for use with vectored interrupt mode, the argument passed should be +of the form "vector=LEVEL" where LEVEL is one of the following values: +"sw0", "sw1", "hw0", "hw1", "hw2", "hw3", "hw4", "hw5". The compiler will +then set the interrupt mask to the corresponding level which will mask all +interrupts up to and including the argument. + +The semantics are as follows: + +- The prologue is modified so that the Exception Program Counter (EPC) and + Status coprocessor registers are saved to the stack. The interrupt mask is + set so that the function can only be interrupted by a higher priority + interrupt. The epilogue will restore the previous values of EPC and Status. + +- The prologue and epilogue are modified to save and restore all non-kernel + registers as necessary. + +- The FPU is disabled in the prologue, as the floating pointer registers are not + spilled to the stack. + +- The function return sequence is changed to use an exception return instruction. + +- The parameter sets the interrupt mask for the function corresponding to the + interrupt level specified. If no mask is specified the interrupt mask + defaults to "eic". + + +interrupt (RISCV) +----------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``interrupt``","``gnu::interrupt``","","","","","Yes" + +Clang supports the GNU style ``__attribute__((interrupt))`` attribute on RISCV +targets. This attribute may be attached to a function definition and instructs +the backend to generate appropriate function entry/exit code so that it can be +used directly as an interrupt service routine. + +Permissible values for this parameter are ``user``, ``supervisor``, +and ``machine``. If there is no parameter, then it defaults to machine. + +Repeated interrupt attribute on the same declaration will cause a warning +to be emitted. In case of repeated declarations, the last one prevails. + +Refer to: +https://gcc.gnu.org/onlinedocs/gcc/RISC-V-Function-Attributes.html +https://riscv.org/specifications/privileged-isa/ +The RISC-V Instruction Set Manual Volume II: Privileged Architecture +Version 1.10. + + +kernel +------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``kernel``","","","","","","Yes" + +``__attribute__((kernel))`` is used to mark a ``kernel`` function in +RenderScript. + +In RenderScript, ``kernel`` functions are used to express data-parallel +computations. The RenderScript runtime efficiently parallelizes ``kernel`` +functions to run on computational resources such as multi-core CPUs and GPUs. +See the RenderScript_ documentation for more information. + +.. _RenderScript: https://developer.android.com/guide/topics/renderscript/compute.html + + +lifetimebound +------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``lifetimebound``","``clang::lifetimebound``","","","","","" + +The ``lifetimebound`` attribute indicates that a resource owned by +a function parameter or implicit object parameter +is retained by the return value of the annotated function +(or, for a parameter of a constructor, in the value of the constructed object). +It is only supported in C++. + +This attribute provides an experimental implementation of the facility +described in the C++ committee paper [http://wg21.link/p0936r0](P0936R0), +and is subject to change as the design of the corresponding functionality +changes. + + +long_call, far +-------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``long_call`` |br| ``far``","``gnu::long_call`` |br| ``gnu::far``","","","","","Yes" + +Clang supports the ``__attribute__((long_call))``, ``__attribute__((far))``, +and ``__attribute__((near))`` attributes on MIPS targets. These attributes may +only be added to function declarations and change the code generated +by the compiler when directly calling the function. The ``near`` attribute +allows calls to the function to be made using the ``jal`` instruction, which +requires the function to be located in the same naturally aligned 256MB +segment as the caller. The ``long_call`` and ``far`` attributes are synonyms +and require the use of a different call sequence that works regardless +of the distance between the functions. + +These attributes have no effect for position-independent code. + +These attributes take priority over command line switches such +as ``-mlong-calls`` and ``-mno-long-calls``. + + +micromips +--------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``micromips``","``gnu::micromips``","","","","","Yes" + +Clang supports the GNU style ``__attribute__((micromips))`` and +``__attribute__((nomicromips))`` attributes on MIPS targets. These attributes +may be attached to a function definition and instructs the backend to generate +or not to generate microMIPS code for that function. + +These attributes override the `-mmicromips` and `-mno-micromips` options +on the command line. + + +mig_server_routine +------------------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``mig_server_routine``","``clang::mig_server_routine``","``clang::mig_server_routine``","","","","Yes" + +The Mach Interface Generator release-on-success convention dictates +functions that follow it to only release arguments passed to them when they +return "success" (a ``kern_return_t`` error code that indicates that +no errors have occured). Otherwise the release is performed by the MIG client +that called the function. The annotation ``__attribute__((mig_server_routine))`` +is applied in order to specify which functions are expected to follow the +convention. This allows the Static Analyzer to find bugs caused by violations of +that convention. The attribute would normally appear on the forward declaration +of the actual server routine in the MIG server header, but it may also be +added to arbitrary functions that need to follow the same convention - for +example, a user can add them to auxiliary functions called by the server routine +that have their return value of type ``kern_return_t`` unconditionally returned +from the routine. The attribute can be applied to C++ methods, and in this case +it will be automatically applied to overrides if the method is virtual. The +attribute can also be written using C++11 syntax: ``[[mig::server_routine]]``. + + +min_vector_width +---------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``min_vector_width``","``clang::min_vector_width``","``clang::min_vector_width``","","","","Yes" + +Clang supports the ``__attribute__((min_vector_width(width)))`` attribute. This +attribute may be attached to a function and informs the backend that this +function desires vectors of at least this width to be generated. Target-specific +maximum vector widths still apply. This means even if you ask for something +larger than the target supports, you will only get what the target supports. +This attribute is meant to be a hint to control target heuristics that may +generate narrower vectors than what the target hardware supports. + +This is currently used by the X86 target to allow some CPUs that support 512-bit +vectors to be limited to using 256-bit vectors to avoid frequency penalties. +This is currently enabled with the ``-prefer-vector-width=256`` command line +option. The ``min_vector_width`` attribute can be used to prevent the backend +from trying to split vector operations to match the ``prefer-vector-width``. All +X86 vector intrinsics from x86intrin.h already set this attribute. Additionally, +use of any of the X86-specific vector builtins will implicitly set this +attribute on the calling function. The intent is that explicitly writing vector +code using the X86 intrinsics will prevent ``prefer-vector-width`` from +affecting the code. + + +no_caller_saved_registers +------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``no_caller_saved_registers``","``gnu::no_caller_saved_registers``","","","","","" + +Use this attribute to indicate that the specified function has no +caller-saved registers. That is, all registers are callee-saved except for +registers used for passing parameters to the function or returning parameters +from the function. +The compiler saves and restores any modified registers that were not used for +passing or returning arguments to the function. + +The user can call functions specified with the 'no_caller_saved_registers' +attribute from an interrupt handler without saving and restoring all +call-clobbered registers. + +Note that 'no_caller_saved_registers' attribute is not a calling convention. +In fact, it only overrides the decision of which registers should be saved by +the caller, but not how the parameters are passed from the caller to the callee. + +For example: + + .. code-block:: c + + __attribute__ ((no_caller_saved_registers, fastcall)) + void f (int arg1, int arg2) { + ... + } + + In this case parameters 'arg1' and 'arg2' will be passed in registers. + In this case, on 32-bit x86 targets, the function 'f' will use ECX and EDX as + register parameters. However, it will not assume any scratch registers and + should save and restore any modified registers except for ECX and EDX. + + +no_sanitize +----------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``no_sanitize``","``clang::no_sanitize``","``clang::no_sanitize``","","","","Yes" + +Use the ``no_sanitize`` attribute on a function or a global variable +declaration to specify that a particular instrumentation or set of +instrumentations should not be applied. The attribute takes a list of +string literals, which have the same meaning as values accepted by the +``-fno-sanitize=`` flag. For example, +``__attribute__((no_sanitize("address", "thread")))`` specifies that +AddressSanitizer and ThreadSanitizer should not be applied to the +function or variable. + +See :ref:`Controlling Code Generation ` for a +full list of supported sanitizer flags. + + +no_sanitize_address, no_address_safety_analysis +----------------------------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``no_address_safety_analysis`` |br| ``no_sanitize_address`` |br| ``no_sanitize_thread`` |br| ``no_sanitize_memory``","``gnu::no_address_safety_analysis`` |br| ``gnu::no_sanitize_address`` |br| ``gnu::no_sanitize_thread`` |br| ``clang::no_sanitize_memory``","``clang::no_sanitize_memory``","","","","Yes" + +.. _langext-address_sanitizer: + +Use ``__attribute__((no_sanitize_address))`` on a function or a global +variable declaration to specify that address safety instrumentation +(e.g. AddressSanitizer) should not be applied. + + +no_sanitize_memory +------------------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``no_address_safety_analysis`` |br| ``no_sanitize_address`` |br| ``no_sanitize_thread`` |br| ``no_sanitize_memory``","``gnu::no_address_safety_analysis`` |br| ``gnu::no_sanitize_address`` |br| ``gnu::no_sanitize_thread`` |br| ``clang::no_sanitize_memory``","``clang::no_sanitize_memory``","","","","Yes" + +.. _langext-memory_sanitizer: + +Use ``__attribute__((no_sanitize_memory))`` on a function declaration to +specify that checks for uninitialized memory should not be inserted +(e.g. by MemorySanitizer). The function may still be instrumented by the tool +to avoid false positives in other places. + + +no_sanitize_thread +------------------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``no_address_safety_analysis`` |br| ``no_sanitize_address`` |br| ``no_sanitize_thread`` |br| ``no_sanitize_memory``","``gnu::no_address_safety_analysis`` |br| ``gnu::no_sanitize_address`` |br| ``gnu::no_sanitize_thread`` |br| ``clang::no_sanitize_memory``","``clang::no_sanitize_memory``","","","","Yes" + +.. _langext-thread_sanitizer: + +Use ``__attribute__((no_sanitize_thread))`` on a function declaration to +specify that checks for data races on plain (non-atomic) memory accesses should +not be inserted by ThreadSanitizer. The function is still instrumented by the +tool to avoid false positives and provide meaningful stack traces. + + +no_speculative_load_hardening +----------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``no_speculative_load_hardening``","``clang::no_speculative_load_hardening``","``clang::no_speculative_load_hardening``","","","","Yes" + +This attribute can be applied to a function declaration in order to indicate + that `Speculative Load Hardening `_ + is *not* needed for the function body. This can also be applied to a method + in Objective C. This attribute will take precedence over the command line flag in + the case where `-mspeculative-load-hardening `_ is specified. + + Warning: This attribute may not prevent Speculative Load Hardening from being + enabled for a function which inlines a function that has the + 'speculative_load_hardening' attribute. This is intended to provide a + maximally conservative model where the code that is marked with the + 'speculative_load_hardening' attribute will always (even when inlined) + be hardened. A user of this attribute may want to mark functions called by + a function they do not want to be hardened with the 'noinline' attribute. + + For example: + + .. code-block:: c + + __attribute__((speculative_load_hardening)) + int foo(int i) { + return i; + } + + // Note: bar() may still have speculative load hardening enabled if + // foo() is inlined into bar(). Mark foo() with __attribute__((noinline)) + // to avoid this situation. + __attribute__((no_speculative_load_hardening)) + int bar(int i) { + return foo(i); + } + + +no_split_stack +-------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``no_split_stack``","``gnu::no_split_stack``","","","","","Yes" + +The ``no_split_stack`` attribute disables the emission of the split stack +preamble for a particular function. It has no effect if ``-fsplit-stack`` +is not specified. + + +no_stack_protector +------------------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``no_stack_protector``","``clang::no_stack_protector``","``clang::no_stack_protector``","","","","Yes" + +Clang supports the ``__attribute__((no_stack_protector))`` attribute which disables +the stack protector on the specified function. This attribute is useful for +selectively disabling the stack protector on some functions when building with +``-fstack-protector`` compiler option. + +For example, it disables the stack protector for the function ``foo`` but function +``bar`` will still be built with the stack protector with the ``-fstack-protector`` +option. + +.. code-block:: c + + int __attribute__((no_stack_protector)) + foo (int x); // stack protection will be disabled for foo. + + int bar(int y); // bar can be built with the stack protector. + + +noalias +------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "","","","``noalias``","","","" + +The ``noalias`` attribute indicates that the only memory accesses inside +function are loads and stores from objects pointed to by its pointer-typed +arguments, with arbitrary offsets. + + +nocf_check +---------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``nocf_check``","``gnu::nocf_check``","","","","","Yes" + +Jump Oriented Programming attacks rely on tampering with addresses used by +indirect call / jmp, e.g. redirect control-flow to non-programmer +intended bytes in the binary. +X86 Supports Indirect Branch Tracking (IBT) as part of Control-Flow +Enforcement Technology (CET). IBT instruments ENDBR instructions used to +specify valid targets of indirect call / jmp. +The ``nocf_check`` attribute has two roles: +1. Appertains to a function - do not add ENDBR instruction at the beginning of +the function. +2. Appertains to a function pointer - do not track the target function of this +pointer (by adding nocf_check prefix to the indirect-call instruction). + + +nodiscard, warn_unused_result +----------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``warn_unused_result``","``nodiscard`` |br| ``clang::warn_unused_result`` |br| ``gnu::warn_unused_result``","``nodiscard``","","","","Yes" + +Clang supports the ability to diagnose when the results of a function call +expression are discarded under suspicious circumstances. A diagnostic is +generated when a function or its return type is marked with ``[[nodiscard]]`` +(or ``__attribute__((warn_unused_result))``) and the function call appears as a +potentially-evaluated discarded-value expression that is not explicitly cast to +`void`. + +.. code-block: c++ + struct [[nodiscard]] error_info { /*...*/ }; + error_info enable_missile_safety_mode(); + + void launch_missiles(); + void test_missiles() { + enable_missile_safety_mode(); // diagnoses + launch_missiles(); + } + error_info &foo(); + void f() { foo(); } // Does not diagnose, error_info is a reference. + + +noduplicate +----------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``noduplicate``","``clang::noduplicate``","``clang::noduplicate``","","","","Yes" + +The ``noduplicate`` attribute can be placed on function declarations to control +whether function calls to this function can be duplicated or not as a result of +optimizations. This is required for the implementation of functions with +certain special requirements, like the OpenCL "barrier" function, that might +need to be run concurrently by all the threads that are executing in lockstep +on the hardware. For example this attribute applied on the function +"nodupfunc" in the code below avoids that: + +.. code-block:: c + + void nodupfunc() __attribute__((noduplicate)); + // Setting it as a C++11 attribute is also valid + // void nodupfunc() [[clang::noduplicate]]; + void foo(); + void bar(); + + nodupfunc(); + if (a > n) { + foo(); + } else { + bar(); + } + +gets possibly modified by some optimizations into code similar to this: + +.. code-block:: c + + if (a > n) { + nodupfunc(); + foo(); + } else { + nodupfunc(); + bar(); + } + +where the call to "nodupfunc" is duplicated and sunk into the two branches +of the condition. + + +nomicromips +----------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``nomicromips``","``gnu::nomicromips``","","","","","Yes" + +Clang supports the GNU style ``__attribute__((micromips))`` and +``__attribute__((nomicromips))`` attributes on MIPS targets. These attributes +may be attached to a function definition and instructs the backend to generate +or not to generate microMIPS code for that function. + +These attributes override the `-mmicromips` and `-mno-micromips` options +on the command line. + + +noreturn +-------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "","``noreturn``","","","","","Yes" + +A function declared as ``[[noreturn]]`` shall not return to its caller. The +compiler will generate a diagnostic for a function declared as ``[[noreturn]]`` +that appears to be capable of returning to its caller. + + +not_tail_called +--------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``not_tail_called``","``clang::not_tail_called``","``clang::not_tail_called``","","","","Yes" + +The ``not_tail_called`` attribute prevents tail-call optimization on statically bound calls. It has no effect on indirect calls. Virtual functions, objective-c methods, and functions marked as ``always_inline`` cannot be marked as ``not_tail_called``. + +For example, it prevents tail-call optimization in the following case: + + .. code-block:: c + + int __attribute__((not_tail_called)) foo1(int); + + int foo2(int a) { + return foo1(a); // No tail-call optimization on direct calls. + } + +However, it doesn't prevent tail-call optimization in this case: + + .. code-block:: c + + int __attribute__((not_tail_called)) foo1(int); + + int foo2(int a) { + int (*fn)(int) = &foo1; + + // not_tail_called has no effect on an indirect call even if the call can be + // resolved at compile time. + return (*fn)(a); + } + +Marking virtual functions as ``not_tail_called`` is an error: + + .. code-block:: c++ + + class Base { + public: + // not_tail_called on a virtual function is an error. + [[clang::not_tail_called]] virtual int foo1(); + + virtual int foo2(); + + // Non-virtual functions can be marked ``not_tail_called``. + [[clang::not_tail_called]] int foo3(); + }; + + class Derived1 : public Base { + public: + int foo1() override; + + // not_tail_called on a virtual function is an error. + [[clang::not_tail_called]] int foo2() override; + }; + + +nothrow +------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``nothrow``","``gnu::nothrow``","","``nothrow``","","","Yes" + +Clang supports the GNU style ``__attribute__((nothrow))`` and Microsoft style +``__declspec(nothrow)`` attribute as an equivalent of `noexcept` on function +declarations. This attribute informs the compiler that the annotated function +does not throw an exception. This prevents exception-unwinding. This attribute +is particularly useful on functions in the C Standard Library that are +guaranteed to not throw an exception. + + +ns_consumed +----------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``ns_consumed``","``clang::ns_consumed``","``clang::ns_consumed``","","","","Yes" + +The behavior of a function with respect to reference counting for Foundation +(Objective-C), CoreFoundation (C) and OSObject (C++) is determined by a naming +convention (e.g. functions starting with "get" are assumed to return at +``+0``). + +It can be overriden using a family of the following attributes. In +Objective-C, the annotation ``__attribute__((ns_returns_retained))`` applied to +a function communicates that the object is returned at ``+1``, and the caller +is responsible for freeing it. +Similiarly, the annotation ``__attribute__((ns_returns_not_retained))`` +specifies that the object is returned at ``+0`` and the ownership remains with +the callee. +The annotation ``__attribute__((ns_consumes_self))`` specifies that +the Objective-C method call consumes the reference to ``self``, e.g. by +attaching it to a supplied parameter. +Additionally, parameters can have an annotation +``__attribute__((ns_consumed))``, which specifies that passing an owned object +as that parameter effectively transfers the ownership, and the caller is no +longer responsible for it. +These attributes affect code generation when interacting with ARC code, and +they are used by the Clang Static Analyzer. + +In C programs using CoreFoundation, a similar set of attributes: +``__attribute__((cf_returns_not_retained))``, +``__attribute__((cf_returns_retained))`` and ``__attribute__((cf_consumed))`` +have the same respective semantics when applied to CoreFoundation objects. +These attributes affect code generation when interacting with ARC code, and +they are used by the Clang Static Analyzer. + +Finally, in C++ interacting with XNU kernel (objects inheriting from OSObject), +the same attribute family is present: +``__attribute__((os_returns_not_retained))``, +``__attribute__((os_returns_retained))`` and ``__attribute__((os_consumed))``, +with the same respective semantics. +Similar to ``__attribute__((ns_consumes_self))``, +``__attribute__((os_consumes_this))`` specifies that the method call consumes +the reference to "this" (e.g., when attaching it to a different object supplied +as a parameter). +Out parameters (parameters the function is meant to write into, +either via pointers-to-pointers or references-to-pointers) +may be annotated with ``__attribute__((os_returns_retained))`` +or ``__attribute__((os_returns_not_retained))`` which specifies that the object +written into the out parameter should (or respectively should not) be released +after use. +Since often out parameters may or may not be written depending on the exit +code of the function, +annotations ``__attribute__((os_returns_retained_on_zero))`` +and ``__attribute__((os_returns_retained_on_non_zero))`` specify that +an out parameter at ``+1`` is written if and only if the function returns a zero +(respectively non-zero) error code. +Observe that return-code-dependent out parameter annotations are only +available for retained out parameters, as non-retained object do not have to be +released by the callee. +These attributes are only used by the Clang Static Analyzer. + +The family of attributes ``X_returns_X_retained`` can be added to functions, +C++ methods, and Objective-C methods and properties. +Attributes ``X_consumed`` can be added to parameters of methods, functions, +and Objective-C methods. + + +ns_consumes_self +---------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``ns_consumes_self``","``clang::ns_consumes_self``","``clang::ns_consumes_self``","","","","Yes" + +The behavior of a function with respect to reference counting for Foundation +(Objective-C), CoreFoundation (C) and OSObject (C++) is determined by a naming +convention (e.g. functions starting with "get" are assumed to return at +``+0``). + +It can be overriden using a family of the following attributes. In +Objective-C, the annotation ``__attribute__((ns_returns_retained))`` applied to +a function communicates that the object is returned at ``+1``, and the caller +is responsible for freeing it. +Similiarly, the annotation ``__attribute__((ns_returns_not_retained))`` +specifies that the object is returned at ``+0`` and the ownership remains with +the callee. +The annotation ``__attribute__((ns_consumes_self))`` specifies that +the Objective-C method call consumes the reference to ``self``, e.g. by +attaching it to a supplied parameter. +Additionally, parameters can have an annotation +``__attribute__((ns_consumed))``, which specifies that passing an owned object +as that parameter effectively transfers the ownership, and the caller is no +longer responsible for it. +These attributes affect code generation when interacting with ARC code, and +they are used by the Clang Static Analyzer. + +In C programs using CoreFoundation, a similar set of attributes: +``__attribute__((cf_returns_not_retained))``, +``__attribute__((cf_returns_retained))`` and ``__attribute__((cf_consumed))`` +have the same respective semantics when applied to CoreFoundation objects. +These attributes affect code generation when interacting with ARC code, and +they are used by the Clang Static Analyzer. + +Finally, in C++ interacting with XNU kernel (objects inheriting from OSObject), +the same attribute family is present: +``__attribute__((os_returns_not_retained))``, +``__attribute__((os_returns_retained))`` and ``__attribute__((os_consumed))``, +with the same respective semantics. +Similar to ``__attribute__((ns_consumes_self))``, +``__attribute__((os_consumes_this))`` specifies that the method call consumes +the reference to "this" (e.g., when attaching it to a different object supplied +as a parameter). +Out parameters (parameters the function is meant to write into, +either via pointers-to-pointers or references-to-pointers) +may be annotated with ``__attribute__((os_returns_retained))`` +or ``__attribute__((os_returns_not_retained))`` which specifies that the object +written into the out parameter should (or respectively should not) be released +after use. +Since often out parameters may or may not be written depending on the exit +code of the function, +annotations ``__attribute__((os_returns_retained_on_zero))`` +and ``__attribute__((os_returns_retained_on_non_zero))`` specify that +an out parameter at ``+1`` is written if and only if the function returns a zero +(respectively non-zero) error code. +Observe that return-code-dependent out parameter annotations are only +available for retained out parameters, as non-retained object do not have to be +released by the callee. +These attributes are only used by the Clang Static Analyzer. + +The family of attributes ``X_returns_X_retained`` can be added to functions, +C++ methods, and Objective-C methods and properties. +Attributes ``X_consumed`` can be added to parameters of methods, functions, +and Objective-C methods. + + +ns_returns_autoreleased +----------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``ns_returns_autoreleased``","``clang::ns_returns_autoreleased``","``clang::ns_returns_autoreleased``","","","","" + +The behavior of a function with respect to reference counting for Foundation +(Objective-C), CoreFoundation (C) and OSObject (C++) is determined by a naming +convention (e.g. functions starting with "get" are assumed to return at +``+0``). + +It can be overriden using a family of the following attributes. In +Objective-C, the annotation ``__attribute__((ns_returns_retained))`` applied to +a function communicates that the object is returned at ``+1``, and the caller +is responsible for freeing it. +Similiarly, the annotation ``__attribute__((ns_returns_not_retained))`` +specifies that the object is returned at ``+0`` and the ownership remains with +the callee. +The annotation ``__attribute__((ns_consumes_self))`` specifies that +the Objective-C method call consumes the reference to ``self``, e.g. by +attaching it to a supplied parameter. +Additionally, parameters can have an annotation +``__attribute__((ns_consumed))``, which specifies that passing an owned object +as that parameter effectively transfers the ownership, and the caller is no +longer responsible for it. +These attributes affect code generation when interacting with ARC code, and +they are used by the Clang Static Analyzer. + +In C programs using CoreFoundation, a similar set of attributes: +``__attribute__((cf_returns_not_retained))``, +``__attribute__((cf_returns_retained))`` and ``__attribute__((cf_consumed))`` +have the same respective semantics when applied to CoreFoundation objects. +These attributes affect code generation when interacting with ARC code, and +they are used by the Clang Static Analyzer. + +Finally, in C++ interacting with XNU kernel (objects inheriting from OSObject), +the same attribute family is present: +``__attribute__((os_returns_not_retained))``, +``__attribute__((os_returns_retained))`` and ``__attribute__((os_consumed))``, +with the same respective semantics. +Similar to ``__attribute__((ns_consumes_self))``, +``__attribute__((os_consumes_this))`` specifies that the method call consumes +the reference to "this" (e.g., when attaching it to a different object supplied +as a parameter). +Out parameters (parameters the function is meant to write into, +either via pointers-to-pointers or references-to-pointers) +may be annotated with ``__attribute__((os_returns_retained))`` +or ``__attribute__((os_returns_not_retained))`` which specifies that the object +written into the out parameter should (or respectively should not) be released +after use. +Since often out parameters may or may not be written depending on the exit +code of the function, +annotations ``__attribute__((os_returns_retained_on_zero))`` +and ``__attribute__((os_returns_retained_on_non_zero))`` specify that +an out parameter at ``+1`` is written if and only if the function returns a zero +(respectively non-zero) error code. +Observe that return-code-dependent out parameter annotations are only +available for retained out parameters, as non-retained object do not have to be +released by the callee. +These attributes are only used by the Clang Static Analyzer. + +The family of attributes ``X_returns_X_retained`` can be added to functions, +C++ methods, and Objective-C methods and properties. +Attributes ``X_consumed`` can be added to parameters of methods, functions, +and Objective-C methods. + + +ns_returns_not_retained +----------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``ns_returns_not_retained``","``clang::ns_returns_not_retained``","``clang::ns_returns_not_retained``","","","","" + +The behavior of a function with respect to reference counting for Foundation +(Objective-C), CoreFoundation (C) and OSObject (C++) is determined by a naming +convention (e.g. functions starting with "get" are assumed to return at +``+0``). + +It can be overriden using a family of the following attributes. In +Objective-C, the annotation ``__attribute__((ns_returns_retained))`` applied to +a function communicates that the object is returned at ``+1``, and the caller +is responsible for freeing it. +Similiarly, the annotation ``__attribute__((ns_returns_not_retained))`` +specifies that the object is returned at ``+0`` and the ownership remains with +the callee. +The annotation ``__attribute__((ns_consumes_self))`` specifies that +the Objective-C method call consumes the reference to ``self``, e.g. by +attaching it to a supplied parameter. +Additionally, parameters can have an annotation +``__attribute__((ns_consumed))``, which specifies that passing an owned object +as that parameter effectively transfers the ownership, and the caller is no +longer responsible for it. +These attributes affect code generation when interacting with ARC code, and +they are used by the Clang Static Analyzer. + +In C programs using CoreFoundation, a similar set of attributes: +``__attribute__((cf_returns_not_retained))``, +``__attribute__((cf_returns_retained))`` and ``__attribute__((cf_consumed))`` +have the same respective semantics when applied to CoreFoundation objects. +These attributes affect code generation when interacting with ARC code, and +they are used by the Clang Static Analyzer. + +Finally, in C++ interacting with XNU kernel (objects inheriting from OSObject), +the same attribute family is present: +``__attribute__((os_returns_not_retained))``, +``__attribute__((os_returns_retained))`` and ``__attribute__((os_consumed))``, +with the same respective semantics. +Similar to ``__attribute__((ns_consumes_self))``, +``__attribute__((os_consumes_this))`` specifies that the method call consumes +the reference to "this" (e.g., when attaching it to a different object supplied +as a parameter). +Out parameters (parameters the function is meant to write into, +either via pointers-to-pointers or references-to-pointers) +may be annotated with ``__attribute__((os_returns_retained))`` +or ``__attribute__((os_returns_not_retained))`` which specifies that the object +written into the out parameter should (or respectively should not) be released +after use. +Since often out parameters may or may not be written depending on the exit +code of the function, +annotations ``__attribute__((os_returns_retained_on_zero))`` +and ``__attribute__((os_returns_retained_on_non_zero))`` specify that +an out parameter at ``+1`` is written if and only if the function returns a zero +(respectively non-zero) error code. +Observe that return-code-dependent out parameter annotations are only +available for retained out parameters, as non-retained object do not have to be +released by the callee. +These attributes are only used by the Clang Static Analyzer. + +The family of attributes ``X_returns_X_retained`` can be added to functions, +C++ methods, and Objective-C methods and properties. +Attributes ``X_consumed`` can be added to parameters of methods, functions, +and Objective-C methods. + + +ns_returns_retained +------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``ns_returns_retained``","``clang::ns_returns_retained``","``clang::ns_returns_retained``","","","","" + +The behavior of a function with respect to reference counting for Foundation +(Objective-C), CoreFoundation (C) and OSObject (C++) is determined by a naming +convention (e.g. functions starting with "get" are assumed to return at +``+0``). + +It can be overriden using a family of the following attributes. In +Objective-C, the annotation ``__attribute__((ns_returns_retained))`` applied to +a function communicates that the object is returned at ``+1``, and the caller +is responsible for freeing it. +Similiarly, the annotation ``__attribute__((ns_returns_not_retained))`` +specifies that the object is returned at ``+0`` and the ownership remains with +the callee. +The annotation ``__attribute__((ns_consumes_self))`` specifies that +the Objective-C method call consumes the reference to ``self``, e.g. by +attaching it to a supplied parameter. +Additionally, parameters can have an annotation +``__attribute__((ns_consumed))``, which specifies that passing an owned object +as that parameter effectively transfers the ownership, and the caller is no +longer responsible for it. +These attributes affect code generation when interacting with ARC code, and +they are used by the Clang Static Analyzer. + +In C programs using CoreFoundation, a similar set of attributes: +``__attribute__((cf_returns_not_retained))``, +``__attribute__((cf_returns_retained))`` and ``__attribute__((cf_consumed))`` +have the same respective semantics when applied to CoreFoundation objects. +These attributes affect code generation when interacting with ARC code, and +they are used by the Clang Static Analyzer. + +Finally, in C++ interacting with XNU kernel (objects inheriting from OSObject), +the same attribute family is present: +``__attribute__((os_returns_not_retained))``, +``__attribute__((os_returns_retained))`` and ``__attribute__((os_consumed))``, +with the same respective semantics. +Similar to ``__attribute__((ns_consumes_self))``, +``__attribute__((os_consumes_this))`` specifies that the method call consumes +the reference to "this" (e.g., when attaching it to a different object supplied +as a parameter). +Out parameters (parameters the function is meant to write into, +either via pointers-to-pointers or references-to-pointers) +may be annotated with ``__attribute__((os_returns_retained))`` +or ``__attribute__((os_returns_not_retained))`` which specifies that the object +written into the out parameter should (or respectively should not) be released +after use. +Since often out parameters may or may not be written depending on the exit +code of the function, +annotations ``__attribute__((os_returns_retained_on_zero))`` +and ``__attribute__((os_returns_retained_on_non_zero))`` specify that +an out parameter at ``+1`` is written if and only if the function returns a zero +(respectively non-zero) error code. +Observe that return-code-dependent out parameter annotations are only +available for retained out parameters, as non-retained object do not have to be +released by the callee. +These attributes are only used by the Clang Static Analyzer. + +The family of attributes ``X_returns_X_retained`` can be added to functions, +C++ methods, and Objective-C methods and properties. +Attributes ``X_consumed`` can be added to parameters of methods, functions, +and Objective-C methods. + + +objc_method_family +------------------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``objc_method_family``","``clang::objc_method_family``","``clang::objc_method_family``","","","","Yes" + +Many methods in Objective-C have conventional meanings determined by their +selectors. It is sometimes useful to be able to mark a method as having a +particular conventional meaning despite not having the right selector, or as +not having the conventional meaning that its selector would suggest. For these +use cases, we provide an attribute to specifically describe the "method family" +that a method belongs to. + +**Usage**: ``__attribute__((objc_method_family(X)))``, where ``X`` is one of +``none``, ``alloc``, ``copy``, ``init``, ``mutableCopy``, or ``new``. This +attribute can only be placed at the end of a method declaration: + +.. code-block:: objc + + - (NSString *)initMyStringValue __attribute__((objc_method_family(none))); + +Users who do not wish to change the conventional meaning of a method, and who +merely want to document its non-standard retain and release semantics, should +use the retaining behavior attributes (``ns_returns_retained``, +``ns_returns_not_retained``, etc). + +Query for this feature with ``__has_attribute(objc_method_family)``. + + +objc_requires_super +------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``objc_requires_super``","``clang::objc_requires_super``","``clang::objc_requires_super``","","","","Yes" + +Some Objective-C classes allow a subclass to override a particular method in a +parent class but expect that the overriding method also calls the overridden +method in the parent class. For these cases, we provide an attribute to +designate that a method requires a "call to ``super``" in the overriding +method in the subclass. + +**Usage**: ``__attribute__((objc_requires_super))``. This attribute can only +be placed at the end of a method declaration: + +.. code-block:: objc + + - (void)foo __attribute__((objc_requires_super)); + +This attribute can only be applied the method declarations within a class, and +not a protocol. Currently this attribute does not enforce any placement of +where the call occurs in the overriding method (such as in the case of +``-dealloc`` where the call must appear at the end). It checks only that it +exists. + +Note that on both OS X and iOS that the Foundation framework provides a +convenience macro ``NS_REQUIRES_SUPER`` that provides syntactic sugar for this +attribute: + +.. code-block:: objc + + - (void)foo NS_REQUIRES_SUPER; + +This macro is conditionally defined depending on the compiler's support for +this attribute. If the compiler does not support the attribute the macro +expands to nothing. + +Operationally, when a method has this annotation the compiler will warn if the +implementation of an override in a subclass does not call super. For example: + +.. code-block:: objc + + warning: method possibly missing a [super AnnotMeth] call + - (void) AnnotMeth{}; + ^ + + +optnone +------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``optnone``","``clang::optnone``","``clang::optnone``","","","","Yes" + +The ``optnone`` attribute suppresses essentially all optimizations +on a function or method, regardless of the optimization level applied to +the compilation unit as a whole. This is particularly useful when you +need to debug a particular function, but it is infeasible to build the +entire application without optimization. Avoiding optimization on the +specified function can improve the quality of the debugging information +for that function. + +This attribute is incompatible with the ``always_inline`` and ``minsize`` +attributes. + + +os_consumed +----------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``os_consumed``","``clang::os_consumed``","``clang::os_consumed``","","","","Yes" + +The behavior of a function with respect to reference counting for Foundation +(Objective-C), CoreFoundation (C) and OSObject (C++) is determined by a naming +convention (e.g. functions starting with "get" are assumed to return at +``+0``). + +It can be overriden using a family of the following attributes. In +Objective-C, the annotation ``__attribute__((ns_returns_retained))`` applied to +a function communicates that the object is returned at ``+1``, and the caller +is responsible for freeing it. +Similiarly, the annotation ``__attribute__((ns_returns_not_retained))`` +specifies that the object is returned at ``+0`` and the ownership remains with +the callee. +The annotation ``__attribute__((ns_consumes_self))`` specifies that +the Objective-C method call consumes the reference to ``self``, e.g. by +attaching it to a supplied parameter. +Additionally, parameters can have an annotation +``__attribute__((ns_consumed))``, which specifies that passing an owned object +as that parameter effectively transfers the ownership, and the caller is no +longer responsible for it. +These attributes affect code generation when interacting with ARC code, and +they are used by the Clang Static Analyzer. + +In C programs using CoreFoundation, a similar set of attributes: +``__attribute__((cf_returns_not_retained))``, +``__attribute__((cf_returns_retained))`` and ``__attribute__((cf_consumed))`` +have the same respective semantics when applied to CoreFoundation objects. +These attributes affect code generation when interacting with ARC code, and +they are used by the Clang Static Analyzer. + +Finally, in C++ interacting with XNU kernel (objects inheriting from OSObject), +the same attribute family is present: +``__attribute__((os_returns_not_retained))``, +``__attribute__((os_returns_retained))`` and ``__attribute__((os_consumed))``, +with the same respective semantics. +Similar to ``__attribute__((ns_consumes_self))``, +``__attribute__((os_consumes_this))`` specifies that the method call consumes +the reference to "this" (e.g., when attaching it to a different object supplied +as a parameter). +Out parameters (parameters the function is meant to write into, +either via pointers-to-pointers or references-to-pointers) +may be annotated with ``__attribute__((os_returns_retained))`` +or ``__attribute__((os_returns_not_retained))`` which specifies that the object +written into the out parameter should (or respectively should not) be released +after use. +Since often out parameters may or may not be written depending on the exit +code of the function, +annotations ``__attribute__((os_returns_retained_on_zero))`` +and ``__attribute__((os_returns_retained_on_non_zero))`` specify that +an out parameter at ``+1`` is written if and only if the function returns a zero +(respectively non-zero) error code. +Observe that return-code-dependent out parameter annotations are only +available for retained out parameters, as non-retained object do not have to be +released by the callee. +These attributes are only used by the Clang Static Analyzer. + +The family of attributes ``X_returns_X_retained`` can be added to functions, +C++ methods, and Objective-C methods and properties. +Attributes ``X_consumed`` can be added to parameters of methods, functions, +and Objective-C methods. + + +os_consumes_this +---------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``os_consumes_this``","``clang::os_consumes_this``","``clang::os_consumes_this``","","","","" + +The behavior of a function with respect to reference counting for Foundation +(Objective-C), CoreFoundation (C) and OSObject (C++) is determined by a naming +convention (e.g. functions starting with "get" are assumed to return at +``+0``). + +It can be overriden using a family of the following attributes. In +Objective-C, the annotation ``__attribute__((ns_returns_retained))`` applied to +a function communicates that the object is returned at ``+1``, and the caller +is responsible for freeing it. +Similiarly, the annotation ``__attribute__((ns_returns_not_retained))`` +specifies that the object is returned at ``+0`` and the ownership remains with +the callee. +The annotation ``__attribute__((ns_consumes_self))`` specifies that +the Objective-C method call consumes the reference to ``self``, e.g. by +attaching it to a supplied parameter. +Additionally, parameters can have an annotation +``__attribute__((ns_consumed))``, which specifies that passing an owned object +as that parameter effectively transfers the ownership, and the caller is no +longer responsible for it. +These attributes affect code generation when interacting with ARC code, and +they are used by the Clang Static Analyzer. + +In C programs using CoreFoundation, a similar set of attributes: +``__attribute__((cf_returns_not_retained))``, +``__attribute__((cf_returns_retained))`` and ``__attribute__((cf_consumed))`` +have the same respective semantics when applied to CoreFoundation objects. +These attributes affect code generation when interacting with ARC code, and +they are used by the Clang Static Analyzer. + +Finally, in C++ interacting with XNU kernel (objects inheriting from OSObject), +the same attribute family is present: +``__attribute__((os_returns_not_retained))``, +``__attribute__((os_returns_retained))`` and ``__attribute__((os_consumed))``, +with the same respective semantics. +Similar to ``__attribute__((ns_consumes_self))``, +``__attribute__((os_consumes_this))`` specifies that the method call consumes +the reference to "this" (e.g., when attaching it to a different object supplied +as a parameter). +Out parameters (parameters the function is meant to write into, +either via pointers-to-pointers or references-to-pointers) +may be annotated with ``__attribute__((os_returns_retained))`` +or ``__attribute__((os_returns_not_retained))`` which specifies that the object +written into the out parameter should (or respectively should not) be released +after use. +Since often out parameters may or may not be written depending on the exit +code of the function, +annotations ``__attribute__((os_returns_retained_on_zero))`` +and ``__attribute__((os_returns_retained_on_non_zero))`` specify that +an out parameter at ``+1`` is written if and only if the function returns a zero +(respectively non-zero) error code. +Observe that return-code-dependent out parameter annotations are only +available for retained out parameters, as non-retained object do not have to be +released by the callee. +These attributes are only used by the Clang Static Analyzer. + +The family of attributes ``X_returns_X_retained`` can be added to functions, +C++ methods, and Objective-C methods and properties. +Attributes ``X_consumed`` can be added to parameters of methods, functions, +and Objective-C methods. + + +os_returns_not_retained +----------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``os_returns_not_retained``","``clang::os_returns_not_retained``","``clang::os_returns_not_retained``","","","","Yes" + +The behavior of a function with respect to reference counting for Foundation +(Objective-C), CoreFoundation (C) and OSObject (C++) is determined by a naming +convention (e.g. functions starting with "get" are assumed to return at +``+0``). + +It can be overriden using a family of the following attributes. In +Objective-C, the annotation ``__attribute__((ns_returns_retained))`` applied to +a function communicates that the object is returned at ``+1``, and the caller +is responsible for freeing it. +Similiarly, the annotation ``__attribute__((ns_returns_not_retained))`` +specifies that the object is returned at ``+0`` and the ownership remains with +the callee. +The annotation ``__attribute__((ns_consumes_self))`` specifies that +the Objective-C method call consumes the reference to ``self``, e.g. by +attaching it to a supplied parameter. +Additionally, parameters can have an annotation +``__attribute__((ns_consumed))``, which specifies that passing an owned object +as that parameter effectively transfers the ownership, and the caller is no +longer responsible for it. +These attributes affect code generation when interacting with ARC code, and +they are used by the Clang Static Analyzer. + +In C programs using CoreFoundation, a similar set of attributes: +``__attribute__((cf_returns_not_retained))``, +``__attribute__((cf_returns_retained))`` and ``__attribute__((cf_consumed))`` +have the same respective semantics when applied to CoreFoundation objects. +These attributes affect code generation when interacting with ARC code, and +they are used by the Clang Static Analyzer. + +Finally, in C++ interacting with XNU kernel (objects inheriting from OSObject), +the same attribute family is present: +``__attribute__((os_returns_not_retained))``, +``__attribute__((os_returns_retained))`` and ``__attribute__((os_consumed))``, +with the same respective semantics. +Similar to ``__attribute__((ns_consumes_self))``, +``__attribute__((os_consumes_this))`` specifies that the method call consumes +the reference to "this" (e.g., when attaching it to a different object supplied +as a parameter). +Out parameters (parameters the function is meant to write into, +either via pointers-to-pointers or references-to-pointers) +may be annotated with ``__attribute__((os_returns_retained))`` +or ``__attribute__((os_returns_not_retained))`` which specifies that the object +written into the out parameter should (or respectively should not) be released +after use. +Since often out parameters may or may not be written depending on the exit +code of the function, +annotations ``__attribute__((os_returns_retained_on_zero))`` +and ``__attribute__((os_returns_retained_on_non_zero))`` specify that +an out parameter at ``+1`` is written if and only if the function returns a zero +(respectively non-zero) error code. +Observe that return-code-dependent out parameter annotations are only +available for retained out parameters, as non-retained object do not have to be +released by the callee. +These attributes are only used by the Clang Static Analyzer. + +The family of attributes ``X_returns_X_retained`` can be added to functions, +C++ methods, and Objective-C methods and properties. +Attributes ``X_consumed`` can be added to parameters of methods, functions, +and Objective-C methods. + + +os_returns_retained +------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``os_returns_retained``","``clang::os_returns_retained``","``clang::os_returns_retained``","","","","Yes" + +The behavior of a function with respect to reference counting for Foundation +(Objective-C), CoreFoundation (C) and OSObject (C++) is determined by a naming +convention (e.g. functions starting with "get" are assumed to return at +``+0``). + +It can be overriden using a family of the following attributes. In +Objective-C, the annotation ``__attribute__((ns_returns_retained))`` applied to +a function communicates that the object is returned at ``+1``, and the caller +is responsible for freeing it. +Similiarly, the annotation ``__attribute__((ns_returns_not_retained))`` +specifies that the object is returned at ``+0`` and the ownership remains with +the callee. +The annotation ``__attribute__((ns_consumes_self))`` specifies that +the Objective-C method call consumes the reference to ``self``, e.g. by +attaching it to a supplied parameter. +Additionally, parameters can have an annotation +``__attribute__((ns_consumed))``, which specifies that passing an owned object +as that parameter effectively transfers the ownership, and the caller is no +longer responsible for it. +These attributes affect code generation when interacting with ARC code, and +they are used by the Clang Static Analyzer. + +In C programs using CoreFoundation, a similar set of attributes: +``__attribute__((cf_returns_not_retained))``, +``__attribute__((cf_returns_retained))`` and ``__attribute__((cf_consumed))`` +have the same respective semantics when applied to CoreFoundation objects. +These attributes affect code generation when interacting with ARC code, and +they are used by the Clang Static Analyzer. + +Finally, in C++ interacting with XNU kernel (objects inheriting from OSObject), +the same attribute family is present: +``__attribute__((os_returns_not_retained))``, +``__attribute__((os_returns_retained))`` and ``__attribute__((os_consumed))``, +with the same respective semantics. +Similar to ``__attribute__((ns_consumes_self))``, +``__attribute__((os_consumes_this))`` specifies that the method call consumes +the reference to "this" (e.g., when attaching it to a different object supplied +as a parameter). +Out parameters (parameters the function is meant to write into, +either via pointers-to-pointers or references-to-pointers) +may be annotated with ``__attribute__((os_returns_retained))`` +or ``__attribute__((os_returns_not_retained))`` which specifies that the object +written into the out parameter should (or respectively should not) be released +after use. +Since often out parameters may or may not be written depending on the exit +code of the function, +annotations ``__attribute__((os_returns_retained_on_zero))`` +and ``__attribute__((os_returns_retained_on_non_zero))`` specify that +an out parameter at ``+1`` is written if and only if the function returns a zero +(respectively non-zero) error code. +Observe that return-code-dependent out parameter annotations are only +available for retained out parameters, as non-retained object do not have to be +released by the callee. +These attributes are only used by the Clang Static Analyzer. + +The family of attributes ``X_returns_X_retained`` can be added to functions, +C++ methods, and Objective-C methods and properties. +Attributes ``X_consumed`` can be added to parameters of methods, functions, +and Objective-C methods. + + +os_returns_retained_on_non_zero +------------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``os_returns_retained_on_non_zero``","``clang::os_returns_retained_on_non_zero``","``clang::os_returns_retained_on_non_zero``","","","","Yes" + +The behavior of a function with respect to reference counting for Foundation +(Objective-C), CoreFoundation (C) and OSObject (C++) is determined by a naming +convention (e.g. functions starting with "get" are assumed to return at +``+0``). + +It can be overriden using a family of the following attributes. In +Objective-C, the annotation ``__attribute__((ns_returns_retained))`` applied to +a function communicates that the object is returned at ``+1``, and the caller +is responsible for freeing it. +Similiarly, the annotation ``__attribute__((ns_returns_not_retained))`` +specifies that the object is returned at ``+0`` and the ownership remains with +the callee. +The annotation ``__attribute__((ns_consumes_self))`` specifies that +the Objective-C method call consumes the reference to ``self``, e.g. by +attaching it to a supplied parameter. +Additionally, parameters can have an annotation +``__attribute__((ns_consumed))``, which specifies that passing an owned object +as that parameter effectively transfers the ownership, and the caller is no +longer responsible for it. +These attributes affect code generation when interacting with ARC code, and +they are used by the Clang Static Analyzer. + +In C programs using CoreFoundation, a similar set of attributes: +``__attribute__((cf_returns_not_retained))``, +``__attribute__((cf_returns_retained))`` and ``__attribute__((cf_consumed))`` +have the same respective semantics when applied to CoreFoundation objects. +These attributes affect code generation when interacting with ARC code, and +they are used by the Clang Static Analyzer. + +Finally, in C++ interacting with XNU kernel (objects inheriting from OSObject), +the same attribute family is present: +``__attribute__((os_returns_not_retained))``, +``__attribute__((os_returns_retained))`` and ``__attribute__((os_consumed))``, +with the same respective semantics. +Similar to ``__attribute__((ns_consumes_self))``, +``__attribute__((os_consumes_this))`` specifies that the method call consumes +the reference to "this" (e.g., when attaching it to a different object supplied +as a parameter). +Out parameters (parameters the function is meant to write into, +either via pointers-to-pointers or references-to-pointers) +may be annotated with ``__attribute__((os_returns_retained))`` +or ``__attribute__((os_returns_not_retained))`` which specifies that the object +written into the out parameter should (or respectively should not) be released +after use. +Since often out parameters may or may not be written depending on the exit +code of the function, +annotations ``__attribute__((os_returns_retained_on_zero))`` +and ``__attribute__((os_returns_retained_on_non_zero))`` specify that +an out parameter at ``+1`` is written if and only if the function returns a zero +(respectively non-zero) error code. +Observe that return-code-dependent out parameter annotations are only +available for retained out parameters, as non-retained object do not have to be +released by the callee. +These attributes are only used by the Clang Static Analyzer. + +The family of attributes ``X_returns_X_retained`` can be added to functions, +C++ methods, and Objective-C methods and properties. +Attributes ``X_consumed`` can be added to parameters of methods, functions, +and Objective-C methods. + + +os_returns_retained_on_zero +--------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``os_returns_retained_on_zero``","``clang::os_returns_retained_on_zero``","``clang::os_returns_retained_on_zero``","","","","Yes" + +The behavior of a function with respect to reference counting for Foundation +(Objective-C), CoreFoundation (C) and OSObject (C++) is determined by a naming +convention (e.g. functions starting with "get" are assumed to return at +``+0``). + +It can be overriden using a family of the following attributes. In +Objective-C, the annotation ``__attribute__((ns_returns_retained))`` applied to +a function communicates that the object is returned at ``+1``, and the caller +is responsible for freeing it. +Similiarly, the annotation ``__attribute__((ns_returns_not_retained))`` +specifies that the object is returned at ``+0`` and the ownership remains with +the callee. +The annotation ``__attribute__((ns_consumes_self))`` specifies that +the Objective-C method call consumes the reference to ``self``, e.g. by +attaching it to a supplied parameter. +Additionally, parameters can have an annotation +``__attribute__((ns_consumed))``, which specifies that passing an owned object +as that parameter effectively transfers the ownership, and the caller is no +longer responsible for it. +These attributes affect code generation when interacting with ARC code, and +they are used by the Clang Static Analyzer. + +In C programs using CoreFoundation, a similar set of attributes: +``__attribute__((cf_returns_not_retained))``, +``__attribute__((cf_returns_retained))`` and ``__attribute__((cf_consumed))`` +have the same respective semantics when applied to CoreFoundation objects. +These attributes affect code generation when interacting with ARC code, and +they are used by the Clang Static Analyzer. + +Finally, in C++ interacting with XNU kernel (objects inheriting from OSObject), +the same attribute family is present: +``__attribute__((os_returns_not_retained))``, +``__attribute__((os_returns_retained))`` and ``__attribute__((os_consumed))``, +with the same respective semantics. +Similar to ``__attribute__((ns_consumes_self))``, +``__attribute__((os_consumes_this))`` specifies that the method call consumes +the reference to "this" (e.g., when attaching it to a different object supplied +as a parameter). +Out parameters (parameters the function is meant to write into, +either via pointers-to-pointers or references-to-pointers) +may be annotated with ``__attribute__((os_returns_retained))`` +or ``__attribute__((os_returns_not_retained))`` which specifies that the object +written into the out parameter should (or respectively should not) be released +after use. +Since often out parameters may or may not be written depending on the exit +code of the function, +annotations ``__attribute__((os_returns_retained_on_zero))`` +and ``__attribute__((os_returns_retained_on_non_zero))`` specify that +an out parameter at ``+1`` is written if and only if the function returns a zero +(respectively non-zero) error code. +Observe that return-code-dependent out parameter annotations are only +available for retained out parameters, as non-retained object do not have to be +released by the callee. +These attributes are only used by the Clang Static Analyzer. + +The family of attributes ``X_returns_X_retained`` can be added to functions, +C++ methods, and Objective-C methods and properties. +Attributes ``X_consumed`` can be added to parameters of methods, functions, +and Objective-C methods. + + +overloadable +------------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``overloadable``","``clang::overloadable``","``clang::overloadable``","","","","Yes" + +Clang provides support for C++ function overloading in C. Function overloading +in C is introduced using the ``overloadable`` attribute. For example, one +might provide several overloaded versions of a ``tgsin`` function that invokes +the appropriate standard function computing the sine of a value with ``float``, +``double``, or ``long double`` precision: + +.. code-block:: c + + #include + float __attribute__((overloadable)) tgsin(float x) { return sinf(x); } + double __attribute__((overloadable)) tgsin(double x) { return sin(x); } + long double __attribute__((overloadable)) tgsin(long double x) { return sinl(x); } + +Given these declarations, one can call ``tgsin`` with a ``float`` value to +receive a ``float`` result, with a ``double`` to receive a ``double`` result, +etc. Function overloading in C follows the rules of C++ function overloading +to pick the best overload given the call arguments, with a few C-specific +semantics: + +* Conversion from ``float`` or ``double`` to ``long double`` is ranked as a + floating-point promotion (per C99) rather than as a floating-point conversion + (as in C++). + +* A conversion from a pointer of type ``T*`` to a pointer of type ``U*`` is + considered a pointer conversion (with conversion rank) if ``T`` and ``U`` are + compatible types. + +* A conversion from type ``T`` to a value of type ``U`` is permitted if ``T`` + and ``U`` are compatible types. This conversion is given "conversion" rank. + +* If no viable candidates are otherwise available, we allow a conversion from a + pointer of type ``T*`` to a pointer of type ``U*``, where ``T`` and ``U`` are + incompatible. This conversion is ranked below all other types of conversions. + Please note: ``U`` lacking qualifiers that are present on ``T`` is sufficient + for ``T`` and ``U`` to be incompatible. + +The declaration of ``overloadable`` functions is restricted to function +declarations and definitions. If a function is marked with the ``overloadable`` +attribute, then all declarations and definitions of functions with that name, +except for at most one (see the note below about unmarked overloads), must have +the ``overloadable`` attribute. In addition, redeclarations of a function with +the ``overloadable`` attribute must have the ``overloadable`` attribute, and +redeclarations of a function without the ``overloadable`` attribute must *not* +have the ``overloadable`` attribute. e.g., + +.. code-block:: c + + int f(int) __attribute__((overloadable)); + float f(float); // error: declaration of "f" must have the "overloadable" attribute + int f(int); // error: redeclaration of "f" must have the "overloadable" attribute + + int g(int) __attribute__((overloadable)); + int g(int) { } // error: redeclaration of "g" must also have the "overloadable" attribute + + int h(int); + int h(int) __attribute__((overloadable)); // error: declaration of "h" must not + // have the "overloadable" attribute + +Functions marked ``overloadable`` must have prototypes. Therefore, the +following code is ill-formed: + +.. code-block:: c + + int h() __attribute__((overloadable)); // error: h does not have a prototype + +However, ``overloadable`` functions are allowed to use a ellipsis even if there +are no named parameters (as is permitted in C++). This feature is particularly +useful when combined with the ``unavailable`` attribute: + +.. code-block:: c++ + + void honeypot(...) __attribute__((overloadable, unavailable)); // calling me is an error + +Functions declared with the ``overloadable`` attribute have their names mangled +according to the same rules as C++ function names. For example, the three +``tgsin`` functions in our motivating example get the mangled names +``_Z5tgsinf``, ``_Z5tgsind``, and ``_Z5tgsine``, respectively. There are two +caveats to this use of name mangling: + +* Future versions of Clang may change the name mangling of functions overloaded + in C, so you should not depend on an specific mangling. To be completely + safe, we strongly urge the use of ``static inline`` with ``overloadable`` + functions. + +* The ``overloadable`` attribute has almost no meaning when used in C++, + because names will already be mangled and functions are already overloadable. + However, when an ``overloadable`` function occurs within an ``extern "C"`` + linkage specification, it's name *will* be mangled in the same way as it + would in C. + +For the purpose of backwards compatibility, at most one function with the same +name as other ``overloadable`` functions may omit the ``overloadable`` +attribute. In this case, the function without the ``overloadable`` attribute +will not have its name mangled. + +For example: + +.. code-block:: c + + // Notes with mangled names assume Itanium mangling. + int f(int); + int f(double) __attribute__((overloadable)); + void foo() { + f(5); // Emits a call to f (not _Z1fi, as it would with an overload that + // was marked with overloadable). + f(1.0); // Emits a call to _Z1fd. + } + +Support for unmarked overloads is not present in some versions of clang. You may +query for it using ``__has_extension(overloadable_unmarked)``. + +Query for this attribute with ``__has_attribute(overloadable)``. + + +reinitializes +------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``reinitializes``","``clang::reinitializes``","","","","","" + +The ``reinitializes`` attribute can be applied to a non-static, non-const C++ +member function to indicate that this member function reinitializes the entire +object to a known state, independent of the previous state of the object. + +This attribute can be interpreted by static analyzers that warn about uses of an +object that has been left in an indeterminate state by a move operation. If a +member function marked with the ``reinitializes`` attribute is called on a +moved-from object, the analyzer can conclude that the object is no longer in an +indeterminate state. + +A typical example where this attribute would be used is on functions that clear +a container class: + +.. code-block:: c++ + + template + class Container { + public: + ... + [[clang::reinitializes]] void Clear(); + ... + }; + + +release_capability, release_shared_capability +--------------------------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``release_capability`` |br| ``release_shared_capability`` |br| ``release_generic_capability`` |br| ``unlock_function``","``clang::release_capability`` |br| ``clang::release_shared_capability`` |br| ``clang::release_generic_capability`` |br| ``clang::unlock_function``","","","","","" + +Marks a function as releasing a capability. + + +short_call, near +---------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``short_call`` |br| ``near``","``gnu::short_call`` |br| ``gnu::near``","","","","","Yes" + +Clang supports the ``__attribute__((long_call))``, ``__attribute__((far))``, +``__attribute__((short__call))``, and ``__attribute__((near))`` attributes +on MIPS targets. These attributes may only be added to function declarations +and change the code generated by the compiler when directly calling +the function. The ``short_call`` and ``near`` attributes are synonyms and +allow calls to the function to be made using the ``jal`` instruction, which +requires the function to be located in the same naturally aligned 256MB segment +as the caller. The ``long_call`` and ``far`` attributes are synonyms and +require the use of a different call sequence that works regardless +of the distance between the functions. + +These attributes have no effect for position-independent code. + +These attributes take priority over command line switches such +as ``-mlong-calls`` and ``-mno-long-calls``. + + +signal +------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``signal``","``gnu::signal``","","","","","Yes" + +Clang supports the GNU style ``__attribute__((signal))`` attribute on +AVR targets. This attribute may be attached to a function definition and instructs +the backend to generate appropriate function entry/exit code so that it can be used +directly as an interrupt service routine. + +Interrupt handler functions defined with the signal attribute do not re-enable interrupts. + + +speculative_load_hardening +-------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``speculative_load_hardening``","``clang::speculative_load_hardening``","``clang::speculative_load_hardening``","","","","Yes" + +This attribute can be applied to a function declaration in order to indicate + that `Speculative Load Hardening `_ + should be enabled for the function body. This can also be applied to a method + in Objective C. This attribute will take precedence over the command line flag in + the case where `-mno-speculative-load-hardening `_ is specified. + + Speculative Load Hardening is a best-effort mitigation against + information leak attacks that make use of control flow + miss-speculation - specifically miss-speculation of whether a branch + is taken or not. Typically vulnerabilities enabling such attacks are + classified as "Spectre variant #1". Notably, this does not attempt to + mitigate against miss-speculation of branch target, classified as + "Spectre variant #2" vulnerabilities. + + When inlining, the attribute is sticky. Inlining a function that + carries this attribute will cause the caller to gain the + attribute. This is intended to provide a maximally conservative model + where the code in a function annotated with this attribute will always + (even after inlining) end up hardened. + + +target +------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``target``","``gnu::target``","","","","","Yes" + +Clang supports the GNU style ``__attribute__((target("OPTIONS")))`` attribute. +This attribute may be attached to a function definition and instructs +the backend to use different code generation options than were passed on the +command line. + +The current set of options correspond to the existing "subtarget features" for +the target with or without a "-mno-" in front corresponding to the absence +of the feature, as well as ``arch="CPU"`` which will change the default "CPU" +for the function. + +Example "subtarget features" from the x86 backend include: "mmx", "sse", "sse4.2", +"avx", "xop" and largely correspond to the machine specific options handled by +the front end. + +Additionally, this attribute supports function multiversioning for ELF based +x86/x86-64 targets, which can be used to create multiple implementations of the +same function that will be resolved at runtime based on the priority of their +``target`` attribute strings. A function is considered a multiversioned function +if either two declarations of the function have different ``target`` attribute +strings, or if it has a ``target`` attribute string of ``default``. For +example: + + .. code-block:: c++ + + __attribute__((target("arch=atom"))) + void foo() {} // will be called on 'atom' processors. + __attribute__((target("default"))) + void foo() {} // will be called on any other processors. + +All multiversioned functions must contain a ``default`` (fallback) +implementation, otherwise usages of the function are considered invalid. +Additionally, a function may not become multiversioned after its first use. + + +try_acquire_capability, try_acquire_shared_capability +----------------------------------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``try_acquire_capability`` |br| ``try_acquire_shared_capability``","``clang::try_acquire_capability`` |br| ``clang::try_acquire_shared_capability``","","","","","" + +Marks a function that attempts to acquire a capability. This function may fail to +actually acquire the capability; they accept a Boolean value determining +whether acquiring the capability means success (true), or failing to acquire +the capability means success (false). + + +xray_always_instrument, xray_never_instrument, xray_log_args +------------------------------------------------------------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``xray_always_instrument`` |br| ``xray_never_instrument``","``clang::xray_always_instrument`` |br| ``clang::xray_never_instrument``","``clang::xray_always_instrument`` |br| ``clang::xray_never_instrument``","","","","Yes" + +``__attribute__((xray_always_instrument))`` or ``[[clang::xray_always_instrument]]`` is used to mark member functions (in C++), methods (in Objective C), and free functions (in C, C++, and Objective C) to be instrumented with XRay. This will cause the function to always have space at the beginning and exit points to allow for runtime patching. + +Conversely, ``__attribute__((xray_never_instrument))`` or ``[[clang::xray_never_instrument]]`` will inhibit the insertion of these instrumentation points. + +If a function has neither of these attributes, they become subject to the XRay heuristics used to determine whether a function should be instrumented or otherwise. + +``__attribute__((xray_log_args(N)))`` or ``[[clang::xray_log_args(N)]]`` is used to preserve N function arguments for the logging function. Currently, only N==1 is supported. + + +xray_always_instrument, xray_never_instrument, xray_log_args +------------------------------------------------------------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``xray_log_args``","``clang::xray_log_args``","``clang::xray_log_args``","","","","Yes" + +``__attribute__((xray_always_instrument))`` or ``[[clang::xray_always_instrument]]`` is used to mark member functions (in C++), methods (in Objective C), and free functions (in C, C++, and Objective C) to be instrumented with XRay. This will cause the function to always have space at the beginning and exit points to allow for runtime patching. + +Conversely, ``__attribute__((xray_never_instrument))`` or ``[[clang::xray_never_instrument]]`` will inhibit the insertion of these instrumentation points. + +If a function has neither of these attributes, they become subject to the XRay heuristics used to determine whether a function should be instrumented or otherwise. + +``__attribute__((xray_log_args(N)))`` or ``[[clang::xray_log_args(N)]]`` is used to preserve N function arguments for the logging function. Currently, only N==1 is supported. + + +Variable Attributes +=================== + + +always_destroy +-------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``always_destroy``","``clang::always_destroy``","","","","","Yes" + +The ``always_destroy`` attribute specifies that a variable with static or thread +storage duration should have its exit-time destructor run. This attribute is the +default unless clang was invoked with -fno-c++-static-destructors. + + +dllexport +--------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``dllexport``","``gnu::dllexport``","","``dllexport``","","","Yes" + +The ``__declspec(dllexport)`` attribute declares a variable, function, or +Objective-C interface to be exported from the module. It is available under the +``-fdeclspec`` flag for compatibility with various compilers. The primary use +is for COFF object files which explicitly specify what interfaces are available +for external use. See the dllexport_ documentation on MSDN for more +information. + +.. _dllexport: https://msdn.microsoft.com/en-us/library/3y1sfaz2.aspx + + +dllimport +--------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``dllimport``","``gnu::dllimport``","","``dllimport``","","","Yes" + +The ``__declspec(dllimport)`` attribute declares a variable, function, or +Objective-C interface to be imported from an external module. It is available +under the ``-fdeclspec`` flag for compatibility with various compilers. The +primary use is for COFF object files which explicitly specify what interfaces +are imported from external modules. See the dllimport_ documentation on MSDN +for more information. + +.. _dllimport: https://msdn.microsoft.com/en-us/library/3y1sfaz2.aspx + + +init_seg +-------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "","","","","","``init_seg``","" + +The attribute applied by ``pragma init_seg()`` controls the section into +which global initialization function pointers are emitted. It is only +available with ``-fms-extensions``. Typically, this function pointer is +emitted into ``.CRT$XCU`` on Windows. The user can change the order of +initialization by using a different section name with the same +``.CRT$XC`` prefix and a suffix that sorts lexicographically before or +after the standard ``.CRT$XCU`` sections. See the init_seg_ +documentation on MSDN for more information. + +.. _init_seg: http://msdn.microsoft.com/en-us/library/7977wcck(v=vs.110).aspx + + +maybe_unused, unused +-------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``unused``","``maybe_unused`` |br| ``gnu::unused``","``maybe_unused``","","","","" + +When passing the ``-Wunused`` flag to Clang, entities that are unused by the +program may be diagnosed. The ``[[maybe_unused]]`` (or +``__attribute__((unused))``) attribute can be used to silence such diagnostics +when the entity cannot be removed. For instance, a local variable may exist +solely for use in an ``assert()`` statement, which makes the local variable +unused when ``NDEBUG`` is defined. + +The attribute may be applied to the declaration of a class, a typedef, a +variable, a function or method, a function parameter, an enumeration, an +enumerator, a non-static data member, or a label. + +.. code-block: c++ + #include + + [[maybe_unused]] void f([[maybe_unused]] bool thing1, + [[maybe_unused]] bool thing2) { + [[maybe_unused]] bool b = thing1 && thing2; + assert(b); + } + + +no_destroy +---------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``no_destroy``","``clang::no_destroy``","","","","","Yes" + +The ``no_destroy`` attribute specifies that a variable with static or thread +storage duration shouldn't have its exit-time destructor run. Annotating every +static and thread duration variable with this attribute is equivalent to +invoking clang with -fno-c++-static-destructors. + +If a variable is declared with this attribute, clang doesn't access check or +generate the type's destructor. If you have a type that you only want to be +annotated with ``no_destroy``, you can therefore declare the destructor private: + +.. code-block:: c++ + + struct only_no_destroy { + only_no_destroy(); + private: + ~only_no_destroy(); + }; + + [[clang::no_destroy]] only_no_destroy global; // fine! + +Note that destructors are still required for subobjects of aggregates annotated +with this attribute. This is because previously constructed subobjects need to +be destroyed if an exception gets thrown before the initialization of the +complete object is complete. For instance: + +.. code-block::c++ + + void f() { + try { + [[clang::no_destroy]] + static only_no_destroy array[10]; // error, only_no_destroy has a private destructor. + } catch (...) { + // Handle the error + } + } + +Here, if the construction of `array[9]` fails with an exception, `array[0..8]` +will be destroyed, so the element's destructor needs to be accessible. + + +nodebug +------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``nodebug``","``gnu::nodebug``","","","","","Yes" + +The ``nodebug`` attribute allows you to suppress debugging information for a +function or method, or for a variable that is not a parameter or a non-static +data member. + + +noescape +-------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``noescape``","``clang::noescape``","``clang::noescape``","","","","Yes" + +``noescape`` placed on a function parameter of a pointer type is used to inform +the compiler that the pointer cannot escape: that is, no reference to the object +the pointer points to that is derived from the parameter value will survive +after the function returns. Users are responsible for making sure parameters +annotated with ``noescape`` do not actuallly escape. + +For example: + +.. code-block:: c + + int *gp; + + void nonescapingFunc(__attribute__((noescape)) int *p) { + *p += 100; // OK. + } + + void escapingFunc(__attribute__((noescape)) int *p) { + gp = p; // Not OK. + } + +Additionally, when the parameter is a `block pointer +`, the same restriction +applies to copies of the block. For example: + +.. code-block:: c + + typedef void (^BlockTy)(); + BlockTy g0, g1; + + void nonescapingFunc(__attribute__((noescape)) BlockTy block) { + block(); // OK. + } + + void escapingFunc(__attribute__((noescape)) BlockTy block) { + g0 = block; // Not OK. + g1 = Block_copy(block); // Not OK either. + } + + +nosvm +----- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``nosvm``","","","","","","Yes" + +OpenCL 2.0 supports the optional ``__attribute__((nosvm))`` qualifier for +pointer variable. It informs the compiler that the pointer does not refer +to a shared virtual memory region. See OpenCL v2.0 s6.7.2 for details. + +Since it is not widely used and has been removed from OpenCL 2.1, it is ignored +by Clang. + + +objc_externally_retained +------------------------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``objc_externally_retained``","``clang::objc_externally_retained``","``clang::objc_externally_retained``","","","","Yes" + +The ``objc_externally_retained`` attribute can be applied to strong local +variables, functions, methods, or blocks to opt into +`externally-retained semantics +`_. + +When applied to the definition of a function, method, or block, every parameter +of the function with implicit strong retainable object pointer type is +considered externally-retained, and becomes ``const``. By explicitly annotating +a parameter with ``__strong``, you can opt back into the default +non-externally-retained behaviour for that parameter. For instance, +``first_param`` is externally-retained below, but not ``second_param``: + +.. code-block:: objc + + __attribute__((objc_externally_retained)) + void f(NSArray *first_param, __strong NSArray *second_param) { + // ... + } + +Likewise, when applied to a strong local variable, that variable becomes +``const`` and is considered externally-retained. + +When compiled without ``-fobjc-arc``, this attribute is ignored. + + +pass_object_size, pass_dynamic_object_size +------------------------------------------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``pass_object_size`` |br| ``pass_dynamic_object_size``","``clang::pass_object_size`` |br| ``clang::pass_dynamic_object_size``","``clang::pass_object_size`` |br| ``clang::pass_dynamic_object_size``","","","","Yes" + +.. Note:: The mangling of functions with parameters that are annotated with + ``pass_object_size`` is subject to change. You can get around this by + using ``__asm__("foo")`` to explicitly name your functions, thus preserving + your ABI; also, non-overloadable C functions with ``pass_object_size`` are + not mangled. + +The ``pass_object_size(Type)`` attribute can be placed on function parameters to +instruct clang to call ``__builtin_object_size(param, Type)`` at each callsite +of said function, and implicitly pass the result of this call in as an invisible +argument of type ``size_t`` directly after the parameter annotated with +``pass_object_size``. Clang will also replace any calls to +``__builtin_object_size(param, Type)`` in the function by said implicit +parameter. + +Example usage: + +.. code-block:: c + + int bzero1(char *const p __attribute__((pass_object_size(0)))) + __attribute__((noinline)) { + int i = 0; + for (/**/; i < (int)__builtin_object_size(p, 0); ++i) { + p[i] = 0; + } + return i; + } + + int main() { + char chars[100]; + int n = bzero1(&chars[0]); + assert(n == sizeof(chars)); + return 0; + } + +If successfully evaluating ``__builtin_object_size(param, Type)`` at the +callsite is not possible, then the "failed" value is passed in. So, using the +definition of ``bzero1`` from above, the following code would exit cleanly: + +.. code-block:: c + + int main2(int argc, char *argv[]) { + int n = bzero1(argv); + assert(n == -1); + return 0; + } + +``pass_object_size`` plays a part in overload resolution. If two overload +candidates are otherwise equally good, then the overload with one or more +parameters with ``pass_object_size`` is preferred. This implies that the choice +between two identical overloads both with ``pass_object_size`` on one or more +parameters will always be ambiguous; for this reason, having two such overloads +is illegal. For example: + +.. code-block:: c++ + + #define PS(N) __attribute__((pass_object_size(N))) + // OK + void Foo(char *a, char *b); // Overload A + // OK -- overload A has no parameters with pass_object_size. + void Foo(char *a PS(0), char *b PS(0)); // Overload B + // Error -- Same signature (sans pass_object_size) as overload B, and both + // overloads have one or more parameters with the pass_object_size attribute. + void Foo(void *a PS(0), void *b); + + // OK + void Bar(void *a PS(0)); // Overload C + // OK + void Bar(char *c PS(1)); // Overload D + + void main() { + char known[10], *unknown; + Foo(unknown, unknown); // Calls overload B + Foo(known, unknown); // Calls overload B + Foo(unknown, known); // Calls overload B + Foo(known, known); // Calls overload B + + Bar(known); // Calls overload D + Bar(unknown); // Calls overload D + } + +Currently, ``pass_object_size`` is a bit restricted in terms of its usage: + +* Only one use of ``pass_object_size`` is allowed per parameter. + +* It is an error to take the address of a function with ``pass_object_size`` on + any of its parameters. If you wish to do this, you can create an overload + without ``pass_object_size`` on any parameters. + +* It is an error to apply the ``pass_object_size`` attribute to parameters that + are not pointers. Additionally, any parameter that ``pass_object_size`` is + applied to must be marked ``const`` at its function's definition. + +Clang also supports the ``pass_dynamic_object_size`` attribute, which behaves +identically to ``pass_object_size``, but evaluates a call to +``__builtin_dynamic_object_size`` at the callee instead of +``__builtin_object_size``. ``__builtin_dynamic_object_size`` provides some extra +runtime checks when the object size can't be determined at compile-time. You can +read more about ``__builtin_dynamic_object_size`` `here +`_. + + +require_constant_initialization +------------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``require_constant_initialization``","``clang::require_constant_initialization``","","","","","Yes" + +This attribute specifies that the variable to which it is attached is intended +to have a `constant initializer `_ +according to the rules of [basic.start.static]. The variable is required to +have static or thread storage duration. If the initialization of the variable +is not a constant initializer an error will be produced. This attribute may +only be used in C++. + +Note that in C++03 strict constant expression checking is not done. Instead +the attribute reports if Clang can emit the variable as a constant, even if it's +not technically a 'constant initializer'. This behavior is non-portable. + +Static storage duration variables with constant initializers avoid hard-to-find +bugs caused by the indeterminate order of dynamic initialization. They can also +be safely used during dynamic initialization across translation units. + +This attribute acts as a compile time assertion that the requirements +for constant initialization have been met. Since these requirements change +between dialects and have subtle pitfalls it's important to fail fast instead +of silently falling back on dynamic initialization. + +.. code-block:: c++ + + // -std=c++14 + #define SAFE_STATIC [[clang::require_constant_initialization]] + struct T { + constexpr T(int) {} + ~T(); // non-trivial + }; + SAFE_STATIC T x = {42}; // Initialization OK. Doesn't check destructor. + SAFE_STATIC T y = 42; // error: variable does not have a constant initializer + // copy initialization is not a constant expression on a non-literal type. + + +section, __declspec(allocate) +----------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``section``","``gnu::section``","","``allocate``","","","Yes" + +The ``section`` attribute allows you to specify a specific section a +global variable or function should be in after translation. + + +swift_context +------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``swift_context``","``clang::swift_context``","``clang::swift_context``","","","","Yes" + +The ``swift_context`` attribute marks a parameter of a ``swiftcall`` +function as having the special context-parameter ABI treatment. + +This treatment generally passes the context value in a special register +which is normally callee-preserved. + +A ``swift_context`` parameter must either be the last parameter or must be +followed by a ``swift_error_result`` parameter (which itself must always be +the last parameter). + +A context parameter must have pointer or reference type. + + +swift_error_result +------------------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``swift_error_result``","``clang::swift_error_result``","``clang::swift_error_result``","","","","Yes" + +The ``swift_error_result`` attribute marks a parameter of a ``swiftcall`` +function as having the special error-result ABI treatment. + +This treatment generally passes the underlying error value in and out of +the function through a special register which is normally callee-preserved. +This is modeled in C by pretending that the register is addressable memory: + +- The caller appears to pass the address of a variable of pointer type. + The current value of this variable is copied into the register before + the call; if the call returns normally, the value is copied back into the + variable. + +- The callee appears to receive the address of a variable. This address + is actually a hidden location in its own stack, initialized with the + value of the register upon entry. When the function returns normally, + the value in that hidden location is written back to the register. + +A ``swift_error_result`` parameter must be the last parameter, and it must be +preceded by a ``swift_context`` parameter. + +A ``swift_error_result`` parameter must have type ``T**`` or ``T*&`` for some +type T. Note that no qualifiers are permitted on the intermediate level. + +It is undefined behavior if the caller does not pass a pointer or +reference to a valid object. + +The standard convention is that the error value itself (that is, the +value stored in the apparent argument) will be null upon function entry, +but this is not enforced by the ABI. + + +swift_indirect_result +--------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``swift_indirect_result``","``clang::swift_indirect_result``","``clang::swift_indirect_result``","","","","Yes" + +The ``swift_indirect_result`` attribute marks a parameter of a ``swiftcall`` +function as having the special indirect-result ABI treatment. + +This treatment gives the parameter the target's normal indirect-result +ABI treatment, which may involve passing it differently from an ordinary +parameter. However, only the first indirect result will receive this +treatment. Furthermore, low-level lowering may decide that a direct result +must be returned indirectly; if so, this will take priority over the +``swift_indirect_result`` parameters. + +A ``swift_indirect_result`` parameter must either be the first parameter or +follow another ``swift_indirect_result`` parameter. + +A ``swift_indirect_result`` parameter must have type ``T*`` or ``T&`` for +some object type ``T``. If ``T`` is a complete type at the point of +definition of a function, it is undefined behavior if the argument +value does not point to storage of adequate size and alignment for a +value of type ``T``. + +Making indirect results explicit in the signature allows C functions to +directly construct objects into them without relying on language +optimizations like C++'s named return value optimization (NRVO). + + +swiftcall +--------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``swiftcall``","``clang::swiftcall``","``clang::swiftcall``","","","","" + +The ``swiftcall`` attribute indicates that a function should be called +using the Swift calling convention for a function or function pointer. + +The lowering for the Swift calling convention, as described by the Swift +ABI documentation, occurs in multiple phases. The first, "high-level" +phase breaks down the formal parameters and results into innately direct +and indirect components, adds implicit paraameters for the generic +signature, and assigns the context and error ABI treatments to parameters +where applicable. The second phase breaks down the direct parameters +and results from the first phase and assigns them to registers or the +stack. The ``swiftcall`` convention only handles this second phase of +lowering; the C function type must accurately reflect the results +of the first phase, as follows: + +- Results classified as indirect by high-level lowering should be + represented as parameters with the ``swift_indirect_result`` attribute. + +- Results classified as direct by high-level lowering should be represented + as follows: + + - First, remove any empty direct results. + + - If there are no direct results, the C result type should be ``void``. + + - If there is one direct result, the C result type should be a type with + the exact layout of that result type. + + - If there are a multiple direct results, the C result type should be + a struct type with the exact layout of a tuple of those results. + +- Parameters classified as indirect by high-level lowering should be + represented as parameters of pointer type. + +- Parameters classified as direct by high-level lowering should be + omitted if they are empty types; otherwise, they should be represented + as a parameter type with a layout exactly matching the layout of the + Swift parameter type. + +- The context parameter, if present, should be represented as a trailing + parameter with the ``swift_context`` attribute. + +- The error result parameter, if present, should be represented as a + trailing parameter (always following a context parameter) with the + ``swift_error_result`` attribute. + +``swiftcall`` does not support variadic arguments or unprototyped functions. + +The parameter ABI treatment attributes are aspects of the function type. +A function type which which applies an ABI treatment attribute to a +parameter is a different type from an otherwise-identical function type +that does not. A single parameter may not have multiple ABI treatment +attributes. + +Support for this feature is target-dependent, although it should be +supported on every target that Swift supports. Query for this support +with ``__has_attribute(swiftcall)``. This implies support for the +``swift_context``, ``swift_error_result``, and ``swift_indirect_result`` +attributes. + + +thread +------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "","","","``thread``","","","" + +The ``__declspec(thread)`` attribute declares a variable with thread local +storage. It is available under the ``-fms-extensions`` flag for MSVC +compatibility. See the documentation for `__declspec(thread)`_ on MSDN. + +.. _`__declspec(thread)`: http://msdn.microsoft.com/en-us/library/9w1sdazb.aspx + +In Clang, ``__declspec(thread)`` is generally equivalent in functionality to the +GNU ``__thread`` keyword. The variable must not have a destructor and must have +a constant initializer, if any. The attribute only applies to variables +declared with static storage duration, such as globals, class static data +members, and static locals. + + +tls_model +--------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``tls_model``","``gnu::tls_model``","","","","","Yes" + +The ``tls_model`` attribute allows you to specify which thread-local storage +model to use. It accepts the following strings: + +* global-dynamic +* local-dynamic +* initial-exec +* local-exec + +TLS models are mutually exclusive. + + +uninitialized +------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``uninitialized``","``clang::uninitialized``","","","","","" + +The command-line parameter ``-ftrivial-auto-var-init=*`` can be used to +initialize trivial automatic stack variables. By default, trivial automatic +stack variables are uninitialized. This attribute is used to override the +command-line parameter, forcing variables to remain uninitialized. It has no +semantic meaning in that using uninitialized values is undefined behavior, +it rather documents the programmer's intent. + + +Field Attributes +================ + + +no_unique_address +----------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "","``no_unique_address``","","","","","" + +The ``no_unique_address`` attribute allows tail padding in a non-static data +member to overlap other members of the enclosing class (and in the special +case when the type is empty, permits it to fully overlap other members). +The field is laid out as if a base class were encountered at the corresponding +point within the class (except that it does not share a vptr with the enclosing +object). + +Example usage: + +.. code-block:: c++ + + template struct my_vector { + T *p; + [[no_unique_address]] Alloc alloc; + // ... + }; + static_assert(sizeof(my_vector>) == sizeof(int*)); + +``[[no_unique_address]]`` is a standard C++20 attribute. Clang supports its use +in C++11 onwards. + + +Type Attributes +=============== + + +align_value +----------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``align_value``","","","","","","Yes" + +The align_value attribute can be added to the typedef of a pointer type or the +declaration of a variable of pointer or reference type. It specifies that the +pointer will point to, or the reference will bind to, only objects with at +least the provided alignment. This alignment value must be some positive power +of 2. + + .. code-block:: c + + typedef double * aligned_double_ptr __attribute__((align_value(64))); + void foo(double & x __attribute__((align_value(128)), + aligned_double_ptr y) { ... } + +If the pointer value does not have the specified alignment at runtime, the +behavior of the program is undefined. + + +hip_pinned_shadow +----------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``hip_pinned_shadow``","","","``__hip_pinned_shadow__``","","","Yes" + +The GNU style attribute __attribute__((hip_pinned_shadow)) or MSVC style attribute +__declspec(hip_pinned_shadow) can be added to the definition of a global variable +to indicate it is a HIP pinned shadow variable. A HIP pinned shadow variable can +be accessed on both device side and host side. It has external linkage and is +not initialized on device side. It has internal linkage and is initialized by +the initializer on host side. + + +noderef +------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``noderef``","``clang::noderef``","``clang::noderef``","","","","" + +The ``noderef`` attribute causes clang to diagnose dereferences of annotated pointer types. +This is ideally used with pointers that point to special memory which cannot be read +from or written to, but allowing for the pointer to be used in pointer arithmetic. +The following are examples of valid expressions where dereferences are diagnosed: + +.. code-block:: c + + int __attribute__((noderef)) *p; + int x = *p; // warning + + int __attribute__((noderef)) **p2; + x = **p2; // warning + + int * __attribute__((noderef)) *p3; + p = *p3; // warning + + struct S { + int a; + }; + struct S __attribute__((noderef)) *s; + x = s->a; // warning + x = (*s).a; // warning + +Not all dereferences may diagnose a warning if the value directed by the pointer may not be +accessed. The following are examples of valid expressions where may not be diagnosed: + +.. code-block:: c + + int *q; + int __attribute__((noderef)) *p; + q = &*p; + q = *&p; + + struct S { + int a; + }; + struct S __attribute__((noderef)) *s; + p = &s->a; + p = &(*s).a; + +``noderef`` is currently only supported for pointers and arrays and not usable for +references or Objective-C object pointers. + +.. code-block: c++ + + int x = 2; + int __attribute__((noderef)) &y = x; // warning: 'noderef' can only be used on an array or pointer type + +.. code-block: objc + + id __attribute__((noderef)) obj = [NSObject new]; // warning: 'noderef' can only be used on an array or pointer type + + +objc_class_stub +--------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``objc_class_stub``","``clang::objc_class_stub``","``clang::objc_class_stub``","","","","Yes" + +This attribute specifies that the Objective-C class to which it applies is +instantiated at runtime. + +Unlike ``__attribute__((objc_runtime_visible))``, a class having this attribute +still has a "class stub" that is visible to the linker. This allows categories +to be defined. Static message sends with the class as a receiver use a special +access pattern to ensure the class is lazily instantiated from the class stub. + +Classes annotated with this attribute cannot be subclassed and cannot have +implementations defined for them. This attribute is intended for use in +Swift-generated headers for classes defined in Swift. + +Adding or removing this attribute to a class is an ABI-breaking change. + + +Statement Attributes +==================== + + +#pragma clang loop +------------------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "","","","","","``clang loop`` |br| ``unroll`` |br| ``nounroll`` |br| ``unroll_and_jam`` |br| ``nounroll_and_jam``","" + +The ``#pragma clang loop`` directive allows loop optimization hints to be +specified for the subsequent loop. The directive allows pipelining to be +disabled, or vectorization, interleaving, and unrolling to be enabled or disabled. +Vector width, interleave count, unrolling count, and the initiation interval +for pipelining can be explicitly specified. See `language extensions +`_ +for details. + + +#pragma unroll, #pragma nounroll +-------------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "","","","","","``clang loop`` |br| ``unroll`` |br| ``nounroll`` |br| ``unroll_and_jam`` |br| ``nounroll_and_jam``","" + +Loop unrolling optimization hints can be specified with ``#pragma unroll`` and +``#pragma nounroll``. The pragma is placed immediately before a for, while, +do-while, or c++11 range-based for loop. + +Specifying ``#pragma unroll`` without a parameter directs the loop unroller to +attempt to fully unroll the loop if the trip count is known at compile time and +attempt to partially unroll the loop if the trip count is not known at compile +time: + +.. code-block:: c++ + + #pragma unroll + for (...) { + ... + } + +Specifying the optional parameter, ``#pragma unroll _value_``, directs the +unroller to unroll the loop ``_value_`` times. The parameter may optionally be +enclosed in parentheses: + +.. code-block:: c++ + + #pragma unroll 16 + for (...) { + ... + } + + #pragma unroll(16) + for (...) { + ... + } + +Specifying ``#pragma nounroll`` indicates that the loop should not be unrolled: + +.. code-block:: c++ + + #pragma nounroll + for (...) { + ... + } + +``#pragma unroll`` and ``#pragma unroll _value_`` have identical semantics to +``#pragma clang loop unroll(full)`` and +``#pragma clang loop unroll_count(_value_)`` respectively. ``#pragma nounroll`` +is equivalent to ``#pragma clang loop unroll(disable)``. See +`language extensions +`_ +for further details including limitations of the unroll hints. + + +__read_only, __write_only, __read_write (read_only, write_only, read_write) +--------------------------------------------------------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "","","","","``__read_only`` |br| ``read_only`` |br| ``__write_only`` |br| ``write_only`` |br| ``__read_write`` |br| ``read_write``","","" + +The access qualifiers must be used with image object arguments or pipe arguments +to declare if they are being read or written by a kernel or function. + +The read_only/__read_only, write_only/__write_only and read_write/__read_write +names are reserved for use as access qualifiers and shall not be used otherwise. + +.. code-block:: c + + kernel void + foo (read_only image2d_t imageA, + write_only image2d_t imageB) { + ... + } + +In the above example imageA is a read-only 2D image object, and imageB is a +write-only 2D image object. + +The read_write (or __read_write) qualifier can not be used with pipe. + +More details can be found in the OpenCL C language Spec v2.0, Section 6.6. + + +fallthrough +----------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "","``fallthrough`` |br| ``clang::fallthrough``","``fallthrough``","","","","" + +The ``fallthrough`` (or ``clang::fallthrough``) attribute is used +to annotate intentional fall-through +between switch labels. It can only be applied to a null statement placed at a +point of execution between any statement and the next switch label. It is +common to mark these places with a specific comment, but this attribute is +meant to replace comments with a more strict annotation, which can be checked +by the compiler. This attribute doesn't change semantics of the code and can +be used wherever an intended fall-through occurs. It is designed to mimic +control-flow statements like ``break;``, so it can be placed in most places +where ``break;`` can, but only if there are no statements on the execution path +between it and the next switch label. + +By default, Clang does not warn on unannotated fallthrough from one ``switch`` +case to another. Diagnostics on fallthrough without a corresponding annotation +can be enabled with the ``-Wimplicit-fallthrough`` argument. + +Here is an example: + +.. code-block:: c++ + + // compile with -Wimplicit-fallthrough + switch (n) { + case 22: + case 33: // no warning: no statements between case labels + f(); + case 44: // warning: unannotated fall-through + g(); + [[clang::fallthrough]]; + case 55: // no warning + if (x) { + h(); + break; + } + else { + i(); + [[clang::fallthrough]]; + } + case 66: // no warning + p(); + [[clang::fallthrough]]; // warning: fallthrough annotation does not + // directly precede case label + q(); + case 77: // warning: unannotated fall-through + r(); + } + + +intel_reqd_sub_group_size +------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``intel_reqd_sub_group_size``","","","","","","Yes" + +The optional attribute intel_reqd_sub_group_size can be used to indicate that +the kernel must be compiled and executed with the specified subgroup size. When +this attribute is present, get_max_sub_group_size() is guaranteed to return the +specified integer value. This is important for the correctness of many subgroup +algorithms, and in some cases may be used by the compiler to generate more optimal +code. See `cl_intel_required_subgroup_size +` +for details. + + +opencl_unroll_hint +------------------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``opencl_unroll_hint``","","","","","","" + +The opencl_unroll_hint attribute qualifier can be used to specify that a loop +(for, while and do loops) can be unrolled. This attribute qualifier can be +used to specify full unrolling or partial unrolling by a specified amount. +This is a compiler hint and the compiler may ignore this directive. See +`OpenCL v2.0 `_ +s6.11.5 for details. + + +suppress +-------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "","``gsl::suppress``","","","","","" + +The ``[[gsl::suppress]]`` attribute suppresses specific +clang-tidy diagnostics for rules of the `C++ Core Guidelines`_ in a portable +way. The attribute can be attached to declarations, statements, and at +namespace scope. + +.. code-block:: c++ + + [[gsl::suppress("Rh-public")]] + void f_() { + int *p; + [[gsl::suppress("type")]] { + p = reinterpret_cast(7); + } + } + namespace N { + [[clang::suppress("type", "bounds")]]; + ... + } + +.. _`C++ Core Guidelines`: https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#inforce-enforcement + + +Declaration Attributes +====================== + + +__single_inhertiance, __multiple_inheritance, __virtual_inheritance +------------------------------------------------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "","","","","``__single_inheritance`` |br| ``__multiple_inheritance`` |br| ``__virtual_inheritance`` |br| ``__unspecified_inheritance``","","" + +This collection of keywords is enabled under ``-fms-extensions`` and controls +the pointer-to-member representation used on ``*-*-win32`` targets. + +The ``*-*-win32`` targets utilize a pointer-to-member representation which +varies in size and alignment depending on the definition of the underlying +class. + +However, this is problematic when a forward declaration is only available and +no definition has been made yet. In such cases, Clang is forced to utilize the +most general representation that is available to it. + +These keywords make it possible to use a pointer-to-member representation other +than the most general one regardless of whether or not the definition will ever +be present in the current translation unit. + +This family of keywords belong between the ``class-key`` and ``class-name``: + +.. code-block:: c++ + + struct __single_inheritance S; + int S::*i; + struct S {}; + +This keyword can be applied to class templates but only has an effect when used +on full specializations: + +.. code-block:: c++ + + template struct __single_inheritance A; // warning: inheritance model ignored on primary template + template struct __multiple_inheritance A; // warning: inheritance model ignored on partial specialization + template <> struct __single_inheritance A; + +Note that choosing an inheritance model less general than strictly necessary is +an error: + +.. code-block:: c++ + + struct __multiple_inheritance S; // error: inheritance model does not match definition + int S::*i; + struct S {}; + + +deprecated +---------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``deprecated``","``gnu::deprecated`` |br| ``deprecated``","``deprecated``","``deprecated``","","","" + +The ``deprecated`` attribute can be applied to a function, a variable, or a +type. This is useful when identifying functions, variables, or types that are +expected to be removed in a future version of a program. + +Consider the function declaration for a hypothetical function ``f``: + +.. code-block:: c++ + + void f(void) __attribute__((deprecated("message", "replacement"))); + +When spelled as `__attribute__((deprecated))`, the deprecated attribute can have +two optional string arguments. The first one is the message to display when +emitting the warning; the second one enables the compiler to provide a Fix-It +to replace the deprecated name with a new name. Otherwise, when spelled as +`[[gnu::deprecated]] or [[deprecated]]`, the attribute can have one optional +string argument which is the message to display when emitting the warning. + + +empty_bases +----------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "","","","``empty_bases``","","","" + +The empty_bases attribute permits the compiler to utilize the +empty-base-optimization more frequently. +This attribute only applies to struct, class, and union types. +It is only supported when using the Microsoft C++ ABI. + + +enum_extensibility +------------------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``enum_extensibility``","``clang::enum_extensibility``","``clang::enum_extensibility``","","","","Yes" + +Attribute ``enum_extensibility`` is used to distinguish between enum definitions +that are extensible and those that are not. The attribute can take either +``closed`` or ``open`` as an argument. ``closed`` indicates a variable of the +enum type takes a value that corresponds to one of the enumerators listed in the +enum definition or, when the enum is annotated with ``flag_enum``, a value that +can be constructed using values corresponding to the enumerators. ``open`` +indicates a variable of the enum type can take any values allowed by the +standard and instructs clang to be more lenient when issuing warnings. + +.. code-block:: c + + enum __attribute__((enum_extensibility(closed))) ClosedEnum { + A0, A1 + }; + + enum __attribute__((enum_extensibility(open))) OpenEnum { + B0, B1 + }; + + enum __attribute__((enum_extensibility(closed),flag_enum)) ClosedFlagEnum { + C0 = 1 << 0, C1 = 1 << 1 + }; + + enum __attribute__((enum_extensibility(open),flag_enum)) OpenFlagEnum { + D0 = 1 << 0, D1 = 1 << 1 + }; + + void foo1() { + enum ClosedEnum ce; + enum OpenEnum oe; + enum ClosedFlagEnum cfe; + enum OpenFlagEnum ofe; + + ce = A1; // no warnings + ce = 100; // warning issued + oe = B1; // no warnings + oe = 100; // no warnings + cfe = C0 | C1; // no warnings + cfe = C0 | C1 | 4; // warning issued + ofe = D0 | D1; // no warnings + ofe = D0 | D1 | 4; // no warnings + } + + +external_source_symbol +---------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``external_source_symbol``","``clang::external_source_symbol``","``clang::external_source_symbol``","","","","Yes" + +The ``external_source_symbol`` attribute specifies that a declaration originates +from an external source and describes the nature of that source. + +The fact that Clang is capable of recognizing declarations that were defined +externally can be used to provide better tooling support for mixed-language +projects or projects that rely on auto-generated code. For instance, an IDE that +uses Clang and that supports mixed-language projects can use this attribute to +provide a correct 'jump-to-definition' feature. For a concrete example, +consider a protocol that's defined in a Swift file: + +.. code-block:: swift + + @objc public protocol SwiftProtocol { + func method() + } + +This protocol can be used from Objective-C code by including a header file that +was generated by the Swift compiler. The declarations in that header can use +the ``external_source_symbol`` attribute to make Clang aware of the fact +that ``SwiftProtocol`` actually originates from a Swift module: + +.. code-block:: objc + + __attribute__((external_source_symbol(language="Swift",defined_in="module"))) + @protocol SwiftProtocol + @required + - (void) method; + @end + +Consequently, when 'jump-to-definition' is performed at a location that +references ``SwiftProtocol``, the IDE can jump to the original definition in +the Swift source file rather than jumping to the Objective-C declaration in the +auto-generated header file. + +The ``external_source_symbol`` attribute is a comma-separated list that includes +clauses that describe the origin and the nature of the particular declaration. +Those clauses can be: + +language=\ *string-literal* + The name of the source language in which this declaration was defined. + +defined_in=\ *string-literal* + The name of the source container in which the declaration was defined. The + exact definition of source container is language-specific, e.g. Swift's + source containers are modules, so ``defined_in`` should specify the Swift + module name. + +generated_declaration + This declaration was automatically generated by some tool. + +The clauses can be specified in any order. The clauses that are listed above are +all optional, but the attribute has to have at least one clause. + + +flag_enum +--------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``flag_enum``","``clang::flag_enum``","``clang::flag_enum``","","","","Yes" + +This attribute can be added to an enumerator to signal to the compiler that it +is intended to be used as a flag type. This will cause the compiler to assume +that the range of the type includes all of the values that you can get by +manipulating bits of the enumerator when issuing warnings. + + +layout_version +-------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "","","","``layout_version``","","","" + +The layout_version attribute requests that the compiler utilize the class +layout rules of a particular compiler version. +This attribute only applies to struct, class, and union types. +It is only supported when using the Microsoft C++ ABI. + + +lto_visibility_public +--------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``lto_visibility_public``","``clang::lto_visibility_public``","``clang::lto_visibility_public``","","","","Yes" + +See :doc:`LTOVisibility`. + + +novtable +-------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "","","","``novtable``","","","" + +This attribute can be added to a class declaration or definition to signal to +the compiler that constructors and destructors will not reference the virtual +function table. It is only supported when using the Microsoft C++ ABI. + + +objc_boxable +------------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``objc_boxable``","``clang::objc_boxable``","``clang::objc_boxable``","","","","Yes" + +Structs and unions marked with the ``objc_boxable`` attribute can be used +with the Objective-C boxed expression syntax, ``@(...)``. + +**Usage**: ``__attribute__((objc_boxable))``. This attribute +can only be placed on a declaration of a trivially-copyable struct or union: + +.. code-block:: objc + + struct __attribute__((objc_boxable)) some_struct { + int i; + }; + union __attribute__((objc_boxable)) some_union { + int i; + float f; + }; + typedef struct __attribute__((objc_boxable)) _some_struct some_struct; + + // ... + + some_struct ss; + NSValue *boxed = @(ss); + + +objc_nonlazy_class +------------------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``objc_nonlazy_class``","``clang::objc_nonlazy_class``","``clang::objc_nonlazy_class``","","","","Yes" + +This attribute can be added to an Objective-C ``@interface`` or +``@implementation`` declaration to add the class to the list of non-lazily +initialized classes. A non-lazy class will be initialized eagerly when the +Objective-C runtime is loaded. This is required for certain system classes which +have instances allocated in non-standard ways, such as the classes for blocks +and constant strings. Adding this attribute is essentially equivalent to +providing a trivial `+load` method but avoids the (fairly small) load-time +overheads associated with defining and calling such a method. + + +objc_runtime_name +----------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``objc_runtime_name``","``clang::objc_runtime_name``","``clang::objc_runtime_name``","","","","Yes" + +By default, the Objective-C interface or protocol identifier is used +in the metadata name for that object. The `objc_runtime_name` +attribute allows annotated interfaces or protocols to use the +specified string argument in the object's metadata name instead of the +default name. + +**Usage**: ``__attribute__((objc_runtime_name("MyLocalName")))``. This attribute +can only be placed before an @protocol or @interface declaration: + +.. code-block:: objc + + __attribute__((objc_runtime_name("MyLocalName"))) + @interface Message + @end + + +objc_runtime_visible +-------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``objc_runtime_visible``","``clang::objc_runtime_visible``","``clang::objc_runtime_visible``","","","","Yes" + +This attribute specifies that the Objective-C class to which it applies is +visible to the Objective-C runtime but not to the linker. Classes annotated +with this attribute cannot be subclassed and cannot have categories defined for +them. + + +objc_subclassing_restricted +--------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``objc_subclassing_restricted``","``clang::objc_subclassing_restricted``","``clang::objc_subclassing_restricted``","","","","Yes" + +This attribute can be added to an Objective-C ``@interface`` declaration to +ensure that this class cannot be subclassed. + + +selectany +--------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``selectany``","``gnu::selectany``","","``selectany``","","","" + +This attribute appertains to a global symbol, causing it to have a weak +definition ( +`linkonce `_ +), allowing the linker to select any definition. + +For more information see +`gcc documentation `_ +or `msvc documentation `_. + + +transparent_union +----------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``transparent_union``","``gnu::transparent_union``","","","","","" + +This attribute can be applied to a union to change the behaviour of calls to +functions that have an argument with a transparent union type. The compiler +behaviour is changed in the following manner: + +- A value whose type is any member of the transparent union can be passed as an + argument without the need to cast that value. + +- The argument is passed to the function using the calling convention of the + first member of the transparent union. Consequently, all the members of the + transparent union should have the same calling convention as its first member. + +Transparent unions are not supported in C++. + + +trivial_abi +----------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``trivial_abi``","``clang::trivial_abi``","","","","","Yes" + +The ``trivial_abi`` attribute can be applied to a C++ class, struct, or union. +It instructs the compiler to pass and return the type using the C ABI for the +underlying type when the type would otherwise be considered non-trivial for the +purpose of calls. +A class annotated with `trivial_abi` can have non-trivial destructors or copy/move constructors without automatically becoming non-trivial for the purposes of calls. For example: + + .. code-block:: c++ + + // A is trivial for the purposes of calls because `trivial_abi` makes the + // user-provided special functions trivial. + struct __attribute__((trivial_abi)) A { + ~A(); + A(const A &); + A(A &&); + int x; + }; + + // B's destructor and copy/move constructor are considered trivial for the + // purpose of calls because A is trivial. + struct B { + A a; + }; + +If a type is trivial for the purposes of calls, has a non-trivial destructor, +and is passed as an argument by value, the convention is that the callee will +destroy the object before returning. + +Attribute ``trivial_abi`` has no effect in the following cases: + +- The class directly declares a virtual base or virtual methods. +- The class has a base class that is non-trivial for the purposes of calls. +- The class has a non-static data member whose type is non-trivial for the purposes of calls, which includes: + + - classes that are non-trivial for the purposes of calls + - __weak-qualified types in Objective-C++ + - arrays of any of the above + + +OpenCL Address Spaces +===================== +The address space qualifier may be used to specify the region of memory that is +used to allocate the object. OpenCL supports the following address spaces: +__generic(generic), __global(global), __local(local), __private(private), +__constant(constant). + + .. code-block:: c + + __constant int c = ...; + + __generic int* foo(global int* g) { + __local int* l; + private int p; + ... + return l; + } + +More details can be found in the OpenCL C language Spec v2.0, Section 6.5. + +constant +-------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "","","","","``__constant`` |br| ``constant``","","" + +The constant address space attribute signals that an object is located in +a constant (non-modifiable) memory region. It is available to all work items. +Any type can be annotated with the constant address space attribute. Objects +with the constant address space qualifier can be declared in any scope and must +have an initializer. + + +generic +------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "","","","","``__generic`` |br| ``generic``","","" + +The generic address space attribute is only available with OpenCL v2.0 and later. +It can be used with pointer types. Variables in global and local scope and +function parameters in non-kernel functions can have the generic address space +type attribute. It is intended to be a placeholder for any other address space +except for '__constant' in OpenCL code which can be used with multiple address +spaces. + + +global +------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "","","","","``__global`` |br| ``global``","","" + +The global address space attribute specifies that an object is allocated in +global memory, which is accessible by all work items. The content stored in this +memory area persists between kernel executions. Pointer types to the global +address space are allowed as function parameters or local variables. Starting +with OpenCL v2.0, the global address space can be used with global (program +scope) variables and static local variable as well. + + +local +----- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "","","","","``__local`` |br| ``local``","","" + +The local address space specifies that an object is allocated in the local (work +group) memory area, which is accessible to all work items in the same work +group. The content stored in this memory region is not accessible after +the kernel execution ends. In a kernel function scope, any variable can be in +the local address space. In other scopes, only pointer types to the local address +space are allowed. Local address space variables cannot have an initializer. + + +private +------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "","","","","``__private`` |br| ``private``","","" + +The private address space specifies that an object is allocated in the private +(work item) memory. Other work items cannot access the same memory area and its +content is destroyed after work item execution ends. Local variables can be +declared in the private address space. Function arguments are always in the +private address space. Kernel function arguments of a pointer or an array type +cannot point to the private address space. + + +AMD GPU Attributes +================== + + +amdgpu_flat_work_group_size +--------------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``amdgpu_flat_work_group_size``","``clang::amdgpu_flat_work_group_size``","","","","","Yes" + +The flat work-group size is the number of work-items in the work-group size +specified when the kernel is dispatched. It is the product of the sizes of the +x, y, and z dimension of the work-group. + +Clang supports the +``__attribute__((amdgpu_flat_work_group_size(, )))`` attribute for the +AMDGPU target. This attribute may be attached to a kernel function definition +and is an optimization hint. + +```` parameter specifies the minimum flat work-group size, and ```` +parameter specifies the maximum flat work-group size (must be greater than +````) to which all dispatches of the kernel will conform. Passing ``0, 0`` +as ``, `` implies the default behavior (``128, 256``). + +If specified, the AMDGPU target backend might be able to produce better machine +code for barriers and perform scratch promotion by estimating available group +segment size. + +An error will be given if: + - Specified values violate subtarget specifications; + - Specified values are not compatible with values provided through other + attributes. + + +amdgpu_num_sgpr +--------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``amdgpu_num_sgpr``","``clang::amdgpu_num_sgpr``","","","","","Yes" + +Clang supports the ``__attribute__((amdgpu_num_sgpr()))`` and +``__attribute__((amdgpu_num_vgpr()))`` attributes for the AMDGPU +target. These attributes may be attached to a kernel function definition and are +an optimization hint. + +If these attributes are specified, then the AMDGPU target backend will attempt +to limit the number of SGPRs and/or VGPRs used to the specified value(s). The +number of used SGPRs and/or VGPRs may further be rounded up to satisfy the +allocation requirements or constraints of the subtarget. Passing ``0`` as +``num_sgpr`` and/or ``num_vgpr`` implies the default behavior (no limits). + +These attributes can be used to test the AMDGPU target backend. It is +recommended that the ``amdgpu_waves_per_eu`` attribute be used to control +resources such as SGPRs and VGPRs since it is aware of the limits for different +subtargets. + +An error will be given if: + - Specified values violate subtarget specifications; + - Specified values are not compatible with values provided through other + attributes; + - The AMDGPU target backend is unable to create machine code that can meet the + request. + + +amdgpu_num_vgpr +--------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``amdgpu_num_vgpr``","``clang::amdgpu_num_vgpr``","","","","","Yes" + +Clang supports the ``__attribute__((amdgpu_num_sgpr()))`` and +``__attribute__((amdgpu_num_vgpr()))`` attributes for the AMDGPU +target. These attributes may be attached to a kernel function definition and are +an optimization hint. + +If these attributes are specified, then the AMDGPU target backend will attempt +to limit the number of SGPRs and/or VGPRs used to the specified value(s). The +number of used SGPRs and/or VGPRs may further be rounded up to satisfy the +allocation requirements or constraints of the subtarget. Passing ``0`` as +``num_sgpr`` and/or ``num_vgpr`` implies the default behavior (no limits). + +These attributes can be used to test the AMDGPU target backend. It is +recommended that the ``amdgpu_waves_per_eu`` attribute be used to control +resources such as SGPRs and VGPRs since it is aware of the limits for different +subtargets. + +An error will be given if: + - Specified values violate subtarget specifications; + - Specified values are not compatible with values provided through other + attributes; + - The AMDGPU target backend is unable to create machine code that can meet the + request. + + +amdgpu_waves_per_eu +------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``amdgpu_waves_per_eu``","``clang::amdgpu_waves_per_eu``","","","","","Yes" + +A compute unit (CU) is responsible for executing the wavefronts of a work-group. +It is composed of one or more execution units (EU), which are responsible for +executing the wavefronts. An EU can have enough resources to maintain the state +of more than one executing wavefront. This allows an EU to hide latency by +switching between wavefronts in a similar way to symmetric multithreading on a +CPU. In order to allow the state for multiple wavefronts to fit on an EU, the +resources used by a single wavefront have to be limited. For example, the number +of SGPRs and VGPRs. Limiting such resources can allow greater latency hiding, +but can result in having to spill some register state to memory. + +Clang supports the ``__attribute__((amdgpu_waves_per_eu([, ])))`` +attribute for the AMDGPU target. This attribute may be attached to a kernel +function definition and is an optimization hint. + +```` parameter specifies the requested minimum number of waves per EU, and +*optional* ```` parameter specifies the requested maximum number of waves +per EU (must be greater than ```` if specified). If ```` is omitted, +then there is no restriction on the maximum number of waves per EU other than +the one dictated by the hardware for which the kernel is compiled. Passing +``0, 0`` as ``, `` implies the default behavior (no limits). + +If specified, this attribute allows an advanced developer to tune the number of +wavefronts that are capable of fitting within the resources of an EU. The AMDGPU +target backend can use this information to limit resources, such as number of +SGPRs, number of VGPRs, size of available group and private memory segments, in +such a way that guarantees that at least ```` wavefronts and at most +```` wavefronts are able to fit within the resources of an EU. Requesting +more wavefronts can hide memory latency but limits available registers which +can result in spilling. Requesting fewer wavefronts can help reduce cache +thrashing, but can reduce memory latency hiding. + +This attribute controls the machine code generated by the AMDGPU target backend +to ensure it is capable of meeting the requested values. However, when the +kernel is executed, there may be other reasons that prevent meeting the request, +for example, there may be wavefronts from other kernels executing on the EU. + +An error will be given if: + - Specified values violate subtarget specifications; + - Specified values are not compatible with values provided through other + attributes; + - The AMDGPU target backend is unable to create machine code that can meet the + request. + + +Calling Conventions +=================== +Clang supports several different calling conventions, depending on the target +platform and architecture. The calling convention used for a function determines +how parameters are passed, how results are returned to the caller, and other +low-level details of calling a function. + +aarch64_vector_pcs +------------------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``aarch64_vector_pcs``","``clang::aarch64_vector_pcs``","``clang::aarch64_vector_pcs``","","","","" + +On AArch64 targets, this attribute changes the calling convention of a +function to preserve additional floating-point and Advanced SIMD registers +relative to the default calling convention used for AArch64. + +This means it is more efficient to call such functions from code that performs +extensive floating-point and vector calculations, because fewer live SIMD and FP +registers need to be saved. This property makes it well-suited for e.g. +floating-point or vector math library functions, which are typically leaf +functions that require a small number of registers. + +However, using this attribute also means that it is more expensive to call +a function that adheres to the default calling convention from within such +a function. Therefore, it is recommended that this attribute is only used +for leaf functions. + +For more information, see the documentation for `aarch64_vector_pcs`_ on +the Arm Developer website. + +.. _`aarch64_vector_pcs`: https://developer.arm.com/products/software-development-tools/hpc/arm-compiler-for-hpc/vector-function-abi + + +fastcall +-------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``fastcall``","``gnu::fastcall``","","","``__fastcall`` |br| ``_fastcall``","","" + +On 32-bit x86 targets, this attribute changes the calling convention of a +function to use ECX and EDX as register parameters and clear parameters off of +the stack on return. This convention does not support variadic calls or +unprototyped functions in C, and has no effect on x86_64 targets. This calling +convention is supported primarily for compatibility with existing code. Users +seeking register parameters should use the ``regparm`` attribute, which does +not require callee-cleanup. See the documentation for `__fastcall`_ on MSDN. + +.. _`__fastcall`: http://msdn.microsoft.com/en-us/library/6xa169sk.aspx + + +ms_abi +------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``ms_abi``","``gnu::ms_abi``","","","","","" + +On non-Windows x86_64 targets, this attribute changes the calling convention of +a function to match the default convention used on Windows x86_64. This +attribute has no effect on Windows targets or non-x86_64 targets. + + +pcs +--- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``pcs``","``gnu::pcs``","","","","","" + +On ARM targets, this attribute can be used to select calling conventions +similar to ``stdcall`` on x86. Valid parameter values are "aapcs" and +"aapcs-vfp". + + +preserve_all +------------ +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``preserve_all``","``clang::preserve_all``","``clang::preserve_all``","","","","" + +On X86-64 and AArch64 targets, this attribute changes the calling convention of +a function. The ``preserve_all`` calling convention attempts to make the code +in the caller even less intrusive than the ``preserve_most`` calling convention. +This calling convention also behaves identical to the ``C`` calling convention +on how arguments and return values are passed, but it uses a different set of +caller/callee-saved registers. This removes the burden of saving and +recovering a large register set before and after the call in the caller. If +the arguments are passed in callee-saved registers, then they will be +preserved by the callee across the call. This doesn't apply for values +returned in callee-saved registers. + +- On X86-64 the callee preserves all general purpose registers, except for + R11. R11 can be used as a scratch register. Furthermore it also preserves + all floating-point registers (XMMs/YMMs). + +The idea behind this convention is to support calls to runtime functions +that don't need to call out to any other functions. + +This calling convention, like the ``preserve_most`` calling convention, will be +used by a future version of the Objective-C runtime and should be considered +experimental at this time. + + +preserve_most +------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``preserve_most``","``clang::preserve_most``","``clang::preserve_most``","","","","" + +On X86-64 and AArch64 targets, this attribute changes the calling convention of +a function. The ``preserve_most`` calling convention attempts to make the code +in the caller as unintrusive as possible. This convention behaves identically +to the ``C`` calling convention on how arguments and return values are passed, +but it uses a different set of caller/callee-saved registers. This alleviates +the burden of saving and recovering a large register set before and after the +call in the caller. If the arguments are passed in callee-saved registers, +then they will be preserved by the callee across the call. This doesn't +apply for values returned in callee-saved registers. + +- On X86-64 the callee preserves all general purpose registers, except for + R11. R11 can be used as a scratch register. Floating-point registers + (XMMs/YMMs) are not preserved and need to be saved by the caller. + +The idea behind this convention is to support calls to runtime functions +that have a hot path and a cold path. The hot path is usually a small piece +of code that doesn't use many registers. The cold path might need to call out to +another function and therefore only needs to preserve the caller-saved +registers, which haven't already been saved by the caller. The +`preserve_most` calling convention is very similar to the ``cold`` calling +convention in terms of caller/callee-saved registers, but they are used for +different types of function calls. ``coldcc`` is for function calls that are +rarely executed, whereas `preserve_most` function calls are intended to be +on the hot path and definitely executed a lot. Furthermore ``preserve_most`` +doesn't prevent the inliner from inlining the function call. + +This calling convention will be used by a future version of the Objective-C +runtime and should therefore still be considered experimental at this time. +Although this convention was created to optimize certain runtime calls to +the Objective-C runtime, it is not limited to this runtime and might be used +by other runtimes in the future too. The current implementation only +supports X86-64 and AArch64, but the intention is to support more architectures +in the future. + + +regcall +------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``regcall``","``gnu::regcall``","","","``__regcall``","","" + +On x86 targets, this attribute changes the calling convention to +`__regcall`_ convention. This convention aims to pass as many arguments +as possible in registers. It also tries to utilize registers for the +return value whenever it is possible. + +.. _`__regcall`: https://software.intel.com/en-us/node/693069 + + +regparm +------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``regparm``","``gnu::regparm``","","","","","" + +On 32-bit x86 targets, the regparm attribute causes the compiler to pass +the first three integer parameters in EAX, EDX, and ECX instead of on the +stack. This attribute has no effect on variadic functions, and all parameters +are passed via the stack as normal. + + +stdcall +------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``stdcall``","``gnu::stdcall``","","","``__stdcall`` |br| ``_stdcall``","","" + +On 32-bit x86 targets, this attribute changes the calling convention of a +function to clear parameters off of the stack on return. This convention does +not support variadic calls or unprototyped functions in C, and has no effect on +x86_64 targets. This calling convention is used widely by the Windows API and +COM applications. See the documentation for `__stdcall`_ on MSDN. + +.. _`__stdcall`: http://msdn.microsoft.com/en-us/library/zxk0tw93.aspx + + +thiscall +-------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``thiscall``","``gnu::thiscall``","","","``__thiscall`` |br| ``_thiscall``","","" + +On 32-bit x86 targets, this attribute changes the calling convention of a +function to use ECX for the first parameter (typically the implicit ``this`` +parameter of C++ methods) and clear parameters off of the stack on return. This +convention does not support variadic calls or unprototyped functions in C, and +has no effect on x86_64 targets. See the documentation for `__thiscall`_ on +MSDN. + +.. _`__thiscall`: http://msdn.microsoft.com/en-us/library/ek8tkfbw.aspx + + +vectorcall +---------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``vectorcall``","``clang::vectorcall``","``clang::vectorcall``","","``__vectorcall`` |br| ``_vectorcall``","","" + +On 32-bit x86 *and* x86_64 targets, this attribute changes the calling +convention of a function to pass vector parameters in SSE registers. + +On 32-bit x86 targets, this calling convention is similar to ``__fastcall``. +The first two integer parameters are passed in ECX and EDX. Subsequent integer +parameters are passed in memory, and callee clears the stack. On x86_64 +targets, the callee does *not* clear the stack, and integer parameters are +passed in RCX, RDX, R8, and R9 as is done for the default Windows x64 calling +convention. + +On both 32-bit x86 and x86_64 targets, vector and floating point arguments are +passed in XMM0-XMM5. Homogeneous vector aggregates of up to four elements are +passed in sequential SSE registers if enough are available. If AVX is enabled, +256 bit vectors are passed in YMM0-YMM5. Any vector or aggregate type that +cannot be passed in registers for any reason is passed by reference, which +allows the caller to align the parameter memory. + +See the documentation for `__vectorcall`_ on MSDN for more details. + +.. _`__vectorcall`: http://msdn.microsoft.com/en-us/library/dn375768.aspx + + +Consumed Annotation Checking +============================ +Clang supports additional attributes for checking basic resource management +properties, specifically for unique objects that have a single owning reference. +The following attributes are currently supported, although **the implementation +for these annotations is currently in development and are subject to change.** + +callable_when +------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``callable_when``","``clang::callable_when``","","","","","Yes" + +Use ``__attribute__((callable_when(...)))`` to indicate what states a method +may be called in. Valid states are unconsumed, consumed, or unknown. Each +argument to this attribute must be a quoted string. E.g.: + +``__attribute__((callable_when("unconsumed", "unknown")))`` + + +consumable +---------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``consumable``","``clang::consumable``","","","","","Yes" + +Each ``class`` that uses any of the typestate annotations must first be marked +using the ``consumable`` attribute. Failure to do so will result in a warning. + +This attribute accepts a single parameter that must be one of the following: +``unknown``, ``consumed``, or ``unconsumed``. + + +param_typestate +--------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``param_typestate``","``clang::param_typestate``","","","","","Yes" + +This attribute specifies expectations about function parameters. Calls to an +function with annotated parameters will issue a warning if the corresponding +argument isn't in the expected state. The attribute is also used to set the +initial state of the parameter when analyzing the function's body. + + +return_typestate +---------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``return_typestate``","``clang::return_typestate``","","","","","Yes" + +The ``return_typestate`` attribute can be applied to functions or parameters. +When applied to a function the attribute specifies the state of the returned +value. The function's body is checked to ensure that it always returns a value +in the specified state. On the caller side, values returned by the annotated +function are initialized to the given state. + +When applied to a function parameter it modifies the state of an argument after +a call to the function returns. The function's body is checked to ensure that +the parameter is in the expected state before returning. + + +set_typestate +------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``set_typestate``","``clang::set_typestate``","","","","","Yes" + +Annotate methods that transition an object into a new state with +``__attribute__((set_typestate(new_state)))``. The new state must be +unconsumed, consumed, or unknown. + + +test_typestate +-------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``test_typestate``","``clang::test_typestate``","","","","","Yes" + +Use ``__attribute__((test_typestate(tested_state)))`` to indicate that a method +returns true if the object is in the specified state.. + + +Type Safety Checking +==================== +Clang supports additional attributes to enable checking type safety properties +that can't be enforced by the C type system. To see warnings produced by these +checks, ensure that -Wtype-safety is enabled. Use cases include: + +* MPI library implementations, where these attributes enable checking that + the buffer type matches the passed ``MPI_Datatype``; +* for HDF5 library there is a similar use case to MPI; +* checking types of variadic functions' arguments for functions like + ``fcntl()`` and ``ioctl()``. + +You can detect support for these attributes with ``__has_attribute()``. For +example: + +.. code-block:: c++ + + #if defined(__has_attribute) + # if __has_attribute(argument_with_type_tag) && \ + __has_attribute(pointer_with_type_tag) && \ + __has_attribute(type_tag_for_datatype) + # define ATTR_MPI_PWT(buffer_idx, type_idx) __attribute__((pointer_with_type_tag(mpi,buffer_idx,type_idx))) + /* ... other macros ... */ + # endif + #endif + + #if !defined(ATTR_MPI_PWT) + # define ATTR_MPI_PWT(buffer_idx, type_idx) + #endif + + int MPI_Send(void *buf, int count, MPI_Datatype datatype /*, other args omitted */) + ATTR_MPI_PWT(1,3); + +argument_with_type_tag +---------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``argument_with_type_tag`` |br| ``pointer_with_type_tag``","``clang::argument_with_type_tag`` |br| ``clang::pointer_with_type_tag``","``clang::argument_with_type_tag`` |br| ``clang::pointer_with_type_tag``","","","","" + +Use ``__attribute__((argument_with_type_tag(arg_kind, arg_idx, +type_tag_idx)))`` on a function declaration to specify that the function +accepts a type tag that determines the type of some other argument. + +This attribute is primarily useful for checking arguments of variadic functions +(``pointer_with_type_tag`` can be used in most non-variadic cases). + +In the attribute prototype above: + * ``arg_kind`` is an identifier that should be used when annotating all + applicable type tags. + * ``arg_idx`` provides the position of a function argument. The expected type of + this function argument will be determined by the function argument specified + by ``type_tag_idx``. In the code example below, "3" means that the type of the + function's third argument will be determined by ``type_tag_idx``. + * ``type_tag_idx`` provides the position of a function argument. This function + argument will be a type tag. The type tag will determine the expected type of + the argument specified by ``arg_idx``. In the code example below, "2" means + that the type tag associated with the function's second argument should agree + with the type of the argument specified by ``arg_idx``. + +For example: + +.. code-block:: c++ + + int fcntl(int fd, int cmd, ...) + __attribute__(( argument_with_type_tag(fcntl,3,2) )); + // The function's second argument will be a type tag; this type tag will + // determine the expected type of the function's third argument. + + +pointer_with_type_tag +--------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``argument_with_type_tag`` |br| ``pointer_with_type_tag``","``clang::argument_with_type_tag`` |br| ``clang::pointer_with_type_tag``","``clang::argument_with_type_tag`` |br| ``clang::pointer_with_type_tag``","","","","" + +Use ``__attribute__((pointer_with_type_tag(ptr_kind, ptr_idx, type_tag_idx)))`` +on a function declaration to specify that the function accepts a type tag that +determines the pointee type of some other pointer argument. + +In the attribute prototype above: + * ``ptr_kind`` is an identifier that should be used when annotating all + applicable type tags. + * ``ptr_idx`` provides the position of a function argument; this function + argument will have a pointer type. The expected pointee type of this pointer + type will be determined by the function argument specified by + ``type_tag_idx``. In the code example below, "1" means that the pointee type + of the function's first argument will be determined by ``type_tag_idx``. + * ``type_tag_idx`` provides the position of a function argument; this function + argument will be a type tag. The type tag will determine the expected pointee + type of the pointer argument specified by ``ptr_idx``. In the code example + below, "3" means that the type tag associated with the function's third + argument should agree with the pointee type of the pointer argument specified + by ``ptr_idx``. + +For example: + +.. code-block:: c++ + + typedef int MPI_Datatype; + int MPI_Send(void *buf, int count, MPI_Datatype datatype /*, other args omitted */) + __attribute__(( pointer_with_type_tag(mpi,1,3) )); + // The function's 3rd argument will be a type tag; this type tag will + // determine the expected pointee type of the function's 1st argument. + + +type_tag_for_datatype +--------------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``type_tag_for_datatype``","``clang::type_tag_for_datatype``","``clang::type_tag_for_datatype``","","","","" + +When declaring a variable, use +``__attribute__((type_tag_for_datatype(kind, type)))`` to create a type tag that +is tied to the ``type`` argument given to the attribute. + +In the attribute prototype above: + * ``kind`` is an identifier that should be used when annotating all applicable + type tags. + * ``type`` indicates the name of the type. + +Clang supports annotating type tags of two forms. + + * **Type tag that is a reference to a declared identifier.** + Use ``__attribute__((type_tag_for_datatype(kind, type)))`` when declaring that + identifier: + + .. code-block:: c++ + + typedef int MPI_Datatype; + extern struct mpi_datatype mpi_datatype_int + __attribute__(( type_tag_for_datatype(mpi,int) )); + #define MPI_INT ((MPI_Datatype) &mpi_datatype_int) + // &mpi_datatype_int is a type tag. It is tied to type "int". + + * **Type tag that is an integral literal.** + Declare a ``static const`` variable with an initializer value and attach + ``__attribute__((type_tag_for_datatype(kind, type)))`` on that declaration: + + .. code-block:: c++ + + typedef int MPI_Datatype; + static const MPI_Datatype mpi_datatype_int + __attribute__(( type_tag_for_datatype(mpi,int) )) = 42; + #define MPI_INT ((MPI_Datatype) 42) + // The number 42 is a type tag. It is tied to type "int". + + +The ``type_tag_for_datatype`` attribute also accepts an optional third argument +that determines how the type of the function argument specified by either +``arg_idx`` or ``ptr_idx`` is compared against the type associated with the type +tag. (Recall that for the ``argument_with_type_tag`` attribute, the type of the +function argument specified by ``arg_idx`` is compared against the type +associated with the type tag. Also recall that for the ``pointer_with_type_tag`` +attribute, the pointee type of the function argument specified by ``ptr_idx`` is +compared against the type associated with the type tag.) There are two supported +values for this optional third argument: + + * ``layout_compatible`` will cause types to be compared according to + layout-compatibility rules (In C++11 [class.mem] p 17, 18, see the + layout-compatibility rules for two standard-layout struct types and for two + standard-layout union types). This is useful when creating a type tag + associated with a struct or union type. For example: + + .. code-block:: c++ + + /* In mpi.h */ + typedef int MPI_Datatype; + struct internal_mpi_double_int { double d; int i; }; + extern struct mpi_datatype mpi_datatype_double_int + __attribute__(( type_tag_for_datatype(mpi, + struct internal_mpi_double_int, layout_compatible) )); + + #define MPI_DOUBLE_INT ((MPI_Datatype) &mpi_datatype_double_int) + + int MPI_Send(void *buf, int count, MPI_Datatype datatype, ...) + __attribute__(( pointer_with_type_tag(mpi,1,3) )); + + /* In user code */ + struct my_pair { double a; int b; }; + struct my_pair *buffer; + MPI_Send(buffer, 1, MPI_DOUBLE_INT /*, ... */); // no warning because the + // layout of my_pair is + // compatible with that of + // internal_mpi_double_int + + struct my_int_pair { int a; int b; } + struct my_int_pair *buffer2; + MPI_Send(buffer2, 1, MPI_DOUBLE_INT /*, ... */); // warning because the + // layout of my_int_pair + // does not match that of + // internal_mpi_double_int + + * ``must_be_null`` specifies that the function argument specified by either + ``arg_idx`` (for the ``argument_with_type_tag`` attribute) or ``ptr_idx`` (for + the ``pointer_with_type_tag`` attribute) should be a null pointer constant. + The second argument to the ``type_tag_for_datatype`` attribute is ignored. For + example: + + .. code-block:: c++ + + /* In mpi.h */ + typedef int MPI_Datatype; + extern struct mpi_datatype mpi_datatype_null + __attribute__(( type_tag_for_datatype(mpi, void, must_be_null) )); + + #define MPI_DATATYPE_NULL ((MPI_Datatype) &mpi_datatype_null) + int MPI_Send(void *buf, int count, MPI_Datatype datatype, ...) + __attribute__(( pointer_with_type_tag(mpi,1,3) )); + + /* In user code */ + struct my_pair { double a; int b; }; + struct my_pair *buffer; + MPI_Send(buffer, 1, MPI_DATATYPE_NULL /*, ... */); // warning: MPI_DATATYPE_NULL + // was specified but buffer + // is not a null pointer + + +Nullability Attributes +====================== +Whether a particular pointer may be "null" is an important concern when working with pointers in the C family of languages. The various nullability attributes indicate whether a particular pointer can be null or not, which makes APIs more expressive and can help static analysis tools identify bugs involving null pointers. Clang supports several kinds of nullability attributes: the ``nonnull`` and ``returns_nonnull`` attributes indicate which function or method parameters and result types can never be null, while nullability type qualifiers indicate which pointer types can be null (``_Nullable``) or cannot be null (``_Nonnull``). + +The nullability (type) qualifiers express whether a value of a given pointer type can be null (the ``_Nullable`` qualifier), doesn't have a defined meaning for null (the ``_Nonnull`` qualifier), or for which the purpose of null is unclear (the ``_Null_unspecified`` qualifier). Because nullability qualifiers are expressed within the type system, they are more general than the ``nonnull`` and ``returns_nonnull`` attributes, allowing one to express (for example) a nullable pointer to an array of nonnull pointers. Nullability qualifiers are written to the right of the pointer to which they apply. For example: + + .. code-block:: c + + // No meaningful result when 'ptr' is null (here, it happens to be undefined behavior). + int fetch(int * _Nonnull ptr) { return *ptr; } + + // 'ptr' may be null. + int fetch_or_zero(int * _Nullable ptr) { + return ptr ? *ptr : 0; + } + + // A nullable pointer to non-null pointers to const characters. + const char *join_strings(const char * _Nonnull * _Nullable strings, unsigned n); + +In Objective-C, there is an alternate spelling for the nullability qualifiers that can be used in Objective-C methods and properties using context-sensitive, non-underscored keywords. For example: + + .. code-block:: objective-c + + @interface NSView : NSResponder + - (nullable NSView *)ancestorSharedWithView:(nonnull NSView *)aView; + @property (assign, nullable) NSView *superview; + @property (readonly, nonnull) NSArray *subviews; + @end + +_Nonnull +-------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "","","","","``_Nonnull``","","" + +The ``_Nonnull`` nullability qualifier indicates that null is not a meaningful value for a value of the ``_Nonnull`` pointer type. For example, given a declaration such as: + + .. code-block:: c + + int fetch(int * _Nonnull ptr); + +a caller of ``fetch`` should not provide a null value, and the compiler will produce a warning if it sees a literal null value passed to ``fetch``. Note that, unlike the declaration attribute ``nonnull``, the presence of ``_Nonnull`` does not imply that passing null is undefined behavior: ``fetch`` is free to consider null undefined behavior or (perhaps for backward-compatibility reasons) defensively handle null. + + +_Null_unspecified +----------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "","","","","``_Null_unspecified``","","" + +The ``_Null_unspecified`` nullability qualifier indicates that neither the ``_Nonnull`` nor ``_Nullable`` qualifiers make sense for a particular pointer type. It is used primarily to indicate that the role of null with specific pointers in a nullability-annotated header is unclear, e.g., due to overly-complex implementations or historical factors with a long-lived API. + + +_Nullable +--------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "","","","","``_Nullable``","","" + +The ``_Nullable`` nullability qualifier indicates that a value of the ``_Nullable`` pointer type can be null. For example, given: + + .. code-block:: c + + int fetch_or_zero(int * _Nullable ptr); + +a caller of ``fetch_or_zero`` can provide null. + + +nonnull +------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``nonnull``","``gnu::nonnull``","","","","","" + +The ``nonnull`` attribute indicates that some function parameters must not be null, and can be used in several different ways. It's original usage (`from GCC `_) is as a function (or Objective-C method) attribute that specifies which parameters of the function are nonnull in a comma-separated list. For example: + + .. code-block:: c + + extern void * my_memcpy (void *dest, const void *src, size_t len) + __attribute__((nonnull (1, 2))); + +Here, the ``nonnull`` attribute indicates that parameters 1 and 2 +cannot have a null value. Omitting the parenthesized list of parameter indices means that all parameters of pointer type cannot be null: + + .. code-block:: c + + extern void * my_memcpy (void *dest, const void *src, size_t len) + __attribute__((nonnull)); + +Clang also allows the ``nonnull`` attribute to be placed directly on a function (or Objective-C method) parameter, eliminating the need to specify the parameter index ahead of type. For example: + + .. code-block:: c + + extern void * my_memcpy (void *dest __attribute__((nonnull)), + const void *src __attribute__((nonnull)), size_t len); + +Note that the ``nonnull`` attribute indicates that passing null to a non-null parameter is undefined behavior, which the optimizer may take advantage of to, e.g., remove null checks. The ``_Nonnull`` type qualifier indicates that a pointer cannot be null in a more general manner (because it is part of the type system) and does not imply undefined behavior, making it more widely applicable. + + +returns_nonnull +--------------- +.. csv-table:: Supported Syntaxes + :header: "GNU", "C++11", "C2x", "``__declspec``", "Keyword", "``#pragma``", "``#pragma clang attribute``" + + "``returns_nonnull``","``gnu::returns_nonnull``","","","","","Yes" + +The ``returns_nonnull`` attribute indicates that a particular function (or Objective-C method) always returns a non-null pointer. For example, a particular system ``malloc`` might be defined to terminate a process when memory is not available rather than returning a null pointer: + + .. code-block:: c + + extern void * malloc (size_t size) __attribute__((returns_nonnull)); + +The ``returns_nonnull`` attribute implies that returning a null pointer is undefined behavior, which the optimizer may take advantage of. The ``_Nonnull`` type qualifier indicates that a pointer cannot be null in a more general manner (because it is part of the type system) and does not imply undefined behavior, making it more widely applicable + + diff --git a/clang/docs/ClangCommandLineReference.rst b/clang/docs/ClangCommandLineReference.rst index 4c1fe07be3a6..5f8264762c85 100644 --- a/clang/docs/ClangCommandLineReference.rst +++ b/clang/docs/ClangCommandLineReference.rst @@ -198,6 +198,10 @@ Filename (or -) to write dependency output to Emit Clang AST files for source inputs +.. option:: -enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang + +Trivial automatic variable initialization to zero is only here for benchmarks, it'll eventually be removed, and I'm OK with that because I'm only using it to benchmark + .. option:: -exported\_symbols\_list .. option:: -faligned-new= @@ -210,10 +214,6 @@ Use approximate transcendental functions Flush denormal floating point values to zero in CUDA device mode. -.. option:: -fcuda-rdc, -fno-cuda-rdc - -Generate relocatable device code, also known as separate compilation mode. - .. option:: -fcuda-short-ptr, -fno-cuda-short-ptr Use 32-bit pointers for accessing const/local/shared address spaces. @@ -222,6 +222,10 @@ Use 32-bit pointers for accessing const/local/shared address spaces. Reserve register r19 (Hexagon only) +.. option:: -fgpu-rdc, -fcuda-rdc, -fno-gpu-rdc + +Generate relocatable device code, also known as separate compilation mode. + .. option:: -fheinous-gnu-extensions .. option:: -flat\_namespace @@ -254,6 +258,10 @@ Use the gcc toolchain at the given directory Generate CodeView debug information +.. option:: -gcodeview-ghash, -gno-codeview-ghash + +Emit type record hashes in a .debug$H section + .. option:: -headerpad\_max\_install\_names .. option:: -help, --help @@ -278,6 +286,8 @@ Make the next included directory (-I or -F) an indexer header map .. option:: -install\_name +.. option:: -interface-stub-version= + .. option:: -keep\_private\_externs .. option:: -lazy\_framework @@ -288,6 +298,10 @@ Make the next included directory (-I or -F) an indexer header map .. option:: -mbig-endian, -EB +.. option:: -mbranch-protection= + +Enforce targets of indirect branches and function returns + .. option:: --migrate Run the migrator @@ -592,6 +606,8 @@ Statically link the sanitizer runtime .. option:: -static-libstdc++ +.. option:: -static-pie + .. option:: -std-default= .. option:: -stdlib=, --stdlib=, --stdlib @@ -612,10 +628,6 @@ C++ standard library to use Generate code for the given target -.. option:: --print-supported-cpus - -Print supported cpu models for the given target - .. option:: -time Time individual commands @@ -636,6 +648,10 @@ Enable some traditional CPP emulation .. option:: -unexported\_symbols\_list +.. option:: -unwindlib=, --unwindlib= + +Unwind library to use + .. option:: -v, --verbose Show commands to run and use verbose output @@ -694,6 +710,10 @@ Only run preprocess and compilation steps Only run preprocess, compile, and assemble steps +.. option:: -emit-interface-stubs + +Generate Inteface Stub Files. + .. option:: -emit-llvm Use the LLVM representation for assembler and object files @@ -798,15 +818,7 @@ Don't use blacklist file for sanitizers .. option:: -fparse-all-comments -.. option:: -frecord-command-line, -frecord-gcc-switches, -fno-record-command-line, -fno-record-gcc-switches - -Generate a section named ".GCC.command.line" containing the clang driver -command-line. After linking, the section may contain multiple command lines, -which will be individually terminated by null bytes. Separate arguments within -a command line are combined with spaces; spaces and backslashes within an -argument are escaped with backslashes. This format differs from the format of -the equivalent section produced by GCC with the -frecord-gcc-switches flag. -This option is currently only supported on ELF targets. +.. option:: -frecord-command-line, -fno-record-command-line, -frecord-gcc-switches .. option:: -fsanitize-address-field-padding= @@ -816,20 +828,18 @@ Level of field padding for AddressSanitizer Enable linker dead stripping of globals in AddressSanitizer -.. option:: -fsanitize-address-use-odr-indicator, -fno-sanitize-address-use-odr-indicator - -Enable ODR indicator globals to avoid false ODR violation reports in partially sanitized programs at the cost of an increase in binary size - .. option:: -fsanitize-address-poison-custom-array-cookie, -fno-sanitize-address-poison-custom-array-cookie -Enable "poisoning" array cookies when allocating arrays with a custom operator new\[\] in Address Sanitizer, preventing accesses to the cookies from user code. An array cookie is a small implementation-defined header added to certain array allocations to record metadata such as the length of the array. Accesses to array cookies from user code are technically allowed by the standard but are more likely to be the result of an out-of-bounds array access. - -An operator new\[\] is "custom" if it is not one of the allocation functions provided by the C++ standard library. Array cookies from non-custom allocation functions are always poisoned. +Enable poisoning array cookies when using custom operator new\[\] in AddressSanitizer .. option:: -fsanitize-address-use-after-scope, -fno-sanitize-address-use-after-scope Enable use-after-scope detection in AddressSanitizer +.. option:: -fsanitize-address-use-odr-indicator, -fno-sanitize-address-use-odr-indicator + +Enable ODR indicator globals to avoid false ODR violation reports in partially sanitized programs at the cost of an increase in binary size + .. option:: -fsanitize-blacklist= Path to blacklist file for sanitizers @@ -846,6 +856,10 @@ Generalize pointers in CFI indirect call type signature checks Specify the type of coverage instrumentation for Sanitizers +.. option:: -fsanitize-hwaddress-abi= + +Select the HWAddressSanitizer ABI to target (interceptor or platform, default interceptor) + .. option:: -fsanitize-link-c++-runtime .. option:: -fsanitize-memory-track-origins, -fno-sanitize-memory-track-origins @@ -908,6 +922,10 @@ Enable function outlining (AArch64 only) .. option:: --param , --param= +.. option:: -print-supported-cpus, --print-supported-cpus, -mcpu=?, -mtune=? + +Print supported cpu models for the given target (if target is not specified, it will print the supported cpus for the default target) + .. option:: -std=, --std=, --std Language standard to compile for @@ -1078,6 +1096,10 @@ Set directory to include search path with prefix Add directory to SYSTEM include search path, absolute paths are relative to -isysroot +.. option:: --libomptarget-nvptx-path= + +Path to libomptarget-nvptx libraries + .. option:: --ptxas-path= Path to ptxas (used for compiling CUDA code) @@ -1235,6 +1257,10 @@ Use ANSI escape codes for diagnostics Use Apple's kernel extensions ABI +.. option:: -fapple-link-rtlib + +Force linking the clang builtins runtime library + .. option:: -fapple-pragma-pack, -fno-apple-pragma-pack Enable Apple gcc-compatible #pragma pack handling @@ -1289,6 +1315,8 @@ Enable C++ static destructor registration (the default) Instrument control-flow architecture protection. Options: return, branch, full, none. +.. option:: -fcf-runtime-abi= + .. option:: -fchar8\_t, -fno-char8\_t Enable C++ builtin type char8\_t @@ -1323,6 +1351,16 @@ Generate coverage mapping to enable code coverage analysis .. option:: -fcreate-profile +.. option:: -fcs-profile-generate + +Generate instrumented code to collect context sensitive execution counts into default.profraw (overridden by LLVM\_PROFILE\_FILE env var) + +.. program:: clang1 +.. option:: -fcs-profile-generate= +.. program:: clang + +Generate instrumented code to collect context sensitive execution counts into /default.profraw (overridden by LLVM\_PROFILE\_FILE env var) + .. option:: -fcxx-exceptions, -fno-cxx-exceptions Enable C++ exceptions @@ -1333,6 +1371,10 @@ Enable C++ exceptions Place each data in its own section (ELF Only) +.. option:: -fdebug-compilation-dir + +The compilation directory to embed in the debug info. + .. option:: -fdebug-info-for-profiling, -fno-debug-info-for-profiling Emit extra debug info to make sample profile more accurate. @@ -1349,6 +1391,10 @@ Emit macro debug information remap file source paths in debug info +.. option:: -fdebug-ranges-base-address, -fno-debug-ranges-base-address + +Use DWARF base address selection entries in debug\_ranges + .. option:: -fdebug-types-section, -fno-debug-types-section Place debug types in their own section (ELF Only) @@ -1657,6 +1703,8 @@ Synthesize retain and release calls for Objective-C pointers Use EH-safe code when synthesizing retains and releases in -fobjc-arc +.. option:: -fobjc-convert-messages-to-runtime-calls, -fno-objc-convert-messages-to-runtime-calls + .. option:: -fobjc-exceptions, -fno-objc-exceptions Enable Objective-C exceptions @@ -1703,8 +1751,16 @@ Emit OpenMP code only for SIMD-based constructs. Specify the file name of any generated YAML optimization record +.. option:: -foptimization-record-passes= + +Only include passes which match a specified regular expression in the generated optimization record (by default, include all passes) + .. option:: -foptimize-sibling-calls, -fno-optimize-sibling-calls +.. option:: -forder-file-instrumentation + +Generate instrumented code to collect order file into default.profraw file (overridden by '=' form of option or LLVM\_PROFILE\_FILE env var) + .. option:: -foutput-class-dir=, --output-class-directory , --output-class-directory= .. option:: -fpack-struct, -fno-pack-struct @@ -1719,6 +1775,10 @@ Specify the default maximum struct packing alignment Recognize and construct Pascal-style string literals +.. option:: -fpass-plugin= + +Load pass plugin from a dynamic shared object file (only with new pass manager). + .. option:: -fpcc-struct-return Override the default ABI to return all structs on the stack @@ -1743,6 +1803,14 @@ Load the named plugin (dynamic shared object) .. option:: -fprofile-dir= +.. option:: -fprofile-exclude-files= + +Instrument only functions from files where names don't match all the regexes separated by a semi-colon + +.. option:: -fprofile-filter-files= + +Instrument only functions from files where names match any regex separated by a semi-colon + .. option:: -fprofile-generate, -fno-profile-generate Generate instrumented code to collect execution counts into default.profraw (overridden by LLVM\_PROFILE\_FILE env var) @@ -1771,6 +1839,10 @@ Generate instrumented code to collect execution counts into (overridden b Use instrumentation data for profile-guided optimization +.. option:: -fprofile-remapping-file=, -fprofile-remapping-file + +Use the remappings described in to match the profile data against names in the program + .. option:: -fprofile-sample-accurate, -fauto-profile-accurate, -fno-profile-sample-accurate Specifies that the sample profile is accurate. If the sample @@ -1834,6 +1906,12 @@ Turn on loop reroller Generate a YAML optimization record file +.. program:: clang1 +.. option:: -fsave-optimization-record= +.. program:: clang + +Generate an optimization record file in a specific format (default: YAML) + .. option:: -fseh-exceptions Use SEH style exceptions @@ -1882,19 +1960,23 @@ Enable the superword-level parallelism vectorization passes Provide minimal debug info in the object/executable to facilitate online symbolication/stack traces in the absence of .dwo/.dwp files when using Split DWARF +.. option:: -fsplit-lto-unit, -fno-split-lto-unit + +Enables splitting of the LTO unit. + .. option:: -fsplit-stack .. option:: -fstack-protector, -fno-stack-protector -Enable stack protectors for functions potentially vulnerable to stack smashing +Enable stack protectors for some functions vulnerable to stack smashing. This uses a loose heuristic which considers functions vulnerable if they contain a char (or 8bit integer) array or constant sized calls to alloca, which are of greater size than ssp-buffer-size (default: 8 bytes). All variable sized calls to alloca are considered vulnerable .. option:: -fstack-protector-all -Force the usage of stack protectors for all functions +Enable stack protectors for all functions .. option:: -fstack-protector-strong -Use a strong heuristic to apply stack protectors to functions +Enable stack protectors for some functions vulnerable to stack smashing. Compared to -fstack-protector, this uses a stronger heuristic that includes functions containing arrays of any size (and any type), as well as any calls to alloca or the taking of an address from a local variable .. option:: -fstack-size-section, -fno-stack-size-section @@ -1926,6 +2008,8 @@ Enable optimizations based on the strict rules for overwriting polymorphic C++ o .. option:: -fstruct-path-tbaa, -fno-struct-path-tbaa +.. option:: -fsymbol-partition= + .. option:: -ftabstop= .. option:: -ftemplate-backtrace-limit= @@ -1944,6 +2028,8 @@ Perform ThinLTO importing using provided function summary index .. option:: -ftime-report +.. option:: -ftime-trace + .. option:: -ftls-model= .. option:: -ftrap-function= @@ -1968,6 +2054,10 @@ Specify the function to be called on overflow Process trigraph sequences +.. option:: -ftrivial-auto-var-init= + +Initialize trivial automatic stack variables: uninitialized (default) \| pattern + .. option:: -funique-section-names, -fno-unique-section-names Use unique names for text and data sections (ELF Only) @@ -2006,6 +2096,10 @@ Enable the loop vectorization passes .. option:: -fverbose-asm, -fno-verbose-asm +.. option:: -fvisibility-global-new-delete-hidden + +Give global C++ operator new and delete declarations hidden visibility + .. option:: -fvisibility-inlines-hidden Give inline C++ member functions hidden visibility by default @@ -2080,6 +2174,14 @@ DEPRECATED: Filename defining the whitelist for imbuing the 'never instrument' X Enable System z vector language extension +.. option:: -mlong-double-128 + +Force long double to be 128 bits + +.. option:: -mlong-double-64 + +Force long double to be 64 bits + .. option:: -pedantic, --pedantic, -no-pedantic, --no-pedantic .. option:: -pedantic-errors, --pedantic-errors @@ -2168,9 +2270,9 @@ Link stack frames through backchain on System Z .. option:: -mconsole -.. option:: -mcpu=, -mv5 (equivalent to -mcpu=hexagonv5), -mv55 (equivalent to -mcpu=hexagonv55), -mv60 (equivalent to -mcpu=hexagonv60), -mv62 (equivalent to -mcpu=hexagonv62), -mv65 (equivalent to -mcpu=hexagonv65) - -Use -mcpu=? to see a list of supported cpu models. +.. program:: clang1 +.. option:: -mcpu=, -mv5 (equivalent to -mcpu=hexagonv5), -mv55 (equivalent to -mcpu=hexagonv55), -mv60 (equivalent to -mcpu=hexagonv60), -mv62 (equivalent to -mcpu=hexagonv62), -mv65 (equivalent to -mcpu=hexagonv65), -mv66 (equivalent to -mcpu=hexagonv66) +.. program:: clang .. option:: -mcrc, -mno-crc @@ -2204,6 +2306,8 @@ Enable merging of globals .. option:: -mhwdiv=, --mhwdiv , --mhwdiv= +.. option:: -mhwmult= + .. option:: -miamcu, -mno-iamcu Use Intel MCU ABI @@ -2226,7 +2330,7 @@ Generate branches with extended addressability, usually via indirect jumps. .. option:: -mmacosx-version-min=, -mmacos-version-min= -Set macOS deployment target +Set Mac OS X deployment target .. option:: -mmcu= @@ -2280,6 +2384,8 @@ Select return address signing scope Use software floating point +.. option:: -mspeculative-load-hardening, -mno-speculative-load-hardening + .. option:: -mstack-alignment= Set the stack alignment @@ -2304,9 +2410,13 @@ The thread model to use, e.g. posix, single (posix by default) .. option:: -mthumb, -mno-thumb -.. option:: -mtune= +.. option:: -mtls-direct-seg-refs, -mno-tls-direct-seg-refs -Use -mtune=? to see a list of supported cpu models. +Enable direct TLS access through segment registers (default) + +.. program:: clang1 +.. option:: -mtune= +.. program:: clang .. option:: -mtvos-version-min=, -mappletvos-version-min= @@ -2318,83 +2428,147 @@ Use -mtune=? to see a list of supported cpu models. .. option:: -mwatchos-version-min= +.. option:: -mwavefrontsize64, -mno-wavefrontsize64 + +Wavefront size 64 is used + .. option:: -mwindows .. option:: -mx32 AARCH64 ------- +.. option:: -fcall-saved-x10 + +Make the x10 register call-saved (AArch64 only) + +.. option:: -fcall-saved-x11 + +Make the x11 register call-saved (AArch64 only) + +.. option:: -fcall-saved-x12 + +Make the x12 register call-saved (AArch64 only) + +.. option:: -fcall-saved-x13 + +Make the x13 register call-saved (AArch64 only) + +.. option:: -fcall-saved-x14 + +Make the x14 register call-saved (AArch64 only) + +.. option:: -fcall-saved-x15 + +Make the x15 register call-saved (AArch64 only) + +.. option:: -fcall-saved-x18 + +Make the x18 register call-saved (AArch64 only) + +.. option:: -fcall-saved-x8 + +Make the x8 register call-saved (AArch64 only) + +.. option:: -fcall-saved-x9 + +Make the x9 register call-saved (AArch64 only) + .. option:: -ffixed-x1 -Reserve the x1 register (AArch64 only) +Reserve the 1 register (AArch64 only) -.. option:: -ffixed-x2 +.. option:: -ffixed-x10 -Reserve the x2 register (AArch64 only) +Reserve the 10 register (AArch64 only) -.. option:: -ffixed-x3 +.. option:: -ffixed-x11 -Reserve the x3 register (AArch64 only) +Reserve the 11 register (AArch64 only) -.. option:: -ffixed-x4 +.. option:: -ffixed-x12 -Reserve the x4 register (AArch64 only) +Reserve the 12 register (AArch64 only) -.. option:: -ffixed-x5 +.. option:: -ffixed-x13 -Reserve the x5 register (AArch64 only) +Reserve the 13 register (AArch64 only) -.. option:: -ffixed-x6 +.. option:: -ffixed-x14 -Reserve the x6 register (AArch64 only) +Reserve the 14 register (AArch64 only) -.. option:: -ffixed-x7 +.. option:: -ffixed-x15 -Reserve the x7 register (AArch64 only) +Reserve the 15 register (AArch64 only) .. option:: -ffixed-x18 -Reserve the x18 register (AArch64 only) +Reserve the 18 register (AArch64 only) + +.. option:: -ffixed-x2 + +Reserve the 2 register (AArch64 only) .. option:: -ffixed-x20 -Reserve the x20 register (AArch64 only) +Reserve the 20 register (AArch64 only) -.. option:: -fcall-saved-x8 +.. option:: -ffixed-x21 -Make the x8 register call-saved (AArch64 only) +Reserve the 21 register (AArch64 only) -.. option:: -fcall-saved-x9 +.. option:: -ffixed-x22 -Make the x9 register call-saved (AArch64 only) +Reserve the 22 register (AArch64 only) -.. option:: -fcall-saved-x10 +.. option:: -ffixed-x23 -Make the x10 register call-saved (AArch64 only) +Reserve the 23 register (AArch64 only) -.. option:: -fcall-saved-x11 +.. option:: -ffixed-x24 -Make the x11 register call-saved (AArch64 only) +Reserve the 24 register (AArch64 only) -.. option:: -fcall-saved-x12 +.. option:: -ffixed-x25 -Make the x12 register call-saved (AArch64 only) +Reserve the 25 register (AArch64 only) -.. option:: -fcall-saved-x13 +.. option:: -ffixed-x26 -Make the x13 register call-saved (AArch64 only) +Reserve the 26 register (AArch64 only) -.. option:: -fcall-saved-x14 +.. option:: -ffixed-x27 -Make the x14 register call-saved (AArch64 only) +Reserve the 27 register (AArch64 only) -.. option:: -fcall-saved-x15 +.. option:: -ffixed-x28 -Make the x15 register call-saved (AArch64 only) +Reserve the 28 register (AArch64 only) -.. option:: -fcall-saved-x18 +.. option:: -ffixed-x3 -Make the x18 register call-saved (AArch64 only) +Reserve the 3 register (AArch64 only) + +.. option:: -ffixed-x4 + +Reserve the 4 register (AArch64 only) + +.. option:: -ffixed-x5 + +Reserve the 5 register (AArch64 only) + +.. option:: -ffixed-x6 + +Reserve the 6 register (AArch64 only) + +.. option:: -ffixed-x7 + +Reserve the 7 register (AArch64 only) + +.. option:: -ffixed-x9 + +Reserve the 9 register (AArch64 only) .. option:: -mfix-cortex-a53-835769, -mno-fix-cortex-a53-835769 @@ -2406,14 +2580,17 @@ Generate code which only uses the general purpose registers (AArch64 only) AMDGPU ------ +.. option:: -mcode-object-v3, -mno-code-object-v3 + +Enable code object v3 (AMDGPU only) + .. option:: -mcumode, -mno-cumode -CU wavefront execution mode is used if enabled and WGP wavefront execution mode -is used if disabled (AMDGPU only) +CU wavefront execution mode is used (AMDGPU only) -.. option:: -mwavefrontsize64, -mno-wavefrontsize64 +.. option:: -msram-ecc, -mno-sram-ecc -Wavefront size 64 is used if enabled and wavefront size 32 if disabled (AMDGPU only) +Enable SRAM ECC (AMDGPU only) .. option:: -mxnack, -mno-xnack @@ -2425,6 +2602,10 @@ ARM Reserve the r9 register (ARM only) +.. option:: -mcmse + +Allow use of CMSE (Armv8-M Security Extensions) + .. option:: -mexecute-only, -mno-execute-only, -mpure-code Disallow generation of data access to code sections (ARM only) @@ -2447,7 +2628,7 @@ Disallow generation of deprecated IT blocks for ARMv8. It is on by default for A .. option:: -mtp= -Read thread pointer from coprocessor register (ARM only) +Thread pointer access method (AArch32/AArch64 only) .. option:: -munaligned-access, -mno-unaligned-access @@ -2605,14 +2786,26 @@ PowerPC WebAssembly ----------- +.. option:: -matomics, -mno-atomics + +.. option:: -mbulk-memory, -mno-bulk-memory + .. option:: -mexception-handling, -mno-exception-handling +.. option:: -mmultivalue, -mno-multivalue + +.. option:: -mmutable-globals, -mno-mutable-globals + .. option:: -mnontrapping-fptoint, -mno-nontrapping-fptoint .. option:: -msign-ext, -mno-sign-ext .. option:: -msimd128, -mno-simd128 +.. option:: -mtail-call, -mno-tail-call + +.. option:: -munimplemented-simd128, -mno-unimplemented-simd128 + X86 --- .. option:: -m3dnow, -mno-3dnow @@ -2627,10 +2820,10 @@ X86 .. option:: -mavx2, -mno-avx2 -.. option:: -mavx512bitalg, -mno-avx512bitalg - .. option:: -mavx512bf16, -mno-avx512bf16 +.. option:: -mavx512bitalg, -mno-avx512bitalg + .. option:: -mavx512bw, -mno-avx512bw .. option:: -mavx512cd, -mno-avx512cd @@ -2779,6 +2972,10 @@ RISCV Enable linker relaxation +.. option:: -msave-restore, -mno-save-restore + +Enable using library calls for save and restore + Optimization level ~~~~~~~~~~~~~~~~~~ @@ -2836,6 +3033,10 @@ ___________ .. option:: -ggdb3 +.. option:: -gline-directives-only + +Emit debug line info directives only + .. option:: -gline-tables-only, -g1, -gmlt Emit debug line number tables only @@ -2866,10 +3067,16 @@ Embed source text in DWARF debug sections .. option:: -gpubnames, -gno-pubnames -.. option:: -grecord-command-line, -grecord-gcc-switches, -gno-record-command-line, -gno-record-gcc-switches +.. option:: -grecord-command-line, -gno-record-command-line, -grecord-gcc-switches .. option:: -gsplit-dwarf +.. program:: clang1 +.. option:: -gsplit-dwarf= +.. program:: clang + +Set DWARF fission mode to either 'split' or 'single' + .. option:: -gstrict-dwarf, -gno-strict-dwarf .. option:: -gz diff --git a/clang/docs/DiagnosticsReference.rst b/clang/docs/DiagnosticsReference.rst index 7d9b1e8359a8..0b6241213083 100644 --- a/clang/docs/DiagnosticsReference.rst +++ b/clang/docs/DiagnosticsReference.rst @@ -207,17 +207,6 @@ This diagnostic is enabled by default. Controls `-Wpointer-bool-conversion`_, `-Wstring-compare`_, `-Wtautological-pointer-compare`_. --Waddress-of-array-temporary ----------------------------- -This diagnostic is enabled by default. - -**Diagnostic text:** - -+---------------------------------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`pointer is initialized by a temporary array, which will be destroyed at the end of the full-expression`| -+---------------------------------------------------------------------------------------------------------------------------------------------+ - - -Waddress-of-packed-member -------------------------- This diagnostic is enabled by default. @@ -244,21 +233,6 @@ This diagnostic is an error by default, but the flag ``-Wno-address-of-temporary ------------------ This diagnostic flag exists for GCC compatibility, and has no effect in Clang. --Waligned-allocation-unavailable --------------------------------- -This diagnostic is an error by default, but the flag ``-Wno-aligned-allocation-unavailable`` can be used to disable the error. - -**Diagnostic text:** - -+--------------------------------------------------+--------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -|:error:`error:` |nbsp| :diagtext:`aligned` |nbsp| |+------------------------+| |nbsp| :diagtext:`function of type '`:placeholder:`B`:diagtext:`' is only available on` |nbsp| :placeholder:`C` |nbsp| :placeholder:`D` |nbsp| :diagtext:`or newer`| -| ||:diagtext:`allocation` || | -| |+------------------------+| | -| ||:diagtext:`deallocation`|| | -| |+------------------------+| | -+--------------------------------------------------+--------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+ - - -Wall ----- Some of the diagnostics controlled by this flag are enabled by default. @@ -473,6 +447,17 @@ This diagnostic is enabled by default. +-----------------------------------------------------------------------------------------------------------------------------+ +-Wargument-outside-range +------------------------ +This diagnostic is an error by default, but the flag ``-Wno-argument-outside-range`` can be used to disable the error. + +**Diagnostic text:** + ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:error:`error:` |nbsp| :diagtext:`argument value` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is outside the valid range \[`:placeholder:`B`:diagtext:`,` |nbsp| :placeholder:`C`:diagtext:`\]`| ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + + -Warray-bounds -------------- This diagnostic is enabled by default. @@ -491,9 +476,17 @@ This diagnostic is enabled by default. |:warning:`warning:` |nbsp| :diagtext:`array index` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is before the beginning of the array`| +----------------------------------------------------------------------------------------------------------------------------------+ -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`array argument is too small; contains` |nbsp| :placeholder:`A` |nbsp| :diagtext:`elements, callee requires at least` |nbsp| :placeholder:`B`| -+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ++---------------------------------------------------------------------------+----------------------------------------------------------------------------+--------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`array argument is too small;` |nbsp| |+--------------------------------------------------------------------------+|:diagtext:`, callee requires at least` |nbsp| :placeholder:`B`| +| ||+------------------------------------------------------------------------+|| | +| |||:diagtext:`contains` |nbsp| :placeholder:`A` |nbsp| :diagtext:`elements`||| | +| ||+------------------------------------------------------------------------+|| | +| |+--------------------------------------------------------------------------+| | +| ||+----------------------------------------------+ || | +| |||:diagtext:`is of size` |nbsp| :placeholder:`A`| || | +| ||+----------------------------------------------+ || | +| |+--------------------------------------------------------------------------+| | ++---------------------------------------------------------------------------+----------------------------------------------------------------------------+--------------------------------------------------------------+ +-----------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`'static' has no effect on zero-length arrays`| @@ -572,13 +565,41 @@ This diagnostic is enabled by default. -Wat-protocol ------------- +This diagnostic flag exists for GCC compatibility, and has no effect in Clang. + +-Watimport-in-framework-header +------------------------------ This diagnostic is enabled by default. **Diagnostic text:** -+-------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`@protocol is using a forward protocol declaration of` |nbsp| :placeholder:`A`| -+-------------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`use of '@import' in framework header is discouraged, including this header requires -fmodules`| ++------------------------------------------------------------------------------------------------------------------------------------+ + + +-Watomic-alignment +------------------ +This diagnostic is enabled by default. + +**Diagnostic text:** + ++---------------------------+------------------------+------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| |+----------------------+| |nbsp| :diagtext:`atomic operation may incur significant performance penalty`| +| ||:diagtext:`large` || | +| |+----------------------+| | +| ||:diagtext:`misaligned`|| | +| |+----------------------+| | ++---------------------------+------------------------+------------------------------------------------------------------------------+ + + +-Watomic-implicit-seq-cst +------------------------- +**Diagnostic text:** + ++---------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`implicit use of sequentially-consistent atomic may incur stronger memory barriers than necessary`| ++---------------------------------------------------------------------------------------------------------------------------------------+ -Watomic-memory-ordering @@ -690,6 +711,20 @@ This diagnostic is enabled by default. |:warning:`warning:` |nbsp| :diagtext:`'unavailable' availability overrides all other availability information`| +--------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------+----------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`ignoring availability attribute` |nbsp| |+--------------------------------------+| +| ||:diagtext:`on '+load' method` || +| |+--------------------------------------+| +| ||:diagtext:`with constructor attribute`|| +| |+--------------------------------------+| +| ||:diagtext:`with destructor attribute` || +| |+--------------------------------------+| ++------------------------------------------------------------------------------+----------------------------------------+ + ++---------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`only 'unavailable' and 'deprecated' are supported for Swift availability`| ++---------------------------------------------------------------------------------------------------------------+ + +------------------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`unknown platform` |nbsp| :placeholder:`A` |nbsp| :diagtext:`in availability macro`| +------------------------------------------------------------------------------------------------------------------------+ @@ -731,6 +766,33 @@ This diagnostic is enabled by default. +---------------------------+--------------------------------+---------------------------------------------------------------------------------------------------+-----------------------------------------------+--------------------------------+ +-Wavr-rtlib-linking-quirks +-------------------------- +This diagnostic is enabled by default. + +**Diagnostic text:** + ++----------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`support for linking stdlibs for microcontroller '`:placeholder:`A`:diagtext:`' is not implemented`| ++----------------------------------------------------------------------------------------------------------------------------------------+ + ++-------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`no avr-gcc installation can be found on the system, cannot link standard libraries`| ++-------------------------------------------------------------------------------------------------------------------------+ + ++--------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`no avr-libc installation can be found on the system, cannot link standard libraries`| ++--------------------------------------------------------------------------------------------------------------------------+ + ++--------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`no target microcontroller specified on command line, cannot link standard libraries, please pass -mmcu=`| ++--------------------------------------------------------------------------------------------------------------------------------------------------------+ + ++-----------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`standard library not linked and so no interrupt vector table or compiler runtime routines will be linked`| ++-----------------------------------------------------------------------------------------------------------------------------------------------+ + + -Wbackend-plugin ---------------- This diagnostic is enabled by default. @@ -779,31 +841,44 @@ Also controls `-Wc++98-compat-bind-to-temporary-copy`_. | |+---------------------+| +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------------------+ -+--------------------------------------------------------------------+-----------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`no viable constructor` |nbsp| |+---------------------------------------+| |nbsp| :diagtext:`of type` |nbsp| :placeholder:`B`:diagtext:`; C++98 requires a copy constructor when binding a reference to a temporary`| -| ||:diagtext:`copying variable` || | -| |+---------------------------------------+| | -| ||:diagtext:`copying parameter` || | -| |+---------------------------------------+| | -| ||:diagtext:`returning object` || | -| |+---------------------------------------+| | -| ||:diagtext:`throwing object` || | -| |+---------------------------------------+| | -| ||:diagtext:`copying member subobject` || | -| |+---------------------------------------+| | -| ||:diagtext:`copying array element` || | -| |+---------------------------------------+| | -| ||:diagtext:`allocating object` || | -| |+---------------------------------------+| | -| ||:diagtext:`copying temporary` || | -| |+---------------------------------------+| | -| ||:diagtext:`initializing base subobject`|| | -| |+---------------------------------------+| | -| ||:diagtext:`initializing vector element`|| | -| |+---------------------------------------+| | -| ||:diagtext:`capturing value` || | -| |+---------------------------------------+| | -+--------------------------------------------------------------------+-----------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+ ++--------------------------------------------------------------------+------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`no viable constructor` |nbsp| |+----------------------------------------------------+| |nbsp| :diagtext:`of type` |nbsp| :placeholder:`B`:diagtext:`; C++98 requires a copy constructor when binding a reference to a temporary`| +| ||:diagtext:`copying variable` || | +| |+----------------------------------------------------+| | +| ||:diagtext:`copying parameter` || | +| |+----------------------------------------------------+| | +| ||:diagtext:`returning object` || | +| |+----------------------------------------------------+| | +| ||:diagtext:`initializing statement expression result`|| | +| |+----------------------------------------------------+| | +| ||:diagtext:`throwing object` || | +| |+----------------------------------------------------+| | +| ||:diagtext:`copying member subobject` || | +| |+----------------------------------------------------+| | +| ||:diagtext:`copying array element` || | +| |+----------------------------------------------------+| | +| ||:diagtext:`allocating object` || | +| |+----------------------------------------------------+| | +| ||:diagtext:`copying temporary` || | +| |+----------------------------------------------------+| | +| ||:diagtext:`initializing base subobject` || | +| |+----------------------------------------------------+| | +| ||:diagtext:`initializing vector element` || | +| |+----------------------------------------------------+| | +| ||:diagtext:`capturing value` || | +| |+----------------------------------------------------+| | ++--------------------------------------------------------------------+------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+ + + +-Wbinding-in-condition +---------------------- +This diagnostic is enabled by default. + +**Diagnostic text:** + ++--------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`ISO C++17 does not permit structured binding declaration in a condition`| ++--------------------------------------------------------------------------------------------------------------+ -Wbitfield-constant-conversion @@ -944,9 +1019,9 @@ This diagnostic is enabled by default. **Diagnostic text:** -+------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`will always overflow destination buffer`| -+------------------------------------------------------------------------------------------------------+ ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`'`:placeholder:`A`:diagtext:`' will always overflow; destination buffer has size` |nbsp| :placeholder:`B`:diagtext:`, but size argument is` |nbsp| :placeholder:`C`| ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -Wbuiltin-requires-header @@ -1180,28 +1255,6 @@ Also controls `-Wc++11-extra-semi`_, `-Wc++11-inline-namespace`_, `-Wc++11-long- |:warning:`warning:` |nbsp| :diagtext:`default template arguments for a function template are a C++11 extension`| +---------------------------------------------------------------------------------------------------------------+ -+-------------------------------------------------------------------+---------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`first declaration of` |nbsp| |+-------------------------------------+| |nbsp| :diagtext:`specialization of` |nbsp| :placeholder:`B` |nbsp| :diagtext:`outside namespace` |nbsp| :placeholder:`C` |nbsp| :diagtext:`is a C++11 extension`| -| ||:diagtext:`class template` || | -| |+-------------------------------------+| | -| ||:diagtext:`class template partial` || | -| |+-------------------------------------+| | -| ||:diagtext:`variable template` || | -| |+-------------------------------------+| | -| ||:diagtext:`variable template partial`|| | -| |+-------------------------------------+| | -| ||:diagtext:`function template` || | -| |+-------------------------------------+| | -| ||:diagtext:`member function` || | -| |+-------------------------------------+| | -| ||:diagtext:`static data member` || | -| |+-------------------------------------+| | -| ||:diagtext:`member class` || | -| |+-------------------------------------+| | -| ||:diagtext:`member enumeration` || | -| |+-------------------------------------+| | -+-------------------------------------------------------------------+---------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+ - +------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`'typename' occurs outside of a template`| +------------------------------------------------------------------------------+ @@ -1260,19 +1313,21 @@ Some of the diagnostics controlled by this flag are enabled by default. **Diagnostic text:** -+-----------------------+----------------------------------------+--------+--------------------------------------------------------------------------------------------------------------------------+ -|:error:`error:` |nbsp| |+--------------------------------------+| |nbsp| |+------------------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`case value` || ||+--------------------------------------------------------------------------------------------------------------+ || -| |+--------------------------------------+| |||:diagtext:`cannot be narrowed from type` |nbsp| :placeholder:`C` |nbsp| :diagtext:`to` |nbsp| :placeholder:`D`| || -| ||:diagtext:`enumerator value` || ||+--------------------------------------------------------------------------------------------------------------+ || -| |+--------------------------------------+| |+------------------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`non-type template argument`|| ||+----------------------------------------------------------------------------------------------------------------------+|| -| |+--------------------------------------+| |||:diagtext:`evaluates to` |nbsp| :placeholder:`C`:diagtext:`, which cannot be narrowed to type` |nbsp| :placeholder:`D`||| -| ||:diagtext:`array size` || ||+----------------------------------------------------------------------------------------------------------------------+|| -| |+--------------------------------------+| |+------------------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`constexpr if condition` || | | -| |+--------------------------------------+| | | -+-----------------------+----------------------------------------+--------+--------------------------------------------------------------------------------------------------------------------------+ ++-----------------------+-----------------------------------------+--------+--------------------------------------------------------------------------------------------------------------------------+ +|:error:`error:` |nbsp| |+---------------------------------------+| |nbsp| |+------------------------------------------------------------------------------------------------------------------------+| +| ||:diagtext:`case value` || ||+--------------------------------------------------------------------------------------------------------------+ || +| |+---------------------------------------+| |||:diagtext:`cannot be narrowed from type` |nbsp| :placeholder:`C` |nbsp| :diagtext:`to` |nbsp| :placeholder:`D`| || +| ||:diagtext:`enumerator value` || ||+--------------------------------------------------------------------------------------------------------------+ || +| |+---------------------------------------+| |+------------------------------------------------------------------------------------------------------------------------+| +| ||:diagtext:`non-type template argument` || ||+----------------------------------------------------------------------------------------------------------------------+|| +| |+---------------------------------------+| |||:diagtext:`evaluates to` |nbsp| :placeholder:`C`:diagtext:`, which cannot be narrowed to type` |nbsp| :placeholder:`D`||| +| ||:diagtext:`array size` || ||+----------------------------------------------------------------------------------------------------------------------+|| +| |+---------------------------------------+| |+------------------------------------------------------------------------------------------------------------------------+| +| ||:diagtext:`constexpr if condition` || | | +| |+---------------------------------------+| | | +| ||:diagtext:`explicit specifier argument`|| | | +| |+---------------------------------------+| | | ++-----------------------+-----------------------------------------+--------+--------------------------------------------------------------------------------------------------------------------------+ +-----------------------------------------------------------------------------------------------------------------------------------------------------------------------+ |:error:`error:` |nbsp| :diagtext:`constant expression evaluates to` |nbsp| :placeholder:`A` |nbsp| :diagtext:`which cannot be narrowed to type` |nbsp| :placeholder:`B`| @@ -1402,6 +1457,10 @@ Some of the diagnostics controlled by this flag are enabled by default. **Diagnostic text:** ++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`ISO C++ standards before C++17 do not allow new expression for type` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to use list-initialization`| ++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + +------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`constexpr if is a C++17 extension`| +------------------------------------------------------------------------+ @@ -1501,8 +1560,30 @@ Synonym for `-Wc++17-extensions`_. -Wc++2a-compat -------------- +Some of the diagnostics controlled by this flag are enabled by default. + **Diagnostic text:** ++------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`consteval is incompatible with C++ standards before C++20`| ++------------------------------------------------------------------------------------------------+ + ++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`aggregate initialization of type` |nbsp| :placeholder:`A` |nbsp| :diagtext:`with user-declared constructors is incompatible with C++2a`| ++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + ++------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`this expression will be parsed as explicit(bool) in C++2a`| ++------------------------------------------------------------------------------------------------+ + ++------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`'<=>' is a single token in C++2a; add a space to avoid a change in behavior`| ++------------------------------------------------------------------------------------------------------------------+ + ++--------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`type of UTF-8 string literal will change from array of const char to array of const char8\_t in C++2a`| ++--------------------------------------------------------------------------------------------------------------------------------------------+ + +-------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`'`:placeholder:`A`:diagtext:`' is a keyword in C++2a`| +-------------------------------------------------------------------------------------------+ @@ -1519,14 +1600,62 @@ Some of the diagnostics controlled by this flag are enabled by default. **Diagnostic text:** ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`use of function template name with no prior declaration in function call with explicit template arguments is a C++2a extension`| ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + +----------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`default member initializer for bit-field is a C++2a extension`| +----------------------------------------------------------------------------------------------------+ ++-----------------------------------------------------------------------------------+-------------------------+----------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`use of this statement in a constexpr` |nbsp| |+-----------------------+| |nbsp| :diagtext:`is a C++2a extension`| +| ||:diagtext:`function` || | +| |+-----------------------+| | +| ||:diagtext:`constructor`|| | +| |+-----------------------+| | ++-----------------------------------------------------------------------------------+-------------------------+----------------------------------------+ + ++------------------------------------------------------------------------------+-------------------------+----------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`function try block in constexpr` |nbsp| |+-----------------------+| |nbsp| :diagtext:`is a C++2a extension`| +| ||:diagtext:`function` || | +| |+-----------------------+| | +| ||:diagtext:`constructor`|| | +| |+-----------------------+| | ++------------------------------------------------------------------------------+-------------------------+----------------------------------------+ + ++---------------------------------------------------------------------------------+--------------------------------------------------------------+----------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`decomposition declaration declared` |nbsp| |+------------------------------------------------------------+| |nbsp| :diagtext:`is a C++2a extension`| +| ||+------------------------------------------+ || | +| |||:diagtext:`'`:placeholder:`B`:diagtext:`'`| || | +| ||+------------------------------------------+ || | +| |+------------------------------------------------------------+| | +| ||+----------------------------------------------------------+|| | +| |||:diagtext:`with '`:placeholder:`B`:diagtext:`' specifiers`||| | +| ||+----------------------------------------------------------+|| | +| |+------------------------------------------------------------+| | ++---------------------------------------------------------------------------------+--------------------------------------------------------------+----------------------------------------+ + +--------------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`explicit capture of 'this' with a capture default of '=' is a C++2a extension`| +--------------------------------------------------------------------------------------------------------------------+ ++-----------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`range-based for loop initialization statements are a C++2a extension`| ++-----------------------------------------------------------------------------------------------------------+ + ++---------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`initialized lambda pack captures are a C++2a extension`| ++---------------------------------------------------------------------------------------------+ + ++----------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`inline nested namespace definition is a C++2a extension`| ++----------------------------------------------------------------------------------------------+ + ++--------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`explicit template parameter list for lambdas is a C++2a extension`| ++--------------------------------------------------------------------------------------------------------+ + +--------------------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`invoking a pointer to a 'const &' member function on an rvalue is a C++2a extension`| +--------------------------------------------------------------------------------------------------------------------------+ @@ -1536,14 +1665,98 @@ Some of the diagnostics controlled by this flag are enabled by default. -------------------------------- **Diagnostic text:** ++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`use of function template name with no prior function template declaration in function call with explicit template arguments is incompatible with C++ standards before C++2a`| ++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + +-------------------------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`default member initializer for bit-field is incompatible with C++ standards before C++2a`| +-------------------------------------------------------------------------------------------------------------------------------+ ++-----------------------------------------------------------------------------------+-------------------------+-------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`use of this statement in a constexpr` |nbsp| |+-----------------------+| |nbsp| :diagtext:`is incompatible with C++ standards before C++2a`| +| ||:diagtext:`function` || | +| |+-----------------------+| | +| ||:diagtext:`constructor`|| | +| |+-----------------------+| | ++-----------------------------------------------------------------------------------+-------------------------+-------------------------------------------------------------------+ + ++------------------------------------------------------------------------------+-------------------------+-------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`function try block in constexpr` |nbsp| |+-----------------------+| |nbsp| :diagtext:`is incompatible with C++ standards before C++2a`| +| ||:diagtext:`function` || | +| |+-----------------------+| | +| ||:diagtext:`constructor`|| | +| |+-----------------------+| | ++------------------------------------------------------------------------------+-------------------------+-------------------------------------------------------------------+ + ++-------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`virtual constexpr functions are incompatible with C++ standards before C++2a`| ++-------------------------------------------------------------------------------------------------------------------+ + ++---------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`decomposition declaration declared` |nbsp| |+------------------------------------------------------------+| |nbsp| :diagtext:`is incompatible with C++ standards before C++2a`| +| ||+------------------------------------------+ || | +| |||:diagtext:`'`:placeholder:`B`:diagtext:`'`| || | +| ||+------------------------------------------+ || | +| |+------------------------------------------------------------+| | +| ||+----------------------------------------------------------+|| | +| |||:diagtext:`with '`:placeholder:`B`:diagtext:`' specifiers`||| | +| ||+----------------------------------------------------------+|| | +| |+------------------------------------------------------------+| | ++---------------------------------------------------------------------------------+--------------------------------------------------------------+-------------------------------------------------------------------+ + ++-------------------------------------------------------------------------+--------------------------------------+----------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`explicitly defaulting this` |nbsp| |+------------------------------------+| |nbsp| :diagtext:`with a type different from the implicit type is incompatible with C++ standards before C++2a`| +| ||:diagtext:`default constructor` || | +| |+------------------------------------+| | +| ||:diagtext:`copy constructor` || | +| |+------------------------------------+| | +| ||:diagtext:`move constructor` || | +| |+------------------------------------+| | +| ||:diagtext:`copy assignment operator`|| | +| |+------------------------------------+| | +| ||:diagtext:`move assignment operator`|| | +| |+------------------------------------+| | +| ||:diagtext:`destructor` || | +| |+------------------------------------+| | ++-------------------------------------------------------------------------+--------------------------------------+----------------------------------------------------------------------------------------------------------------+ + +-----------------------------------------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`explicit capture of 'this' with a capture default of '=' is incompatible with C++ standards before C++2a`| +-----------------------------------------------------------------------------------------------------------------------------------------------+ ++--------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`range-based for loop initialization statements are incompatible with C++ standards before C++2a`| ++--------------------------------------------------------------------------------------------------------------------------------------+ + ++------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`initialized lambda capture packs are incompatible with C++ standards before C++2a`| ++------------------------------------------------------------------------------------------------------------------------+ + ++-------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`inline nested namespace definition is incompatible with C++ standards before C++2a`| ++-------------------------------------------------------------------------------------------------------------------------+ + ++---------------------------+----------------------------------+-----------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| |+--------------------------------+| |nbsp| :diagtext:`of lambda is incompatible with C++ standards before C++2a`| +| ||:diagtext:`default construction`|| | +| |+--------------------------------+| | +| ||:diagtext:`assignment` || | +| |+--------------------------------+| | ++---------------------------+----------------------------------+-----------------------------------------------------------------------------+ + ++-----------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`explicit template parameter list for lambdas is incompatible with C++ standards before C++2a`| ++-----------------------------------------------------------------------------------------------------------------------------------+ + ++-----------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`'<=>' operator is incompatible with C++ standards before C++2a`| ++-----------------------------------------------------------------------------------------------------+ + ++----------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`'char8\_t' type specifier is incompatible with C++ standards before C++20`| ++----------------------------------------------------------------------------------------------------------------+ + -Wc++98-c++11-c++14-c++17-compat-pedantic ----------------------------------------- @@ -1560,6 +1773,16 @@ Also controls `-Wc++98-c++11-c++14-c++17-compat`_. -------------------------- **Diagnostic text:** ++------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`class template argument deduction is incompatible with C++ standards before C++17`|+---------------------------------------------------------------------------------+| +| || || +| |+---------------------------------------------------------------------------------+| +| ||+-------------------------------------------------------------------------------+|| +| |||:diagtext:`; for compatibility, use explicit type name` |nbsp| :placeholder:`B`||| +| ||+-------------------------------------------------------------------------------+|| +| |+---------------------------------------------------------------------------------+| ++------------------------------------------------------------------------------------------------------------------------+-----------------------------------------------------------------------------------+ + +---------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`constexpr if is incompatible with C++ standards before C++17`| +---------------------------------------------------------------------------------------------------+ @@ -1688,10 +1911,18 @@ Also controls `-Wc++98-c++11-c++14-compat`_. |:warning:`warning:` |nbsp| :diagtext:`'decltype(auto)' type specifier is incompatible with C++ standards before C++14`| +----------------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`return type deduction is incompatible with C++ standards before C++14`| ++------------------------------------------------------------------------------------------------------------+ + +--------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`digit separators are incompatible with C++ standards before C++14`| +--------------------------------------------------------------------------------------------------------+ ++----------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`generic lambdas are incompatible with C++11`| ++----------------------------------------------------------------------------------+ + +-------------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`initialized lambda captures are incompatible with C++ standards before C++14`| +-------------------------------------------------------------------------------------------------------------------+ @@ -1801,9 +2032,13 @@ Also controls `-Wc++98-c++11-c++14-c++17-compat`_, `-Wc++98-c++11-c++14-compat`_ |:warning:`warning:` |nbsp| :diagtext:`jump from this goto statement to its label is incompatible with C++98`| +------------------------------------------------------------------------------------------------------------+ -+---------------------------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`jump from this indirect goto statement to one of its possible targets is incompatible with C++98`| -+---------------------------------------------------------------------------------------------------------------------------------------+ ++-------------------------------------------------------------+----------------------+--------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`jump from this` |nbsp| |+--------------------+| |nbsp| :diagtext:`goto statement to one of its possible targets is incompatible with C++98`| +| ||:diagtext:`indirect`|| | +| |+--------------------+| | +| ||:diagtext:`asm` || | +| |+--------------------+| | ++-------------------------------------------------------------+----------------------+--------------------------------------------------------------------------------------------+ +------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`initialization of initializer\_list object is incompatible with C++98`| @@ -1855,7 +2090,7 @@ Also controls `-Wc++98-c++11-c++14-c++17-compat`_, `-Wc++98-c++11-c++14-compat`_ +---------------------------+------------------------------+------------------------------------------------------------------------------------------------+--------------------------------------+----------------------------------------------+ |:warning:`warning:` |nbsp| |+----------------------------+| |nbsp| :diagtext:`member` |nbsp| :placeholder:`B` |nbsp| :diagtext:`with a non-trivial` |nbsp| |+------------------------------------+| |nbsp| :diagtext:`is incompatible with C++98`| -| ||:diagtext:`anonymous struct`|| ||:diagtext:`constructor` || | +| ||:diagtext:`anonymous struct`|| ||:diagtext:`default constructor` || | | |+----------------------------+| |+------------------------------------+| | | ||:diagtext:`union` || ||:diagtext:`copy constructor` || | | |+----------------------------+| |+------------------------------------+| | @@ -1949,28 +2184,6 @@ Also controls `-Wc++98-c++11-c++14-c++17-compat`_, `-Wc++98-c++11-c++14-compat`_ |:warning:`warning:` |nbsp| :diagtext:`default template arguments for a function template are incompatible with C++98`| +---------------------------------------------------------------------------------------------------------------------+ -+---------------------------+---------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| |+-------------------------------------+| |nbsp| :diagtext:`specialization of` |nbsp| :placeholder:`B` |nbsp| :diagtext:`outside namespace` |nbsp| :placeholder:`C` |nbsp| :diagtext:`is incompatible with C++98`| -| ||:diagtext:`class template` || | -| |+-------------------------------------+| | -| ||:diagtext:`class template partial` || | -| |+-------------------------------------+| | -| ||:diagtext:`variable template` || | -| |+-------------------------------------+| | -| ||:diagtext:`variable template partial`|| | -| |+-------------------------------------+| | -| ||:diagtext:`function template` || | -| |+-------------------------------------+| | -| ||:diagtext:`member function` || | -| |+-------------------------------------+| | -| ||:diagtext:`static data member` || | -| |+-------------------------------------+| | -| ||:diagtext:`member class` || | -| |+-------------------------------------+| | -| ||:diagtext:`member enumeration` || | -| |+-------------------------------------+| | -+---------------------------+---------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ - +----------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`trailing return types are incompatible with C++98`| +----------------------------------------------------------------------------------------+ @@ -2022,29 +2235,42 @@ Also controls `-Wc++98-c++11-c++14-c++17-compat`_, `-Wc++98-c++11-c++14-compat`_ ------------------------------------- **Diagnostic text:** -+---------------------------+-----------------------------------------+----------------------------------------------------------------------------------------------------------------------------+------------------------------------------------+----------------------------+ -|:warning:`warning:` |nbsp| |+---------------------------------------+| |nbsp| :diagtext:`of type` |nbsp| :placeholder:`C` |nbsp| :diagtext:`when binding a reference to a temporary would` |nbsp| |+----------------------------------------------+| |nbsp| :diagtext:`in C++98`| -| ||:diagtext:`copying variable` || ||:diagtext:`invoke an inaccessible constructor`|| | -| |+---------------------------------------+| |+----------------------------------------------+| | -| ||:diagtext:`copying parameter` || ||:diagtext:`find no viable constructor` || | -| |+---------------------------------------+| |+----------------------------------------------+| | -| ||:diagtext:`returning object` || ||:diagtext:`find ambiguous constructors` || | -| |+---------------------------------------+| |+----------------------------------------------+| | -| ||:diagtext:`throwing object` || ||:diagtext:`invoke a deleted constructor` || | -| |+---------------------------------------+| |+----------------------------------------------+| | -| ||:diagtext:`copying member subobject` || | | | -| |+---------------------------------------+| | | | -| ||:diagtext:`copying array element` || | | | -| |+---------------------------------------+| | | | -| ||:diagtext:`allocating object` || | | | -| |+---------------------------------------+| | | | -| ||:diagtext:`copying temporary` || | | | -| |+---------------------------------------+| | | | -| ||:diagtext:`initializing base subobject`|| | | | -| |+---------------------------------------+| | | | -| ||:diagtext:`initializing vector element`|| | | | -| |+---------------------------------------+| | | | -+---------------------------+-----------------------------------------+----------------------------------------------------------------------------------------------------------------------------+------------------------------------------------+----------------------------+ ++---------------------------+------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+------------------------------------------------+----------------------------+ +|:warning:`warning:` |nbsp| |+----------------------------------------------------+| |nbsp| :diagtext:`of type` |nbsp| :placeholder:`C` |nbsp| :diagtext:`when binding a reference to a temporary would` |nbsp| |+----------------------------------------------+| |nbsp| :diagtext:`in C++98`| +| ||:diagtext:`copying variable` || ||:diagtext:`invoke an inaccessible constructor`|| | +| |+----------------------------------------------------+| |+----------------------------------------------+| | +| ||:diagtext:`copying parameter` || ||:diagtext:`find no viable constructor` || | +| |+----------------------------------------------------+| |+----------------------------------------------+| | +| ||:diagtext:`returning object` || ||:diagtext:`find ambiguous constructors` || | +| |+----------------------------------------------------+| |+----------------------------------------------+| | +| ||:diagtext:`initializing statement expression result`|| ||:diagtext:`invoke a deleted constructor` || | +| |+----------------------------------------------------+| |+----------------------------------------------+| | +| ||:diagtext:`throwing object` || | | | +| |+----------------------------------------------------+| | | | +| ||:diagtext:`copying member subobject` || | | | +| |+----------------------------------------------------+| | | | +| ||:diagtext:`copying array element` || | | | +| |+----------------------------------------------------+| | | | +| ||:diagtext:`allocating object` || | | | +| |+----------------------------------------------------+| | | | +| ||:diagtext:`copying temporary` || | | | +| |+----------------------------------------------------+| | | | +| ||:diagtext:`initializing base subobject` || | | | +| |+----------------------------------------------------+| | | | +| ||:diagtext:`initializing vector element` || | | | +| |+----------------------------------------------------+| | | | +| ||:diagtext:`capturing value` || | | | +| |+----------------------------------------------------+| | | | ++---------------------------+------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------+------------------------------------------------+----------------------------+ + + +-Wc++98-compat-extra-semi +------------------------- +**Diagnostic text:** + ++-------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`extra ';' outside of a function is incompatible with C++98`| ++-------------------------------------------------------------------------------------------------+ -Wc++98-compat-local-type-template-args @@ -2058,7 +2284,7 @@ Also controls `-Wc++98-c++11-c++14-c++17-compat`_, `-Wc++98-c++11-c++14-compat`_ -Wc++98-compat-pedantic ----------------------- -Also controls `-Wc++98-c++11-c++14-c++17-compat-pedantic`_, `-Wc++98-c++11-c++14-compat-pedantic`_, `-Wc++98-c++11-compat-pedantic`_, `-Wc++98-compat`_, `-Wc++98-compat-bind-to-temporary-copy`_. +Also controls `-Wc++98-c++11-c++14-c++17-compat-pedantic`_, `-Wc++98-c++11-c++14-compat-pedantic`_, `-Wc++98-c++11-compat-pedantic`_, `-Wc++98-compat`_, `-Wc++98-compat-bind-to-temporary-copy`_, `-Wc++98-compat-extra-semi`_. **Diagnostic text:** @@ -2098,10 +2324,6 @@ Also controls `-Wc++98-c++11-c++14-c++17-compat-pedantic`_, `-Wc++98-c++11-c++14 |:warning:`warning:` |nbsp| :diagtext:`#line number greater than 32767 is incompatible with C++98`| +-------------------------------------------------------------------------------------------------+ -+-------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`extra ';' outside of a function is incompatible with C++98`| -+-------------------------------------------------------------------------------------------------+ - +----------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`variadic macros are incompatible with C++98`| +----------------------------------------------------------------------------------+ @@ -2225,6 +2447,21 @@ Some of the diagnostics controlled by this flag are enabled by default. +---------------------------------------------------------------------------------------+ +-Wcall-to-pure-virtual-from-ctor-dtor +------------------------------------- +This diagnostic is enabled by default. + +**Diagnostic text:** + ++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------+----------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`call to pure virtual member function` |nbsp| :placeholder:`A` |nbsp| :diagtext:`has undefined behavior; overrides of` |nbsp| :placeholder:`A` |nbsp| :diagtext:`in subclasses are not available in the` |nbsp| |+-----------------------+| |nbsp| :diagtext:`of` |nbsp| :placeholder:`C`| +| ||:diagtext:`constructor`|| | +| |+-----------------------+| | +| ||:diagtext:`destructor` || | +| |+-----------------------+| | ++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------+----------------------------------------------+ + + -Wcast-align ------------ **Diagnostic text:** @@ -2275,6 +2512,29 @@ This diagnostic is enabled by default. +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +-Wcast-qual-unrelated +--------------------- +This diagnostic is enabled by default. + +**Diagnostic text:** + ++---------------------------------------------------------------------+-----------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`ISO C++ does not allow` |nbsp| |+---------------------------------+| |nbsp| :diagtext:`from` |nbsp| :placeholder:`B` |nbsp| :diagtext:`to` |nbsp| :placeholder:`C` |nbsp| :diagtext:`because it casts away qualifiers, even though the source and destination types are unrelated`| +| ||:diagtext:`const\_cast` || | +| |+---------------------------------+| | +| ||:diagtext:`static\_cast` || | +| |+---------------------------------+| | +| ||:diagtext:`reinterpret\_cast` || | +| |+---------------------------------+| | +| ||:diagtext:`dynamic\_cast` || | +| |+---------------------------------+| | +| ||:diagtext:`C-style cast` || | +| |+---------------------------------+| | +| ||:diagtext:`functional-style cast`|| | +| |+---------------------------------+| | ++---------------------------------------------------------------------+-----------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + + -Wchar-align ------------ This diagnostic flag exists for GCC compatibility, and has no effect in Clang. @@ -2310,14 +2570,18 @@ This diagnostic is enabled by default. |:warning:`warning:` |nbsp| :diagtext:`support for '/Yc' and '/Yu' with different filenames not implemented yet; flags ignored`| +------------------------------------------------------------------------------------------------------------------------------+ -+--------------------------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`support for '`:placeholder:`A`:diagtext:`' without a filename not implemented yet; flag ignored`| -+--------------------------------------------------------------------------------------------------------------------------------------+ - +----------------------------------------------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`support for '`:placeholder:`A`:diagtext:`' without a corresponding /FI flag not implemented yet; flag ignored`| +----------------------------------------------------------------------------------------------------------------------------------------------------+ ++-------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`#pragma hdrstop filename not supported, /Fp can be used to specify precompiled header filename`| ++-------------------------------------------------------------------------------------------------------------------------------------+ + ++-----------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`definition of macro` |nbsp| :placeholder:`A` |nbsp| :diagtext:`does not match definition in precompiled header`| ++-----------------------------------------------------------------------------------------------------------------------------------------------------+ + -Wclass-varargs --------------- @@ -2397,6 +2661,17 @@ This diagnostic is enabled by default. +----------------------------------------------------------------------------------------------------------------------+ +-Wconcepts-ts-compat +-------------------- +This diagnostic is enabled by default. + +**Diagnostic text:** + ++---------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`ISO C++2a does not permit the 'bool' keyword after 'concept'`| ++---------------------------------------------------------------------------------------------------+ + + -Wconditional-type-mismatch --------------------------- This diagnostic is enabled by default. @@ -2444,7 +2719,7 @@ This diagnostic is enabled by default. --------------------- This diagnostic is enabled by default. -Also controls `-Wbitfield-constant-conversion`_. +Also controls `-Wbitfield-constant-conversion`_, `-Wobjc-bool-constant-conversion`_. **Diagnostic text:** @@ -2516,7 +2791,7 @@ This diagnostic is enabled by default. ------------ Some of the diagnostics controlled by this flag are enabled by default. -Also controls `-Wbitfield-enum-conversion`_, `-Wbool-conversion`_, `-Wconstant-conversion`_, `-Wenum-conversion`_, `-Wfloat-conversion`_, `-Wint-conversion`_, `-Wliteral-conversion`_, `-Wnon-literal-null-conversion`_, `-Wnull-conversion`_, `-Wobjc-literal-conversion`_, `-Wshorten-64-to-32`_, `-Wsign-conversion`_, `-Wstring-conversion`_. +Also controls `-Wbitfield-enum-conversion`_, `-Wbool-conversion`_, `-Wconstant-conversion`_, `-Wenum-conversion`_, `-Wfloat-conversion`_, `-Wimplicit-float-conversion`_, `-Wimplicit-int-conversion`_, `-Wint-conversion`_, `-Wliteral-conversion`_, `-Wnon-literal-null-conversion`_, `-Wnull-conversion`_, `-Wobjc-literal-conversion`_, `-Wshorten-64-to-32`_, `-Wsign-conversion`_, `-Wstring-conversion`_. **Diagnostic text:** @@ -2524,18 +2799,14 @@ Also controls `-Wbitfield-enum-conversion`_, `-Wbool-conversion`_, `-Wconstant-c |:warning:`warning:` |nbsp| :diagtext:`implicit conversion discards imaginary component:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to` |nbsp| :placeholder:`B`| +--------------------------------------------------------------------------------------------------------------------------------------------------------------+ -+----------------------------------------------------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`implicit conversion loses floating-point precision:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to` |nbsp| :placeholder:`B`| -+----------------------------------------------------------------------------------------------------------------------------------------------------------------+ - -+---------------------------------------------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`implicit conversion loses integer precision:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to` |nbsp| :placeholder:`B`| -+---------------------------------------------------------------------------------------------------------------------------------------------------------+ - +--------------------------------------------------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`implicit conversion turns vector to scalar:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to` |nbsp| :placeholder:`B`| +--------------------------------------------------------------------------------------------------------------------------------------------------------+ ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`passing non-generic address space pointer to` |nbsp| :placeholder:`A` |nbsp| :diagtext:`may cause dynamic conversion affecting performance`| ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + +-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`non-type template argument with value '`:placeholder:`A`:diagtext:`' converted to '`:placeholder:`B`:diagtext:`' for unsigned template parameter of type` |nbsp| :placeholder:`C`| +-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ @@ -2593,10 +2864,30 @@ Synonym for `-W#warnings`_. +------------------------------------------------------------------------------------------------------------+----------------------+--------------------------------------------------------------------------------------------+------------------------+ +-Wctad-maybe-unsupported +------------------------ +**Diagnostic text:** + ++--------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`may not intend to support class template argument deduction`| ++--------------------------------------------------------------------------------------------------------------------------+ + + -Wctor-dtor-privacy ------------------- This diagnostic flag exists for GCC compatibility, and has no effect in Clang. +-Wctu +----- +This diagnostic is enabled by default. + +**Diagnostic text:** + ++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`imported AST from '`:placeholder:`A`:diagtext:`' had been generated for a different target, current:` |nbsp| :placeholder:`B`:diagtext:`, imported:` |nbsp| :placeholder:`C`| ++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + + -Wcuda-compat ------------- Some of the diagnostics controlled by this flag are enabled by default. @@ -2637,6 +2928,55 @@ Some of the diagnostics controlled by this flag are enabled by default. +---------------------------------------------------------------------------------------------------------------------------------------+--------------------+----------------------------------------------------------------------------+ +-Wdangling +---------- +This diagnostic is enabled by default. + +Also controls `-Wdangling-field`_, `-Wdangling-initializer-list`_, `-Wreturn-stack-address`_. + +**Diagnostic text:** + ++---------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------+----------------------------+---------------------------------------------------------------+ +|:warning:`warning:` |nbsp| |+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| |nbsp| |+--------------------------+|:diagtext:`will be destroyed at the end of the full-expression`| +| ||+-----------------------------+---------------------------------------------------------+--------+------------------------------------------------------------------------+|| ||+------------------------+|| | +| |||:diagtext:`temporary` |nbsp| |+-------------------------------------------------------+| |nbsp| |+----------------------------------------------------------------------+||| |||:placeholder:`D` |nbsp| ||| | +| ||| ||:diagtext:`whose address is used as value of` || ||+-------------------------------+------------------------------------+|||| ||+------------------------+|| | +| ||| |+-------------------------------------------------------+| |||+-----------------------------+|:diagtext:`member of local variable`||||| |+--------------------------+| | +| ||| ||+--------------------------------+--------------------+|| |||| || ||||| || || | +| ||| |||+------------------------------+|:diagtext:`bound to`||| |||+-----------------------------+| ||||| |+--------------------------+| | +| ||| |||| || ||| ||||:diagtext:`reference` |nbsp| || ||||| | | | +| ||| |||+------------------------------+| ||| |||+-----------------------------+| ||||| | | | +| ||| ||||:diagtext:`implicitly` |nbsp| || ||| ||+-------------------------------+------------------------------------+|||| | | | +| ||| |||+------------------------------+| ||| |+----------------------------------------------------------------------+||| | | | +| ||| ||+--------------------------------+--------------------+|| ||+-------------------------+-----------------------+ |||| | | | +| ||| |+-------------------------------------------------------+| |||:diagtext:`local` |nbsp| |+---------------------+| |||| | | | +| ||| | | ||| ||:diagtext:`variable` || |||| | | | +| ||| | | ||| |+---------------------+| |||| | | | +| ||| | | ||| ||:diagtext:`reference`|| |||| | | | +| ||| | | ||| |+---------------------+| |||| | | | +| ||| | | ||+-------------------------+-----------------------+ |||| | | | +| ||| | | |+----------------------------------------------------------------------+||| | | | +| ||+-----------------------------+---------------------------------------------------------+--------+------------------------------------------------------------------------+|| | | | +| |+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| | | | +| ||+---------------------------------+----------------------------------------------------------+ || | | | +| |||:diagtext:`array backing` |nbsp| |+--------------------------------------------------------+| || | | | +| ||| ||:diagtext:`initializer list subobject of local variable`|| || | | | +| ||| |+--------------------------------------------------------+| || | | | +| ||| ||:diagtext:`local initializer list` || || | | | +| ||| |+--------------------------------------------------------+| || | | | +| ||+---------------------------------+----------------------------------------------------------+ || | | | +| |+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| | | | ++---------------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------+----------------------------+---------------------------------------------------------------+ + ++---------------------------------------------------------------------------+-----------------------------------------------+------------------------------------------------------------------------------------------------------------------------------+---------------------------+--------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`sorry, lifetime extension of` |nbsp| |+---------------------------------------------+| |nbsp| :diagtext:`created by aggregate initialization using default member initializer is not supported; lifetime of` |nbsp| |+-------------------------+| |nbsp| :diagtext:`will end at the end of the full-expression`| +| ||:diagtext:`temporary` || ||:diagtext:`temporary` || | +| |+---------------------------------------------+| |+-------------------------+| | +| ||:diagtext:`backing array of initializer list`|| ||:diagtext:`backing array`|| | +| |+---------------------------------------------+| |+-------------------------+| | ++---------------------------------------------------------------------------+-----------------------------------------------+------------------------------------------------------------------------------------------------------------------------------+---------------------------+--------------------------------------------------------------+ + + -Wdangling-else --------------- This diagnostic is enabled by default. @@ -2654,21 +2994,33 @@ This diagnostic is enabled by default. **Diagnostic text:** -+---------------------------------------------------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`binding reference member` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to stack allocated parameter` |nbsp| :placeholder:`B`| -+---------------------------------------------------------------------------------------------------------------------------------------------------------------+ ++-------------------------------------------------------------------------------------------------------------------------------------+-----------------------+------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`binding reference member` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to stack allocated` |nbsp| |+---------------------+| |nbsp| :placeholder:`B`| +| ||:diagtext:`variable` || | +| |+---------------------+| | +| ||:diagtext:`parameter`|| | +| |+---------------------+| | ++-------------------------------------------------------------------------------------------------------------------------------------+-----------------------+------------------------+ -+----------------------------------------------------------------+----------------------------------+----------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`binding reference` |nbsp| |+--------------------------------+|:diagtext:`member` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to a temporary value`| -| || || | -| |+--------------------------------+| | -| ||:diagtext:`subobject of` |nbsp| || | -| |+--------------------------------+| | -+----------------------------------------------------------------+----------------------------------+----------------------------------------------------------------------------------+ ++---------------------------+--------------------------------------------------------+--------+----------------------------------+--------------------------------------------------+----------------------+------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| |+------------------------------------------------------+| |nbsp| |+--------------------------------+|:diagtext:`member` |nbsp| :placeholder:`A` |nbsp| |+--------------------+| |nbsp| :diagtext:`a temporary object whose lifetime is shorter than the lifetime of the constructed object`| +| ||:diagtext:`reference` || || || ||:diagtext:`binds to`|| | +| |+------------------------------------------------------+| |+--------------------------------+| |+--------------------+| | +| ||:diagtext:`backing array for 'std::initializer\_list'`|| ||:diagtext:`subobject of` |nbsp| || ||:diagtext:`is` || | +| |+------------------------------------------------------+| |+--------------------------------+| |+--------------------+| | ++---------------------------+--------------------------------------------------------+--------+----------------------------------+--------------------------------------------------+----------------------+------------------------------------------------------------------------------------------------------------+ -+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`initializing pointer member` |nbsp| :placeholder:`A` |nbsp| :diagtext:`with the stack address of parameter` |nbsp| :placeholder:`B`| -+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ++-----------------------------------------------------------------------------------------------------------------------------------------------+-----------------------+------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`initializing pointer member` |nbsp| :placeholder:`A` |nbsp| :diagtext:`with the stack address of` |nbsp| |+---------------------+| |nbsp| :placeholder:`B`| +| ||:diagtext:`variable` || | +| |+---------------------+| | +| ||:diagtext:`parameter`|| | +| |+---------------------+| | ++-----------------------------------------------------------------------------------------------------------------------------------------------+-----------------------+------------------------+ + ++--------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`temporary bound to reference member of allocated object will be destroyed at the end of the full-expression`| ++--------------------------------------------------------------------------------------------------------------------------------------------------+ -Wdangling-initializer-list @@ -2677,13 +3029,24 @@ This diagnostic is enabled by default. **Diagnostic text:** -+-----------------------------------------------------------------------------------------------------------------+---------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`array backing the initializer list will be destroyed at the end of` |nbsp| |+-------------------------------+| -| ||:diagtext:`the full-expression`|| -| |+-------------------------------+| -| ||:diagtext:`the constructor` || -| |+-------------------------------+| -+-----------------------------------------------------------------------------------------------------------------+---------------------------------+ ++------------------------------------------------------------+----------------------------------------------------------------+-----------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`array backing` |nbsp| |+--------------------------------------------------------------+| |nbsp| :diagtext:`will be destroyed at the end of the full-expression`| +| ||:diagtext:`initializer list subobject of the allocated object`|| | +| |+--------------------------------------------------------------+| | +| ||:diagtext:`the allocated initializer list` || | +| |+--------------------------------------------------------------+| | ++------------------------------------------------------------+----------------------------------------------------------------+-----------------------------------------------------------------------+ + + +-Wdarwin-sdk-settings +--------------------- +This diagnostic is enabled by default. + +**Diagnostic text:** + ++----------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`SDK settings were ignored as 'SDKSettings.json' could not be parsed`| ++----------------------------------------------------------------------------------------------------------+ -Wdate-time @@ -2726,6 +3089,29 @@ This diagnostic is enabled by default. +-----------------------------------------------------------------------------------+ +-Wdefaulted-function-deleted +---------------------------- +This diagnostic is enabled by default. + +**Diagnostic text:** + ++-------------------------------------------------------------------+--------------------------------------+-----------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`explicitly defaulted` |nbsp| |+------------------------------------+| |nbsp| :diagtext:`is implicitly deleted`| +| ||:diagtext:`default constructor` || | +| |+------------------------------------+| | +| ||:diagtext:`copy constructor` || | +| |+------------------------------------+| | +| ||:diagtext:`move constructor` || | +| |+------------------------------------+| | +| ||:diagtext:`copy assignment operator`|| | +| |+------------------------------------+| | +| ||:diagtext:`move assignment operator`|| | +| |+------------------------------------+| | +| ||:diagtext:`destructor` || | +| |+------------------------------------+| | ++-------------------------------------------------------------------+--------------------------------------+-----------------------------------------+ + + -Wdelegating-ctor-cycles ------------------------ This diagnostic is an error by default, but the flag ``-Wno-delegating-ctor-cycles`` can be used to disable the error. @@ -2737,6 +3123,21 @@ This diagnostic is an error by default, but the flag ``-Wno-delegating-ctor-cycl +------------------------------------------------------------------------------------------------------------------------+ +-Wdelete-abstract-non-virtual-dtor +---------------------------------- +This diagnostic is enabled by default. + +**Diagnostic text:** + ++---------------------------+------------------------+------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| |+----------------------+| |nbsp| :diagtext:`called on` |nbsp| :placeholder:`B` |nbsp| :diagtext:`that is abstract but has non-virtual destructor`| +| ||:diagtext:`delete` || | +| |+----------------------+| | +| ||:diagtext:`destructor`|| | +| |+----------------------+| | ++---------------------------+------------------------+------------------------------------------------------------------------------------------------------------------------+ + + -Wdelete-incomplete ------------------- This diagnostic is enabled by default. @@ -2752,20 +3153,10 @@ This diagnostic is enabled by default. +--------------------------------------------------------------------------------------------------------------------------------------------------+ --Wdelete-non-virtual-dtor -------------------------- -Some of the diagnostics controlled by this flag are enabled by default. - +-Wdelete-non-abstract-non-virtual-dtor +-------------------------------------- **Diagnostic text:** -+---------------------------+------------------------+------------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| |+----------------------+| |nbsp| :diagtext:`called on` |nbsp| :placeholder:`B` |nbsp| :diagtext:`that is abstract but has non-virtual destructor`| -| ||:diagtext:`delete` || | -| |+----------------------+| | -| ||:diagtext:`destructor`|| | -| |+----------------------+| | -+---------------------------+------------------------+------------------------------------------------------------------------------------------------------------------------+ - +---------------------------+------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| |+----------------------+| |nbsp| :diagtext:`called on non-final` |nbsp| :placeholder:`B` |nbsp| :diagtext:`that has virtual functions but non-virtual destructor`| | ||:diagtext:`delete` || | @@ -2775,11 +3166,18 @@ Some of the diagnostics controlled by this flag are enabled by default. +---------------------------+------------------------+----------------------------------------------------------------------------------------------------------------------------------------+ +-Wdelete-non-virtual-dtor +------------------------- +Some of the diagnostics controlled by this flag are enabled by default. + +Controls `-Wdelete-abstract-non-virtual-dtor`_, `-Wdelete-non-abstract-non-virtual-dtor`_. + + -Wdeprecated ------------ Some of the diagnostics controlled by this flag are enabled by default. -Also controls `-Wdeprecated-attributes`_, `-Wdeprecated-declarations`_, `-Wdeprecated-dynamic-exception-spec`_, `-Wdeprecated-increment-bool`_, `-Wdeprecated-register`_, `-Wdeprecated-writable-strings`_. +Also controls `-Wdeprecated-attributes`_, `-Wdeprecated-declarations`_, `-Wdeprecated-dynamic-exception-spec`_, `-Wdeprecated-increment-bool`_, `-Wdeprecated-register`_, `-Wdeprecated-this-capture`_, `-Wdeprecated-writable-strings`_. **Diagnostic text:** @@ -2957,6 +3355,15 @@ This diagnostic is enabled by default. +-------------------------------------------------------------------------------------------------------------------+ +-Wdeprecated-this-capture +------------------------- +**Diagnostic text:** + ++-------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`implicit capture of 'this' with a capture default of '=' is deprecated`| ++-------------------------------------------------------------------------------------------------------------+ + + -Wdeprecated-writable-strings ----------------------------- Synonym for `-Wc++11-compat-deprecated-writable-strings`_. @@ -3283,7 +3690,7 @@ Also controls `-Wdocumentation-unknown-command`_. -Wduplicate-decl-specifier -------------------------- -This diagnostic is enabled by default. +Some of the diagnostics controlled by this flag are enabled by default. **Diagnostic text:** @@ -3295,6 +3702,14 @@ This diagnostic is enabled by default. |:warning:`warning:` |nbsp| :diagtext:`duplicate '`:placeholder:`A`:diagtext:`' declaration specifier`| +-----------------------------------------------------------------------------------------------------+ ++-------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`multiple identical address spaces specified for type`| ++-------------------------------------------------------------------------------------------+ + ++-----------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`duplicate '`:placeholder:`A`:diagtext:`' declaration specifier`| ++-----------------------------------------------------------------------------------------------------+ + -Wduplicate-enum ---------------- @@ -3418,6 +3833,21 @@ This diagnostic is enabled by default. +-------------------------------------------------------------------------------------------------+ +-Wempty-init-stmt +----------------- +**Diagnostic text:** + ++--------------------------------------------------------------------------+-----------------------------+---------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`empty initialization statement of '`|+---------------------------+|:diagtext:`' has no effect`| +| ||:diagtext:`if` || | +| |+---------------------------+| | +| ||:diagtext:`switch` || | +| |+---------------------------+| | +| ||:diagtext:`range-based for`|| | +| |+---------------------------+| | ++--------------------------------------------------------------------------+-----------------------------+---------------------------+ + + -Wempty-translation-unit ------------------------ **Diagnostic text:** @@ -3540,6 +3970,21 @@ Some of the diagnostics controlled by this flag are enabled by default. +-------------------------------------------------------------------------------------------------+ +-Wexperimental-isel +------------------- +This diagnostic is enabled by default. + +**Diagnostic text:** + ++------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`-fexperimental-isel support for the '`:placeholder:`A`:diagtext:`' architecture is incomplete`| ++------------------------------------------------------------------------------------------------------------------------------------+ + ++----------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`-fexperimental-isel support is incomplete for this architecture at the current optimization level`| ++----------------------------------------------------------------------------------------------------------------------------------------+ + + -Wexplicit-initialize-call -------------------------- This diagnostic is enabled by default. @@ -3564,13 +4009,34 @@ This diagnostic is enabled by default. +-------------------------------------------------------------------------------------------------------------------------------------+ --Wextended-offsetof -------------------- +-Wexport-unnamed +---------------- +This diagnostic is enabled by default. + **Diagnostic text:** -+--------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`using extended field designator is an extension`| -+--------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------+------------------------------+------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`ISO C++20 does not permit` |nbsp| |+----------------------------+| |nbsp| :diagtext:`declaration to appear in an export block`| +| ||:diagtext:`an empty` || | +| |+----------------------------+| | +| ||:diagtext:`a static\_assert`|| | +| |+----------------------------+| | ++------------------------------------------------------------------------+------------------------------+------------------------------------------------------------+ + ++-------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`ISO C++20 does not permit a declaration that does not introduce any names to be exported`| ++-------------------------------------------------------------------------------------------------------------------------------+ + + +-Wexport-using-directive +------------------------ +This diagnostic is enabled by default. + +**Diagnostic text:** + ++-----------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`ISO C++20 does not permit using directive to be exported`| ++-----------------------------------------------------------------------------------------------+ -Wextern-c-compat @@ -3603,7 +4069,7 @@ This diagnostic is enabled by default. ------- Some of the diagnostics controlled by this flag are enabled by default. -Also controls `-Wignored-qualifiers`_, `-Winitializer-overrides`_, `-Wmissing-field-initializers`_, `-Wmissing-method-return-type`_, `-Wnull-pointer-arithmetic`_, `-Wsemicolon-before-method-body`_, `-Wsign-compare`_, `-Wunused-parameter`_. +Also controls `-Wempty-init-stmt`_, `-Wignored-qualifiers`_, `-Winitializer-overrides`_, `-Wmissing-field-initializers`_, `-Wmissing-method-return-type`_, `-Wnull-pointer-arithmetic`_, `-Wsemicolon-before-method-body`_, `-Wsign-compare`_, `-Wunused-parameter`_. **Diagnostic text:** @@ -3625,7 +4091,7 @@ This diagnostic is enabled by default. -Wextra-semi ------------ -Also controls `-Wc++11-extra-semi`_. +Also controls `-Wc++11-extra-semi`_, `-Wc++98-compat-extra-semi`_. **Diagnostic text:** @@ -3648,6 +4114,17 @@ Also controls `-Wc++11-extra-semi`_. +---------------------------------------------------------------------------------+ +-Wextra-semi-stmt +----------------- +Also controls `-Wempty-init-stmt`_. + +**Diagnostic text:** + ++-------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`empty expression statement has no effect; remove unnecessary ';' to silence this warning`| ++-------------------------------------------------------------------------------------------------------------------------------+ + + -Wextra-tokens -------------- This diagnostic is enabled by default. @@ -3669,9 +4146,18 @@ This diagnostic is enabled by default. **Diagnostic text:** -+------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`falling back to` |nbsp| :placeholder:`A`| -+------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`falling back to` |nbsp| :placeholder:`A`| ++------------------------------------------------------------------------------+ + + +-Wfixed-enum-extension +---------------------- +**Diagnostic text:** + ++-----------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`enumeration types with a fixed underlying type are a Clang extension`| ++-----------------------------------------------------------------------------------------------------------+ -Wflag-enum @@ -3722,9 +4208,13 @@ Also controls `-Wfloat-overflow-conversion`_, `-Wfloat-zero-conversion`_. --------------------------- **Diagnostic text:** -+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`implicit conversion of out of range value from` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to` |nbsp| :placeholder:`B` |nbsp| :diagtext:`changes value from` |nbsp| :placeholder:`C` |nbsp| :diagtext:`to` |nbsp| :placeholder:`D`| -+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`implicit conversion from` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to` |nbsp| :placeholder:`B` |nbsp| :diagtext:`changes value from` |nbsp| :placeholder:`C` |nbsp| :diagtext:`to` |nbsp| :placeholder:`D`| ++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + ++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`implicit conversion of out of range value from` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to` |nbsp| :placeholder:`B` |nbsp| :diagtext:`is undefined`| ++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -Wfloat-zero-conversion @@ -3960,6 +4450,14 @@ This diagnostic is enabled by default. ----------------- **Diagnostic text:** ++---------------------------+----------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| |+--------------------------------------------+| |nbsp| :diagtext:`'`:placeholder:`A`:diagtext:`' should not be used as format arguments; add an explicit cast to` |nbsp| :placeholder:`B` |nbsp| :diagtext:`instead`| +| ||:diagtext:`values of type` || | +| |+--------------------------------------------+| | +| ||:diagtext:`enum values with underlying type`|| | +| |+--------------------------------------------+| | ++---------------------------+----------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + +------------------------------------------------------------------------------------------------------------------------------------+-----------------------------+------------------------+ |:warning:`warning:` |nbsp| :diagtext:`format specifies type` |nbsp| :placeholder:`A` |nbsp| :diagtext:`but the argument has` |nbsp| |+---------------------------+| |nbsp| :placeholder:`B`| | ||:diagtext:`type` || | @@ -4002,6 +4500,21 @@ Some of the diagnostics controlled by this flag are enabled by default. Controls `-Wformat-nonliteral`_, `-Wformat-security`_, `-Wformat-y2k`_. +-Wfortify-source +---------------- +This diagnostic is enabled by default. + +**Diagnostic text:** + ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`'`:placeholder:`A`:diagtext:`' will always overflow; destination buffer has size` |nbsp| :placeholder:`B`:diagtext:`, but size argument is` |nbsp| :placeholder:`C`| ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`'`:placeholder:`A`:diagtext:`' size argument is too large; destination buffer has size` |nbsp| :placeholder:`B`:diagtext:`, but size argument is` |nbsp| :placeholder:`C`| ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + + -Wfour-char-constants --------------------- **Diagnostic text:** @@ -4024,6 +4537,17 @@ The text of this diagnostic is not controlled by Clang. +--------------------------------------------------------------------------------------------------------------------------------------+ +-Wframework-include-private-from-public +--------------------------------------- +This diagnostic is enabled by default. + +**Diagnostic text:** + ++-------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`public framework header includes private framework header '`:placeholder:`A`:diagtext:`'`| ++-------------------------------------------------------------------------------------------------------------------------------+ + + -Wfunction-def-in-objc-container -------------------------------- This diagnostic is enabled by default. @@ -4035,6 +4559,21 @@ This diagnostic is enabled by default. +--------------------------------------------------------------------------------------------------------+ +-Wfunction-multiversion +----------------------- +This diagnostic is enabled by default. + +**Diagnostic text:** + ++-------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`body of cpu\_dispatch function will be ignored`| ++-------------------------------------------------------------------------------------+ + ++---------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`CPU list contains duplicate entries; attribute ignored`| ++---------------------------------------------------------------------------------------------+ + + -Wfuture-compat --------------- This diagnostic flag exists for GCC compatibility, and has no effect in Clang. @@ -4073,6 +4612,14 @@ Some of the diagnostics controlled by this flag are enabled by default. |:warning:`warning:` |nbsp| :diagtext:`GCC does not allow an attribute in this position on a function declaration`| +-----------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`GCC does not allow the` |nbsp| :placeholder:`A` |nbsp| :diagtext:`attribute to be written on a type`| ++------------------------------------------------------------------------------------------------------------------------------------------+ + ++-------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`GCC does not allow variable declarations in for loop initializers before C99`| ++-------------------------------------------------------------------------------------------------------------------+ + +----------------------------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`'`:placeholder:`A`:diagtext:`' is bound to current loop, GCC binds it to the enclosing loop`| +----------------------------------------------------------------------------------------------------------------------------------+ @@ -4433,6 +4980,10 @@ This diagnostic is enabled by default. **Diagnostic text:** ++--------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`'trivial\_abi' cannot be applied to` |nbsp| :placeholder:`A`| ++--------------------------------------------------------------------------------------------------+ + +---------------------------+-------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| |+-----------------+| |nbsp| :diagtext:`will always resolve to` |nbsp| :placeholder:`A` |nbsp| :diagtext:`even if weak definition of` |nbsp| :placeholder:`B` |nbsp| :diagtext:`is overridden`| | ||:diagtext:`alias`|| | @@ -4461,6 +5012,10 @@ This diagnostic is enabled by default. |:warning:`warning:` |nbsp| :diagtext:`attribute` |nbsp| :placeholder:`A` |nbsp| :diagtext:`after definition is ignored`| +-----------------------------------------------------------------------------------------------------------------------+ ++---------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`'dllexport' attribute ignored on explicit instantiation definition`| ++---------------------------------------------------------------------------------------------------------+ + +--------------------------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`attribute can only be applied to instance variables or properties`| +--------------------------------------------------------------------------------------------------------------------------------+ @@ -4557,124 +5112,64 @@ This diagnostic is enabled by default. |:warning:`warning:` |nbsp| :diagtext:`\_\_weak attribute cannot be specified on an automatic variable when ARC is not enabled`| +------------------------------------------------------------------------------------------------------------------------------+ -+------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`attribute only applies to` |nbsp| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`functions` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`unions` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`variables and functions` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`functions and global variables` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`functions, variables, and Objective-C interfaces` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`functions and methods` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`parameters` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`functions, methods and blocks` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`functions, methods, and classes` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`functions, methods, and parameters` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`functions, methods, and global variables` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`classes` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`enums` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`variables` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`methods` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`fields and global variables` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`structs` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`parameters and typedefs` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`variables and typedefs` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`thread-local variables` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`variables and fields` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`variables, data members and tag types` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`types and namespaces` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`Objective-C interfaces` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`methods and properties` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`functions, methods, and properties` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`struct or union` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`struct, union or class` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`types` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`Objective-C instance methods` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`init methods of interface or class extension declarations` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`variables, functions and classes` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`functions, variables, classes, and Objective-C interfaces` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`Objective-C protocols` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`variables with static or thread storage duration` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`functions, methods, properties, and global variables` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`structs, unions, and typedefs` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`structs and typedefs` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`interface or protocol declarations` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`kernel functions` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`non-K&R-style functions` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`variables, enums, fields and typedefs` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`functions, methods, enums, and classes` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`structs, classes, variables, functions, and inline namespaces` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`variables, functions, methods, types, enumerations, enumerators, labels, and non-static data members`|| -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`classes and enumerations` || -| |+----------------------------------------------------------------------------------------------------------------+| -| ||:diagtext:`named declarations` || -| |+----------------------------------------------------------------------------------------------------------------+| -+------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------+---------------------------------------------------+ +|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`attribute only applies to` |nbsp| |+-------------------------------------------------+| +| ||:diagtext:`functions` || +| |+-------------------------------------------------+| +| ||:diagtext:`unions` || +| |+-------------------------------------------------+| +| ||:diagtext:`variables and functions` || +| |+-------------------------------------------------+| +| ||:diagtext:`functions and methods` || +| |+-------------------------------------------------+| +| ||:diagtext:`functions, methods and blocks` || +| |+-------------------------------------------------+| +| ||:diagtext:`functions, methods, and parameters` || +| |+-------------------------------------------------+| +| ||:diagtext:`variables` || +| |+-------------------------------------------------+| +| ||:diagtext:`variables and fields` || +| |+-------------------------------------------------+| +| ||:diagtext:`variables, data members and tag types`|| +| |+-------------------------------------------------+| +| ||:diagtext:`types and namespaces` || +| |+-------------------------------------------------+| +| ||:diagtext:`variables, functions and classes` || +| |+-------------------------------------------------+| +| ||:diagtext:`kernel functions` || +| |+-------------------------------------------------+| +| ||:diagtext:`non-K&R-style functions` || +| |+-------------------------------------------------+| ++------------------------------------------------------------------------------------------------+---------------------------------------------------+ + ++----------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`attribute only applies to` |nbsp| :placeholder:`B`| ++----------------------------------------------------------------------------------------------------------------+ +--------------------------------------------------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`attribute` |nbsp| :placeholder:`A` |nbsp| :diagtext:`ignored, because it cannot be applied to omitted return type`| +--------------------------------------------------------------------------------------------------------------------------------------------------------+ -+----------------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`calling convention` |nbsp| :placeholder:`A` |nbsp| :diagtext:`ignored for this target`| -+----------------------------------------------------------------------------------------------------------------------------+ - -+-------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`calling convention ignored on constructor/destructor`| -+-------------------------------------------------------------------------------------------------------------------+ - -+--------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`calling convention ignored on variadic function`| -+--------------------------------------------------------------------------------------------------------------+ ++----------------------------------------------------------------------------------------------------------+---------------------------------------+ +|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`calling convention is not supported` |nbsp| |+-------------------------------------+| +| ||:diagtext:`for this target` || +| |+-------------------------------------+| +| ||:diagtext:`on variadic function` || +| |+-------------------------------------+| +| ||:diagtext:`on constructor/destructor`|| +| |+-------------------------------------+| +| ||:diagtext:`on builtin function` || +| |+-------------------------------------+| ++----------------------------------------------------------------------------------------------------------+---------------------------------------+ +-------------------------------------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`attribute` |nbsp| :placeholder:`A` |nbsp| :diagtext:`ignored, because it cannot be applied to a type`| +-------------------------------------------------------------------------------------------------------------------------------------------+ ++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`ignoring \_\_declspec(allocator) because the function return type` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is not a pointer or reference type`| ++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + +------------------------------------------------------------------------------------------------------------------------+-----------------------+----------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`attribute` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is ignored, place it after "`|+---------------------+|:diagtext:`" to apply attribute to type declaration`| | ||:diagtext:`class` || | @@ -4721,35 +5216,63 @@ This diagnostic is enabled by default. | |+----------------------------------+| +---------------------------------------------------------------------------+------------------------------------+ ++------------------------------------------------------------------------------------------------------------------+-----------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`'objc\_externally\_retained' can only be applied to local variables` |nbsp| |+---------------------------------+| +| ||:diagtext:`of retainable type` || +| |+---------------------------------+| +| ||:diagtext:`with strong ownership`|| +| |+---------------------------------+| ++------------------------------------------------------------------------------------------------------------------+-----------------------------------+ + +--------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`'internal\_linkage' attribute on a non-static local variable is ignored`| +--------------------------------------------------------------------------------------------------------------+ ++---------------------------+--------------------+-------------------------------------------------------------------------------------+----------------------------------+ +|:warning:`warning:` |nbsp| |+------------------+| |nbsp| :diagtext:`'interrupt' attribute only applies to functions that have` |nbsp| |+--------------------------------+| +| ||:diagtext:`MIPS` || ||:diagtext:`no parameters` || +| |+------------------+| |+--------------------------------+| +| ||:diagtext:`MSP430`|| ||:diagtext:`a 'void' return type`|| +| |+------------------+| |+--------------------------------+| +| ||:diagtext:`RISC-V`|| | | +| |+------------------+| | | ++---------------------------+--------------------+-------------------------------------------------------------------------------------+----------------------------------+ + +--------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`qualifiers after comma in declarator list are ignored`| +--------------------------------------------------------------------------------------------+ -+-------------------------------------------------------------------------------------------------------------+----------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`MIPS 'interrupt' attribute only applies to functions that have` |nbsp| |+--------------------------------+| -| ||:diagtext:`no parameters` || -| |+--------------------------------+| -| ||:diagtext:`a 'void' return type`|| -| |+--------------------------------+| -+-------------------------------------------------------------------------------------------------------------+----------------------------------+ ++------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`'mig\_server\_routine' attribute only applies to routines that return a kern\_return\_t`| ++------------------------------------------------------------------------------------------------------------------------------+ +---------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`unknown attribute '`:placeholder:`A`:diagtext:`'`| +---------------------------------------------------------------------------------------+ -+------------------------------------------------------------------------------------------------+-----------------------------------+------------------------------+ -|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`attribute only applies to` |nbsp| |+---------------------------------+| |nbsp| :diagtext:`parameters`| -| ||:diagtext:`Objective-C object` || | -| |+---------------------------------+| | -| ||:diagtext:`pointer` || | -| |+---------------------------------+| | -| ||:diagtext:`pointer-to-CF-pointer`|| | -| |+---------------------------------+| | -+------------------------------------------------------------------------------------------------+-----------------------------------+------------------------------+ ++-------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`'nocf\_check' attribute ignored; use -fcf-protection to enable the attribute`| ++-------------------------------------------------------------------------------------------------------------------+ + ++---------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`'noderef' can only be used on an array or pointer type`| ++---------------------------------------------------------------------------------------------+ + ++--------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`'nothrow' attribute conflicts with exception specification; attribute ignored`| ++--------------------------------------------------------------------------------------------------------------------+ + ++------------------------------------------------------------------------------------------------+---------------------------------------------------+------------------------------+ +|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`attribute only applies to` |nbsp| |+-------------------------------------------------+| |nbsp| :diagtext:`parameters`| +| ||:diagtext:`Objective-C object` || | +| |+-------------------------------------------------+| | +| ||:diagtext:`pointer` || | +| |+-------------------------------------------------+| | +| ||:diagtext:`pointer-to-CF-pointer` || | +| |+-------------------------------------------------+| | +| ||:diagtext:`pointer/reference-to-OSObject-pointer`|| | +| |+-------------------------------------------------+| | ++------------------------------------------------------------------------------------------------+---------------------------------------------------+------------------------------+ +------------------------------------------------------------------------------------------------+------------------------+---------------------------------------+--------------------------------------+ |:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`attribute only applies to` |nbsp| |+----------------------+| |nbsp| :diagtext:`that return` |nbsp| |+------------------------------------+| @@ -4765,6 +5288,10 @@ This diagnostic is enabled by default. |:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`attribute is deprecated and ignored in OpenCL version` |nbsp| :placeholder:`B`| +--------------------------------------------------------------------------------------------------------------------------------------------+ ++----------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`repeated RISC-V 'interrupt' attribute`| ++----------------------------------------------------------------------------+ + +---------------------------+-----------------------+---------------------------------------------------------------------------------------------------------------------------------------------+-----------------------+-------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| |+---------------------+| |nbsp| :diagtext:`of field` |nbsp| :placeholder:`B` |nbsp| :diagtext:`(`:placeholder:`C` |nbsp| :diagtext:`bits) does not match the` |nbsp| |+---------------------+| |nbsp| :diagtext:`of the first field in transparent union; transparent\_union attribute ignored`| | ||:diagtext:`alignment`|| ||:diagtext:`alignment`|| | @@ -4803,13 +5330,17 @@ This diagnostic is enabled by default. |:warning:`warning:` |nbsp| :diagtext:`\_\_declspec attribute` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is not supported`| +-------------------------------------------------------------------------------------------------------------------------+ -+-------------------------------------------------------+-------------------------+----------------------------------+---------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`ignoring` |nbsp| |+-----------------------+|+--------------------------------+| |nbsp| :diagtext:`'`:placeholder:`C`:diagtext:`' in the target attribute string`| -| ||:diagtext:`unsupported`||| || | -| |+-----------------------+|+--------------------------------+| | -| ||:diagtext:`duplicate` ||| |nbsp| :diagtext:`architecture`|| | -| |+-----------------------+|+--------------------------------+| | -+-------------------------------------------------------+-------------------------+----------------------------------+---------------------------------------------------------------------------------+ ++---------------------------+-------------------------+----------------------------------+---------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| |+-----------------------+|+--------------------------------+| |nbsp| :diagtext:`'`:placeholder:`C`:diagtext:`' in the 'target' attribute string; 'target' attribute ignored`| +| ||:diagtext:`unsupported`||| || | +| |+-----------------------+|+--------------------------------+| | +| ||:diagtext:`duplicate` ||| |nbsp| :diagtext:`architecture`|| | +| |+-----------------------+|+--------------------------------+| | ++---------------------------+-------------------------+----------------------------------+---------------------------------------------------------------------------------------------------------------+ + ++----------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`'\_\_clang\_\_' is a predefined macro name, not an attribute scope specifier; did you mean '\_Clang' instead?`| ++----------------------------------------------------------------------------------------------------------------------------------------------------+ -Wignored-optimization-argument @@ -4842,11 +5373,22 @@ This diagnostic is enabled by default. +------------------------------------------------------------------------------------------+------------------------------------------------------------------------------+ +-Wignored-pragma-optimize +------------------------- +This diagnostic is enabled by default. + +**Diagnostic text:** + ++--------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`'#pragma optimize' is not supported`| ++--------------------------------------------------------------------------+ + + -Wignored-pragmas ----------------- This diagnostic is enabled by default. -Also controls `-Wignored-pragma-intrinsic`_. +Also controls `-Wignored-pragma-intrinsic`_, `-Wignored-pragma-optimize`_. **Diagnostic text:** @@ -4882,6 +5424,10 @@ Also controls `-Wignored-pragma-intrinsic`_. |:warning:`warning:` |nbsp| :diagtext:`unexpected debug command '`:placeholder:`A`:diagtext:`'`| +----------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`unknown module '`:placeholder:`A`:diagtext:`'`| ++------------------------------------------------------------------------------------+ + +------------------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`expected action or ')' in '#pragma` |nbsp| :placeholder:`A`:diagtext:`' - ignored`| +------------------------------------------------------------------------------------------------------------------------+ @@ -4894,6 +5440,10 @@ Also controls `-Wignored-pragma-intrinsic`_. |:warning:`warning:` |nbsp| :diagtext:`missing ':' or ')' after` |nbsp| :placeholder:`A` |nbsp| :diagtext:`- ignoring`| +---------------------------------------------------------------------------------------------------------------------+ ++----------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`expected ',' in '#pragma` |nbsp| :placeholder:`A`:diagtext:`'`| ++----------------------------------------------------------------------------------------------------+ + +---------------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`expected identifier in '#pragma` |nbsp| :placeholder:`A`:diagtext:`' - ignored`| +---------------------------------------------------------------------------------------------------------------------+ @@ -4942,6 +5492,10 @@ Also controls `-Wignored-pragma-intrinsic`_. |:warning:`warning:` |nbsp| :diagtext:`expected push, pop or a string literal for the section name in '#pragma` |nbsp| :placeholder:`A`:diagtext:`' - ignored`| +-------------------------------------------------------------------------------------------------------------------------------------------------------------+ ++--------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`expected string literal in '#pragma` |nbsp| :placeholder:`A`:diagtext:`' - ignoring`| ++--------------------------------------------------------------------------------------------------------------------------+ + +---------------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`extra tokens at end of '#pragma` |nbsp| :placeholder:`A`:diagtext:`' - ignored`| +---------------------------------------------------------------------------------------------------------------------+ @@ -4958,10 +5512,30 @@ Also controls `-Wignored-pragma-intrinsic`_. |:warning:`warning:` |nbsp| :diagtext:`unknown action for '#pragma` |nbsp| :placeholder:`A`:diagtext:`' - ignored`| +-----------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`unexpected argument '`:placeholder:`A`:diagtext:`' to '#pragma` |nbsp| :placeholder:`B`:diagtext:`'`|+------------------------------------------------+| +| || || +| |+------------------------------------------------+| +| ||+----------------------------------------------+|| +| |||:diagtext:`; expected` |nbsp| :placeholder:`D`||| +| ||+----------------------------------------------+|| +| |+------------------------------------------------+| ++------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------+ + +------------------------------------------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`unknown action '`:placeholder:`B`:diagtext:`' for '#pragma` |nbsp| :placeholder:`A`:diagtext:`' - ignored`| +------------------------------------------------------------------------------------------------------------------------------------------------+ ++--------------------------------------------------------------------------------------------------------+--------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`missing argument to '#pragma` |nbsp| :placeholder:`A`:diagtext:`'`|+------------------------------------------------+| +| || || +| |+------------------------------------------------+| +| ||+----------------------------------------------+|| +| |||:diagtext:`; expected` |nbsp| :placeholder:`C`||| +| ||+----------------------------------------------+|| +| |+------------------------------------------------+| ++--------------------------------------------------------------------------------------------------------+--------------------------------------------------+ + +----------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`incorrect use of '#pragma ms\_struct on\|off' - ignored`| +----------------------------------------------------------------------------------------------+ @@ -5039,13 +5613,13 @@ Some of the diagnostics controlled by this flag are enabled by default. |:warning:`warning:` |nbsp| :diagtext:`'`:placeholder:`A`:diagtext:`' qualifier on omitted return type` |nbsp| :placeholder:`B` |nbsp| :diagtext:`has no effect`| +---------------------------------------------------------------------------------------------------------------------------------------------------------------+ -+------------------------------------------------------------------------------------+---------------+------------------------------------------+-------------------+-----------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`'`:placeholder:`A`:diagtext:`' type qualifier`|+-------------+| |nbsp| :diagtext:`on return type` |nbsp| |+-----------------+| |nbsp| :diagtext:`no effect`| -| || || ||:diagtext:`:has` || | -| |+-------------+| |+-----------------+| | -| ||:diagtext:`s`|| ||:diagtext:`:have`|| | -| |+-------------+| |+-----------------+| | -+------------------------------------------------------------------------------------+---------------+------------------------------------------+-------------------+-----------------------------+ ++------------------------------------------------------------------------------------+---------------+------------------------------------------+------------------+-----------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`'`:placeholder:`A`:diagtext:`' type qualifier`|+-------------+| |nbsp| :diagtext:`on return type` |nbsp| |+----------------+| |nbsp| :diagtext:`no effect`| +| || || ||:diagtext:`has` || | +| |+-------------+| |+----------------+| | +| ||:diagtext:`s`|| ||:diagtext:`have`|| | +| |+-------------+| |+----------------+| | ++------------------------------------------------------------------------------------+---------------+------------------------------------------+------------------+-----------------------------+ +---------------------------------------------------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`'`:placeholder:`A`:diagtext:`' qualifier on function type` |nbsp| :placeholder:`B` |nbsp| :diagtext:`has no effect`| @@ -5126,19 +5700,39 @@ Also controls `-Wimplicit-fallthrough-per-function`_. +------------------------------------------------------------------------------------------------------------------+ +-Wimplicit-fixed-point-conversion +--------------------------------- +This diagnostic is enabled by default. + +**Diagnostic text:** + ++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`implicit conversion from` |nbsp| :placeholder:`A` |nbsp| :diagtext:`cannot fit within the range of values for` |nbsp| :placeholder:`B`| ++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + + +-Wimplicit-float-conversion +--------------------------- +**Diagnostic text:** + ++----------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`implicit conversion loses floating-point precision:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to` |nbsp| :placeholder:`B`| ++----------------------------------------------------------------------------------------------------------------------------------------------------------------+ + ++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`implicit conversion when assigning computation result loses floating-point precision:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to` |nbsp| :placeholder:`B`| ++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + + -Wimplicit-function-declaration ------------------------------- Some of the diagnostics controlled by this flag are enabled by default. **Diagnostic text:** -+----------------------------------------------------------------------------------------------------------------------------------------+--------------------+ -|:warning:`warning:` |nbsp| :diagtext:`implicit declaration of function` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is invalid in` |nbsp| |+------------------+| -| ||:diagtext:`C99` || -| |+------------------+| -| ||:diagtext:`OpenCL`|| -| |+------------------+| -+----------------------------------------------------------------------------------------------------------------------------------------+--------------------+ ++------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`implicit declaration of function` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is invalid in C99`| ++------------------------------------------------------------------------------------------------------------------------------------+ +---------------------------------------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`implicitly declaring library function '`:placeholder:`A`:diagtext:`' with type` |nbsp| :placeholder:`B`| @@ -5164,6 +5758,19 @@ This diagnostic is enabled by default. +--------------------------------------------------------------------------------+ +-Wimplicit-int-conversion +------------------------- +**Diagnostic text:** + ++---------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`higher order bits are zeroes after implicit conversion`| ++---------------------------------------------------------------------------------------------+ + ++---------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`implicit conversion loses integer precision:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to` |nbsp| :placeholder:`B`| ++---------------------------------------------------------------------------------------------------------------------------------------------------------+ + + -Wimplicit-retain-self ---------------------- **Diagnostic text:** @@ -5214,9 +5821,9 @@ This diagnostic is enabled by default. **Diagnostic text:** -+------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`#include\_next with absolute path`| -+------------------------------------------------------------------------+ ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`#include\_next in file found relative to primary source file or found by absolute path; will search from start of include path`| ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -Winclude-next-outside-header @@ -5225,9 +5832,9 @@ This diagnostic is enabled by default. **Diagnostic text:** -+----------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`#include\_next in primary source file`| -+----------------------------------------------------------------------------+ ++--------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`#include\_next in primary source file; will search from start of include path`| ++--------------------------------------------------------------------------------------------------------------------+ -Wincompatible-exception-spec @@ -5295,6 +5902,10 @@ This diagnostic is an error by default, but the flag ``-Wno-incompatible-ms-stru |:error:`error:` |nbsp| :diagtext:`ms\_struct may not produce Microsoft-compatible layouts for classes with base classes or virtual functions`| +---------------------------------------------------------------------------------------------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:error:`error:` |nbsp| :diagtext:`ms\_struct may not produce Microsoft-compatible layouts with fundamental data types with sizes that aren't a power of two`| ++------------------------------------------------------------------------------------------------------------------------------------------------------------+ + -Wincompatible-pointer-types ---------------------------- @@ -5388,6 +5999,17 @@ This diagnostic is enabled by default. +------------------------------------------------------------------------------------------------------------------------------------+ +-Wincomplete-framework-module-declaration +----------------------------------------- +This diagnostic is enabled by default. + +**Diagnostic text:** + ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`skipping '`:placeholder:`A`:diagtext:`' because module declaration of '`:placeholder:`B`:diagtext:`' lacks the 'framework' qualifier`| ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + + -Wincomplete-implementation --------------------------- This diagnostic is enabled by default. @@ -5642,6 +6264,18 @@ Also controls `-Wignored-optimization-argument`_. **Diagnostic text:** ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`the given MCU supports` |nbsp| :placeholder:`A` |nbsp| :diagtext:`hardware multiply, but -mhwmult is set to` |nbsp| :placeholder:`B`:diagtext:`.`| ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`no MCU device specified, but '-mhwmult' is set to 'auto', assuming no hardware multiply. Use -mmcu to specify a MSP430 device, or -mhwmult to set hardware multiply type explicitly.`| ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + ++----------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`the given MCU does not support hardware multiply, but -mhwmult is set to` |nbsp| :placeholder:`A`:diagtext:`.`| ++----------------------------------------------------------------------------------------------------------------------------------------------------+ + +-----------------------------------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`the object size sanitizer has no effect at -O0, but is explicitly enabled:` |nbsp| :placeholder:`A`| +-----------------------------------------------------------------------------------------------------------------------------------------+ @@ -5900,6 +6534,10 @@ This diagnostic is enabled by default. |:warning:`warning:` |nbsp| :diagtext:`implicit conversion from` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to` |nbsp| :placeholder:`B` |nbsp| :diagtext:`changes value from` |nbsp| :placeholder:`C` |nbsp| :diagtext:`to` |nbsp| :placeholder:`D`| +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`implicit conversion of out of range value from` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to` |nbsp| :placeholder:`B` |nbsp| :diagtext:`is undefined`| ++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + -Wliteral-range --------------- @@ -6065,6 +6703,21 @@ This diagnostic is enabled by default. +----------------------------------------------------------------+---------------------------------------+------------------------------------------------------+ +-Wmemset-transposed-args +------------------------ +This diagnostic is enabled by default. + +**Diagnostic text:** + ++---------------------------+-----------------------------------------------------+---------------------------------------------------------------+ +|:warning:`warning:` |nbsp| |+---------------------------------------------------+|:diagtext:`; did you mean to transpose the last two arguments?`| +| ||:diagtext:`'size' argument to memset is '0'` || | +| |+---------------------------------------------------+| | +| ||:diagtext:`setting buffer to a 'sizeof' expression`|| | +| |+---------------------------------------------------+| | ++---------------------------+-----------------------------------------------------+---------------------------------------------------------------+ + + -Wmemsize-comparison -------------------- This diagnostic is enabled by default. @@ -6093,7 +6746,7 @@ This diagnostic is enabled by default. ----------- Some of the diagnostics controlled by this flag are enabled by default. -Controls `-Winconsistent-dllimport`_, `-Wmicrosoft-anon-tag`_, `-Wmicrosoft-cast`_, `-Wmicrosoft-charize`_, `-Wmicrosoft-comment-paste`_, `-Wmicrosoft-const-init`_, `-Wmicrosoft-cpp-macro`_, `-Wmicrosoft-default-arg-redefinition`_, `-Wmicrosoft-end-of-file`_, `-Wmicrosoft-enum-forward-reference`_, `-Wmicrosoft-enum-value`_, `-Wmicrosoft-exception-spec`_, `-Wmicrosoft-explicit-constructor-call`_, `-Wmicrosoft-extra-qualification`_, `-Wmicrosoft-fixed-enum`_, `-Wmicrosoft-flexible-array`_, `-Wmicrosoft-goto`_, `-Wmicrosoft-include`_, `-Wmicrosoft-mutable-reference`_, `-Wmicrosoft-pure-definition`_, `-Wmicrosoft-redeclare-static`_, `-Wmicrosoft-sealed`_, `-Wmicrosoft-template`_, `-Wmicrosoft-union-member-reference`_, `-Wmicrosoft-unqualified-friend`_, `-Wmicrosoft-using-decl`_, `-Wmicrosoft-void-pseudo-dtor`_. +Controls `-Winconsistent-dllimport`_, `-Wmicrosoft-anon-tag`_, `-Wmicrosoft-cast`_, `-Wmicrosoft-charize`_, `-Wmicrosoft-comment-paste`_, `-Wmicrosoft-const-init`_, `-Wmicrosoft-cpp-macro`_, `-Wmicrosoft-default-arg-redefinition`_, `-Wmicrosoft-drectve-section`_, `-Wmicrosoft-end-of-file`_, `-Wmicrosoft-enum-forward-reference`_, `-Wmicrosoft-enum-value`_, `-Wmicrosoft-exception-spec`_, `-Wmicrosoft-explicit-constructor-call`_, `-Wmicrosoft-extra-qualification`_, `-Wmicrosoft-fixed-enum`_, `-Wmicrosoft-flexible-array`_, `-Wmicrosoft-goto`_, `-Wmicrosoft-include`_, `-Wmicrosoft-mutable-reference`_, `-Wmicrosoft-pure-definition`_, `-Wmicrosoft-redeclare-static`_, `-Wmicrosoft-sealed`_, `-Wmicrosoft-template`_, `-Wmicrosoft-union-member-reference`_, `-Wmicrosoft-unqualified-friend`_, `-Wmicrosoft-using-decl`_, `-Wmicrosoft-void-pseudo-dtor`_. -Wmicrosoft-anon-tag @@ -6187,6 +6840,17 @@ This diagnostic is enabled by default. +-----------------------------------------------------------------------+ +-Wmicrosoft-drectve-section +--------------------------- +This diagnostic is enabled by default. + +**Diagnostic text:** + ++---------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`#pragma` |nbsp| :placeholder:`A`:diagtext:`(".drectve") has undefined behavior, use #pragma comment(linker, ...) instead`| ++---------------------------------------------------------------------------------------------------------------------------------------------------------------+ + + -Wmicrosoft-end-of-file ----------------------- **Diagnostic text:** @@ -6333,6 +6997,17 @@ This diagnostic is enabled by default. +----------------------------------------------------------------------------------------------------------+ +-Wmicrosoft-inaccessible-base +----------------------------- +This diagnostic is enabled by default. + +**Diagnostic text:** + ++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`accessing inaccessible direct base` |nbsp| :placeholder:`A` |nbsp| :diagtext:`of` |nbsp| :placeholder:`B` |nbsp| :diagtext:`is a Microsoft extension`| ++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + + -Wmicrosoft-include ------------------- This diagnostic is enabled by default. @@ -6400,10 +7075,6 @@ This diagnostic is enabled by default. |:warning:`warning:` |nbsp| :diagtext:`use of identifier` |nbsp| :placeholder:`A` |nbsp| :diagtext:`found via unqualified lookup into dependent bases of class templates is a Microsoft extension`| +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -+--------------------------------------------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`explicit specialization of` |nbsp| :placeholder:`A` |nbsp| :diagtext:`within class scope is a Microsoft extension`| -+--------------------------------------------------------------------------------------------------------------------------------------------------------+ - +-------------------------------------------------------------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`using the undeclared type` |nbsp| :placeholder:`A` |nbsp| :diagtext:`as a default template argument is a Microsoft extension`| +-------------------------------------------------------------------------------------------------------------------------------------------------------------------+ @@ -6412,32 +7083,36 @@ This diagnostic is enabled by default. |:warning:`warning:` |nbsp| :diagtext:`non-type template argument containing a dereference operation is a Microsoft extension`| +-----------------------------------------------------------------------------------------------------------------------------+ -+---------------------------+---------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| |+-------------------------------------+| |nbsp| :diagtext:`specialization of` |nbsp| :placeholder:`B` |nbsp| :diagtext:`outside namespace enclosing` |nbsp| :placeholder:`C` |nbsp| :diagtext:`is a Microsoft extension`| -| ||:diagtext:`class template` || | -| |+-------------------------------------+| | -| ||:diagtext:`class template partial` || | -| |+-------------------------------------+| | -| ||:diagtext:`variable template` || | -| |+-------------------------------------+| | -| ||:diagtext:`variable template partial`|| | -| |+-------------------------------------+| | -| ||:diagtext:`function template` || | -| |+-------------------------------------+| | -| ||:diagtext:`member function` || | -| |+-------------------------------------+| | -| ||:diagtext:`static data member` || | -| |+-------------------------------------+| | -| ||:diagtext:`member class` || | -| |+-------------------------------------+| | -| ||:diagtext:`member enumeration` || | -| |+-------------------------------------+| | -+---------------------------+---------------------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ++---------------------------+---------------------------------------+-----------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------+--------------------------------------------+ +|:warning:`warning:` |nbsp| |+-------------------------------------+| |nbsp| :diagtext:`specialization of` |nbsp| :placeholder:`B` |nbsp| :diagtext:`not in` |nbsp| |+----------------------------------------------------------------------------------------+| |nbsp| :diagtext:`is a Microsoft extension`| +| ||:diagtext:`class template` || ||+---------------------------------------------------------+ || | +| |+-------------------------------------+| |||:diagtext:`a namespace enclosing` |nbsp| :placeholder:`C`| || | +| ||:diagtext:`class template partial` || ||+---------------------------------------------------------+ || | +| |+-------------------------------------+| |+----------------------------------------------------------------------------------------+| | +| ||:diagtext:`variable template` || ||+--------------------------------------------------------------------------------------+|| | +| |+-------------------------------------+| |||:diagtext:`class` |nbsp| :placeholder:`C` |nbsp| :diagtext:`or an enclosing namespace`||| | +| ||:diagtext:`variable template partial`|| ||+--------------------------------------------------------------------------------------+|| | +| |+-------------------------------------+| |+----------------------------------------------------------------------------------------+| | +| ||:diagtext:`function template` || | | | +| |+-------------------------------------+| | | | +| ||:diagtext:`member function` || | | | +| |+-------------------------------------+| | | | +| ||:diagtext:`static data member` || | | | +| |+-------------------------------------+| | | | +| ||:diagtext:`member class` || | | | +| |+-------------------------------------+| | | | +| ||:diagtext:`member enumeration` || | | | +| |+-------------------------------------+| | | | ++---------------------------+---------------------------------------+-----------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------+--------------------------------------------+ +------------------------------------------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`template argument for template type parameter must be a type; omitted 'typename' is a Microsoft extension`| +------------------------------------------------------------------------------------------------------------------------------------------------+ ++-------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`'static' can only be specified inside the class definition`| ++-------------------------------------------------------------------------------------------------+ + +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`use of undeclared identifier` |nbsp| :placeholder:`A`:diagtext:`; unqualified lookup into dependent bases of class template` |nbsp| :placeholder:`B` |nbsp| :diagtext:`is a Microsoft extension`| +--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ @@ -6528,25 +7203,25 @@ This diagnostic is enabled by default. ----------------- **Diagnostic text:** -+---------------------------------------------------------------------------------+--------------------------+------------------------------+-----------------------------------------------------------+--------------------------+------------------------------+ -|:warning:`warning:` |nbsp| :placeholder:`C` |nbsp| :diagtext:`defined as` |nbsp| |+------------------------+|+----------------------------+| |nbsp| :diagtext:`here but previously declared as` |nbsp| |+------------------------+|+----------------------------+| -| ||:diagtext:`a struct` ||| || ||:diagtext:`a struct` ||| || -| |+------------------------+|+----------------------------+| |+------------------------+|+----------------------------+| -| ||:diagtext:`an interface`||| |nbsp| :diagtext:`template`|| ||:diagtext:`an interface`||| |nbsp| :diagtext:`template`|| -| |+------------------------+|+----------------------------+| |+------------------------+|+----------------------------+| -| ||:diagtext:`a class` || | ||:diagtext:`a class` || | -| |+------------------------+| | |+------------------------+| | -+---------------------------------------------------------------------------------+--------------------------+------------------------------+-----------------------------------------------------------+--------------------------+------------------------------+ ++---------------------------------------------------------------------------------+--------------------------+------------------------------+-----------------------------------------------------------+--------------------------+------------------------------+----------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :placeholder:`C` |nbsp| :diagtext:`defined as` |nbsp| |+------------------------+|+----------------------------+| |nbsp| :diagtext:`here but previously declared as` |nbsp| |+------------------------+|+----------------------------+|:diagtext:`; this is valid, but may result in linker errors under the Microsoft C++ ABI`| +| ||:diagtext:`a struct` ||| || ||:diagtext:`a struct` ||| || | +| |+------------------------+|+----------------------------+| |+------------------------+|+----------------------------+| | +| ||:diagtext:`an interface`||| |nbsp| :diagtext:`template`|| ||:diagtext:`an interface`||| |nbsp| :diagtext:`template`|| | +| |+------------------------+|+----------------------------+| |+------------------------+|+----------------------------+| | +| ||:diagtext:`a class` || | ||:diagtext:`a class` || | | +| |+------------------------+| | |+------------------------+| | | ++---------------------------------------------------------------------------------+--------------------------+------------------------------+-----------------------------------------------------------+--------------------------+------------------------------+----------------------------------------------------------------------------------------+ -+---------------------------+-----------------------+------------------------------+--------------------------------------------------------------------------------+-----------------------+------------------------------+ -|:warning:`warning:` |nbsp| |+---------------------+|+----------------------------+| |nbsp| :placeholder:`C` |nbsp| :diagtext:`was previously declared as a` |nbsp| |+---------------------+|+----------------------------+| -| ||:diagtext:`struct` ||| || ||:diagtext:`struct` ||| || -| |+---------------------+|+----------------------------+| |+---------------------+|+----------------------------+| -| ||:diagtext:`interface`||| |nbsp| :diagtext:`template`|| ||:diagtext:`interface`||| |nbsp| :diagtext:`template`|| -| |+---------------------+|+----------------------------+| |+---------------------+|+----------------------------+| -| ||:diagtext:`class` || | ||:diagtext:`class` || | -| |+---------------------+| | |+---------------------+| | -+---------------------------+-----------------------+------------------------------+--------------------------------------------------------------------------------+-----------------------+------------------------------+ ++---------------------------+-----------------------+------------------------------+--------------------------------------------------------------------------------+-----------------------+------------------------------+----------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| |+---------------------+|+----------------------------+| |nbsp| :placeholder:`C` |nbsp| :diagtext:`was previously declared as a` |nbsp| |+---------------------+|+----------------------------+|:diagtext:`; this is valid, but may result in linker errors under the Microsoft C++ ABI`| +| ||:diagtext:`struct` ||| || ||:diagtext:`struct` ||| || | +| |+---------------------+|+----------------------------+| |+---------------------+|+----------------------------+| | +| ||:diagtext:`interface`||| |nbsp| :diagtext:`template`|| ||:diagtext:`interface`||| |nbsp| :diagtext:`template`|| | +| |+---------------------+|+----------------------------+| |+---------------------+|+----------------------------+| | +| ||:diagtext:`class` || | ||:diagtext:`class` || | | +| |+---------------------+| | |+---------------------+| | | ++---------------------------+-----------------------+------------------------------+--------------------------------------------------------------------------------+-----------------------+------------------------------+----------------------------------------------------------------------------------------+ -Wmissing-braces @@ -6755,6 +7430,21 @@ This diagnostic is enabled by default. +----------------------------------------------------------------------------------------------------------------+ +-Rmodule-import +--------------- +**Diagnostic text:** + ++------------------------------------------------------------------------------------+-----------------------------------------------------------+-------------------------------------------------------+ +|:remark:`remark:` |nbsp| :diagtext:`importing module '`:placeholder:`A`:diagtext:`'`|+---------------------------------------------------------+| |nbsp| :diagtext:`from '`:placeholder:`B`:diagtext:`'`| +| || || | +| |+---------------------------------------------------------+| | +| ||+-------------------------------------------------------+|| | +| ||| |nbsp| :diagtext:`into '`:placeholder:`D`:diagtext:`'`||| | +| ||+-------------------------------------------------------+|| | +| |+---------------------------------------------------------+| | ++------------------------------------------------------------------------------------+-----------------------------------------------------------+-------------------------------------------------------+ + + -Wmodule-import-in-extern-c --------------------------- This diagnostic is an error by default, but the flag ``-Wno-module-import-in-extern-c`` can be used to disable the error. @@ -6797,7 +7487,7 @@ Controls `-Wcast-of-sel-type`_, `-Wchar-subscripts`_, `-Wcomment`_, `-Wdelete-no -Wmove ------ -Controls `-Wpessimizing-move`_, `-Wredundant-move`_, `-Wself-move`_. +Controls `-Wpessimizing-move`_, `-Wredundant-move`_, `-Wreturn-std-move`_, `-Wself-move`_. -Wmsvc-include @@ -6888,6 +7578,25 @@ This diagnostic is enabled by default. +----------------------------------------------------------------+ +-Wnoderef +--------- +This diagnostic is enabled by default. + +**Diagnostic text:** + ++----------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`dereferencing` |nbsp| :placeholder:`A`:diagtext:`; was declared with a 'noderef' type`| ++----------------------------------------------------------------------------------------------------------------------------+ + ++-----------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`dereferencing expression marked as 'noderef'`| ++-----------------------------------------------------------------------------------+ + ++-----------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`casting to dereferenceable pointer removes 'noderef' attribute`| ++-----------------------------------------------------------------------------------------------------+ + + -Wnoexcept-type --------------- Synonym for `-Wc++17-compat-mangling`_. @@ -7033,6 +7742,25 @@ This diagnostic is enabled by default. +---------------------------------------------------------------------------------------------------------------------+ +-Wnontrivial-memaccess +---------------------- +This diagnostic is enabled by default. + +**Diagnostic text:** + ++---------------------------+-------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------+ +|:warning:`warning:` |nbsp| |+-----------------------------+| |nbsp| :diagtext:`this` |nbsp| :placeholder:`B` |nbsp| :diagtext:`call is a pointer to record` |nbsp| :placeholder:`C` |nbsp| :diagtext:`that is not trivial to` |nbsp| |+----------------------------------------+| +| ||:diagtext:`destination for` || ||:diagtext:`primitive-default-initialize`|| +| |+-----------------------------+| |+----------------------------------------+| +| ||:diagtext:`source of` || ||:diagtext:`primitive-copy` || +| |+-----------------------------+| |+----------------------------------------+| +| ||:diagtext:`first operand of` || | | +| |+-----------------------------+| | | +| ||:diagtext:`second operand of`|| | | +| |+-----------------------------+| | | ++---------------------------+-------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------+ + + -Wnsconsumed-mismatch --------------------- This diagnostic is enabled by default. @@ -7274,16 +8002,38 @@ This diagnostic is enabled by default. +---------------------------------------------------------------------------------------------------------------------------+-------------------------+---------------------------------------------------------------------------------------------------------------------------------+ +-Wobjc-bool-constant-conversion +------------------------------- +This diagnostic is enabled by default. + +**Diagnostic text:** + ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`implicit conversion from constant value` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to BOOL; the only well defined values for BOOL are YES and NO`| ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + + +-Wobjc-boxing +------------- +This diagnostic is enabled by default. + +**Diagnostic text:** + ++-------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`string is ill-formed as UTF-8 and will become a null` |nbsp| :placeholder:`A` |nbsp| :diagtext:`when boxed`| ++-------------------------------------------------------------------------------------------------------------------------------------------------+ + + -Wobjc-circular-container ------------------------- This diagnostic is enabled by default. **Diagnostic text:** -+-----------------------------------------------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`adding '`:placeholder:`A`:diagtext:`' to '`:placeholder:`B`:diagtext:`' might cause circular dependency in container`| -+-----------------------------------------------------------------------------------------------------------------------------------------------------------+ - ++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`adding` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to` |nbsp| :placeholder:`B` |nbsp| :diagtext:`might cause circular dependency in container`| ++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + -Wobjc-cocoa-api ---------------- @@ -7504,6 +8254,15 @@ This diagnostic is enabled by default. +-----------------------------------------------------------------------------------------------------------------------------+ +-Wobjc-property-assign-on-object-type +------------------------------------- +**Diagnostic text:** + ++--------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`'assign' property of object type may become a dangling reference; consider using 'unsafe\_unretained'`| ++--------------------------------------------------------------------------------------------------------------------------------------------+ + + -Wobjc-property-implementation ------------------------------ This diagnostic is enabled by default. @@ -7699,10 +8458,102 @@ This diagnostic is enabled by default. **Diagnostic text:** ++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`template parameter lists have a different number of parameters (`:placeholder:`A` |nbsp| :diagtext:`vs` |nbsp| :placeholder:`B`:diagtext:`)`| ++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + ++------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`template parameter has different kinds in different translation units`| ++------------------------------------------------------------------------------------------------------------+ + ++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`field` |nbsp| :placeholder:`A` |nbsp| :diagtext:`declared with incompatible types in different translation units (`:placeholder:`B` |nbsp| :diagtext:`vs.` |nbsp| :placeholder:`C`:diagtext:`)`| ++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + ++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`external function` |nbsp| :placeholder:`A` |nbsp| :diagtext:`declared with incompatible types in different translation units (`:placeholder:`B` |nbsp| :diagtext:`vs.` |nbsp| :placeholder:`C`:diagtext:`)`| ++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + ++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`instance variable` |nbsp| :placeholder:`A` |nbsp| :diagtext:`declared with incompatible types in different translation units (`:placeholder:`B` |nbsp| :diagtext:`vs.` |nbsp| :placeholder:`C`:diagtext:`)`| ++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + ++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`non-type template parameter declared with incompatible types in different translation units (`:placeholder:`A` |nbsp| :diagtext:`vs.` |nbsp| :placeholder:`B`:diagtext:`)`| ++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + ++---------------------------+----------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| |+--------------------+| |nbsp| :diagtext:`method` |nbsp| :placeholder:`B` |nbsp| :diagtext:`has a different number of parameters in different translation units (`:placeholder:`C` |nbsp| :diagtext:`vs.` |nbsp| :placeholder:`D`:diagtext:`)`| +| ||:diagtext:`class` || | +| |+--------------------+| | +| ||:diagtext:`instance`|| | +| |+--------------------+| | ++---------------------------+----------------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + ++---------------------------+----------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| |+--------------------+| |nbsp| :diagtext:`method` |nbsp| :placeholder:`B` |nbsp| :diagtext:`has a parameter with a different types in different translation units (`:placeholder:`C` |nbsp| :diagtext:`vs.` |nbsp| :placeholder:`D`:diagtext:`)`| +| ||:diagtext:`class` || | +| |+--------------------+| | +| ||:diagtext:`instance`|| | +| |+--------------------+| | ++---------------------------+----------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + ++---------------------------+----------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| |+--------------------+| |nbsp| :diagtext:`method` |nbsp| :placeholder:`B` |nbsp| :diagtext:`has incompatible result types in different translation units (`:placeholder:`C` |nbsp| :diagtext:`vs.` |nbsp| :placeholder:`D`:diagtext:`)`| +| ||:diagtext:`class` || | +| |+--------------------+| | +| ||:diagtext:`instance`|| | +| |+--------------------+| | ++---------------------------+----------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + ++---------------------------+----------------------+-------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| |+--------------------+| |nbsp| :diagtext:`method` |nbsp| :placeholder:`B` |nbsp| :diagtext:`is variadic in one translation unit and not variadic in another`| +| ||:diagtext:`class` || | +| |+--------------------+| | +| ||:diagtext:`instance`|| | +| |+--------------------+| | ++---------------------------+----------------------+-------------------------------------------------------------------------------------------------------------------------------------+ + ++----------------------------------------------------------------------------------------------------------------------+-------------------------+--------------------------------------------------+-------------------------+-----------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`property` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is implemented with` |nbsp| |+-----------------------+| |nbsp| :diagtext:`in one translation but` |nbsp| |+-----------------------+| |nbsp| :diagtext:`in another translation unit`| +| ||:diagtext:`@synthesize`|| ||:diagtext:`@dynamic` || | +| |+-----------------------+| |+-----------------------+| | +| ||:diagtext:`@dynamic` || ||:diagtext:`@synthesize`|| | +| |+-----------------------+| |+-----------------------+| | ++----------------------------------------------------------------------------------------------------------------------+-------------------------+--------------------------------------------------+-------------------------+-----------------------------------------------+ + ++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`property` |nbsp| :placeholder:`A` |nbsp| :diagtext:`declared with incompatible types in different translation units (`:placeholder:`B` |nbsp| :diagtext:`vs.` |nbsp| :placeholder:`C`:diagtext:`)`| ++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + ++---------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`class` |nbsp| :placeholder:`A` |nbsp| :diagtext:`has incompatible superclasses`| ++---------------------------------------------------------------------------------------------------------------------+ + ++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`property` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is synthesized to different ivars in different translation units (`:placeholder:`B` |nbsp| :diagtext:`vs.` |nbsp| :placeholder:`C`:diagtext:`)`| ++-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + ++------------------------------------------------------------------------------------+-------------------+----------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`parameter kind mismatch; parameter is` |nbsp| |+-----------------+| |nbsp| :diagtext:`parameter pack`| +| ||:diagtext:`not a`|| | +| |+-----------------+| | +| ||:diagtext:`a` || | +| |+-----------------+| | ++------------------------------------------------------------------------------------+-------------------+----------------------------------+ + +--------------------------------------------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`type` |nbsp| :placeholder:`A` |nbsp| :diagtext:`has incompatible definitions in different translation units`| +--------------------------------------------------------------------------------------------------------------------------------------------------+ ++-----------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`external variable` |nbsp| :placeholder:`A` |nbsp| :diagtext:`defined in multiple translation units`| ++-----------------------------------------------------------------------------------------------------------------------------------------+ + ++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`external variable` |nbsp| :placeholder:`A` |nbsp| :diagtext:`declared with incompatible types in different translation units (`:placeholder:`B` |nbsp| :diagtext:`vs.` |nbsp| :placeholder:`C`:diagtext:`)`| ++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + -Wold-style-cast ---------------- @@ -7738,6 +8589,10 @@ This diagnostic is enabled by default. |:warning:`warning:` |nbsp| :diagtext:`aligned clause will be ignored because the requested alignment is not a power of 2`| +-------------------------------------------------------------------------------------------------------------------------+ ++----------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`allocator with the 'thread' trait access has unspecified behavior on '`:placeholder:`A`:diagtext:`' directive`| ++----------------------------------------------------------------------------------------------------------------------------------------------------+ + +---------------------------------------------------------------------------------+---------------------------------------------------+-------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`zero linear step (`:placeholder:`A` |nbsp| |+-------------------------------------------------+|:diagtext:`should probably be const)`| | || || | @@ -7746,6 +8601,16 @@ This diagnostic is enabled by default. | |+-------------------------------------------------+| | +---------------------------------------------------------------------------------+---------------------------------------------------+-------------------------------------+ ++---------------------------------------------------------------------------+----------------------------------------------+-----------------------------------------------------------+----------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`allocate directive specifies` |nbsp| |+--------------------------------------------+| |nbsp| :diagtext:`allocator while previously used` |nbsp| |+--------------------------------------------+| +| ||:diagtext:`default` || ||:diagtext:`default` || +| |+--------------------------------------------+| |+--------------------------------------------+| +| ||+------------------------------------------+|| ||+------------------------------------------+|| +| |||:diagtext:`'`:placeholder:`B`:diagtext:`'`||| |||:diagtext:`'`:placeholder:`D`:diagtext:`'`||| +| ||+------------------------------------------+|| ||+------------------------------------------+|| +| |+--------------------------------------------+| |+--------------------------------------------+| ++---------------------------------------------------------------------------+----------------------------------------------+-----------------------------------------------------------+----------------------------------------------+ + -Wopenmp-loop-form ------------------ @@ -7772,6 +8637,14 @@ This diagnostic is enabled by default. |:warning:`warning:` |nbsp| :diagtext:`The OpenMP offloading target '`:placeholder:`A`:diagtext:`' is similar to target '`:placeholder:`B`:diagtext:`' already specified - will be ignored.`| +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`No library '`:placeholder:`A`:diagtext:`' found in the default clang lib directory or in LIBRARY\_PATH. Expect degraded performance due to no inlining of runtime functions on target devices.`| ++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + ++----------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`Non-trivial type` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is mapped, only trivial types are guaranteed to be mapped correctly`| ++----------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + +-----------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`declaration is not declared in any declare target region`| +-----------------------------------------------------------------------------------------------+ @@ -7787,14 +8660,14 @@ This diagnostic is enabled by default. |:warning:`warning:` |nbsp| :diagtext:`option '-ffine-grained-bitfield-accesses' cannot be enabled together with a sanitizer; flag ignored`| +------------------------------------------------------------------------------------------------------------------------------------------+ ++-------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`The '`:placeholder:`A`:diagtext:`' architecture does not support -moutline; flag ignored`| ++-------------------------------------------------------------------------------------------------------------------------------+ + +----------------------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`option '`:placeholder:`A`:diagtext:`' was ignored by the PS4 toolchain, using '-fPIC'`| +----------------------------------------------------------------------------------------------------------------------------+ -+-------------------------------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`ignoring '-mabicalls' option as it cannot be used with non position-independent code and the N64 ABI`| -+-------------------------------------------------------------------------------------------------------------------------------------------+ - +-------------------------------------------------------------------------------------------------------------------+-------------------------------------------+----------------------+ |:warning:`warning:` |nbsp| :diagtext:`ignoring '-mlong-calls' option as it is not currently supported with` |nbsp| |+-----------------------------------------+|:diagtext:`-mabicalls`| | || || | @@ -7803,6 +8676,29 @@ This diagnostic is enabled by default. | |+-----------------------------------------+| | +-------------------------------------------------------------------------------------------------------------------+-------------------------------------------+----------------------+ ++-----------------------------------------------------------------------------------------------------------------------+-------------------------------+----------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`ignoring '`:placeholder:`A`:diagtext:`' option as it cannot be used with` |nbsp| |+-----------------------------+| |nbsp| :diagtext:`-mabicalls and the N64 ABI`| +| ||:diagtext:`implicit usage of`|| | +| |+-----------------------------+| | +| || || | +| |+-----------------------------+| | ++-----------------------------------------------------------------------------------------------------------------------+-------------------------------+----------------------------------------------+ + ++----------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`auto-vectorization requires HVX, use -mhvx to enable it`| ++----------------------------------------------------------------------------------------------+ + + +-Wordered-compare-function-pointers +----------------------------------- +This diagnostic is enabled by default. + +**Diagnostic text:** + ++------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`ordered comparison of function pointers (`:placeholder:`A` |nbsp| :diagtext:`and` |nbsp| :placeholder:`B`:diagtext:`)`| ++------------------------------------------------------------------------------------------------------------------------------------------------------------+ + -Wout-of-line-declaration ------------------------- @@ -7885,6 +8781,7 @@ This diagnostic is enabled by default. | |+---------------------+| +-----------------------------------------------------------------------------------------------+-----------------------+ + -Woverride-init --------------- Synonym for `-Winitializer-overrides`_. @@ -8079,10 +8976,14 @@ This diagnostic is enabled by default. -Wpedantic ---------- -Also controls `-Wc++11-extra-semi`_, `-Wc++11-long-long`_, `-Wc++14-binary-literal`_, `-Wc11-extensions`_, `-Wcomplex-component-init`_, `-Wdeclaration-after-statement`_, `-Wdollar-in-identifier-extension`_, `-Wembedded-directive`_, `-Wempty-translation-unit`_, `-Wextended-offsetof`_, `-Wflexible-array-extensions`_, `-Wformat-pedantic`_, `-Wfour-char-constants`_, `-Wgnu-anonymous-struct`_, `-Wgnu-auto-type`_, `-Wgnu-binary-literal`_, `-Wgnu-case-range`_, `-Wgnu-complex-integer`_, `-Wgnu-compound-literal-initializer`_, `-Wgnu-conditional-omitted-operand`_, `-Wgnu-empty-initializer`_, `-Wgnu-empty-struct`_, `-Wgnu-flexible-array-initializer`_, `-Wgnu-flexible-array-union-member`_, `-Wgnu-folding-constant`_, `-Wgnu-imaginary-constant`_, `-Wgnu-include-next`_, `-Wgnu-label-as-value`_, `-Wgnu-redeclared-enum`_, `-Wgnu-statement-expression`_, `-Wgnu-union-cast`_, `-Wgnu-zero-line-directive`_, `-Wgnu-zero-variadic-macro-arguments`_, `-Wimport-preprocessor-directive-pedantic`_, `-Wkeyword-macro`_, `-Wlanguage-extension-token`_, `-Wlong-long`_, `-Wmicrosoft-charize`_, `-Wmicrosoft-comment-paste`_, `-Wmicrosoft-cpp-macro`_, `-Wmicrosoft-end-of-file`_, `-Wmicrosoft-enum-value`_, `-Wmicrosoft-fixed-enum`_, `-Wmicrosoft-flexible-array`_, `-Wmicrosoft-redeclare-static`_, `-Wnested-anon-types`_, `-Wnullability-extension`_, `-Woverlength-strings`_, `-Wretained-language-linkage`_, `-Wundefined-internal-type`_, `-Wvla-extension`_, `-Wzero-length-array`_. +Also controls `-Wc++11-extra-semi`_, `-Wc++11-long-long`_, `-Wc++14-binary-literal`_, `-Wc11-extensions`_, `-Wcomplex-component-init`_, `-Wdeclaration-after-statement`_, `-Wdollar-in-identifier-extension`_, `-Wembedded-directive`_, `-Wempty-translation-unit`_, `-Wfixed-enum-extension`_, `-Wflexible-array-extensions`_, `-Wfour-char-constants`_, `-Wgnu-anonymous-struct`_, `-Wgnu-auto-type`_, `-Wgnu-binary-literal`_, `-Wgnu-case-range`_, `-Wgnu-complex-integer`_, `-Wgnu-compound-literal-initializer`_, `-Wgnu-conditional-omitted-operand`_, `-Wgnu-empty-initializer`_, `-Wgnu-empty-struct`_, `-Wgnu-flexible-array-initializer`_, `-Wgnu-flexible-array-union-member`_, `-Wgnu-folding-constant`_, `-Wgnu-imaginary-constant`_, `-Wgnu-include-next`_, `-Wgnu-label-as-value`_, `-Wgnu-redeclared-enum`_, `-Wgnu-statement-expression`_, `-Wgnu-union-cast`_, `-Wgnu-zero-line-directive`_, `-Wgnu-zero-variadic-macro-arguments`_, `-Wimport-preprocessor-directive-pedantic`_, `-Wkeyword-macro`_, `-Wlanguage-extension-token`_, `-Wlong-long`_, `-Wmicrosoft-charize`_, `-Wmicrosoft-comment-paste`_, `-Wmicrosoft-cpp-macro`_, `-Wmicrosoft-end-of-file`_, `-Wmicrosoft-enum-value`_, `-Wmicrosoft-fixed-enum`_, `-Wmicrosoft-flexible-array`_, `-Wmicrosoft-redeclare-static`_, `-Wnested-anon-types`_, `-Wnullability-extension`_, `-Woverlength-strings`_, `-Wretained-language-linkage`_, `-Wundefined-internal-type`_, `-Wvla-extension`_, `-Wzero-length-array`_. **Diagnostic text:** ++-----------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`duplicate '`:placeholder:`A`:diagtext:`' declaration specifier`| ++-----------------------------------------------------------------------------------------------------+ + +------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`'enable\_if' is a clang extension`| +------------------------------------------------------------------------+ @@ -8115,31 +9016,37 @@ Also controls `-Wc++11-extra-semi`_, `-Wc++11-long-long`_, `-Wc++14-binary-liter | |+------------------+| | +--------------------------------------------------------+--------------------+------------------------------------------------------------+ -+--------------------------------------------------------------------+-----------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`no viable constructor` |nbsp| |+---------------------------------------+| |nbsp| :diagtext:`of type` |nbsp| :placeholder:`B`:diagtext:`; C++98 requires a copy constructor when binding a reference to a temporary`| -| ||:diagtext:`copying variable` || | -| |+---------------------------------------+| | -| ||:diagtext:`copying parameter` || | -| |+---------------------------------------+| | -| ||:diagtext:`returning object` || | -| |+---------------------------------------+| | -| ||:diagtext:`throwing object` || | -| |+---------------------------------------+| | -| ||:diagtext:`copying member subobject` || | -| |+---------------------------------------+| | -| ||:diagtext:`copying array element` || | -| |+---------------------------------------+| | -| ||:diagtext:`allocating object` || | -| |+---------------------------------------+| | -| ||:diagtext:`copying temporary` || | -| |+---------------------------------------+| | -| ||:diagtext:`initializing base subobject`|| | -| |+---------------------------------------+| | -| ||:diagtext:`initializing vector element`|| | -| |+---------------------------------------+| | -| ||:diagtext:`capturing value` || | -| |+---------------------------------------+| | -+--------------------------------------------------------------------+-----------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+ ++--------------------------------------------------------------------+------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`no viable constructor` |nbsp| |+----------------------------------------------------+| |nbsp| :diagtext:`of type` |nbsp| :placeholder:`B`:diagtext:`; C++98 requires a copy constructor when binding a reference to a temporary`| +| ||:diagtext:`copying variable` || | +| |+----------------------------------------------------+| | +| ||:diagtext:`copying parameter` || | +| |+----------------------------------------------------+| | +| ||:diagtext:`returning object` || | +| |+----------------------------------------------------+| | +| ||:diagtext:`initializing statement expression result`|| | +| |+----------------------------------------------------+| | +| ||:diagtext:`throwing object` || | +| |+----------------------------------------------------+| | +| ||:diagtext:`copying member subobject` || | +| |+----------------------------------------------------+| | +| ||:diagtext:`copying array element` || | +| |+----------------------------------------------------+| | +| ||:diagtext:`allocating object` || | +| |+----------------------------------------------------+| | +| ||:diagtext:`copying temporary` || | +| |+----------------------------------------------------+| | +| ||:diagtext:`initializing base subobject` || | +| |+----------------------------------------------------+| | +| ||:diagtext:`initializing vector element` || | +| |+----------------------------------------------------+| | +| ||:diagtext:`capturing value` || | +| |+----------------------------------------------------+| | ++--------------------------------------------------------------------+------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------+ + ++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`ISO C++ standards before C++17 do not allow new expression for type` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to use list-initialization`| ++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +--------------------------------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`parameter` |nbsp| :placeholder:`A` |nbsp| :diagtext:`was not declared, defaulting to type 'int'`| @@ -8185,25 +9092,33 @@ Also controls `-Wc++11-extra-semi`_, `-Wc++11-long-long`_, `-Wc++14-binary-liter |:warning:`warning:` |nbsp| :diagtext:`flexible array members are a C99 feature`| +-------------------------------------------------------------------------------+ -+---------------------------------------------------------------+-----------------------+--------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`invalid application of '`|+---------------------+|:diagtext:`' to a function type`| -| ||:diagtext:`sizeof` || | -| |+---------------------+| | -| ||:diagtext:`alignof` || | -| |+---------------------+| | -| ||:diagtext:`vec\_step`|| | -| |+---------------------+| | -+---------------------------------------------------------------+-----------------------+--------------------------------+ - -+---------------------------------------------------------------+-----------------------+----------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`invalid application of '`|+---------------------+|:diagtext:`' to a void type`| -| ||:diagtext:`sizeof` || | -| |+---------------------+| | -| ||:diagtext:`alignof` || | -| |+---------------------+| | -| ||:diagtext:`vec\_step`|| | -| |+---------------------+| | -+---------------------------------------------------------------+-----------------------+----------------------------+ ++---------------------------------------------------------------+-----------------------------------------------------+--------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`invalid application of '`|+---------------------------------------------------+|:diagtext:`' to a function type`| +| ||:diagtext:`sizeof` || | +| |+---------------------------------------------------+| | +| ||:diagtext:`alignof` || | +| |+---------------------------------------------------+| | +| ||:diagtext:`vec\_step` || | +| |+---------------------------------------------------+| | +| ||:diagtext:`\_\_builtin\_omp\_required\_simd\_align`|| | +| |+---------------------------------------------------+| | +| ||:diagtext:`\_\_alignof` || | +| |+---------------------------------------------------+| | ++---------------------------------------------------------------+-----------------------------------------------------+--------------------------------+ + ++---------------------------------------------------------------+-----------------------------------------------------+----------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`invalid application of '`|+---------------------------------------------------+|:diagtext:`' to a void type`| +| ||:diagtext:`sizeof` || | +| |+---------------------------------------------------+| | +| ||:diagtext:`alignof` || | +| |+---------------------------------------------------+| | +| ||:diagtext:`vec\_step` || | +| |+---------------------------------------------------+| | +| ||:diagtext:`\_\_builtin\_omp\_required\_simd\_align`|| | +| |+---------------------------------------------------+| | +| ||:diagtext:`\_\_alignof` || | +| |+---------------------------------------------------+| | ++---------------------------------------------------------------+-----------------------------------------------------+----------------------------+ +-------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`ISO C90 does not allow subscripting non-lvalue array`| @@ -8313,6 +9228,14 @@ Also controls `-Wc++11-extra-semi`_, `-Wc++11-long-long`_, `-Wc++14-binary-liter | |+------------------+| | +-----------------------------------------------------------------------------+--------------------+---------------------------------------------+ ++------------------------------------------------------------------------------------------------------------------------------------+-----------------------------+------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`format specifies type` |nbsp| :placeholder:`A` |nbsp| :diagtext:`but the argument has` |nbsp| |+---------------------------+| |nbsp| :placeholder:`B`| +| ||:diagtext:`type` || | +| |+---------------------------+| | +| ||:diagtext:`underlying type`|| | +| |+---------------------------+| | ++------------------------------------------------------------------------------------------------------------------------------------+-----------------------------+------------------------+ + +---------------------------------------------------+----------------------+-----------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`void` |nbsp| |+--------------------+| |nbsp| :placeholder:`A` |nbsp| :diagtext:`should not return void expression`| | ||:diagtext:`function`|| | @@ -8451,6 +9374,10 @@ Also controls `-Wc++11-extra-semi`_, `-Wc++11-long-long`_, `-Wc++14-binary-liter |:warning:`warning:` |nbsp| :diagtext:`empty macro arguments are a C99 feature`| +------------------------------------------------------------------------------+ ++--------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`variadic macros are a Clang extension in OpenCL`| ++--------------------------------------------------------------------------------------+ + +----------------------------------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`C requires #line number to be less than` |nbsp| :placeholder:`A`:diagtext:`, allowed as extension`| +----------------------------------------------------------------------------------------------------------------------------------------+ @@ -8510,25 +9437,33 @@ Some of the diagnostics controlled by this flag are enabled by default. | |+---------------------+| |+-------------+| | +----------------------------------------------------+-----------------------+---------------------------+---------------+----------------------------------------------+ -+---------------------------------------------------------------+-----------------------+--------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`invalid application of '`|+---------------------+|:diagtext:`' to a function type`| -| ||:diagtext:`sizeof` || | -| |+---------------------+| | -| ||:diagtext:`alignof` || | -| |+---------------------+| | -| ||:diagtext:`vec\_step`|| | -| |+---------------------+| | -+---------------------------------------------------------------+-----------------------+--------------------------------+ - -+---------------------------------------------------------------+-----------------------+----------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`invalid application of '`|+---------------------+|:diagtext:`' to a void type`| -| ||:diagtext:`sizeof` || | -| |+---------------------+| | -| ||:diagtext:`alignof` || | -| |+---------------------+| | -| ||:diagtext:`vec\_step`|| | -| |+---------------------+| | -+---------------------------------------------------------------+-----------------------+----------------------------+ ++---------------------------------------------------------------+-----------------------------------------------------+--------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`invalid application of '`|+---------------------------------------------------+|:diagtext:`' to a function type`| +| ||:diagtext:`sizeof` || | +| |+---------------------------------------------------+| | +| ||:diagtext:`alignof` || | +| |+---------------------------------------------------+| | +| ||:diagtext:`vec\_step` || | +| |+---------------------------------------------------+| | +| ||:diagtext:`\_\_builtin\_omp\_required\_simd\_align`|| | +| |+---------------------------------------------------+| | +| ||:diagtext:`\_\_alignof` || | +| |+---------------------------------------------------+| | ++---------------------------------------------------------------+-----------------------------------------------------+--------------------------------+ + ++---------------------------------------------------------------+-----------------------------------------------------+----------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`invalid application of '`|+---------------------------------------------------+|:diagtext:`' to a void type`| +| ||:diagtext:`sizeof` || | +| |+---------------------------------------------------+| | +| ||:diagtext:`alignof` || | +| |+---------------------------------------------------+| | +| ||:diagtext:`vec\_step` || | +| |+---------------------------------------------------+| | +| ||:diagtext:`\_\_builtin\_omp\_required\_simd\_align`|| | +| |+---------------------------------------------------+| | +| ||:diagtext:`\_\_alignof` || | +| |+---------------------------------------------------+| | ++---------------------------------------------------------------+-----------------------------------------------------+----------------------------+ +-----------------------------------------------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`subtraction of pointers to type` |nbsp| :placeholder:`A` |nbsp| :diagtext:`of zero size has undefined behavior`| @@ -8560,6 +9495,17 @@ This diagnostic is enabled by default. +-------------------------------------------------+------------------------------+---------------------------------------------------------------------------------+ +-Wpointer-integer-compare +------------------------- +This diagnostic is enabled by default. + +**Diagnostic text:** + ++-----------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`comparison between pointer and integer (`:placeholder:`A` |nbsp| :diagtext:`and` |nbsp| :placeholder:`B`:diagtext:`)`| ++-----------------------------------------------------------------------------------------------------------------------------------------------------------+ + + -Wpointer-sign -------------- This diagnostic is enabled by default. @@ -8726,26 +9672,34 @@ This diagnostic is enabled by default. **Diagnostic text:** -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`top-level module '`:placeholder:`A`:diagtext:`' in private module map, expected a submodule of '`:placeholder:`B`:diagtext:`'`| -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ++----------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`expected canonical name for private module '`:placeholder:`A`:diagtext:`'`| ++----------------------------------------------------------------------------------------------------------------+ + ++----------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`private submodule '`:placeholder:`A`:diagtext:`' in private module map, expected top-level module`| ++----------------------------------------------------------------------------------------------------------------------------------------+ +----------------------------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`module '`:placeholder:`A`:diagtext:`' already re-exported as '`:placeholder:`B`:diagtext:`'`| +----------------------------------------------------------------------------------------------------------------------------------+ ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`no submodule named` |nbsp| :placeholder:`A` |nbsp| :diagtext:`in module '`:placeholder:`B`:diagtext:`'; using top level '`:placeholder:`C`:diagtext:`'`| ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + -Wprofile-instr-missing ----------------------- **Diagnostic text:** -+-----------------------------------------------------------------------------------------------------------------------------+---------------+---------------------------------------------+-------------------+---------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`profile data may be incomplete: of` |nbsp| :placeholder:`A` |nbsp| :diagtext:`function`|+-------------+|:diagtext:`,` |nbsp| :placeholder:`B` |nbsp| |+-----------------+| |nbsp| :diagtext:`no data`| -| || || ||:diagtext:`:has` || | -| |+-------------+| |+-----------------+| | -| ||:diagtext:`s`|| ||:diagtext:`:have`|| | -| |+-------------+| |+-----------------+| | -+-----------------------------------------------------------------------------------------------------------------------------+---------------+---------------------------------------------+-------------------+---------------------------+ ++-----------------------------------------------------------------------------------------------------------------------------+---------------+---------------------------------------------+------------------+---------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`profile data may be incomplete: of` |nbsp| :placeholder:`A` |nbsp| :diagtext:`function`|+-------------+|:diagtext:`,` |nbsp| :placeholder:`B` |nbsp| |+----------------+| |nbsp| :diagtext:`no data`| +| || || ||:diagtext:`has` || | +| |+-------------+| |+----------------+| | +| ||:diagtext:`s`|| ||:diagtext:`have`|| | +| |+-------------+| |+----------------+| | ++-----------------------------------------------------------------------------------------------------------------------------+---------------+---------------------------------------------+------------------+---------------------------+ -Wprofile-instr-out-of-date @@ -8754,13 +9708,13 @@ This diagnostic is enabled by default. **Diagnostic text:** -+------------------------------------------------------------------------------------------------------------------------------+---------------+---------------------------------------------+-------------------+--------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`profile data may be out of date: of` |nbsp| :placeholder:`A` |nbsp| :diagtext:`function`|+-------------+|:diagtext:`,` |nbsp| :placeholder:`B` |nbsp| |+-----------------+| |nbsp| :diagtext:`mismatched data that will be ignored`| -| || || ||:diagtext:`:has` || | -| |+-------------+| |+-----------------+| | -| ||:diagtext:`s`|| ||:diagtext:`:have`|| | -| |+-------------+| |+-----------------+| | -+------------------------------------------------------------------------------------------------------------------------------+---------------+---------------------------------------------+-------------------+--------------------------------------------------------+ ++------------------------------------------------------------------------------------------------------------------------------+---------------+---------------------------------------------+------------------+--------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`profile data may be out of date: of` |nbsp| :placeholder:`A` |nbsp| :diagtext:`function`|+-------------+|:diagtext:`,` |nbsp| :placeholder:`B` |nbsp| |+----------------+| |nbsp| :diagtext:`mismatched data that will be ignored`| +| || || ||:diagtext:`has` || | +| |+-------------+| |+----------------+| | +| ||:diagtext:`s`|| ||:diagtext:`have`|| | +| |+-------------+| |+----------------+| | ++------------------------------------------------------------------------------------------------------------------------------+---------------+---------------------------------------------+------------------+--------------------------------------------------------+ -Wprofile-instr-unprofiled @@ -8861,6 +9815,15 @@ This diagnostic is enabled by default. +---------------------------------------------------------------------------------------------------------+ +-Wquoted-include-in-framework-header +------------------------------------ +**Diagnostic text:** + ++-------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`double-quoted include "`:placeholder:`A`:diagtext:`" in framework header, expected angle-bracketed instead`| ++-------------------------------------------------------------------------------------------------------------------------------------------------+ + + -Wrange-loop-analysis --------------------- **Diagnostic text:** @@ -9064,13 +10027,35 @@ This diagnostic is enabled by default. | |+------------------------+| | +--------------------------------------------------------+--------------------------+------------------------------------------+ -+---------------------------+--------------------------+-------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| |+------------------------+| |nbsp| :diagtext:`stack memory associated with local variable` |nbsp| :placeholder:`B` |nbsp| :diagtext:`returned`| -| ||:diagtext:`address of` || | -| |+------------------------+| | -| ||:diagtext:`reference to`|| | -| |+------------------------+| | -+---------------------------+--------------------------+-------------------------------------------------------------------------------------------------------------------+ ++---------------------------+--------------------------+--------------------------------------------------------+----------------------------+----------------------------------------------------+ +|:warning:`warning:` |nbsp| |+------------------------+| |nbsp| :diagtext:`stack memory associated with` |nbsp| |+--------------------------+| |nbsp| :placeholder:`B` |nbsp| :diagtext:`returned`| +| ||:diagtext:`address of` || ||:diagtext:`local variable`|| | +| |+------------------------+| |+--------------------------+| | +| ||:diagtext:`reference to`|| ||:diagtext:`parameter` || | +| |+------------------------+| |+--------------------------+| | ++---------------------------+--------------------------+--------------------------------------------------------+----------------------------+----------------------------------------------------+ + + +-Wreturn-std-move +----------------- +**Diagnostic text:** + ++-------------------------------------------------------------------------------------------------------------------------------------+----------------------+---------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`local variable` |nbsp| :placeholder:`A` |nbsp| :diagtext:`will be copied despite being` |nbsp| |+--------------------+| |nbsp| :diagtext:`by name`| +| ||:diagtext:`returned`|| | +| |+--------------------+| | +| ||:diagtext:`thrown` || | +| |+--------------------+| | ++-------------------------------------------------------------------------------------------------------------------------------------+----------------------+---------------------------+ + + +-Wreturn-std-move-in-c++11 +-------------------------- +**Diagnostic text:** + ++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`prior to the resolution of a defect report against ISO C++11, local variable` |nbsp| :placeholder:`A` |nbsp| :diagtext:`would have been copied despite being returned by name, due to its not matching the function return type`| ++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -Wreturn-type @@ -9149,17 +10134,6 @@ This diagnostic is enabled by default. +-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ --Wrtti-for-exceptions ---------------------- -This diagnostic is enabled by default. - -**Diagnostic text:** - -+--------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`implicitly enabling rtti for exception handling`| -+--------------------------------------------------------------------------------------+ - - -Rsanitize-address ------------------ **Diagnostic text:** @@ -9199,9 +10173,17 @@ This diagnostic is enabled by default. |:warning:`warning:` |nbsp| :diagtext:`section attribute is specified on redeclared variable`| +--------------------------------------------------------------------------------------------+ -+----------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`section does not match previous declaration`| -+----------------------------------------------------------------------------------+ ++------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`duplicate code segment specifiers`| ++------------------------------------------------------------------------+ + ++---------------------------+---------------------+-------------------------------------------------------+ +|:warning:`warning:` |nbsp| |+-------------------+| |nbsp| :diagtext:`does not match previous declaration`| +| ||:diagtext:`codeseg`|| | +| |+-------------------+| | +| ||:diagtext:`section`|| | +| |+-------------------+| | ++---------------------------+---------------------+-------------------------------------------------------+ -Wselector @@ -9228,7 +10210,7 @@ Also controls `-Wselector-type-mismatch`_. ------------- Some of the diagnostics controlled by this flag are enabled by default. -Also controls `-Wself-assign-field`_. +Also controls `-Wself-assign-field`_, `-Wself-assign-overloaded`_. **Diagnostic text:** @@ -9252,6 +10234,15 @@ This diagnostic is enabled by default. +--------------------------------------------------------+-------------------------------+-----------------------------+ +-Wself-assign-overloaded +------------------------ +**Diagnostic text:** + ++------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`explicitly assigning value of variable of type` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to itself`| ++------------------------------------------------------------------------------------------------------------------------------------------+ + + -Wself-move ----------- **Diagnostic text:** @@ -9357,9 +10348,15 @@ Controls `-Wshadow`_, `-Wshadow-field`_, `-Wshadow-field-in-constructor`_, `-Wsh -------------- **Diagnostic text:** -+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`non-static data member '`:placeholder:`A`:diagtext:`' of '`:placeholder:`B`:diagtext:`' shadows member inherited from type '`:placeholder:`C`:diagtext:`'`| -+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ++---------------------------+------------------------------------+--------------------------------+--------------------------------------------------+----------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| |+----------------------------------+| |nbsp| :placeholder:`A` |nbsp| |+------------------------------------------------+|:diagtext:`shadows member inherited from type` |nbsp| :placeholder:`C`| +| ||:diagtext:`parameter` || || || | +| |+----------------------------------+| |+------------------------------------------------+| | +| ||:diagtext:`non-static data member`|| ||+----------------------------------------------+|| | +| |+----------------------------------+| |||:diagtext:`of` |nbsp| :placeholder:`B` |nbsp| ||| | +| | | ||+----------------------------------------------+|| | +| | | |+------------------------------------------------+| | ++---------------------------+------------------------------------+--------------------------------+--------------------------------------------------+----------------------------------------------------------------------+ -Wshadow-field-in-constructor @@ -9518,6 +10515,10 @@ This diagnostic is enabled by default. |:warning:`warning:` |nbsp| :diagtext:`operand of ? changes signedness:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`to` |nbsp| :placeholder:`B`| +---------------------------------------------------------------------------------------------------------------------------------------------+ ++-----------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`the resulting value is always non-negative after implicit conversion`| ++-----------------------------------------------------------------------------------------------------------+ + -Wsign-promo ------------ @@ -9554,6 +10555,17 @@ This diagnostic is enabled by default. +--------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +-Wsizeof-pointer-div +-------------------- +This diagnostic is enabled by default. + +**Diagnostic text:** + ++-------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`'`:placeholder:`A`:diagtext:`' will return the size of the pointer, not the array itself`| ++-------------------------------------------------------------------------------------------------------------------------------+ + + -Wsizeof-pointer-memaccess -------------------------- This diagnostic is enabled by default. @@ -9728,6 +10740,17 @@ This diagnostic is enabled by default. +----------------------------------------------------------------------------------------------------------------------------------------------------+ +-Wstdlibcxx-not-found +--------------------- +This diagnostic is enabled by default. + +**Diagnostic text:** + ++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`include path for libstdc++ headers not found; pass '-stdlib=libc++' on the command line to use the libc++ standard library instead`| ++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + + -Wstrict-aliasing ----------------- This diagnostic flag exists for GCC compatibility, and has no effect in Clang. @@ -9896,6 +10919,24 @@ This diagnostic is enabled by default. +--------------------------------------------------------------------------------------------------------------------------------+ +-Wsuspicious-bzero +------------------ +This diagnostic is enabled by default. + +**Diagnostic text:** + ++----------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`'size' argument to bzero is '0'`| ++----------------------------------------------------------------------+ + + +-Wsuspicious-memaccess +---------------------- +This diagnostic is enabled by default. + +Controls `-Wdynamic-class-memaccess`_, `-Wmemset-transposed-args`_, `-Wnontrivial-memaccess`_, `-Wsizeof-pointer-memaccess`_, `-Wsuspicious-bzero`_. + + -Wswitch -------- This diagnostic is enabled by default. @@ -9906,25 +10947,25 @@ This diagnostic is enabled by default. |:warning:`warning:` |nbsp| :diagtext:`overflow converting case value to switch condition type (`:placeholder:`A` |nbsp| :diagtext:`to` |nbsp| :placeholder:`B`:diagtext:`)`| +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -+---------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| |+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| -| ||+-----------------------------------------------------------------------------------------------+ || -| |||:diagtext:`:enumeration value` |nbsp| :placeholder:`B` |nbsp| :diagtext:`not handled in switch`| || -| ||+-----------------------------------------------------------------------------------------------+ || -| |+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| -| ||+-----------------------------------------------------------------------------------------------------------------------------------------------+ || -| |||:diagtext:`:enumeration values` |nbsp| :placeholder:`B` |nbsp| :diagtext:`and` |nbsp| :placeholder:`C` |nbsp| :diagtext:`not handled in switch`| || -| ||+-----------------------------------------------------------------------------------------------------------------------------------------------+ || -| |+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| -| ||+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ || -| |||:diagtext:`:enumeration values` |nbsp| :placeholder:`B`:diagtext:`,` |nbsp| :placeholder:`C`:diagtext:`, and` |nbsp| :placeholder:`D` |nbsp| :diagtext:`not handled in switch`| || -| ||+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ || -| |+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| -| ||+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+|| -| |||:diagtext:`:`:placeholder:`A` |nbsp| :diagtext:`enumeration values not handled in switch:` |nbsp| :placeholder:`B`:diagtext:`,` |nbsp| :placeholder:`C`:diagtext:`,` |nbsp| :placeholder:`D`:diagtext:`...`||| -| ||+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+|| -| |+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| -+---------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ++---------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| |+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| +| ||+----------------------------------------------------------------------------------------------+ || +| |||:diagtext:`enumeration value` |nbsp| :placeholder:`B` |nbsp| :diagtext:`not handled in switch`| || +| ||+----------------------------------------------------------------------------------------------+ || +| |+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| +| ||+----------------------------------------------------------------------------------------------------------------------------------------------+ || +| |||:diagtext:`enumeration values` |nbsp| :placeholder:`B` |nbsp| :diagtext:`and` |nbsp| :placeholder:`C` |nbsp| :diagtext:`not handled in switch`| || +| ||+----------------------------------------------------------------------------------------------------------------------------------------------+ || +| |+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| +| ||+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ || +| |||:diagtext:`enumeration values` |nbsp| :placeholder:`B`:diagtext:`,` |nbsp| :placeholder:`C`:diagtext:`, and` |nbsp| :placeholder:`D` |nbsp| :diagtext:`not handled in switch`| || +| ||+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ || +| |+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| +| ||+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+|| +| |||:placeholder:`A` |nbsp| :diagtext:`enumeration values not handled in switch:` |nbsp| :placeholder:`B`:diagtext:`,` |nbsp| :placeholder:`C`:diagtext:`,` |nbsp| :placeholder:`D`:diagtext:`...`||| +| ||+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+|| +| |+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| ++---------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`case value not in enumerated type` |nbsp| :placeholder:`A`| @@ -9950,25 +10991,25 @@ This diagnostic flag exists for GCC compatibility, and has no effect in Clang. ------------- **Diagnostic text:** -+---------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| |+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| -| ||+----------------------------------------------------------------------------------------------------------+ || -| |||:diagtext:`:enumeration value` |nbsp| :placeholder:`B` |nbsp| :diagtext:`not explicitly handled in switch`| || -| ||+----------------------------------------------------------------------------------------------------------+ || -| |+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| -| ||+----------------------------------------------------------------------------------------------------------------------------------------------------------+ || -| |||:diagtext:`:enumeration values` |nbsp| :placeholder:`B` |nbsp| :diagtext:`and` |nbsp| :placeholder:`C` |nbsp| :diagtext:`not explicitly handled in switch`| || -| ||+----------------------------------------------------------------------------------------------------------------------------------------------------------+ || -| |+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| -| ||+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ || -| |||:diagtext:`:enumeration values` |nbsp| :placeholder:`B`:diagtext:`,` |nbsp| :placeholder:`C`:diagtext:`, and` |nbsp| :placeholder:`D` |nbsp| :diagtext:`not explicitly handled in switch`| || -| ||+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ || -| |+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| -| ||+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+|| -| |||:diagtext:`:`:placeholder:`A` |nbsp| :diagtext:`enumeration values not explicitly handled in switch:` |nbsp| :placeholder:`B`:diagtext:`,` |nbsp| :placeholder:`C`:diagtext:`,` |nbsp| :placeholder:`D`:diagtext:`...`||| -| ||+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+|| -| |+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| -+---------------------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ ++---------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| |+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| +| ||+---------------------------------------------------------------------------------------------------------+ || +| |||:diagtext:`enumeration value` |nbsp| :placeholder:`B` |nbsp| :diagtext:`not explicitly handled in switch`| || +| ||+---------------------------------------------------------------------------------------------------------+ || +| |+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| +| ||+---------------------------------------------------------------------------------------------------------------------------------------------------------+ || +| |||:diagtext:`enumeration values` |nbsp| :placeholder:`B` |nbsp| :diagtext:`and` |nbsp| :placeholder:`C` |nbsp| :diagtext:`not explicitly handled in switch`| || +| ||+---------------------------------------------------------------------------------------------------------------------------------------------------------+ || +| |+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| +| ||+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ || +| |||:diagtext:`enumeration values` |nbsp| :placeholder:`B`:diagtext:`,` |nbsp| :placeholder:`C`:diagtext:`, and` |nbsp| :placeholder:`D` |nbsp| :diagtext:`not explicitly handled in switch`| || +| ||+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ || +| |+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| +| ||+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+|| +| |||:placeholder:`A` |nbsp| :diagtext:`enumeration values not explicitly handled in switch:` |nbsp| :placeholder:`B`:diagtext:`,` |nbsp| :placeholder:`C`:diagtext:`,` |nbsp| :placeholder:`D`:diagtext:`...`||| +| ||+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+|| +| |+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| ++---------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -Wsync-fetch-and-nand-semantics-changed @@ -9990,18 +11031,16 @@ This diagnostic flag exists for GCC compatibility, and has no effect in Clang. ---------------------- Some of the diagnostics controlled by this flag are enabled by default. -Also controls `-Wtautological-constant-compare`_, `-Wtautological-overlap-compare`_, `-Wtautological-pointer-compare`_, `-Wtautological-undefined-compare`_. +Also controls `-Wtautological-constant-compare`_, `-Wtautological-objc-bool-compare`_, `-Wtautological-overlap-compare`_, `-Wtautological-pointer-compare`_, `-Wtautological-undefined-compare`_. **Diagnostic text:** +---------------------------+---------------------------+--------------------------------------------------+------------------------+ |:warning:`warning:` |nbsp| |+-------------------------+|:diagtext:`comparison always evaluates to` |nbsp| |+----------------------+| -| ||:diagtext:`self-` || ||:diagtext:`false` || +| ||:diagtext:`self-` || ||:diagtext:`a constant`|| | |+-------------------------+| |+----------------------+| -| ||:diagtext:`array` |nbsp| || ||:diagtext:`true` || +| ||:diagtext:`array` |nbsp| || ||:placeholder:`C` || | |+-------------------------+| |+----------------------+| -| | | ||:diagtext:`a constant`|| -| | | |+----------------------+| +---------------------------+---------------------------+--------------------------------------------------+------------------------+ +-------------------------------------------------------------------------------------+-------------------+ @@ -10017,17 +11056,26 @@ Also controls `-Wtautological-constant-compare`_, `-Wtautological-overlap-compar ------------------------------- This diagnostic is enabled by default. -Also controls `-Wtautological-constant-out-of-range-compare`_, `-Wtautological-unsigned-enum-zero-compare`_, `-Wtautological-unsigned-zero-compare`_. +Also controls `-Wtautological-constant-out-of-range-compare`_. **Diagnostic text:** -+---------------------------------------------------------+------------------+--------------------------------+------------------+-------------------------------------+-------------------+ -|:warning:`warning:` |nbsp| :diagtext:`comparison` |nbsp| |+----------------+| |nbsp| :placeholder:`C` |nbsp| |+----------------+| |nbsp| :diagtext:`is always` |nbsp| |+-----------------+| -| ||:placeholder:`D`|| ||:placeholder:`B`|| ||:diagtext:`false`|| -| |+----------------+| |+----------------+| |+-----------------+| -| ||:placeholder:`B`|| ||:placeholder:`D`|| ||:diagtext:`true` || -| |+----------------+| |+----------------+| |+-----------------+| -+---------------------------------------------------------+------------------+--------------------------------+------------------+-------------------------------------+-------------------+ ++----------------------------------------------------------------------+------------------------------------------------+--------------------------------+----------------------------------------------------------+-----------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`result of comparison of` |nbsp| |+----------------------------------------------+| |nbsp| :diagtext:`with` |nbsp| |+--------------------------------------------------------+| |nbsp| :diagtext:`is always` |nbsp| :placeholder:`E`| +| ||+--------------------------------------------+|| ||+------------------------------------------------------+|| | +| |||:diagtext:`constant` |nbsp| :placeholder:`A`||| |||:diagtext:`expression of type` |nbsp| :placeholder:`C`||| | +| ||+--------------------------------------------+|| ||+------------------------------------------------------+|| | +| |+----------------------------------------------+| |+--------------------------------------------------------+| | +| ||:diagtext:`true` || ||:diagtext:`boolean expression` || | +| |+----------------------------------------------+| |+--------------------------------------------------------+| | +| ||:diagtext:`false` || | | | +| |+----------------------------------------------+| | | | ++----------------------------------------------------------------------+------------------------------------------------+--------------------------------+----------------------------------------------------------+-----------------------------------------------------+ + + +-Wtautological-constant-in-range-compare +---------------------------------------- +Controls `-Wtautological-type-limit-compare`_, `-Wtautological-unsigned-enum-zero-compare`_, `-Wtautological-unsigned-zero-compare`_. -Wtautological-constant-out-of-range-compare @@ -10036,17 +11084,28 @@ This diagnostic is enabled by default. **Diagnostic text:** -+------------------------------------------------------------+------------------------------------------------+--------------------------------+----------------------------------------------------------+-------------------------------------+-------------------+ -|:warning:`warning:` |nbsp| :diagtext:`comparison of` |nbsp| |+----------------------------------------------+| |nbsp| :diagtext:`with` |nbsp| |+--------------------------------------------------------+| |nbsp| :diagtext:`is always` |nbsp| |+-----------------+| -| ||+--------------------------------------------+|| ||+------------------------------------------------------+|| ||:diagtext:`false`|| -| |||:diagtext:`constant` |nbsp| :placeholder:`A`||| |||:diagtext:`expression of type` |nbsp| :placeholder:`C`||| |+-----------------+| -| ||+--------------------------------------------+|| ||+------------------------------------------------------+|| ||:diagtext:`true` || -| |+----------------------------------------------+| |+--------------------------------------------------------+| |+-----------------+| -| ||:diagtext:`true` || ||:diagtext:`boolean expression` || | | -| |+----------------------------------------------+| |+--------------------------------------------------------+| | | -| ||:diagtext:`false` || | | | | -| |+----------------------------------------------+| | | | | -+------------------------------------------------------------+------------------------------------------------+--------------------------------+----------------------------------------------------------+-------------------------------------+-------------------+ ++----------------------------------------------------------------------+------------------------------------------------+--------------------------------+----------------------------------------------------------+-----------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`result of comparison of` |nbsp| |+----------------------------------------------+| |nbsp| :diagtext:`with` |nbsp| |+--------------------------------------------------------+| |nbsp| :diagtext:`is always` |nbsp| :placeholder:`E`| +| ||+--------------------------------------------+|| ||+------------------------------------------------------+|| | +| |||:diagtext:`constant` |nbsp| :placeholder:`A`||| |||:diagtext:`expression of type` |nbsp| :placeholder:`C`||| | +| ||+--------------------------------------------+|| ||+------------------------------------------------------+|| | +| |+----------------------------------------------+| |+--------------------------------------------------------+| | +| ||:diagtext:`true` || ||:diagtext:`boolean expression` || | +| |+----------------------------------------------+| |+--------------------------------------------------------+| | +| ||:diagtext:`false` || | | | +| |+----------------------------------------------+| | | | ++----------------------------------------------------------------------+------------------------------------------------+--------------------------------+----------------------------------------------------------+-----------------------------------------------------+ + + +-Wtautological-objc-bool-compare +-------------------------------- +This diagnostic is enabled by default. + +**Diagnostic text:** + ++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`result of comparison of constant` |nbsp| :placeholder:`A` |nbsp| :diagtext:`with expression of type BOOL is always` |nbsp| :placeholder:`B`:diagtext:`, as the only well defined values for BOOL are YES and NO`| ++------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -Wtautological-overlap-compare @@ -10087,6 +11146,19 @@ This diagnostic is enabled by default. +------------------------------------------------------------+------------------------+----------------------------------------------------------+-------------------------+-----------------------------------------------------+-------------------+ +-Wtautological-type-limit-compare +--------------------------------- +**Diagnostic text:** + ++-------------------------------------------------------------------+------------------+--------------------------------+------------------+-----------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`result of comparison` |nbsp| |+----------------+| |nbsp| :placeholder:`C` |nbsp| |+----------------+| |nbsp| :diagtext:`is always` |nbsp| :placeholder:`E`| +| ||:placeholder:`D`|| ||:placeholder:`B`|| | +| |+----------------+| |+----------------+| | +| ||:placeholder:`B`|| ||:placeholder:`D`|| | +| |+----------------+| |+----------------+| | ++-------------------------------------------------------------------+------------------+--------------------------------+------------------+-----------------------------------------------------+ + + -Wtautological-undefined-compare -------------------------------- This diagnostic is enabled by default. @@ -10112,32 +11184,28 @@ This diagnostic is enabled by default. -Wtautological-unsigned-enum-zero-compare ----------------------------------------- -This diagnostic is enabled by default. - **Diagnostic text:** -+------------------------------------------------------------+--------------------------------------+--------------------------------+--------------------------------------+-------------------------------------+-------------------+ -|:warning:`warning:` |nbsp| :diagtext:`comparison of` |nbsp| |+------------------------------------+| |nbsp| :placeholder:`C` |nbsp| |+------------------------------------+| |nbsp| :diagtext:`is always` |nbsp| |+-----------------+| -| ||:placeholder:`D` || ||:diagtext:`unsigned enum expression`|| ||:diagtext:`false`|| -| |+------------------------------------+| |+------------------------------------+| |+-----------------+| -| ||:diagtext:`unsigned enum expression`|| ||:placeholder:`D` || ||:diagtext:`true` || -| |+------------------------------------+| |+------------------------------------+| |+-----------------+| -+------------------------------------------------------------+--------------------------------------+--------------------------------+--------------------------------------+-------------------------------------+-------------------+ ++----------------------------------------------------------------------+--------------------------------------+--------------------------------+--------------------------------------+-----------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`result of comparison of` |nbsp| |+------------------------------------+| |nbsp| :placeholder:`C` |nbsp| |+------------------------------------+| |nbsp| :diagtext:`is always` |nbsp| :placeholder:`E`| +| ||:placeholder:`D` || ||:diagtext:`unsigned enum expression`|| | +| |+------------------------------------+| |+------------------------------------+| | +| ||:diagtext:`unsigned enum expression`|| ||:placeholder:`D` || | +| |+------------------------------------+| |+------------------------------------+| | ++----------------------------------------------------------------------+--------------------------------------+--------------------------------+--------------------------------------+-----------------------------------------------------+ -Wtautological-unsigned-zero-compare ------------------------------------ -This diagnostic is enabled by default. - **Diagnostic text:** -+------------------------------------------------------------+---------------------------------+--------------------------------+---------------------------------+-------------------------------------+-------------------+ -|:warning:`warning:` |nbsp| :diagtext:`comparison of` |nbsp| |+-------------------------------+| |nbsp| :placeholder:`C` |nbsp| |+-------------------------------+| |nbsp| :diagtext:`is always` |nbsp| |+-----------------+| -| ||:placeholder:`D` || ||:diagtext:`unsigned expression`|| ||:diagtext:`false`|| -| |+-------------------------------+| |+-------------------------------+| |+-----------------+| -| ||:diagtext:`unsigned expression`|| ||:placeholder:`D` || ||:diagtext:`true` || -| |+-------------------------------+| |+-------------------------------+| |+-----------------+| -+------------------------------------------------------------+---------------------------------+--------------------------------+---------------------------------+-------------------------------------+-------------------+ ++----------------------------------------------------------------------+---------------------------------+--------------------------------+---------------------------------+-----------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`result of comparison of` |nbsp| |+-------------------------------+| |nbsp| :placeholder:`C` |nbsp| |+-------------------------------+| |nbsp| :diagtext:`is always` |nbsp| :placeholder:`E`| +| ||:placeholder:`D` || ||:diagtext:`unsigned expression`|| | +| |+-------------------------------+| |+-------------------------------+| | +| ||:diagtext:`unsigned expression`|| ||:placeholder:`D` || | +| |+-------------------------------+| |+-------------------------------+| | ++----------------------------------------------------------------------+---------------------------------+--------------------------------+---------------------------------+-----------------------------------------------------+ -Wtentative-definition-incomplete-type @@ -10188,17 +11256,17 @@ Controls `-Wthread-safety-analysis`_, `-Wthread-safety-attributes`_, `-Wthread-s |:warning:`warning:` |nbsp| :diagtext:`cannot call function '`:placeholder:`B`:diagtext:`' while` |nbsp| :placeholder:`A` |nbsp| :diagtext:`'`:placeholder:`C`:diagtext:`' is held`| +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ -+---------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`calling function '`:placeholder:`B`:diagtext:`' requires holding` |nbsp| :placeholder:`A` |nbsp| |+--------------------------------------------------------+| -| ||+------------------------------------------+ || -| |||:diagtext:`'`:placeholder:`C`:diagtext:`'`| || -| ||+------------------------------------------+ || -| |+--------------------------------------------------------+| -| ||+------------------------------------------------------+|| -| |||:diagtext:`'`:placeholder:`C`:diagtext:`' exclusively`||| -| ||+------------------------------------------------------+|| -| |+--------------------------------------------------------+| -+---------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+ ++---------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`calling function` |nbsp| :placeholder:`B` |nbsp| :diagtext:`requires holding` |nbsp| :placeholder:`A` |nbsp| |+--------------------------------------------------------+| +| ||+------------------------------------------+ || +| |||:diagtext:`'`:placeholder:`C`:diagtext:`'`| || +| ||+------------------------------------------+ || +| |+--------------------------------------------------------+| +| ||+------------------------------------------------------+|| +| |||:diagtext:`'`:placeholder:`C`:diagtext:`' exclusively`||| +| ||+------------------------------------------------------+|| +| |+--------------------------------------------------------+| ++---------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+ +--------------------------------------------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`'`:placeholder:`B`:diagtext:`' is acquired exclusively and shared in the same scope`| @@ -10224,45 +11292,45 @@ Controls `-Wthread-safety-analysis`_, `-Wthread-safety-attributes`_, `-Wthread-s | |+---------------------+| |+---------------------+| | +----------------------------------------------------------------------------------------------------------------------------------------+-----------------------+--------------------------------------------+-----------------------+--------------------------+ -+---------------------------+---------------------+---------------------------------------------------------------------------------------------------+-----------------------------------+ -|:warning:`warning:` |nbsp| |+-------------------+| |nbsp| :diagtext:`the value pointed to by '`:placeholder:`A`:diagtext:`' requires holding` |nbsp| |+---------------------------------+| -| ||:diagtext:`reading`|| ||:diagtext:`any mutex` || -| |+-------------------+| |+---------------------------------+| -| ||:diagtext:`writing`|| ||:diagtext:`any mutex exclusively`|| -| |+-------------------+| |+---------------------------------+| -+---------------------------+---------------------+---------------------------------------------------------------------------------------------------+-----------------------------------+ - -+---------------------------+---------------------+---------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+ -|:warning:`warning:` |nbsp| |+-------------------+| |nbsp| :diagtext:`the value pointed to by '`:placeholder:`B`:diagtext:`' requires holding` |nbsp| :placeholder:`A` |nbsp| |+--------------------------------------------------------+| -| ||:diagtext:`reading`|| ||+------------------------------------------+ || -| |+-------------------+| |||:diagtext:`'`:placeholder:`C`:diagtext:`'`| || -| ||:diagtext:`writing`|| ||+------------------------------------------+ || -| |+-------------------+| |+--------------------------------------------------------+| -| | | ||+------------------------------------------------------+|| -| | | |||:diagtext:`'`:placeholder:`C`:diagtext:`' exclusively`||| -| | | ||+------------------------------------------------------+|| -| | | |+--------------------------------------------------------+| -+---------------------------+---------------------+---------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+ - -+---------------------------+---------------------+------------------------------------------------------------------------------------+-----------------------------------+ -|:warning:`warning:` |nbsp| |+-------------------+| |nbsp| :diagtext:`variable '`:placeholder:`A`:diagtext:`' requires holding` |nbsp| |+---------------------------------+| -| ||:diagtext:`reading`|| ||:diagtext:`any mutex` || -| |+-------------------+| |+---------------------------------+| -| ||:diagtext:`writing`|| ||:diagtext:`any mutex exclusively`|| -| |+-------------------+| |+---------------------------------+| -+---------------------------+---------------------+------------------------------------------------------------------------------------+-----------------------------------+ - -+---------------------------+---------------------+------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+ -|:warning:`warning:` |nbsp| |+-------------------+| |nbsp| :diagtext:`variable '`:placeholder:`B`:diagtext:`' requires holding` |nbsp| :placeholder:`A` |nbsp| |+--------------------------------------------------------+| -| ||:diagtext:`reading`|| ||+------------------------------------------+ || -| |+-------------------+| |||:diagtext:`'`:placeholder:`C`:diagtext:`'`| || -| ||:diagtext:`writing`|| ||+------------------------------------------+ || -| |+-------------------+| |+--------------------------------------------------------+| -| | | ||+------------------------------------------------------+|| -| | | |||:diagtext:`'`:placeholder:`C`:diagtext:`' exclusively`||| -| | | ||+------------------------------------------------------+|| -| | | |+--------------------------------------------------------+| -+---------------------------+---------------------+------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+ ++---------------------------+---------------------+---------------------------------------------------------------------------------------------------------------+-----------------------------------+ +|:warning:`warning:` |nbsp| |+-------------------+| |nbsp| :diagtext:`the value pointed to by` |nbsp| :placeholder:`A` |nbsp| :diagtext:`requires holding` |nbsp| |+---------------------------------+| +| ||:diagtext:`reading`|| ||:diagtext:`any mutex` || +| |+-------------------+| |+---------------------------------+| +| ||:diagtext:`writing`|| ||:diagtext:`any mutex exclusively`|| +| |+-------------------+| |+---------------------------------+| ++---------------------------+---------------------+---------------------------------------------------------------------------------------------------------------+-----------------------------------+ + ++---------------------------+---------------------+---------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+ +|:warning:`warning:` |nbsp| |+-------------------+| |nbsp| :diagtext:`the value pointed to by` |nbsp| :placeholder:`B` |nbsp| :diagtext:`requires holding` |nbsp| :placeholder:`A` |nbsp| |+--------------------------------------------------------+| +| ||:diagtext:`reading`|| ||+------------------------------------------+ || +| |+-------------------+| |||:diagtext:`'`:placeholder:`C`:diagtext:`'`| || +| ||:diagtext:`writing`|| ||+------------------------------------------+ || +| |+-------------------+| |+--------------------------------------------------------+| +| | | ||+------------------------------------------------------+|| +| | | |||:diagtext:`'`:placeholder:`C`:diagtext:`' exclusively`||| +| | | ||+------------------------------------------------------+|| +| | | |+--------------------------------------------------------+| ++---------------------------+---------------------+---------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+ + ++---------------------------+---------------------+------------------------------------------------------------------------------------------------+-----------------------------------+ +|:warning:`warning:` |nbsp| |+-------------------+| |nbsp| :diagtext:`variable` |nbsp| :placeholder:`A` |nbsp| :diagtext:`requires holding` |nbsp| |+---------------------------------+| +| ||:diagtext:`reading`|| ||:diagtext:`any mutex` || +| |+-------------------+| |+---------------------------------+| +| ||:diagtext:`writing`|| ||:diagtext:`any mutex exclusively`|| +| |+-------------------+| |+---------------------------------+| ++---------------------------+---------------------+------------------------------------------------------------------------------------------------+-----------------------------------+ + ++---------------------------+---------------------+------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+ +|:warning:`warning:` |nbsp| |+-------------------+| |nbsp| :diagtext:`variable` |nbsp| :placeholder:`B` |nbsp| :diagtext:`requires holding` |nbsp| :placeholder:`A` |nbsp| |+--------------------------------------------------------+| +| ||:diagtext:`reading`|| ||+------------------------------------------+ || +| |+-------------------+| |||:diagtext:`'`:placeholder:`C`:diagtext:`'`| || +| ||:diagtext:`writing`|| ||+------------------------------------------+ || +| |+-------------------+| |+--------------------------------------------------------+| +| | | ||+------------------------------------------------------+|| +| | | |||:diagtext:`'`:placeholder:`C`:diagtext:`' exclusively`||| +| | | ||+------------------------------------------------------+|| +| | | |+--------------------------------------------------------+| ++---------------------------+---------------------+------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+ -Wthread-safety-attributes @@ -10289,6 +11357,14 @@ Controls `-Wthread-safety-analysis`_, `-Wthread-safety-attributes`_, `-Wthread-s |:warning:`warning:` |nbsp| :diagtext:`ignoring` |nbsp| :placeholder:`A` |nbsp| :diagtext:`attribute because its argument is invalid`| +------------------------------------------------------------------------------------------------------------------------------------+ ++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`attribute without capability arguments refers to 'this', but` |nbsp| :placeholder:`B` |nbsp| :diagtext:`isn't annotated with 'capability' or 'scoped\_lockable' attribute`| ++----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + ++----------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :placeholder:`A` |nbsp| :diagtext:`attribute without capability arguments can only be applied to non-static methods of a class`| ++----------------------------------------------------------------------------------------------------------------------------------------------------------+ + -Wthread-safety-beta -------------------- @@ -10312,70 +11388,70 @@ Controls `-Wthread-safety-analysis`_, `-Wthread-safety-attributes`_, `-Wthread-s ----------------------- **Diagnostic text:** -+---------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`calling function '`:placeholder:`B`:diagtext:`' requires holding` |nbsp| :placeholder:`A` |nbsp| |+--------------------------------------------------------+| -| ||+------------------------------------------+ || -| |||:diagtext:`'`:placeholder:`C`:diagtext:`'`| || -| ||+------------------------------------------+ || -| |+--------------------------------------------------------+| -| ||+------------------------------------------------------+|| -| |||:diagtext:`'`:placeholder:`C`:diagtext:`' exclusively`||| -| ||+------------------------------------------------------+|| -| |+--------------------------------------------------------+| -+---------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+ - -+---------------------------+---------------------+---------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+ -|:warning:`warning:` |nbsp| |+-------------------+| |nbsp| :diagtext:`the value pointed to by '`:placeholder:`B`:diagtext:`' requires holding` |nbsp| :placeholder:`A` |nbsp| |+--------------------------------------------------------+| -| ||:diagtext:`reading`|| ||+------------------------------------------+ || -| |+-------------------+| |||:diagtext:`'`:placeholder:`C`:diagtext:`'`| || -| ||:diagtext:`writing`|| ||+------------------------------------------+ || -| |+-------------------+| |+--------------------------------------------------------+| -| | | ||+------------------------------------------------------+|| -| | | |||:diagtext:`'`:placeholder:`C`:diagtext:`' exclusively`||| -| | | ||+------------------------------------------------------+|| -| | | |+--------------------------------------------------------+| -+---------------------------+---------------------+---------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+ - -+---------------------------+---------------------+------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+ -|:warning:`warning:` |nbsp| |+-------------------+| |nbsp| :diagtext:`variable '`:placeholder:`B`:diagtext:`' requires holding` |nbsp| :placeholder:`A` |nbsp| |+--------------------------------------------------------+| -| ||:diagtext:`reading`|| ||+------------------------------------------+ || -| |+-------------------+| |||:diagtext:`'`:placeholder:`C`:diagtext:`'`| || -| ||:diagtext:`writing`|| ||+------------------------------------------+ || -| |+-------------------+| |+--------------------------------------------------------+| -| | | ||+------------------------------------------------------+|| -| | | |||:diagtext:`'`:placeholder:`C`:diagtext:`' exclusively`||| -| | | ||+------------------------------------------------------+|| -| | | |+--------------------------------------------------------+| -+---------------------------+---------------------+------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+ ++---------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`calling function` |nbsp| :placeholder:`B` |nbsp| :diagtext:`requires holding` |nbsp| :placeholder:`A` |nbsp| |+--------------------------------------------------------+| +| ||+------------------------------------------+ || +| |||:diagtext:`'`:placeholder:`C`:diagtext:`'`| || +| ||+------------------------------------------+ || +| |+--------------------------------------------------------+| +| ||+------------------------------------------------------+|| +| |||:diagtext:`'`:placeholder:`C`:diagtext:`' exclusively`||| +| ||+------------------------------------------------------+|| +| |+--------------------------------------------------------+| ++---------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+ + ++---------------------------+---------------------+---------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+ +|:warning:`warning:` |nbsp| |+-------------------+| |nbsp| :diagtext:`the value pointed to by` |nbsp| :placeholder:`B` |nbsp| :diagtext:`requires holding` |nbsp| :placeholder:`A` |nbsp| |+--------------------------------------------------------+| +| ||:diagtext:`reading`|| ||+------------------------------------------+ || +| |+-------------------+| |||:diagtext:`'`:placeholder:`C`:diagtext:`'`| || +| ||:diagtext:`writing`|| ||+------------------------------------------+ || +| |+-------------------+| |+--------------------------------------------------------+| +| | | ||+------------------------------------------------------+|| +| | | |||:diagtext:`'`:placeholder:`C`:diagtext:`' exclusively`||| +| | | ||+------------------------------------------------------+|| +| | | |+--------------------------------------------------------+| ++---------------------------+---------------------+---------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+ + ++---------------------------+---------------------+------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+ +|:warning:`warning:` |nbsp| |+-------------------+| |nbsp| :diagtext:`variable` |nbsp| :placeholder:`B` |nbsp| :diagtext:`requires holding` |nbsp| :placeholder:`A` |nbsp| |+--------------------------------------------------------+| +| ||:diagtext:`reading`|| ||+------------------------------------------+ || +| |+-------------------+| |||:diagtext:`'`:placeholder:`C`:diagtext:`'`| || +| ||:diagtext:`writing`|| ||+------------------------------------------+ || +| |+-------------------+| |+--------------------------------------------------------+| +| | | ||+------------------------------------------------------+|| +| | | |||:diagtext:`'`:placeholder:`C`:diagtext:`' exclusively`||| +| | | ||+------------------------------------------------------+|| +| | | |+--------------------------------------------------------+| ++---------------------------+---------------------+------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+ -Wthread-safety-reference ------------------------- **Diagnostic text:** -+----------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`passing variable '`:placeholder:`B`:diagtext:`' by reference requires holding` |nbsp| :placeholder:`A` |nbsp| |+--------------------------------------------------------+| -| ||+------------------------------------------+ || -| |||:diagtext:`'`:placeholder:`C`:diagtext:`'`| || -| ||+------------------------------------------+ || -| |+--------------------------------------------------------+| -| ||+------------------------------------------------------+|| -| |||:diagtext:`'`:placeholder:`C`:diagtext:`' exclusively`||| -| ||+------------------------------------------------------+|| -| |+--------------------------------------------------------+| -+----------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+ - -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`passing the value that '`:placeholder:`B`:diagtext:`' points to by reference requires holding` |nbsp| :placeholder:`A` |nbsp| |+--------------------------------------------------------+| -| ||+------------------------------------------+ || -| |||:diagtext:`'`:placeholder:`C`:diagtext:`'`| || -| ||+------------------------------------------+ || -| |+--------------------------------------------------------+| -| ||+------------------------------------------------------+|| -| |||:diagtext:`'`:placeholder:`C`:diagtext:`' exclusively`||| -| ||+------------------------------------------------------+|| -| |+--------------------------------------------------------+| -+--------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+ ++----------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`passing variable` |nbsp| :placeholder:`B` |nbsp| :diagtext:`by reference requires holding` |nbsp| :placeholder:`A` |nbsp| |+--------------------------------------------------------+| +| ||+------------------------------------------+ || +| |||:diagtext:`'`:placeholder:`C`:diagtext:`'`| || +| ||+------------------------------------------+ || +| |+--------------------------------------------------------+| +| ||+------------------------------------------------------+|| +| |||:diagtext:`'`:placeholder:`C`:diagtext:`' exclusively`||| +| ||+------------------------------------------------------+|| +| |+--------------------------------------------------------+| ++----------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+ + ++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`passing the value that` |nbsp| :placeholder:`B` |nbsp| :diagtext:`points to by reference requires holding` |nbsp| :placeholder:`A` |nbsp| |+--------------------------------------------------------+| +| ||+------------------------------------------+ || +| |||:diagtext:`'`:placeholder:`C`:diagtext:`'`| || +| ||+------------------------------------------+ || +| |+--------------------------------------------------------+| +| ||+------------------------------------------------------+|| +| |||:diagtext:`'`:placeholder:`C`:diagtext:`' exclusively`||| +| ||+------------------------------------------------------+|| +| |+--------------------------------------------------------+| ++--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------+ -Wthread-safety-verbose @@ -10412,7 +11488,13 @@ This diagnostic is enabled by default. -Wtype-limits ------------- -This diagnostic flag exists for GCC compatibility, and has no effect in Clang. +Synonym for `-Wtautological-constant-in-range-compare`_. + + +-Wtype-limits +------------- +Synonym for `-Wtautological-constant-in-range-compare`_. + -Wtype-safety ------------- @@ -10592,6 +11674,17 @@ This diagnostic is enabled by default. +---------------------------------------------------------------------------------------------------------------------------------------------------------+ +-Wunderaligned-exception-object +------------------------------- +This diagnostic is enabled by default. + +**Diagnostic text:** + ++---------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`underaligned exception object thrown`| ++---------------------------------------------------------------------------+ + + -Wunevaluated-expression ------------------------ This diagnostic is enabled by default. @@ -10656,6 +11749,17 @@ This diagnostic is enabled by default. +---------------------------------------------------------------------------------------------+ +-Wunicode-homoglyph +------------------- +This diagnostic is enabled by default. + +**Diagnostic text:** + ++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`treating Unicode character as identifier character rather than as '`:placeholder:`B`:diagtext:`' symbol`| ++-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + + -Wunicode-whitespace -------------------- This diagnostic is enabled by default. @@ -10667,6 +11771,17 @@ This diagnostic is enabled by default. +-------------------------------------------------------------------------------+ +-Wunicode-zero-width +-------------------- +This diagnostic is enabled by default. + +**Diagnostic text:** + ++----------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`identifier contains Unicode character that is invisible in some environments`| ++----------------------------------------------------------------------------------------------------------------------------------------------------+ + + -Wuninitialized --------------- Some of the diagnostics controlled by this flag are enabled by default. @@ -10687,9 +11802,13 @@ Also controls `-Wsometimes-uninitialized`_, `-Wstatic-self-init`_. |:warning:`warning:` |nbsp| :diagtext:`reference` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is not yet bound to a value when used here`| +--------------------------------------------------------------------------------------------------------------------------------------+ -+------------------------------------------------------------------------------------------------------------------------------------------------+ -|:warning:`warning:` |nbsp| :diagtext:`block pointer variable` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is uninitialized when captured by block`| -+------------------------------------------------------------------------------------------------------------------------------------------------+ ++-------------------------------------------------------------------------------------------------------------------+---------------------------+------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`block pointer variable` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is` |nbsp| |+-------------------------+| |nbsp| :diagtext:`when captured by block`| +| ||:diagtext:`uninitialized`|| | +| |+-------------------------+| | +| ||:diagtext:`null` || | +| |+-------------------------+| | ++-------------------------------------------------------------------------------------------------------------------+---------------------------+------------------------------------------+ +---------------------------------------------------------------------------------------------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`variable` |nbsp| :placeholder:`A` |nbsp| :diagtext:`is uninitialized when used within its own initialization`| @@ -10718,6 +11837,10 @@ This diagnostic is enabled by default. |:warning:`warning:` |nbsp| :diagtext:`unknown argument ignored in clang-cl: '`:placeholder:`A`:diagtext:`'`| +-----------------------------------------------------------------------------------------------------------+ ++--------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`unknown argument ignored in clang-cl '`:placeholder:`A`:diagtext:`'; did you mean '`:placeholder:`B`:diagtext:`'?`| ++--------------------------------------------------------------------------------------------------------------------------------------------------------+ + -Wunknown-attributes -------------------- @@ -10775,6 +11898,18 @@ Some of the diagnostics controlled by this flag are enabled by default. |:warning:`warning:` |nbsp| :diagtext:`unexpected token in pragma diagnostic`| +----------------------------------------------------------------------------+ ++----------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`#pragma execution\_character\_set expected '`:placeholder:`A`:diagtext:`'`| ++----------------------------------------------------------------------------------------------------------------+ + ++------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`#pragma execution\_character\_set invalid value '`:placeholder:`A`:diagtext:`', only 'UTF-8' is supported`| ++------------------------------------------------------------------------------------------------------------------------------------------------+ + ++-------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`#pragma execution\_character\_set expected 'push' or 'pop'`| ++-------------------------------------------------------------------------------------------------+ + +-------------------------------------------------------------+ |:warning:`warning:` |nbsp| :diagtext:`unknown pragma ignored`| +-------------------------------------------------------------+ @@ -11048,6 +12183,17 @@ This diagnostic is enabled by default. +-------------------------------------------------------------------------------------------------------------------------------------------------+ +-Wunsupported-target-opt +------------------------ +This diagnostic is enabled by default. + +**Diagnostic text:** + ++---------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`debug information option '`:placeholder:`A`:diagtext:`' is not supported for target '`:placeholder:`B`:diagtext:`'`| ++---------------------------------------------------------------------------------------------------------------------------------------------------------+ + + -Wunsupported-visibility ------------------------ This diagnostic is enabled by default. @@ -11138,19 +12284,17 @@ This diagnostic is enabled by default. **Diagnostic text:** -+---------------------------+-----------------------------------------+--------------------------------------------+ -|:warning:`warning:` |nbsp| |+---------------------------------------+| |nbsp| :diagtext:`comparison result unused`| -| ||+----------------+--------------------+|| | -| |||+--------------+|:diagtext:`equality`||| | -| |||| || ||| | -| |||+--------------+| ||| | -| ||||:diagtext:`in`|| ||| | -| |||+--------------+| ||| | -| ||+----------------+--------------------+|| | -| |+---------------------------------------+| | -| ||:diagtext:`relational` || | -| |+---------------------------------------+| | -+---------------------------+-----------------------------------------+--------------------------------------------+ ++---------------------------+------------------------+--------------------------------------------+ +|:warning:`warning:` |nbsp| |+----------------------+| |nbsp| :diagtext:`comparison result unused`| +| ||:diagtext:`equality` || | +| |+----------------------+| | +| ||:diagtext:`inequality`|| | +| |+----------------------+| | +| ||:diagtext:`relational`|| | +| |+----------------------+| | +| ||:diagtext:`three-way` || | +| |+----------------------+| | ++---------------------------+------------------------+--------------------------------------------+ -Wunused-const-variable From cb4f353383d674e5284c835e93760fd89c1e171d Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Thu, 25 Jul 2019 15:06:35 +0000 Subject: [PATCH 032/289] Merging r366811, r366880, r366900, r366991 and r366992: ------------------------------------------------------------------------ r366811 | sammccall | 2019-07-23 16:30:28 +0200 (Tue, 23 Jul 2019) | 9 lines [clangd] Log version, cwd, args, and transport on startup. NFC Reviewers: hokein Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D65146 ------------------------------------------------------------------------ ------------------------------------------------------------------------ r366880 | sammccall | 2019-07-24 11:33:27 +0200 (Wed, 24 Jul 2019) | 9 lines [clangd] Reformat use of cl::opt: use unqualified name and don't bin-pack attributes. NFC Reviewers: kadircet Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D65154 ------------------------------------------------------------------------ ------------------------------------------------------------------------ r366900 | sammccall | 2019-07-24 14:41:52 +0200 (Wed, 24 Jul 2019) | 16 lines [clangd] Add categories to help options, and only show clangd options. Summary: Restricting the categories prevents extra unwanted options from creeping into help (D60663), and removes a bunch of noise from --help-hidden. While here, remove `static` from the opts in favor of an anon namespace, to reduce the noise level. Reviewers: hokein Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D65200 ------------------------------------------------------------------------ ------------------------------------------------------------------------ r366991 | sammccall | 2019-07-25 09:54:48 +0200 (Thu, 25 Jul 2019) | 13 lines [clangd] Also accept flags from CLANGD_FLAGS variable. This simplifies various workflows, particularly in debugging/development. e.g. editors will tend to propagate flags, so you can run `env CLANGD_FLAGS=-input-mirror-file=/tmp/mirror vim foo.cc` rather than change the configuration in a persistent way. (This also gives us a generic lever when we don't know how to customize the flags in some particular LSP client). While here, add a test for this and other startup logging, and fix a couple of direct writes to errs() that should have been logs. Differential Revision: https://reviews.llvm.org/D65153 ------------------------------------------------------------------------ ------------------------------------------------------------------------ r366992 | sammccall | 2019-07-25 10:00:54 +0200 (Thu, 25 Jul 2019) | 9 lines [clangd] Provide help text to users who run `clangd` in a terminal. Reviewers: hokein Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D65201 ------------------------------------------------------------------------ llvm-svn: 367025 --- .../clangd/index/Serialization.cpp | 4 +- clang-tools-extra/clangd/test/log.test | 9 + clang-tools-extra/clangd/tool/ClangdMain.cpp | 543 +++++++++++------- 3 files changed, 341 insertions(+), 215 deletions(-) create mode 100644 clang-tools-extra/clangd/test/log.test diff --git a/clang-tools-extra/clangd/index/Serialization.cpp b/clang-tools-extra/clangd/index/Serialization.cpp index 188a5cc1862d..90520fdc2cea 100644 --- a/clang-tools-extra/clangd/index/Serialization.cpp +++ b/clang-tools-extra/clangd/index/Serialization.cpp @@ -690,7 +690,7 @@ std::unique_ptr loadIndex(llvm::StringRef SymbolFilename, trace::Span OverallTracer("LoadIndex"); auto Buffer = llvm::MemoryBuffer::getFile(SymbolFilename); if (!Buffer) { - llvm::errs() << "Can't open " << SymbolFilename << "\n"; + elog("Can't open {0}", SymbolFilename); return nullptr; } @@ -707,7 +707,7 @@ std::unique_ptr loadIndex(llvm::StringRef SymbolFilename, if (I->Relations) Relations = std::move(*I->Relations); } else { - llvm::errs() << "Bad Index: " << llvm::toString(I.takeError()) << "\n"; + elog("Bad Index: {0}", I.takeError()); return nullptr; } } diff --git a/clang-tools-extra/clangd/test/log.test b/clang-tools-extra/clangd/test/log.test new file mode 100644 index 000000000000..7f17f072fd89 --- /dev/null +++ b/clang-tools-extra/clangd/test/log.test @@ -0,0 +1,9 @@ +# RUN: not env CLANGD_FLAGS=-index-file=no-such-index clangd -lit-test &1 >/dev/null | FileCheck %s +CHECK: I[{{.*}}] clangd version {{.*}} +CHECK: Working directory: {{.*}} +CHECK: argv[0]: clangd +CHECK: argv[1]: -lit-test +CHECK: CLANGD_FLAGS: -index-file=no-such-index +CHECK: E[{{.*}}] Can't open no-such-index +CHECK: Starting LSP over stdin/stdout + diff --git a/clang-tools-extra/clangd/tool/ClangdMain.cpp b/clang-tools-extra/clangd/tool/ClangdMain.cpp index 5db3d5c23065..840f3d6453f2 100644 --- a/clang-tools-extra/clangd/tool/ClangdMain.cpp +++ b/clang-tools-extra/clangd/tool/ClangdMain.cpp @@ -22,6 +22,7 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" +#include "llvm/Support/Process.h" #include "llvm/Support/Program.h" #include "llvm/Support/Signals.h" #include "llvm/Support/TargetSelect.h" @@ -35,129 +36,165 @@ namespace clang { namespace clangd { +namespace { + +using llvm::cl::cat; +using llvm::cl::CommaSeparated; +using llvm::cl::desc; +using llvm::cl::Hidden; +using llvm::cl::init; +using llvm::cl::list; +using llvm::cl::opt; +using llvm::cl::OptionCategory; +using llvm::cl::values; + +// All flags must be placed in a category, or they will be shown neither in +// --help, nor --help-hidden! +OptionCategory CompileCommands("clangd compilation flags options"); +OptionCategory Features("clangd feature options"); +OptionCategory Misc("clangd miscellaneous options"); +OptionCategory Protocol("clangd protocol and logging options"); +const OptionCategory *ClangdCategories[] = {&Features, &Protocol, + &CompileCommands, &Misc}; -static llvm::cl::opt CompileCommandsDir( +enum CompileArgsFrom { LSPCompileArgs, FilesystemCompileArgs }; +opt CompileArgsFrom{ + "compile_args_from", + cat(CompileCommands), + desc("The source of compile commands"), + values(clEnumValN(LSPCompileArgs, "lsp", + "All compile commands come from LSP and " + "'compile_commands.json' files are ignored"), + clEnumValN(FilesystemCompileArgs, "filesystem", + "All compile commands come from the " + "'compile_commands.json' files")), + init(FilesystemCompileArgs), + Hidden, +}; + +opt CompileCommandsDir{ "compile-commands-dir", - llvm::cl::desc("Specify a path to look for compile_commands.json. If path " - "is invalid, clangd will look in the current directory and " - "parent paths of each source file")); + cat(CompileCommands), + desc("Specify a path to look for compile_commands.json. If path " + "is invalid, clangd will look in the current directory and " + "parent paths of each source file"), +}; -static llvm::cl::opt - WorkerThreadsCount("j", - llvm::cl::desc("Number of async workers used by clangd"), - llvm::cl::init(getDefaultAsyncThreadsCount())); +opt ResourceDir{ + "resource-dir", + cat(CompileCommands), + desc("Directory for system clang headers"), + init(""), + Hidden, +}; -// FIXME: also support "plain" style where signatures are always omitted. -enum CompletionStyleFlag { Detailed, Bundled }; -static llvm::cl::opt CompletionStyle( - "completion-style", - llvm::cl::desc("Granularity of code completion suggestions"), - llvm::cl::values( - clEnumValN(Detailed, "detailed", - "One completion item for each semantically distinct " - "completion, with full type information"), - clEnumValN(Bundled, "bundled", - "Similar completion items (e.g. function overloads) are " - "combined. Type information shown where possible"))); +list QueryDriverGlobs{ + "query-driver", + cat(CompileCommands), + desc( + "Comma separated list of globs for white-listing gcc-compatible " + "drivers that are safe to execute. Drivers matching any of these globs " + "will be used to extract system includes. e.g. " + "/usr/bin/**/clang-*,/path/to/repo/**/g++-*"), + CommaSeparated, +}; // FIXME: Flags are the wrong mechanism for user preferences. // We should probably read a dotfile or similar. -static llvm::cl::opt IncludeIneligibleResults( - "include-ineligible-results", - llvm::cl::desc( - "Include ineligible completion results (e.g. private members)"), - llvm::cl::init(CodeCompleteOptions().IncludeIneligibleResults), - llvm::cl::Hidden); - -static llvm::cl::opt InputStyle( - "input-style", llvm::cl::desc("Input JSON stream encoding"), - llvm::cl::values( - clEnumValN(JSONStreamStyle::Standard, "standard", "usual LSP protocol"), - clEnumValN(JSONStreamStyle::Delimited, "delimited", - "messages delimited by --- lines, with # comment support")), - llvm::cl::init(JSONStreamStyle::Standard), llvm::cl::Hidden); - -static llvm::cl::opt - PrettyPrint("pretty", llvm::cl::desc("Pretty-print JSON output"), - llvm::cl::init(false)); - -static llvm::cl::opt LogLevel( - "log", llvm::cl::desc("Verbosity of log messages written to stderr"), - llvm::cl::values(clEnumValN(Logger::Error, "error", "Error messages only"), - clEnumValN(Logger::Info, "info", - "High level execution tracing"), - clEnumValN(Logger::Debug, "verbose", "Low level details")), - llvm::cl::init(Logger::Info)); - -static llvm::cl::opt - Test("lit-test", - llvm::cl::desc("Abbreviation for -input-style=delimited -pretty -sync " - "-enable-test-scheme -log=verbose." - "Intended to simplify lit tests"), - llvm::cl::init(false), llvm::cl::Hidden); - -static llvm::cl::opt EnableTestScheme( - "enable-test-uri-scheme", - llvm::cl::desc("Enable 'test:' URI scheme. Only use in lit tests"), - llvm::cl::init(false), llvm::cl::Hidden); +opt AllScopesCompletion{ + "all-scopes-completion", + cat(Features), + desc("If set to true, code completion will include index symbols that are " + "not defined in the scopes (e.g. " + "namespaces) visible from the code completion point. Such completions " + "can insert scope qualifiers"), + init(true), +}; -enum PCHStorageFlag { Disk, Memory }; -static llvm::cl::opt PCHStorage( - "pch-storage", - llvm::cl::desc("Storing PCHs in memory increases memory usages, but may " - "improve performance"), - llvm::cl::values( - clEnumValN(PCHStorageFlag::Disk, "disk", "store PCHs on disk"), - clEnumValN(PCHStorageFlag::Memory, "memory", "store PCHs in memory")), - llvm::cl::init(PCHStorageFlag::Disk)); +opt ShowOrigins{ + "debug-origin", + cat(Features), + desc("Show origins of completion items"), + init(CodeCompleteOptions().ShowOrigins), + Hidden, +}; -static llvm::cl::opt LimitResults( - "limit-results", - llvm::cl::desc("Limit the number of results returned by clangd. " - "0 means no limit (default=100)"), - llvm::cl::init(100)); +opt EnableBackgroundIndex{ + "background-index", + cat(Features), + desc("Index project code in the background and persist index on disk. " + "Experimental"), + init(true), +}; -static llvm::cl::opt - Sync("sync", llvm::cl::desc("Parse on main thread. If set, -j is ignored"), - llvm::cl::init(false), llvm::cl::Hidden); +opt EnableClangTidy{ + "clang-tidy", + cat(Features), + desc("Enable clang-tidy diagnostics"), + init(true), +}; -static llvm::cl::opt - ResourceDir("resource-dir", - llvm::cl::desc("Directory for system clang headers"), - llvm::cl::init(""), llvm::cl::Hidden); +opt ClangTidyChecks{ + "clang-tidy-checks", + cat(Features), + desc("List of clang-tidy checks to run (this will override " + ".clang-tidy files). Only meaningful when -clang-tidy flag is on"), + init(""), +}; -static llvm::cl::opt InputMirrorFile( - "input-mirror-file", - llvm::cl::desc( - "Mirror all LSP input to the specified file. Useful for debugging"), - llvm::cl::init(""), llvm::cl::Hidden); +opt CodeCompletionParse{ + "completion-parse", + cat(Features), + desc("Whether the clang-parser is used for code-completion"), + values(clEnumValN(CodeCompleteOptions::AlwaysParse, "always", + "Block until the parser can be used"), + clEnumValN(CodeCompleteOptions::ParseIfReady, "auto", + "Use text-based completion if the parser " + "is not ready"), + clEnumValN(CodeCompleteOptions::NeverParse, "never", + "Always used text-based completion")), + init(CodeCompleteOptions().RunParser), + Hidden, +}; -static llvm::cl::opt EnableIndex( - "index", - llvm::cl::desc( - "Enable index-based features. By default, clangd maintains an index " - "built from symbols in opened files. Global index support needs to " - "enabled separatedly"), - llvm::cl::init(true), llvm::cl::Hidden); +// FIXME: also support "plain" style where signatures are always omitted. +enum CompletionStyleFlag { Detailed, Bundled }; +opt CompletionStyle{ + "completion-style", + cat(Features), + desc("Granularity of code completion suggestions"), + values(clEnumValN(Detailed, "detailed", + "One completion item for each semantically distinct " + "completion, with full type information"), + clEnumValN(Bundled, "bundled", + "Similar completion items (e.g. function overloads) are " + "combined. Type information shown where possible")), +}; -static llvm::cl::opt AllScopesCompletion( - "all-scopes-completion", - llvm::cl::desc( - "If set to true, code completion will include index symbols that are " - "not defined in the scopes (e.g. " - "namespaces) visible from the code completion point. Such completions " - "can insert scope qualifiers"), - llvm::cl::init(true)); - -static llvm::cl::opt ShowOrigins( - "debug-origin", llvm::cl::desc("Show origins of completion items"), - llvm::cl::init(CodeCompleteOptions().ShowOrigins), llvm::cl::Hidden); - -static llvm::cl::opt HeaderInsertion( +opt FallbackStyle{ + "fallback-style", + cat(Features), + desc("clang-format style to apply by default when " + "no .clang-format file is found"), + init(clang::format::DefaultFallbackStyle), +}; + +opt EnableFunctionArgSnippets{ + "function-arg-placeholders", + cat(Features), + desc("When disabled, completions contain only parentheses for " + "function calls. When enabled, completions also contain " + "placeholders for method parameters"), + init(CodeCompleteOptions().EnableFunctionArgSnippets), + Hidden, +}; + +opt HeaderInsertion{ "header-insertion", - llvm::cl::desc("Add #include directives when accepting code completions"), - llvm::cl::init(CodeCompleteOptions().InsertIncludes), - llvm::cl::values( + cat(Features), + desc("Add #include directives when accepting code completions"), + init(CodeCompleteOptions().InsertIncludes), + values( clEnumValN(CodeCompleteOptions::IWYU, "iwyu", "Include what you use. " "Insert the owning header for top-level symbols, unless the " @@ -165,118 +202,173 @@ static llvm::cl::opt HeaderInsertion( "forward-declared"), clEnumValN( CodeCompleteOptions::NeverInsert, "never", - "Never insert #include directives as part of code completion"))); + "Never insert #include directives as part of code completion")), +}; -static llvm::cl::opt HeaderInsertionDecorators( +opt HeaderInsertionDecorators{ "header-insertion-decorators", - llvm::cl::desc("Prepend a circular dot or space before the completion " - "label, depending on whether " - "an include line will be inserted or not"), - llvm::cl::init(true)); + cat(Features), + desc("Prepend a circular dot or space before the completion " + "label, depending on whether " + "an include line will be inserted or not"), + init(true), +}; + +opt HiddenFeatures{ + "hidden-features", + cat(Features), + desc("Enable hidden features mostly useful to clangd developers"), + init(false), + Hidden, +}; + +opt IncludeIneligibleResults{ + "include-ineligible-results", + cat(Features), + desc("Include ineligible completion results (e.g. private members)"), + init(CodeCompleteOptions().IncludeIneligibleResults), + Hidden, +}; + +opt EnableIndex{ + "index", + cat(Features), + desc("Enable index-based features. By default, clangd maintains an index " + "built from symbols in opened files. Global index support needs to " + "enabled separatedly"), + init(true), + Hidden, +}; + +opt LimitResults{ + "limit-results", + cat(Features), + desc("Limit the number of results returned by clangd. " + "0 means no limit (default=100)"), + init(100), +}; + +opt SuggestMissingIncludes{ + "suggest-missing-includes", + cat(Features), + desc("Attempts to fix diagnostic errors caused by missing " + "includes using index"), + init(true), +}; + +list TweakList{ + "tweaks", + cat(Features), + desc("Specify a list of Tweaks to enable (only for clangd developers)."), + Hidden, + CommaSeparated, +}; -static llvm::cl::opt IndexFile( +opt WorkerThreadsCount{ + "j", + cat(Misc), + desc("Number of async workers used by clangd"), + init(getDefaultAsyncThreadsCount()), +}; + +opt IndexFile{ "index-file", - llvm::cl::desc( + cat(Misc), + desc( "Index file to build the static index. The file must have been created " "by a compatible clangd-indexer\n" "WARNING: This option is experimental only, and will be removed " "eventually. Don't rely on it"), - llvm::cl::init(""), llvm::cl::Hidden); + init(""), + Hidden, +}; -static llvm::cl::opt EnableBackgroundIndex( - "background-index", - llvm::cl::desc( - "Index project code in the background and persist index on disk. " - "Experimental"), - llvm::cl::init(true)); +opt Test{ + "lit-test", + cat(Misc), + desc("Abbreviation for -input-style=delimited -pretty -sync " + "-enable-test-scheme -log=verbose. " + "Intended to simplify lit tests"), + init(false), + Hidden, +}; -enum CompileArgsFrom { LSPCompileArgs, FilesystemCompileArgs }; -static llvm::cl::opt CompileArgsFrom( - "compile_args_from", llvm::cl::desc("The source of compile commands"), - llvm::cl::values(clEnumValN(LSPCompileArgs, "lsp", - "All compile commands come from LSP and " - "'compile_commands.json' files are ignored"), - clEnumValN(FilesystemCompileArgs, "filesystem", - "All compile commands come from the " - "'compile_commands.json' files")), - llvm::cl::init(FilesystemCompileArgs), llvm::cl::Hidden); - -static llvm::cl::opt EnableFunctionArgSnippets( - "function-arg-placeholders", - llvm::cl::desc("When disabled, completions contain only parentheses for " - "function calls. When enabled, completions also contain " - "placeholders for method parameters"), - llvm::cl::init(CodeCompleteOptions().EnableFunctionArgSnippets), - llvm::cl::Hidden); +enum PCHStorageFlag { Disk, Memory }; +opt PCHStorage{ + "pch-storage", + cat(Misc), + desc("Storing PCHs in memory increases memory usages, but may " + "improve performance"), + values( + clEnumValN(PCHStorageFlag::Disk, "disk", "store PCHs on disk"), + clEnumValN(PCHStorageFlag::Memory, "memory", "store PCHs in memory")), + init(PCHStorageFlag::Disk), +}; -static llvm::cl::opt ClangTidyChecks( - "clang-tidy-checks", - llvm::cl::desc( - "List of clang-tidy checks to run (this will override " - ".clang-tidy files). Only meaningful when -clang-tidy flag is on"), - llvm::cl::init("")); - -static llvm::cl::opt - EnableClangTidy("clang-tidy", - llvm::cl::desc("Enable clang-tidy diagnostics"), - llvm::cl::init(true)); - -static llvm::cl::opt - FallbackStyle("fallback-style", - llvm::cl::desc("clang-format style to apply by default when " - "no .clang-format file is found"), - llvm::cl::init(clang::format::DefaultFallbackStyle)); - -static llvm::cl::opt SuggestMissingIncludes( - "suggest-missing-includes", - llvm::cl::desc("Attempts to fix diagnostic errors caused by missing " - "includes using index"), - llvm::cl::init(true)); +opt Sync{ + "sync", + cat(Misc), + desc("Parse on main thread. If set, -j is ignored"), + init(false), + Hidden, +}; -static llvm::cl::opt ForceOffsetEncoding( - "offset-encoding", - llvm::cl::desc("Force the offsetEncoding used for character positions. " - "This bypasses negotiation via client capabilities"), - llvm::cl::values(clEnumValN(OffsetEncoding::UTF8, "utf-8", - "Offsets are in UTF-8 bytes"), - clEnumValN(OffsetEncoding::UTF16, "utf-16", - "Offsets are in UTF-16 code units")), - llvm::cl::init(OffsetEncoding::UnsupportedEncoding)); - -static llvm::cl::opt - CodeCompletionParse( - "completion-parse", - llvm::cl::desc("Whether the clang-parser is used for code-completion"), - llvm::cl::values(clEnumValN(CodeCompleteOptions::AlwaysParse, "always", - "Block until the parser can be used"), - clEnumValN(CodeCompleteOptions::ParseIfReady, "auto", - "Use text-based completion if the parser " - "is not ready"), - clEnumValN(CodeCompleteOptions::NeverParse, "never", - "Always used text-based completion")), - llvm::cl::init(CodeCompleteOptions().RunParser), llvm::cl::Hidden); - -static llvm::cl::opt HiddenFeatures( - "hidden-features", - llvm::cl::desc("Enable hidden features mostly useful to clangd developers"), - llvm::cl::init(false), llvm::cl::Hidden); +opt InputStyle{ + "input-style", + cat(Protocol), + desc("Input JSON stream encoding"), + values( + clEnumValN(JSONStreamStyle::Standard, "standard", "usual LSP protocol"), + clEnumValN(JSONStreamStyle::Delimited, "delimited", + "messages delimited by --- lines, with # comment support")), + init(JSONStreamStyle::Standard), + Hidden, +}; -static llvm::cl::list QueryDriverGlobs( - "query-driver", - llvm::cl::desc( - "Comma separated list of globs for white-listing gcc-compatible " - "drivers that are safe to execute. Drivers matching any of these globs " - "will be used to extract system includes. e.g. " - "/usr/bin/**/clang-*,/path/to/repo/**/g++-*"), - llvm::cl::CommaSeparated); +opt EnableTestScheme{ + "enable-test-uri-scheme", + cat(Protocol), + desc("Enable 'test:' URI scheme. Only use in lit tests"), + init(false), + Hidden, +}; -static llvm::cl::list TweakList( - "tweaks", - llvm::cl::desc( - "Specify a list of Tweaks to enable (only for clangd developers)."), - llvm::cl::Hidden, llvm::cl::CommaSeparated); +opt InputMirrorFile{ + "input-mirror-file", + cat(Protocol), + desc("Mirror all LSP input to the specified file. Useful for debugging"), + init(""), + Hidden, +}; -namespace { +opt LogLevel{ + "log", + cat(Protocol), + desc("Verbosity of log messages written to stderr"), + values(clEnumValN(Logger::Error, "error", "Error messages only"), + clEnumValN(Logger::Info, "info", "High level execution tracing"), + clEnumValN(Logger::Debug, "verbose", "Low level details")), + init(Logger::Info), +}; + +opt ForceOffsetEncoding{ + "offset-encoding", + cat(Protocol), + desc("Force the offsetEncoding used for character positions. " + "This bypasses negotiation via client capabilities"), + values( + clEnumValN(OffsetEncoding::UTF8, "utf-8", "Offsets are in UTF-8 bytes"), + clEnumValN(OffsetEncoding::UTF16, "utf-16", + "Offsets are in UTF-16 code units")), + init(OffsetEncoding::UnsupportedEncoding), +}; + +opt PrettyPrint{ + "pretty", + cat(Protocol), + desc("Pretty-print JSON output"), + init(false), +}; /// \brief Supports a test URI scheme with relaxed constraints for lit tests. /// The path in a test URI will be combined with a platform-specific fake @@ -342,14 +434,19 @@ int main(int argc, char *argv[]) { llvm::cl::SetVersionPrinter([](llvm::raw_ostream &OS) { OS << clang::getClangToolFullVersion("clangd") << "\n"; }); - llvm::cl::ParseCommandLineOptions( - argc, argv, - "clangd is a language server that provides IDE-like features to editors. " - "\n\nIt should be used via an editor plugin rather than invoked " - "directly. " - "For more information, see:" - "\n\thttps://clang.llvm.org/extra/clangd.html" - "\n\thttps://microsoft.github.io/language-server-protocol/"); + const char *FlagsEnvVar = "CLANGD_FLAGS"; + const char *Overview = + R"(clangd is a language server that provides IDE-like features to editors. + +It should be used via an editor plugin rather than invoked directly. For more information, see: + https://clang.llvm.org/extra/clangd/ + https://microsoft.github.io/language-server-protocol/ + +clangd accepts flags on the commandline, and in the CLANGD_FLAGS environment variable. +)"; + llvm::cl::HideUnrelatedOptions(ClangdCategories); + llvm::cl::ParseCommandLineOptions(argc, argv, Overview, + /*Errs=*/nullptr, FlagsEnvVar); if (Test) { Sync = true; InputStyle = JSONStreamStyle::Delimited; @@ -414,11 +511,29 @@ int main(int argc, char *argv[]) { if (Tracer) TracingSession.emplace(*Tracer); + // If a user ran `clangd` in a terminal without redirecting anything, + // it's somewhat likely they're confused about how to use clangd. + // Show them the help overview, which explains. + if (llvm::outs().is_displayed() && llvm::errs().is_displayed()) + llvm::errs() << Overview << "\n"; // Use buffered stream to stderr (we still flush each log message). Unbuffered // stream can cause significant (non-deterministic) latency for the logger. llvm::errs().SetBuffered(); StreamLogger Logger(llvm::errs(), LogLevel); LoggingSession LoggingSession(Logger); + // Write some initial logs before we start doing any real work. + log("{0}", clang::getClangToolFullVersion("clangd")); + { + SmallString<128> CWD; + if (auto Err = llvm::sys::fs::current_path(CWD)) + log("Working directory unknown: {0}", Err.message()); + else + log("Working directory: {0}", CWD); + } + for (int I = 0; I < argc; ++I) + log("argv[{0}]: {1}", I, argv[I]); + if (auto EnvFlags = llvm::sys::Process::GetEnv(FlagsEnvVar)) + log("{0}: {1}", FlagsEnvVar, *EnvFlags); // If --compile-commands-dir arg was invoked, check value and override default // path. @@ -497,12 +612,14 @@ int main(int argc, char *argv[]) { std::unique_ptr TransportLayer; if (getenv("CLANGD_AS_XPC_SERVICE")) { #if CLANGD_BUILD_XPC + log("Starting LSP over XPC service"); TransportLayer = newXPCTransport(); #else llvm::errs() << "This clangd binary wasn't built with XPC support.\n"; return (int)ErrorResultCode::CantRunAsXPCService; #endif } else { + log("Starting LSP over stdin/stdout"); TransportLayer = newJSONTransport( stdin, llvm::outs(), InputMirrorStream ? InputMirrorStream.getPointer() : nullptr, From 8f23294be7893406507ea04c59eb072c98291bb6 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Fri, 26 Jul 2019 16:36:50 +0000 Subject: [PATCH 033/289] Merging r366985: ------------------------------------------------------------------------ r366985 | labath | 2019-07-25 08:38:33 +0200 (Thu, 25 Jul 2019) | 16 lines LLGS: fix tracking execve on linux Summary: Due to a logic error, lldb-server ended up asserting/crashing every time the debugged process attempted an execve(). This fixes the error, and extends TestExec to work on other platforms too. The "extension" consists of avoiding non-standard posix_spawn extensions and using the classic execve() call, which should be available on any platform that actually supports re-execing. I change the test decorator from @skipUnlessDarwin to @skipIfWindows. Reviewers: clayborg, jasonmolenda Subscribers: lldb-commits Differential Revision: https://reviews.llvm.org/D65207 ------------------------------------------------------------------------ llvm-svn: 367128 --- .../test/functionalities/exec/TestExec.py | 4 +- .../test/functionalities/exec/main.cpp | 82 +++---------------- .../Process/Linux/NativeProcessLinux.cpp | 9 +- 3 files changed, 16 insertions(+), 79 deletions(-) diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/exec/TestExec.py b/lldb/packages/Python/lldbsuite/test/functionalities/exec/TestExec.py index 48bd515c963d..2d6baa1a2f2d 100644 --- a/lldb/packages/Python/lldbsuite/test/functionalities/exec/TestExec.py +++ b/lldb/packages/Python/lldbsuite/test/functionalities/exec/TestExec.py @@ -18,17 +18,17 @@ class ExecTestCase(TestBase): mydir = TestBase.compute_mydir(__file__) - @skipUnlessDarwin @expectedFailureAll(archs=['i386'], bugnumber="rdar://28656532") @expectedFailureAll(oslist=["ios", "tvos", "watchos", "bridgeos"], bugnumber="rdar://problem/34559552") # this exec test has problems on ios systems @skipIfSanitized # rdar://problem/43756823 + @skipIfWindows def test_hitting_exec (self): self.do_test(False) - @skipUnlessDarwin @expectedFailureAll(archs=['i386'], bugnumber="rdar://28656532") @expectedFailureAll(oslist=["ios", "tvos", "watchos", "bridgeos"], bugnumber="rdar://problem/34559552") # this exec test has problems on ios systems @skipIfSanitized # rdar://problem/43756823 + @skipIfWindows def test_skipping_exec (self): self.do_test(True) diff --git a/lldb/packages/Python/lldbsuite/test/functionalities/exec/main.cpp b/lldb/packages/Python/lldbsuite/test/functionalities/exec/main.cpp index 92206b2d88ef..4475bbe4452f 100644 --- a/lldb/packages/Python/lldbsuite/test/functionalities/exec/main.cpp +++ b/lldb/packages/Python/lldbsuite/test/functionalities/exec/main.cpp @@ -1,76 +1,16 @@ -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include #include #include +#include -static void -exit_with_errno (int err, const char *prefix) -{ - if (err) - { - fprintf (stderr, - "%s%s", - prefix ? prefix : "", - strerror(err)); - exit (err); - } -} - -static pid_t -spawn_process (const char *progname, - const char **argv, - const char **envp, - int &err) -{ - pid_t pid = 0; - - const posix_spawn_file_actions_t *file_actions = NULL; - posix_spawnattr_t attr; - err = posix_spawnattr_init (&attr); - if (err) - return pid; - - short flags = POSIX_SPAWN_SETEXEC | POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK; - err = posix_spawnattr_setflags (&attr, flags); - if (err == 0) - { - // Use the default signal masks - sigset_t no_signals; - sigset_t all_signals; - sigemptyset (&no_signals); - sigfillset (&all_signals); - posix_spawnattr_setsigmask(&attr, &no_signals); - posix_spawnattr_setsigdefault(&attr, &all_signals); - - err = posix_spawn (&pid, - progname, - file_actions, - &attr, - (char * const *)argv, - (char * const *)envp); - - posix_spawnattr_destroy(&attr); - } - return pid; -} - -int -main (int argc, char const **argv) -{ - char *buf = (char*) malloc (strlen (argv[0]) + 12); - strlcpy (buf, argv[0], strlen (argv[0]) + 1); - std::string directory_name (::dirname (buf)); +int main(int argc, char const **argv) { + char *buf = strdup(argv[0]); // Set breakpoint 1 here + std::string directory_name(::dirname(buf)); - std::string other_program = directory_name + "/secondprog"; - int err = 0; // Set breakpoint 1 here - spawn_process (other_program.c_str(), argv, NULL, err); - if (err) - exit_with_errno (err, "posix_spawn x86_64 error"); - return 0; + std::string other_program = directory_name + "/secondprog"; + execve(other_program.c_str(), const_cast(argv), nullptr); + perror("execve"); + abort(); } diff --git a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp index 7637237aa16b..c1da6f3d2575 100644 --- a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp +++ b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp @@ -599,12 +599,9 @@ void NativeProcessLinux::MonitorSIGTRAP(const siginfo_t &info, // which only copies the main thread. LLDB_LOG(log, "exec received, stop tracking all but main thread"); - for (auto i = m_threads.begin(); i != m_threads.end();) { - if ((*i)->GetID() == GetID()) - i = m_threads.erase(i); - else - ++i; - } + llvm::erase_if(m_threads, [&](std::unique_ptr &t) { + return t->GetID() != GetID(); + }); assert(m_threads.size() == 1); auto *main_thread = static_cast(m_threads[0].get()); From d14ea71e84137a5da4702dbc3f04f74f9d92b46e Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Fri, 26 Jul 2019 16:45:43 +0000 Subject: [PATCH 034/289] Merging r367039 and r367103: ------------------------------------------------------------------------ r367039 | erichkeane | 2019-07-25 19:14:45 +0200 (Thu, 25 Jul 2019) | 6 lines Remove CallingConvMethodType This seems to be an old vestage of a previous implementation of getting the default calling convention, and everything is now using CXXABI/ASTContext's getDefaultCallingConvention. Remove it, since it isn't doing anything. ------------------------------------------------------------------------ ------------------------------------------------------------------------ r367103 | erichkeane | 2019-07-26 14:36:12 +0200 (Fri, 26 Jul 2019) | 6 lines Make the CXXABIs respect the target's default calling convention. SPIR targets need to have all functions be SPIR calling convention, however the CXXABIs were just returning CC_C in all non-'this-CC' cases. https://reviews.llvm.org/D65294 ------------------------------------------------------------------------ llvm-svn: 367129 --- clang/include/clang/Basic/TargetInfo.h | 8 +--- clang/lib/AST/ASTContext.cpp | 2 +- clang/lib/AST/ItaniumCXXABI.cpp | 2 +- clang/lib/AST/MicrosoftCXXABI.cpp | 2 +- clang/lib/Basic/Targets/SPIR.h | 2 +- clang/lib/Basic/Targets/X86.h | 6 +-- .../addrspace-derived-base.cl | 4 +- .../CodeGenOpenCLCXX/addrspace-of-this.cl | 40 +++++++++---------- .../CodeGenOpenCLCXX/addrspace-operators.cl | 8 ++-- .../CodeGenOpenCLCXX/addrspace-with-class.cl | 30 +++++++------- .../method-overload-address-space.cl | 14 +++---- .../template-address-spaces.cl | 6 +-- 12 files changed, 59 insertions(+), 65 deletions(-) diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h index 7a8384f5fbc0..c6c966dfbe2c 100644 --- a/clang/include/clang/Basic/TargetInfo.h +++ b/clang/include/clang/Basic/TargetInfo.h @@ -1249,15 +1249,9 @@ class TargetInfo : public virtual TransferrableTargetInfo, bool isBigEndian() const { return BigEndian; } bool isLittleEndian() const { return !BigEndian; } - enum CallingConvMethodType { - CCMT_Unknown, - CCMT_Member, - CCMT_NonMember - }; - /// Gets the default calling convention for the given target and /// declaration context. - virtual CallingConv getDefaultCallingConv(CallingConvMethodType MT) const { + virtual CallingConv getDefaultCallingConv() const { // Not all targets will specify an explicit calling convention that we can // express. This will always do the right thing, even though it's not // an explicit calling convention. diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 0d69eb90abaf..468c7f47657d 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -10035,7 +10035,7 @@ CallingConv ASTContext::getDefaultCallingConvention(bool IsVariadic, break; } } - return Target->getDefaultCallingConv(TargetInfo::CCMT_Unknown); + return Target->getDefaultCallingConv(); } bool ASTContext::isNearlyEmpty(const CXXRecordDecl *RD) const { diff --git a/clang/lib/AST/ItaniumCXXABI.cpp b/clang/lib/AST/ItaniumCXXABI.cpp index 727a905d08a1..77fb5a1d33b3 100644 --- a/clang/lib/AST/ItaniumCXXABI.cpp +++ b/clang/lib/AST/ItaniumCXXABI.cpp @@ -177,7 +177,7 @@ class ItaniumCXXABI : public CXXABI { if (!isVariadic && T.isWindowsGNUEnvironment() && T.getArch() == llvm::Triple::x86) return CC_X86ThisCall; - return CC_C; + return Context.getTargetInfo().getDefaultCallingConv(); } // We cheat and just check that the class has a vtable pointer, and that it's diff --git a/clang/lib/AST/MicrosoftCXXABI.cpp b/clang/lib/AST/MicrosoftCXXABI.cpp index 4dc4156df9ca..444e55f777fa 100644 --- a/clang/lib/AST/MicrosoftCXXABI.cpp +++ b/clang/lib/AST/MicrosoftCXXABI.cpp @@ -82,7 +82,7 @@ class MicrosoftCXXABI : public CXXABI { if (!isVariadic && Context.getTargetInfo().getTriple().getArch() == llvm::Triple::x86) return CC_X86ThisCall; - return CC_C; + return Context.getTargetInfo().getDefaultCallingConv(); } bool isNearlyEmpty(const CXXRecordDecl *RD) const override { diff --git a/clang/lib/Basic/Targets/SPIR.h b/clang/lib/Basic/Targets/SPIR.h index 6023c868dbdc..802ccf8b671e 100644 --- a/clang/lib/Basic/Targets/SPIR.h +++ b/clang/lib/Basic/Targets/SPIR.h @@ -88,7 +88,7 @@ class LLVM_LIBRARY_VISIBILITY SPIRTargetInfo : public TargetInfo { : CCCR_Warning; } - CallingConv getDefaultCallingConv(CallingConvMethodType MT) const override { + CallingConv getDefaultCallingConv() const override { return CC_SpirFunction; } diff --git a/clang/lib/Basic/Targets/X86.h b/clang/lib/Basic/Targets/X86.h index 588b6d3da1d6..dd1e7db6c81e 100644 --- a/clang/lib/Basic/Targets/X86.h +++ b/clang/lib/Basic/Targets/X86.h @@ -320,8 +320,8 @@ class LLVM_LIBRARY_VISIBILITY X86TargetInfo : public TargetInfo { } } - CallingConv getDefaultCallingConv(CallingConvMethodType MT) const override { - return MT == CCMT_Member ? CC_X86ThisCall : CC_C; + CallingConv getDefaultCallingConv() const override { + return CC_C; } bool hasSjLjLowering() const override { return true; } @@ -659,7 +659,7 @@ class LLVM_LIBRARY_VISIBILITY X86_64TargetInfo : public X86TargetInfo { } } - CallingConv getDefaultCallingConv(CallingConvMethodType MT) const override { + CallingConv getDefaultCallingConv() const override { return CC_C; } diff --git a/clang/test/CodeGenOpenCLCXX/addrspace-derived-base.cl b/clang/test/CodeGenOpenCLCXX/addrspace-derived-base.cl index 59e29ee41719..d5ffcbce99dc 100644 --- a/clang/test/CodeGenOpenCLCXX/addrspace-derived-base.cl +++ b/clang/test/CodeGenOpenCLCXX/addrspace-derived-base.cl @@ -12,11 +12,11 @@ public: void foo() { D d; //CHECK: addrspacecast %class.D* %d to %class.D addrspace(4)* - //CHECK: call i32 @_ZNU3AS41D5getmbEv(%class.D addrspace(4)* + //CHECK: call spir_func i32 @_ZNU3AS41D5getmbEv(%class.D addrspace(4)* d.getmb(); } //Derived and Base are in the same address space. -//CHECK: define linkonce_odr i32 @_ZNU3AS41D5getmbEv(%class.D addrspace(4)* %this) +//CHECK: define linkonce_odr spir_func i32 @_ZNU3AS41D5getmbEv(%class.D addrspace(4)* %this) //CHECK: bitcast %class.D addrspace(4)* %this1 to %struct.B addrspace(4)* diff --git a/clang/test/CodeGenOpenCLCXX/addrspace-of-this.cl b/clang/test/CodeGenOpenCLCXX/addrspace-of-this.cl index aa1a91e4dc76..6780c5366c71 100644 --- a/clang/test/CodeGenOpenCLCXX/addrspace-of-this.cl +++ b/clang/test/CodeGenOpenCLCXX/addrspace-of-this.cl @@ -81,32 +81,32 @@ __kernel void test__global() { // COMMON: @_ZNU3AS41C7outsideEv(%class.C addrspace(4)* %this) // EXPL-LABEL: @__cxx_global_var_init() -// EXPL: call void @_ZNU3AS41CC1Ev(%class.C addrspace(4)* addrspacecast (%class.C addrspace(1)* @c to %class.C addrspace(4)*)) +// EXPL: call spir_func void @_ZNU3AS41CC1Ev(%class.C addrspace(4)* addrspacecast (%class.C addrspace(1)* @c to %class.C addrspace(4)*)) // COMMON-LABEL: @test__global() // Test the address space of 'this' when invoking a method. -// COMMON: call i32 @_ZNU3AS41C3getEv(%class.C addrspace(4)* addrspacecast (%class.C addrspace(1)* @c to %class.C addrspace(4)*)) +// COMMON: call spir_func i32 @_ZNU3AS41C3getEv(%class.C addrspace(4)* addrspacecast (%class.C addrspace(1)* @c to %class.C addrspace(4)*)) // Test the address space of 'this' when invoking a method using a pointer to the object. -// COMMON: call i32 @_ZNU3AS41C3getEv(%class.C addrspace(4)* addrspacecast (%class.C addrspace(1)* @c to %class.C addrspace(4)*)) +// COMMON: call spir_func i32 @_ZNU3AS41C3getEv(%class.C addrspace(4)* addrspacecast (%class.C addrspace(1)* @c to %class.C addrspace(4)*)) // Test the address space of 'this' when invoking a method that is declared in the file contex. -// COMMON: call i32 @_ZNU3AS41C7outsideEv(%class.C addrspace(4)* addrspacecast (%class.C addrspace(1)* @c to %class.C addrspace(4)*)) +// COMMON: call spir_func i32 @_ZNU3AS41C7outsideEv(%class.C addrspace(4)* addrspacecast (%class.C addrspace(1)* @c to %class.C addrspace(4)*)) // Test the address space of 'this' when invoking copy-constructor. // COMMON: [[C1GEN:%[.a-z0-9]+]] = addrspacecast %class.C* %c1 to %class.C addrspace(4)* // IMPL: [[C1VOID:%[0-9]+]] = bitcast %class.C* %c1 to i8* // IMPL: call void @llvm.memcpy.p0i8.p4i8.i32(i8* {{.*}}[[C1VOID]], i8 addrspace(4)* {{.*}}addrspacecast (i8 addrspace(1)* bitcast (%class.C addrspace(1)* @c to i8 addrspace(1)*) to i8 addrspace(4)*) -// EXPL: call void @_ZNU3AS41CC1ERU3AS4KS_(%class.C addrspace(4)* [[C1GEN]], %class.C addrspace(4)* dereferenceable(4) addrspacecast (%class.C addrspace(1)* @c to %class.C addrspace(4)*)) +// EXPL: call spir_func void @_ZNU3AS41CC1ERU3AS4KS_(%class.C addrspace(4)* [[C1GEN]], %class.C addrspace(4)* dereferenceable(4) addrspacecast (%class.C addrspace(1)* @c to %class.C addrspace(4)*)) // Test the address space of 'this' when invoking a constructor. // EXPL: [[C2GEN:%[.a-z0-9]+]] = addrspacecast %class.C* %c2 to %class.C addrspace(4)* -// EXPL: call void @_ZNU3AS41CC1Ev(%class.C addrspace(4)* [[C2GEN]]) +// EXPL: call spir_func void @_ZNU3AS41CC1Ev(%class.C addrspace(4)* [[C2GEN]]) // Test the address space of 'this' when invoking assignment operator. // COMMON: [[C1GEN:%[.a-z0-9]+]] = addrspacecast %class.C* %c1 to %class.C addrspace(4)* // COMMON: [[C2GEN:%[.a-z0-9]+]] = addrspacecast %class.C* %c2 to %class.C addrspace(4)* -// EXPL: call dereferenceable(4) %class.C addrspace(4)* @_ZNU3AS41CaSERU3AS4KS_(%class.C addrspace(4)* [[C2GEN]], %class.C addrspace(4)* dereferenceable(4) [[C1GEN]]) +// EXPL: call spir_func dereferenceable(4) %class.C addrspace(4)* @_ZNU3AS41CaSERU3AS4KS_(%class.C addrspace(4)* [[C2GEN]], %class.C addrspace(4)* dereferenceable(4) [[C1GEN]]) // IMPL: [[C2GENVOID:%[0-9]+]] = bitcast %class.C addrspace(4)* [[C2GEN]] to i8 addrspace(4)* // IMPL: [[C1GENVOID:%[0-9]+]] = bitcast %class.C addrspace(4)* [[C1GEN]] to i8 addrspace(4)* // IMPL: call void @llvm.memcpy.p4i8.p4i8.i32(i8 addrspace(4)* {{.*}}[[C2GENVOID]], i8 addrspace(4)* {{.*}}[[C1GENVOID]] @@ -114,12 +114,12 @@ __kernel void test__global() { // Test the address space of 'this' when invoking the operator+ // COMMON: [[C1GEN:%[.a-z0-9]+]] = addrspacecast %class.C* %c1 to %class.C addrspace(4)* // COMMON: [[C2GEN:%[.a-z0-9]+]] = addrspacecast %class.C* %c2 to %class.C addrspace(4)* -// COMMON: call void @_ZNU3AS41CplERU3AS4KS_(%class.C* sret %c3, %class.C addrspace(4)* [[C1GEN]], %class.C addrspace(4)* dereferenceable(4) [[C2GEN]]) +// COMMON: call spir_func void @_ZNU3AS41CplERU3AS4KS_(%class.C* sret %c3, %class.C addrspace(4)* [[C1GEN]], %class.C addrspace(4)* dereferenceable(4) [[C2GEN]]) // Test the address space of 'this' when invoking the move constructor // COMMON: [[C4GEN:%[.a-z0-9]+]] = addrspacecast %class.C* %c4 to %class.C addrspace(4)* // COMMON: [[CALL:%call[0-9]+]] = call spir_func dereferenceable(4) %class.C addrspace(4)* @_Z3foov() -// EXPL: call void @_ZNU3AS41CC1EOU3AS4S_(%class.C addrspace(4)* [[C4GEN]], %class.C addrspace(4)* dereferenceable(4) [[CALL]]) +// EXPL: call spir_func void @_ZNU3AS41CC1EOU3AS4S_(%class.C addrspace(4)* [[C4GEN]], %class.C addrspace(4)* dereferenceable(4) [[CALL]]) // IMPL: [[C4VOID:%[0-9]+]] = bitcast %class.C* %c4 to i8* // IMPL: [[CALLVOID:%[0-9]+]] = bitcast %class.C addrspace(4)* [[CALL]] to i8 addrspace(4)* // IMPL: call void @llvm.memcpy.p0i8.p4i8.i32(i8* {{.*}}[[C4VOID]], i8 addrspace(4)* {{.*}}[[CALLVOID]] @@ -127,7 +127,7 @@ __kernel void test__global() { // Test the address space of 'this' when invoking the move assignment // COMMON: [[C5GEN:%[.a-z0-9]+]] = addrspacecast %class.C* %c5 to %class.C addrspace(4)* // COMMON: [[CALL:%call[0-9]+]] = call spir_func dereferenceable(4) %class.C addrspace(4)* @_Z3foov() -// EXPL: call void @_ZNU3AS41CC1EOU3AS4S_(%class.C addrspace(4)* [[C5GEN]], %class.C addrspace(4)* dereferenceable(4) [[CALL]]) +// EXPL: call spir_func void @_ZNU3AS41CC1EOU3AS4S_(%class.C addrspace(4)* [[C5GEN]], %class.C addrspace(4)* dereferenceable(4) [[CALL]]) // IMPL: [[C5VOID:%[0-9]+]] = bitcast %class.C* %c5 to i8* // IMPL: [[CALLVOID:%[0-9]+]] = bitcast %class.C addrspace(4)* [[CALL]] to i8 addrspace(4)* // IMPL: call void @llvm.memcpy.p0i8.p4i8.i32(i8* {{.*}}[[C5VOID]], i8 addrspace(4)* {{.*}}[[CALLVOID]] @@ -149,25 +149,25 @@ TEST(__local) // COMMON-LABEL: @test__local // Test that we don't initialize an object in local address space. -// EXPL-NOT: call void @_ZNU3AS41CC1Ev(%class.C addrspace(4)* addrspacecast (%class.C addrspace(3)* @_ZZ11test__localE1c to %class.C addrspace(4)*)) +// EXPL-NOT: call spir_func void @_ZNU3AS41CC1Ev(%class.C addrspace(4)* addrspacecast (%class.C addrspace(3)* @_ZZ11test__localE1c to %class.C addrspace(4)*)) // Test the address space of 'this' when invoking a method. -// COMMON: call i32 @_ZNU3AS41C3getEv(%class.C addrspace(4)* addrspacecast (%class.C addrspace(3)* @_ZZ11test__localE1c to %class.C addrspace(4)*)) +// COMMON: call spir_func i32 @_ZNU3AS41C3getEv(%class.C addrspace(4)* addrspacecast (%class.C addrspace(3)* @_ZZ11test__localE1c to %class.C addrspace(4)*)) // Test the address space of 'this' when invoking copy-constructor. // COMMON: [[C1GEN:%[.a-z0-9]+]] = addrspacecast %class.C* %c1 to %class.C addrspace(4)* -// EXPL: call void @_ZNU3AS41CC1ERU3AS4KS_(%class.C addrspace(4)* [[C1GEN]], %class.C addrspace(4)* dereferenceable(4) addrspacecast (%class.C addrspace(3)* @_ZZ11test__localE1c to %class.C addrspace(4)*)) +// EXPL: call spir_func void @_ZNU3AS41CC1ERU3AS4KS_(%class.C addrspace(4)* [[C1GEN]], %class.C addrspace(4)* dereferenceable(4) addrspacecast (%class.C addrspace(3)* @_ZZ11test__localE1c to %class.C addrspace(4)*)) // IMPL: [[C1VOID:%[0-9]+]] = bitcast %class.C* %c1 to i8* // IMPL: call void @llvm.memcpy.p0i8.p4i8.i32(i8* {{.*}}[[C1VOID]], i8 addrspace(4)* {{.*}}addrspacecast (i8 addrspace(3)* bitcast (%class.C addrspace(3)* @_ZZ11test__localE1c to i8 addrspace(3)*) to i8 addrspace(4)*), i32 4, i1 false) // Test the address space of 'this' when invoking a constructor. // EXPL: [[C2GEN:%[.a-z0-9]+]] = addrspacecast %class.C* %c2 to %class.C addrspace(4)* -// EXPL: call void @_ZNU3AS41CC1Ev(%class.C addrspace(4)* [[C2GEN]]) +// EXPL: call spir_func void @_ZNU3AS41CC1Ev(%class.C addrspace(4)* [[C2GEN]]) // Test the address space of 'this' when invoking assignment operator. // COMMON: [[C1GEN:%[.a-z0-9]+]] = addrspacecast %class.C* %c1 to %class.C addrspace(4)* // COMMON: [[C2GEN:%[.a-z0-9]+]] = addrspacecast %class.C* %c2 to %class.C addrspace(4)* -// EXPL: call dereferenceable(4) %class.C addrspace(4)* @_ZNU3AS41CaSERU3AS4KS_(%class.C addrspace(4)* [[C2GEN]], %class.C addrspace(4)* dereferenceable(4) [[C1GEN]]) +// EXPL: call spir_func dereferenceable(4) %class.C addrspace(4)* @_ZNU3AS41CaSERU3AS4KS_(%class.C addrspace(4)* [[C2GEN]], %class.C addrspace(4)* dereferenceable(4) [[C1GEN]]) // IMPL: [[C2GENVOID:%[0-9]+]] = bitcast %class.C addrspace(4)* [[C2GEN]] to i8 addrspace(4)* // IMPL: [[C1GENVOID:%[0-9]+]] = bitcast %class.C addrspace(4)* [[C1GEN]] to i8 addrspace(4)* // IMPL: call void @llvm.memcpy.p4i8.p4i8.i32(i8 addrspace(4)* {{.*}}[[C2GENVOID]], i8 addrspace(4)* {{.*}}[[C1GENVOID]] @@ -178,28 +178,28 @@ TEST(__private) // Test the address space of 'this' when invoking a constructor for an object in non-default address space // EXPL: [[CGEN:%[.a-z0-9]+]] = addrspacecast %class.C* %c to %class.C addrspace(4)* -// EXPL: call void @_ZNU3AS41CC1Ev(%class.C addrspace(4)* [[CGEN]]) +// EXPL: call spir_func void @_ZNU3AS41CC1Ev(%class.C addrspace(4)* [[CGEN]]) // Test the address space of 'this' when invoking a method. // COMMON: [[CGEN:%[.a-z0-9]+]] = addrspacecast %class.C* %c to %class.C addrspace(4)* -// COMMON: call i32 @_ZNU3AS41C3getEv(%class.C addrspace(4)* [[CGEN]]) +// COMMON: call spir_func i32 @_ZNU3AS41C3getEv(%class.C addrspace(4)* [[CGEN]]) // Test the address space of 'this' when invoking a copy-constructor. // COMMON: [[C1GEN:%[.a-z0-9]+]] = addrspacecast %class.C* %c1 to %class.C addrspace(4)* // COMMON: [[CGEN:%[.a-z0-9]+]] = addrspacecast %class.C* %c to %class.C addrspace(4)* -// EXPL: call void @_ZNU3AS41CC1ERU3AS4KS_(%class.C addrspace(4)* [[C1GEN]], %class.C addrspace(4)* dereferenceable(4) [[CGEN]]) +// EXPL: call spir_func void @_ZNU3AS41CC1ERU3AS4KS_(%class.C addrspace(4)* [[C1GEN]], %class.C addrspace(4)* dereferenceable(4) [[CGEN]]) // IMPL: [[C1VOID:%[0-9]+]] = bitcast %class.C* %c1 to i8* // IMPL: [[CGENVOID:%[0-9]+]] = bitcast %class.C addrspace(4)* [[CGEN]] to i8 addrspace(4)* // IMPL: call void @llvm.memcpy.p0i8.p4i8.i32(i8* {{.*}}[[C1VOID]], i8 addrspace(4)* {{.*}}[[CGENVOID]] // Test the address space of 'this' when invoking a constructor. // EXPL: [[C2GEN:%[.a-z0-9]+]] = addrspacecast %class.C* %c2 to %class.C addrspace(4)* -// EXPL: call void @_ZNU3AS41CC1Ev(%class.C addrspace(4)* [[C2GEN]]) +// EXPL: call spir_func void @_ZNU3AS41CC1Ev(%class.C addrspace(4)* [[C2GEN]]) // Test the address space of 'this' when invoking a copy-assignment. // COMMON: [[C1GEN:%[.a-z0-9]+]] = addrspacecast %class.C* %c1 to %class.C addrspace(4)* // COMMON: [[C2GEN:%[.a-z0-9]+]] = addrspacecast %class.C* %c2 to %class.C addrspace(4)* -// EXPL: call dereferenceable(4) %class.C addrspace(4)* @_ZNU3AS41CaSERU3AS4KS_(%class.C addrspace(4)* [[C2GEN]], %class.C addrspace(4)* dereferenceable(4) [[C1GEN]]) +// EXPL: call spir_func dereferenceable(4) %class.C addrspace(4)* @_ZNU3AS41CaSERU3AS4KS_(%class.C addrspace(4)* [[C2GEN]], %class.C addrspace(4)* dereferenceable(4) [[C1GEN]]) // IMPL: [[C2GENVOID:%[0-9]+]] = bitcast %class.C addrspace(4)* [[C2GEN]] to i8 addrspace(4)* // IMPL: [[C1GENVOID:%[0-9]+]] = bitcast %class.C addrspace(4)* [[C1GEN]] to i8 addrspace(4)* // IMPL: call void @llvm.memcpy.p4i8.p4i8.i32(i8 addrspace(4)* {{.*}}[[C2GENVOID]], i8 addrspace(4)* {{.*}}[[C1GENVOID]] diff --git a/clang/test/CodeGenOpenCLCXX/addrspace-operators.cl b/clang/test/CodeGenOpenCLCXX/addrspace-operators.cl index 254be1bb85b7..d26efcac4277 100644 --- a/clang/test/CodeGenOpenCLCXX/addrspace-operators.cl +++ b/clang/test/CodeGenOpenCLCXX/addrspace-operators.cl @@ -20,10 +20,10 @@ __global int globI; void bar() { C c; //CHECK: [[A1:%[.a-z0-9]+]] = addrspacecast %class.C* [[C:%[a-z0-9]+]] to %class.C addrspace(4)* - //CHECK: call void @_ZNU3AS41C6AssignE1E(%class.C addrspace(4)* [[A1]], i32 0) + //CHECK: call spir_func void @_ZNU3AS41C6AssignE1E(%class.C addrspace(4)* [[A1]], i32 0) c.Assign(a); //CHECK: [[A2:%[.a-z0-9]+]] = addrspacecast %class.C* [[C]] to %class.C addrspace(4)* - //CHECK: call void @_ZNU3AS41C8OrAssignE1E(%class.C addrspace(4)* [[A2]], i32 0) + //CHECK: call spir_func void @_ZNU3AS41C8OrAssignE1E(%class.C addrspace(4)* [[A2]], i32 0) c.OrAssign(a); E e; @@ -45,7 +45,7 @@ void bar() { globVI -= a; } -//CHECK: define linkonce_odr void @_ZNU3AS41C6AssignE1E(%class.C addrspace(4)*{{[ %a-z0-9]*}}, i32{{[ %a-z0-9]*}}) +//CHECK: define linkonce_odr spir_func void @_ZNU3AS41C6AssignE1E(%class.C addrspace(4)*{{[ %a-z0-9]*}}, i32{{[ %a-z0-9]*}}) //CHECK: [[THIS_ADDR:%[.a-z0-9]+]] = alloca %class.C addrspace(4) //CHECK: [[E_ADDR:%[.a-z0-9]+]] = alloca i32 //CHECK: store %class.C addrspace(4)* {{%[a-z0-9]+}}, %class.C addrspace(4)** [[THIS_ADDR]] @@ -55,7 +55,7 @@ void bar() { //CHECK: [[ME:%[a-z0-9]+]] = getelementptr inbounds %class.C, %class.C addrspace(4)* [[THIS1]], i32 0, i32 0 //CHECK: store i32 [[E]], i32 addrspace(4)* [[ME]] -//CHECK: define linkonce_odr void @_ZNU3AS41C8OrAssignE1E(%class.C addrspace(4)*{{[ %a-z0-9]*}}, i32{{[ %a-z0-9]*}}) +//CHECK: define linkonce_odr spir_func void @_ZNU3AS41C8OrAssignE1E(%class.C addrspace(4)*{{[ %a-z0-9]*}}, i32{{[ %a-z0-9]*}}) //CHECK: [[THIS_ADDR:%[.a-z0-9]+]] = alloca %class.C addrspace(4) //CHECK: [[E_ADDR:%[.a-z0-9]+]] = alloca i32 //CHECK: store %class.C addrspace(4)* {{%[a-z0-9]+}}, %class.C addrspace(4)** [[THIS_ADDR]] diff --git a/clang/test/CodeGenOpenCLCXX/addrspace-with-class.cl b/clang/test/CodeGenOpenCLCXX/addrspace-with-class.cl index 21ba1ca251d8..a477559c900b 100644 --- a/clang/test/CodeGenOpenCLCXX/addrspace-with-class.cl +++ b/clang/test/CodeGenOpenCLCXX/addrspace-with-class.cl @@ -23,17 +23,17 @@ __constant MyType const2(2); // CHECK: @glob = addrspace(1) global %struct.MyType zeroinitializer MyType glob(1); -// CHECK: call void @_ZNU3AS26MyTypeC1Ei(%struct.MyType addrspace(2)* @const1, i32 1) -// CHECK: call void @_ZNU3AS26MyTypeC1Ei(%struct.MyType addrspace(2)* @const2, i32 2) -// CHECK: call void @_ZNU3AS46MyTypeC1Ei(%struct.MyType addrspace(4)* addrspacecast (%struct.MyType addrspace(1)* @glob to %struct.MyType addrspace(4)*), i32 1) +// CHECK: call spir_func void @_ZNU3AS26MyTypeC1Ei(%struct.MyType addrspace(2)* @const1, i32 1) +// CHECK: call spir_func void @_ZNU3AS26MyTypeC1Ei(%struct.MyType addrspace(2)* @const2, i32 2) +// CHECK: call spir_func void @_ZNU3AS46MyTypeC1Ei(%struct.MyType addrspace(4)* addrspacecast (%struct.MyType addrspace(1)* @glob to %struct.MyType addrspace(4)*), i32 1) // CHECK-LABEL: define spir_kernel void @fooGlobal() kernel void fooGlobal() { - // CHECK: call i32 @_ZNU3AS46MyType3barEv(%struct.MyType addrspace(4)* addrspacecast (%struct.MyType addrspace(1)* @glob to %struct.MyType addrspace(4)*)) + // CHECK: call spir_func i32 @_ZNU3AS46MyType3barEv(%struct.MyType addrspace(4)* addrspacecast (%struct.MyType addrspace(1)* @glob to %struct.MyType addrspace(4)*)) glob.bar(); - // CHECK: call i32 @_ZNU3AS26MyType3barEv(%struct.MyType addrspace(2)* @const1) + // CHECK: call spir_func i32 @_ZNU3AS26MyType3barEv(%struct.MyType addrspace(2)* @const1) const1.bar(); - // CHECK: call void @_ZNU3AS26MyTypeD1Ev(%struct.MyType addrspace(2)* @const1) + // CHECK: call spir_func void @_ZNU3AS26MyTypeD1Ev(%struct.MyType addrspace(2)* @const1) const1.~MyType(); } @@ -41,19 +41,19 @@ kernel void fooGlobal() { kernel void fooLocal() { // CHECK: [[VAR:%.*]] = alloca %struct.MyType // CHECK: [[REG:%.*]] = addrspacecast %struct.MyType* [[VAR]] to %struct.MyType addrspace(4)* - // CHECK: call void @_ZNU3AS46MyTypeC1Ei(%struct.MyType addrspace(4)* [[REG]], i32 3) + // CHECK: call spir_func void @_ZNU3AS46MyTypeC1Ei(%struct.MyType addrspace(4)* [[REG]], i32 3) MyType myLocal(3); // CHECK: [[REG:%.*]] = addrspacecast %struct.MyType* [[VAR]] to %struct.MyType addrspace(4)* - // CHECK: call i32 @_ZNU3AS46MyType3barEv(%struct.MyType addrspace(4)* [[REG]]) + // CHECK: call spir_func i32 @_ZNU3AS46MyType3barEv(%struct.MyType addrspace(4)* [[REG]]) myLocal.bar(); // CHECK: [[REG:%.*]] = addrspacecast %struct.MyType* [[VAR]] to %struct.MyType addrspace(4)* - // CHECK: call void @_ZNU3AS46MyTypeD1Ev(%struct.MyType addrspace(4)* [[REG]]) + // CHECK: call spir_func void @_ZNU3AS46MyTypeD1Ev(%struct.MyType addrspace(4)* [[REG]]) } // Ensure all members are defined for all the required address spaces. -// CHECK-DEFINITIONS-DAG: define linkonce_odr void @_ZNU3AS26MyTypeC1Ei(%struct.MyType addrspace(2)* %this, i32 %i) -// CHECK-DEFINITIONS-DAG: define linkonce_odr void @_ZNU3AS46MyTypeC1Ei(%struct.MyType addrspace(4)* %this, i32 %i) -// CHECK-DEFINITIONS-DAG: define linkonce_odr void @_ZNU3AS26MyTypeD1Ev(%struct.MyType addrspace(2)* %this) -// CHECK-DEFINITIONS-DAG: define linkonce_odr void @_ZNU3AS46MyTypeD1Ev(%struct.MyType addrspace(4)* %this) -// CHECK-DEFINITIONS-DAG: define linkonce_odr i32 @_ZNU3AS26MyType3barEv(%struct.MyType addrspace(2)* %this) -// CHECK-DEFINITIONS-DAG: define linkonce_odr i32 @_ZNU3AS46MyType3barEv(%struct.MyType addrspace(4)* %this) +// CHECK-DEFINITIONS-DAG: define linkonce_odr spir_func void @_ZNU3AS26MyTypeC1Ei(%struct.MyType addrspace(2)* %this, i32 %i) +// CHECK-DEFINITIONS-DAG: define linkonce_odr spir_func void @_ZNU3AS46MyTypeC1Ei(%struct.MyType addrspace(4)* %this, i32 %i) +// CHECK-DEFINITIONS-DAG: define linkonce_odr spir_func void @_ZNU3AS26MyTypeD1Ev(%struct.MyType addrspace(2)* %this) +// CHECK-DEFINITIONS-DAG: define linkonce_odr spir_func void @_ZNU3AS46MyTypeD1Ev(%struct.MyType addrspace(4)* %this) +// CHECK-DEFINITIONS-DAG: define linkonce_odr spir_func i32 @_ZNU3AS26MyType3barEv(%struct.MyType addrspace(2)* %this) +// CHECK-DEFINITIONS-DAG: define linkonce_odr spir_func i32 @_ZNU3AS46MyType3barEv(%struct.MyType addrspace(4)* %this) diff --git a/clang/test/CodeGenOpenCLCXX/method-overload-address-space.cl b/clang/test/CodeGenOpenCLCXX/method-overload-address-space.cl index 0864589b051e..6bec3fa33b01 100644 --- a/clang/test/CodeGenOpenCLCXX/method-overload-address-space.cl +++ b/clang/test/CodeGenOpenCLCXX/method-overload-address-space.cl @@ -15,21 +15,21 @@ __kernel void k() { __global C &c_ref = c1; __global C *c_ptr; - // CHECK: call void @_ZNU3AS11C3fooEv(%struct.C addrspace(1)* + // CHECK: call spir_func void @_ZNU3AS11C3fooEv(%struct.C addrspace(1)* c1.foo(); - // CHECK: call void @_ZNU3AS31C3fooEv(%struct.C addrspace(3)* + // CHECK: call spir_func void @_ZNU3AS31C3fooEv(%struct.C addrspace(3)* c2.foo(); - // CHECK: call void @_ZNU3AS41C3fooEv(%struct.C addrspace(4)* + // CHECK: call spir_func void @_ZNU3AS41C3fooEv(%struct.C addrspace(4)* c3.foo(); - // CHECK: call void @_ZNU3AS11C3fooEv(%struct.C addrspace(1)* + // CHECK: call spir_func void @_ZNU3AS11C3fooEv(%struct.C addrspace(1)* c_ptr->foo(); - // CHECK: void @_ZNU3AS11C3fooEv(%struct.C addrspace(1)* + // CHECK: spir_func void @_ZNU3AS11C3fooEv(%struct.C addrspace(1)* c_ref.foo(); - // CHECK: call void @_ZNU3AS41C3barEv(%struct.C addrspace(4)* addrspacecast (%struct.C addrspace(1)* @c1 to %struct.C addrspace(4)*)) + // CHECK: call spir_func void @_ZNU3AS41C3barEv(%struct.C addrspace(4)* addrspacecast (%struct.C addrspace(1)* @c1 to %struct.C addrspace(4)*)) c1.bar(); //FIXME: Doesn't compile yet //c_ptr->bar(); - // CHECK: call void @_ZNU3AS41C3barEv(%struct.C addrspace(4)* addrspacecast (%struct.C addrspace(1)* @c1 to %struct.C addrspace(4)*)) + // CHECK: call spir_func void @_ZNU3AS41C3barEv(%struct.C addrspace(4)* addrspacecast (%struct.C addrspace(1)* @c1 to %struct.C addrspace(4)*)) c_ref.bar(); } diff --git a/clang/test/CodeGenOpenCLCXX/template-address-spaces.cl b/clang/test/CodeGenOpenCLCXX/template-address-spaces.cl index 4ceb7b44b473..7b553c2c0dcf 100644 --- a/clang/test/CodeGenOpenCLCXX/template-address-spaces.cl +++ b/clang/test/CodeGenOpenCLCXX/template-address-spaces.cl @@ -14,11 +14,11 @@ T S::foo() { return a;} // CHECK: %struct.S.1 = type { i32 addrspace(1)* } // CHECK: [[A1:%[.a-z0-9]+]] = addrspacecast %struct.S* %{{[a-z0-9]+}} to %struct.S addrspace(4)* -// CHECK: %call = call i32 @_ZNU3AS41SIiE3fooEv(%struct.S addrspace(4)* [[A1]]) #1 +// CHECK: %call = call spir_func i32 @_ZNU3AS41SIiE3fooEv(%struct.S addrspace(4)* [[A1]]) #1 // CHECK: [[A2:%[.a-z0-9]+]] = addrspacecast %struct.S.0* %{{[a-z0-9]+}} to %struct.S.0 addrspace(4)* -// CHECK: %call1 = call i32 addrspace(4)* @_ZNU3AS41SIPU3AS4iE3fooEv(%struct.S.0 addrspace(4)* [[A2]]) #1 +// CHECK: %call1 = call spir_func i32 addrspace(4)* @_ZNU3AS41SIPU3AS4iE3fooEv(%struct.S.0 addrspace(4)* [[A2]]) #1 // CHECK: [[A3:%[.a-z0-9]+]] = addrspacecast %struct.S.1* %{{[a-z0-9]+}} to %struct.S.1 addrspace(4)* -// CHECK: %call2 = call i32 addrspace(1)* @_ZNU3AS41SIPU3AS1iE3fooEv(%struct.S.1 addrspace(4)* [[A3]]) #1 +// CHECK: %call2 = call spir_func i32 addrspace(1)* @_ZNU3AS41SIPU3AS1iE3fooEv(%struct.S.1 addrspace(4)* [[A3]]) #1 void bar(){ S sint; From e202588048d76388a2a033bb6fd6e3b9271f6fe2 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Fri, 26 Jul 2019 17:42:03 +0000 Subject: [PATCH 035/289] Merging r367112: ------------------------------------------------------------------------ r367112 | sammccall | 2019-07-26 16:07:11 +0200 (Fri, 26 Jul 2019) | 11 lines [clangd] Fix background index not triggering on windows due to case mismatch. Summary: This isn't a general fix to all paths where we assume case-sensitivity, it's a minimally-invasive fix targeting the llvm 9 branch. Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D65320 ------------------------------------------------------------------------ llvm-svn: 367135 --- .../clangd/GlobalCompilationDatabase.cpp | 82 ++++++++++++------- .../clangd/GlobalCompilationDatabase.h | 16 ++-- 2 files changed, 61 insertions(+), 37 deletions(-) diff --git a/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp b/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp index 885bf15c616c..ed3b86f0f55b 100644 --- a/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp +++ b/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp @@ -117,20 +117,41 @@ DirectoryBasedGlobalCompilationDatabase::getCompileCommand(PathRef File) const { return None; } -std::pair -DirectoryBasedGlobalCompilationDatabase::getCDBInDirLocked(PathRef Dir) const { - // FIXME(ibiryukov): Invalidate cached compilation databases on changes - auto CachedIt = CompilationDatabases.find(Dir); - if (CachedIt != CompilationDatabases.end()) - return {CachedIt->second.CDB.get(), CachedIt->second.SentBroadcast}; - std::string Error = ""; +// For platforms where paths are case-insensitive (but case-preserving), +// we need to do case-insensitive comparisons and use lowercase keys. +// FIXME: Make Path a real class with desired semantics instead. +// This class is not the only place this problem exists. +// FIXME: Mac filesystems default to case-insensitive, but may be sensitive. + +static std::string maybeCaseFoldPath(PathRef Path) { +#if defined(_WIN32) || defined(__APPLE__) + return Path.lower(); +#else + return Path; +#endif +} - CachedCDB Entry; - Entry.CDB = tooling::CompilationDatabase::loadFromDirectory(Dir, Error); - auto Result = Entry.CDB.get(); - CompilationDatabases[Dir] = std::move(Entry); +static bool pathEqual(PathRef A, PathRef B) { +#if defined(_WIN32) || defined(__APPLE__) + return A.equals_lower(B); +#else + return A == B; +#endif +} - return {Result, false}; +DirectoryBasedGlobalCompilationDatabase::CachedCDB & +DirectoryBasedGlobalCompilationDatabase::getCDBInDirLocked(PathRef Dir) const { + // FIXME(ibiryukov): Invalidate cached compilation databases on changes + // FIXME(sammccall): this function hot, avoid copying key when hitting cache. + auto Key = maybeCaseFoldPath(Dir); + auto R = CompilationDatabases.try_emplace(Key); + if (R.second) { // Cache miss, try to load CDB. + CachedCDB &Entry = R.first->second; + std::string Error = ""; + Entry.CDB = tooling::CompilationDatabase::loadFromDirectory(Dir, Error); + Entry.Path = Dir; + } + return R.first->second; } llvm::Optional @@ -139,38 +160,41 @@ DirectoryBasedGlobalCompilationDatabase::lookupCDB( assert(llvm::sys::path::is_absolute(Request.FileName) && "path must be absolute"); + bool ShouldBroadcast = false; CDBLookupResult Result; - bool SentBroadcast = false; { std::lock_guard Lock(Mutex); + CachedCDB *Entry = nullptr; if (CompileCommandsDir) { - std::tie(Result.CDB, SentBroadcast) = - getCDBInDirLocked(*CompileCommandsDir); - Result.PI.SourceRoot = *CompileCommandsDir; + Entry = &getCDBInDirLocked(*CompileCommandsDir); } else { // Traverse the canonical version to prevent false positives. i.e.: // src/build/../a.cc can detect a CDB in /src/build if not canonicalized. + // FIXME(sammccall): this loop is hot, use a union-find-like structure. actOnAllParentDirectories(removeDots(Request.FileName), - [this, &SentBroadcast, &Result](PathRef Path) { - std::tie(Result.CDB, SentBroadcast) = - getCDBInDirLocked(Path); - Result.PI.SourceRoot = Path; - return Result.CDB != nullptr; + [&](PathRef Path) { + Entry = &getCDBInDirLocked(Path); + return Entry->CDB != nullptr; }); } - if (!Result.CDB) + if (!Entry || !Entry->CDB) return llvm::None; // Mark CDB as broadcasted to make sure discovery is performed once. - if (Request.ShouldBroadcast && !SentBroadcast) - CompilationDatabases[Result.PI.SourceRoot].SentBroadcast = true; + if (Request.ShouldBroadcast && !Entry->SentBroadcast) { + Entry->SentBroadcast = true; + ShouldBroadcast = true; + } + + Result.CDB = Entry->CDB.get(); + Result.PI.SourceRoot = Entry->Path; } // FIXME: Maybe make the following part async, since this can block retrieval // of compile commands. - if (Request.ShouldBroadcast && !SentBroadcast) + if (ShouldBroadcast) broadcastCDB(Result); return Result; } @@ -200,9 +224,9 @@ void DirectoryBasedGlobalCompilationDatabase::broadcastCDB( if (!It.second) return true; - auto Res = getCDBInDirLocked(Path); - It.first->second = Res.first != nullptr; - return Path == Result.PI.SourceRoot; + CachedCDB &Entry = getCDBInDirLocked(Path); + It.first->second = Entry.CDB != nullptr; + return pathEqual(Path, Result.PI.SourceRoot); }); } } @@ -213,7 +237,7 @@ void DirectoryBasedGlobalCompilationDatabase::broadcastCDB( // Independent of whether it has an entry for that file or not. actOnAllParentDirectories(File, [&](PathRef Path) { if (DirectoryHasCDB.lookup(Path)) { - if (Path == Result.PI.SourceRoot) + if (pathEqual(Path, Result.PI.SourceRoot)) // Make sure listeners always get a canonical path for the file. GovernedFiles.push_back(removeDots(File)); // Stop as soon as we hit a CDB. diff --git a/clang-tools-extra/clangd/GlobalCompilationDatabase.h b/clang-tools-extra/clangd/GlobalCompilationDatabase.h index 35708c8e3024..7acca43d1bb9 100644 --- a/clang-tools-extra/clangd/GlobalCompilationDatabase.h +++ b/clang-tools-extra/clangd/GlobalCompilationDatabase.h @@ -80,8 +80,13 @@ class DirectoryBasedGlobalCompilationDatabase llvm::Optional getProjectInfo(PathRef File) const override; private: - std::pair - getCDBInDirLocked(PathRef File) const; + /// Caches compilation databases loaded from directories. + struct CachedCDB { + std::string Path; // Not case-folded. + std::unique_ptr CDB = nullptr; + bool SentBroadcast = false; + }; + CachedCDB &getCDBInDirLocked(PathRef File) const; struct CDBLookupRequest { PathRef FileName; @@ -98,12 +103,7 @@ class DirectoryBasedGlobalCompilationDatabase void broadcastCDB(CDBLookupResult Res) const; mutable std::mutex Mutex; - /// Caches compilation databases loaded from directories(keys are - /// directories). - struct CachedCDB { - std::unique_ptr CDB = nullptr; - bool SentBroadcast = false; - }; + // Keyed by possibly-case-folded directory path. mutable llvm::StringMap CompilationDatabases; /// Used for command argument pointing to folder where compile_commands.json From d1b122cbdf22744b4333b1056ebea90e38a6b306 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Fri, 26 Jul 2019 20:47:20 +0000 Subject: [PATCH 036/289] Merging r367134: ------------------------------------------------------------------------ r367134 | nathan-huckleberry | 2019-07-26 19:29:35 +0200 (Fri, 26 Jul 2019) | 16 lines [Sema] Fix -Wuninitialized for struct assignment from GNU C statement expression Summary: Do not automatically report self references of structs in statement expression as warnings. Instead wait for uninitialized cfg analysis. https://bugs.llvm.org/show_bug.cgi?id=42604 Reviewers: aaron.ballman, rsmith, nickdesaulniers Reviewed By: aaron.ballman, nickdesaulniers Subscribers: nathanchance, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D64678 ------------------------------------------------------------------------ llvm-svn: 367150 --- clang/lib/Sema/SemaDecl.cpp | 9 ++- .../warn-uninitialized-statement-expression.c | 56 +++++++++++++++++++ 2 files changed, 62 insertions(+), 3 deletions(-) create mode 100644 clang/test/Sema/warn-uninitialized-statement-expression.c diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index a6c52b7d4b2b..cf8ad9c90551 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -11527,9 +11527,12 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) { // Check for self-references within variable initializers. // Variables declared within a function/method body (except for references) // are handled by a dataflow analysis. - if (!VDecl->hasLocalStorage() || VDecl->getType()->isRecordType() || - VDecl->getType()->isReferenceType()) { - CheckSelfReference(*this, RealDecl, Init, DirectInit); + // This is undefined behavior in C++, but valid in C. + if (getLangOpts().CPlusPlus) { + if (!VDecl->hasLocalStorage() || VDecl->getType()->isRecordType() || + VDecl->getType()->isReferenceType()) { + CheckSelfReference(*this, RealDecl, Init, DirectInit); + } } // If the type changed, it means we had an incomplete type that was diff --git a/clang/test/Sema/warn-uninitialized-statement-expression.c b/clang/test/Sema/warn-uninitialized-statement-expression.c new file mode 100644 index 000000000000..4e29ee01eab9 --- /dev/null +++ b/clang/test/Sema/warn-uninitialized-statement-expression.c @@ -0,0 +1,56 @@ +// RUN: %clang_cc1 -fsyntax-only -Wuninitialized -verify %s + +void init(int *); + +void foo(void) { + int i = ({ + init(&i); + i; + }); +} + +void foo_bad(void) { + int i = ({ + int z = i; // expected-warning{{variable 'i' is uninitialized when used within its own initialization}} + init(&i); + i; + }); +} + +struct widget { + int x, y; +}; +void init2(struct widget *); + +void bar(void) { + struct widget my_widget = ({ + init2(&my_widget); + my_widget; + }); + struct widget a = (init2(&a), a); +} + +void bar_bad(void) { + struct widget my_widget = ({ + struct widget z = my_widget; // expected-warning{{variable 'my_widget' is uninitialized when used within its own initialization}} + int x = my_widget.x; //FIXME: There should be an uninitialized warning here + init2(&my_widget); + my_widget; + }); +} + +void baz(void) { + struct widget a = ({ + struct widget b = ({ + b = a; // expected-warning{{variable 'a' is uninitialized when used within its own initialization}} + }); + a; + }); +} + +void f(void) { + struct widget *a = ({ + init2(a); // expected-warning{{variable 'a' is uninitialized when used within its own initialization}} + a; + }); +} From 1634b4bc934d67cb5fa356a925ba8efca2259f12 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Fri, 26 Jul 2019 21:31:11 +0000 Subject: [PATCH 037/289] [clang][docs][release notes] mention asm goto support By Nick Desaulniers! Differential revision: https://reviews.llvm.org/D65302 llvm-svn: 367158 --- clang/docs/ReleaseNotes.rst | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index dadcc77f4803..c94868a39ed4 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -111,6 +111,12 @@ C Language Changes in Clang in all C-family languages. This macro is similar to ``__FILE__`` except it will always provide the last path component when possible. +- Initial support for ``asm goto`` statements (a GNU C extension) has been + added for control flow from inline assembly to labels. The main consumers of + this construct are the Linux kernel (CONFIG_JUMP_LABEL=y) and glib. There are + still a few unsupported corner cases in Clang's integrated assembler and + IfConverter. Please file bugs for any issues you run into. + - ... C11 Feature Support @@ -242,6 +248,33 @@ The following methods have been added: Significant Known Problems ========================== +Linux Kernel +============ + +With support for asm goto, the mainline Linux kernel for x86_64 is now buildable +(and bootable) with Clang 9. Other architectures that don't require +CONFIG_JUMP_LABEL=y such as arm, aarch64, ppc32, ppc64le, (and possibly mips) +have been supported with older releases of Clang (Clang 4 was first used with +aarch64). + +The Android and ChromeOS Linux distributions have moved to building their Linux +kernels with Clang, and Google is currently testing Clang built kernels for +their production Linux kernels. + +Further, LLD, llvm-objcopy, llvm-ar, llvm-nm, llvm-objdump can all be used to +build a working Linux kernel. + +More information about building Linux kernels with Clang can be found: + +- `ClangBuiltLinux web page `_. +- `Issue Tracker `_. +- `Wiki `_. +- `Mailing List `_. +- `Bi-weekly Meeting `_. +- #clangbuiltlinux on Freenode. +- `Clang Meta bug `_. +- `Continuous Integration `_. + Additional Information ====================== From 7dd0d28f14fc1ca77f90750b401a42a17c8207f0 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Mon, 29 Jul 2019 08:56:00 +0000 Subject: [PATCH 038/289] Merging r367055: ------------------------------------------------------------------------ r367055 | compnerd | 2019-07-25 22:59:48 +0200 (Thu, 25 Jul 2019) | 6 lines Revert "Revert "CodeGen: ensure placeholder instruction for cleanup is created"" This reverts commit fd1274fa78cb0fd32cc1fa2e6f5bb8e62d29df19. Add an explicit triple for the test which is pattern matching overly aggressively. ------------------------------------------------------------------------ llvm-svn: 367209 --- clang/lib/CodeGen/CGExprAgg.cpp | 19 ++++--- .../pr40771-ctad-with-lambda-copy-capture.cpp | 55 +++++++++++++++++++ 2 files changed, 66 insertions(+), 8 deletions(-) create mode 100644 clang/test/CodeGenCXX/pr40771-ctad-with-lambda-copy-capture.cpp diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp index 695facd50b67..0a57870a7c58 100644 --- a/clang/lib/CodeGen/CGExprAgg.cpp +++ b/clang/lib/CodeGen/CGExprAgg.cpp @@ -1495,6 +1495,13 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) { // initializers throws an exception. SmallVector cleanups; llvm::Instruction *cleanupDominator = nullptr; + auto addCleanup = [&](const EHScopeStack::stable_iterator &cleanup) { + cleanups.push_back(cleanup); + if (!cleanupDominator) // create placeholder once needed + cleanupDominator = CGF.Builder.CreateAlignedLoad( + CGF.Int8Ty, llvm::Constant::getNullValue(CGF.Int8PtrTy), + CharUnits::One()); + }; unsigned curInitIndex = 0; @@ -1519,7 +1526,7 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) { if (QualType::DestructionKind dtorKind = Base.getType().isDestructedType()) { CGF.pushDestroy(dtorKind, V, Base.getType()); - cleanups.push_back(CGF.EHStack.stable_begin()); + addCleanup(CGF.EHStack.stable_begin()); } } } @@ -1596,15 +1603,9 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) { = field->getType().isDestructedType()) { assert(LV.isSimple()); if (CGF.needsEHCleanup(dtorKind)) { - if (!cleanupDominator) - cleanupDominator = CGF.Builder.CreateAlignedLoad( - CGF.Int8Ty, - llvm::Constant::getNullValue(CGF.Int8PtrTy), - CharUnits::One()); // placeholder - CGF.pushDestroy(EHCleanup, LV.getAddress(), field->getType(), CGF.getDestroyer(dtorKind), false); - cleanups.push_back(CGF.EHStack.stable_begin()); + addCleanup(CGF.EHStack.stable_begin()); pushedCleanup = true; } } @@ -1620,6 +1621,8 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) { // Deactivate all the partial cleanups in reverse order, which // generally means popping them. + assert((cleanupDominator || cleanups.empty()) && + "Missing cleanupDominator before deactivating cleanup blocks"); for (unsigned i = cleanups.size(); i != 0; --i) CGF.DeactivateCleanupBlock(cleanups[i-1], cleanupDominator); diff --git a/clang/test/CodeGenCXX/pr40771-ctad-with-lambda-copy-capture.cpp b/clang/test/CodeGenCXX/pr40771-ctad-with-lambda-copy-capture.cpp new file mode 100644 index 000000000000..36cec1e7068e --- /dev/null +++ b/clang/test/CodeGenCXX/pr40771-ctad-with-lambda-copy-capture.cpp @@ -0,0 +1,55 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm --std=c++17 -fcxx-exceptions -fexceptions -discard-value-names %s -o - | FileCheck %s + +struct Q { Q(); }; +struct R { R(Q); ~R(); }; +struct S { S(Q); ~S(); }; +struct T : R, S {}; + +Q q; +T t { R{q}, S{q} }; + +// CHECK-LABEL: define internal void @__cxx_global_var_init.1() {{.*}} { +// CHECK-NEXT: [[TMP_R:%[a-z0-9.]+]] = alloca %struct.R, align 1 +// CHECK-NEXT: [[TMP_Q1:%[a-z0-9.]+]] = alloca %struct.Q, align 1 +// CHECK-NEXT: [[TMP_S:%[a-z0-9.]+]] = alloca %struct.S, align 1 +// CHECK-NEXT: [[TMP_Q2:%[a-z0-9.]+]] = alloca %struct.Q, align 1 +// CHECK-NEXT: [[XPT:%[a-z0-9.]+]] = alloca i8* +// CHECK-NEXT: [[SLOT:%[a-z0-9.]+]] = alloca i32 +// CHECK-NEXT: [[ACTIVE:%[a-z0-9.]+]] = alloca i1, align 1 +// CHECK-NEXT: call void @_ZN1RC1E1Q(%struct.R* [[TMP_R]]) +// CHECK-NEXT: store i1 true, i1* [[ACTIVE]], align 1 +// CHECK-NEXT: invoke void @_ZN1SC1E1Q(%struct.S* [[TMP_S]]) +// CHECK-NEXT: to label %[[L1:[a-z0-9.]+]] unwind label %[[L2:[a-z0-9.]+]] +// CHECK-EMPTY: +// CHECK-NEXT: [[L1]]: +// CHECK-NEXT: store i1 false, i1* [[ACTIVE]], align 1 +// CHECK-NEXT: call void @_ZN1SD1Ev(%struct.S* +// CHECK-NEXT: call void @_ZN1RD1Ev(%struct.R* +// CHECK-NEXT: [[EXIT:%[a-z0-9.]+]] = call i32 @__cxa_atexit( +// CHECK-NEXT: ret void +// CHECK-EMPTY: +// CHECK-NEXT: [[L2]]: +// CHECK-NEXT: [[LP:%[a-z0-9.]+]] = landingpad { i8*, i32 } +// CHECK-NEXT: cleanup +// CHECK-NEXT: [[X1:%[a-z0-9.]+]] = extractvalue { i8*, i32 } [[LP]], 0 +// CHECK-NEXT: store i8* [[X1]], i8** [[XPT]], align 8 +// CHECK-NEXT: [[X2:%[a-z0-9.]+]] = extractvalue { i8*, i32 } [[LP]], 1 +// CHECK-NEXT: store i32 [[X2]], i32* [[SLOT]], align 4 +// CHECK-NEXT: [[IS_ACT:%[a-z0-9.]+]] = load i1, i1* [[ACTIVE]], align 1 +// CHECK-NEXT: br i1 [[IS_ACT]], label %[[L3:[a-z0-9.]+]], label %[[L4:[a-z0-9.]+]] +// CHECK-EMPTY: +// CHECK-NEXT: [[L3]]: +// CHECK-NEXT: call void @_ZN1RD1Ev(%struct.R* +// CHECK-NEXT: br label %[[L4]] +// CHECK-EMPTY: +// CHECK-NEXT: [[L4]]: +// CHECK-NEXT: call void @_ZN1RD1Ev(%struct.R* [[TMP_R]]) +// CHECK-NEXT: br label %[[L5:[a-z0-9.]+]] +// CHECK-EMPTY: +// CHECK-NEXT: [[L5]]: +// CHECK-NEXT: [[EXN:%[a-z0-9.]+]] = load i8*, i8** [[XPT]], align 8 +// CHECK-NEXT: [[SEL:%[a-z0-9.]+]] = load i32, i32* [[SLOT]], align 4 +// CHECK-NEXT: [[LV1:%[a-z0-9.]+]] = insertvalue { i8*, i32 } undef, i8* [[EXN]], 0 +// CHECK-NEXT: [[LV2:%[a-z0-9.]+]] = insertvalue { i8*, i32 } [[LV1]], i32 [[SEL]], 1 +// CHECK-NEXT: resume { i8*, i32 } [[LV2]] +// CHECK-NEXT: } From 556a6ff50cae544d272688aaad84e1436b305abb Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Mon, 29 Jul 2019 08:59:09 +0000 Subject: [PATCH 039/289] Merging r367030: ------------------------------------------------------------------------ r367030 | yhs | 2019-07-25 18:01:26 +0200 (Thu, 25 Jul 2019) | 38 lines [BPF] fix CO-RE incorrect index access string Currently, we expect the CO-RE offset relocation records a string encoding the original getelementptr access index, so kernel bpf loader can decode it correctly. For example, struct s { int a; int b; }; struct t { int c; int d; }; #define _(x) (__builtin_preserve_access_index(x)) int get_value(const void *addr1, const void *addr2); int test(struct s *arg1, struct t *arg2) { return get_value(_(&arg1->b), _(&arg2->d)); } We expect two offset relocations: reloc 1: type s, access index 0, 1 reloc 2: type t, access index 0, 1 Two globals are created to retain access indexes for the above two relocations with global variable names. The first global has a name "0:1:". Unfortunately, the second global has the name "0:1:.1" as the llvm internals automatically add suffix ".1" to a global with the same name. Later on, the BPF peels the last character and record "0:1" and "0:1:." in the relocation table. This is not desirable. BPF backend could use the global variable suffix knowledge to generate correct access str. This patch rather took an approach not relying on that knowledge. It generates "s:0:1:" and "t:0:1:" to avoid global variable suffixes and later on generate correct index access string "0:1" for both records. Signed-off-by: Yonghong Song Differential Revision: https://reviews.llvm.org/D65258 ------------------------------------------------------------------------ llvm-svn: 367210 --- .../Target/BPF/BPFAbstractMemberAccess.cpp | 22 ++--- llvm/lib/Target/BPF/BTFDebug.cpp | 11 ++- .../BPF/CORE/offset-reloc-access-str.ll | 95 +++++++++++++++++++ 3 files changed, 111 insertions(+), 17 deletions(-) create mode 100644 llvm/test/CodeGen/BPF/CORE/offset-reloc-access-str.ll diff --git a/llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp b/llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp index 51d4cbc8a429..509484b71544 100644 --- a/llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp +++ b/llvm/lib/Target/BPF/BPFAbstractMemberAccess.cpp @@ -116,9 +116,8 @@ class BPFAbstractMemberAccess final : public ModulePass { void replaceWithGEP(std::vector &CallList, uint32_t NumOfZerosIndex, uint32_t DIIndex); - Value *computeBaseAndAccessStr(CallInst *Call, std::string &AccessStr, - std::string &AccessKey, uint32_t Kind, - MDNode *&TypeMeta); + Value *computeBaseAndAccessKey(CallInst *Call, std::string &AccessKey, + uint32_t Kind, MDNode *&TypeMeta); bool getAccessIndex(const Value *IndexValue, uint64_t &AccessIndex); bool transformGEPChain(Module &M, CallInst *Call, uint32_t Kind); }; @@ -340,8 +339,7 @@ bool BPFAbstractMemberAccess::getAccessIndex(const Value *IndexValue, /// Compute the base of the whole preserve_*_access_index chains, i.e., the base /// pointer of the first preserve_*_access_index call, and construct the access /// string, which will be the name of a global variable. -Value *BPFAbstractMemberAccess::computeBaseAndAccessStr(CallInst *Call, - std::string &AccessStr, +Value *BPFAbstractMemberAccess::computeBaseAndAccessKey(CallInst *Call, std::string &AccessKey, uint32_t Kind, MDNode *&TypeMeta) { @@ -392,16 +390,16 @@ Value *BPFAbstractMemberAccess::computeBaseAndAccessStr(CallInst *Call, if (!LastTypeName.size() || AccessIndices.size() > TypeNameIndex + 2) return nullptr; - // Construct the type string AccessStr. + // Construct the type string AccessKey. for (unsigned I = 0; I < AccessIndices.size(); ++I) - AccessStr = std::to_string(AccessIndices[I]) + ":" + AccessStr; + AccessKey = std::to_string(AccessIndices[I]) + ":" + AccessKey; if (TypeNameIndex == AccessIndices.size() - 1) - AccessStr = "0:" + AccessStr; + AccessKey = "0:" + AccessKey; // Access key is the type name + access string, uniquely identifying // one kernel memory access. - AccessKey = LastTypeName + ":" + AccessStr; + AccessKey = LastTypeName + ":" + AccessKey; return Base; } @@ -410,10 +408,10 @@ Value *BPFAbstractMemberAccess::computeBaseAndAccessStr(CallInst *Call, /// transformation to a chain of relocable GEPs. bool BPFAbstractMemberAccess::transformGEPChain(Module &M, CallInst *Call, uint32_t Kind) { - std::string AccessStr, AccessKey; + std::string AccessKey; MDNode *TypeMeta = nullptr; Value *Base = - computeBaseAndAccessStr(Call, AccessStr, AccessKey, Kind, TypeMeta); + computeBaseAndAccessKey(Call, AccessKey, Kind, TypeMeta); if (!Base) return false; @@ -432,7 +430,7 @@ bool BPFAbstractMemberAccess::transformGEPChain(Module &M, CallInst *Call, if (GEPGlobals.find(AccessKey) == GEPGlobals.end()) { GV = new GlobalVariable(M, Type::getInt64Ty(BB->getContext()), false, - GlobalVariable::ExternalLinkage, NULL, AccessStr); + GlobalVariable::ExternalLinkage, NULL, AccessKey); GV->addAttribute(BPFCoreSharedInfo::AmaAttr); // Set the metadata (debuginfo types) for the global. if (TypeMeta) diff --git a/llvm/lib/Target/BPF/BTFDebug.cpp b/llvm/lib/Target/BPF/BTFDebug.cpp index fa35c6619e21..3105eaec57ab 100644 --- a/llvm/lib/Target/BPF/BTFDebug.cpp +++ b/llvm/lib/Target/BPF/BTFDebug.cpp @@ -1006,19 +1006,20 @@ void BTFDebug::generateOffsetReloc(const MachineInstr *MI, unsigned RootId = populateStructType(RootTy); setTypeFromId(RootId, &PrevStructType, &PrevArrayType); unsigned RootTySize = PrevStructType->getStructSize(); + StringRef IndexPattern = AccessPattern.substr(AccessPattern.find_first_of(':') + 1); BTFOffsetReloc OffsetReloc; OffsetReloc.Label = ORSym; - OffsetReloc.OffsetNameOff = addString(AccessPattern.drop_back()); + OffsetReloc.OffsetNameOff = addString(IndexPattern.drop_back()); OffsetReloc.TypeID = RootId; uint32_t Start = 0, End = 0, Offset = 0; bool FirstAccess = true; - for (auto C : AccessPattern) { + for (auto C : IndexPattern) { if (C != ':') { End++; } else { - std::string SubStr = AccessPattern.substr(Start, End - Start); + std::string SubStr = IndexPattern.substr(Start, End - Start); int Loc = std::stoi(SubStr); if (FirstAccess) { @@ -1043,7 +1044,7 @@ void BTFDebug::generateOffsetReloc(const MachineInstr *MI, End = Start; } } - AccessOffsets[RootTy->getName().str() + ":" + AccessPattern.str()] = Offset; + AccessOffsets[AccessPattern.str()] = Offset; OffsetRelocTable[SecNameOff].push_back(OffsetReloc); } @@ -1227,7 +1228,7 @@ bool BTFDebug::InstLower(const MachineInstr *MI, MCInst &OutMI) { MDNode *MDN = GVar->getMetadata(LLVMContext::MD_preserve_access_index); DIType *Ty = dyn_cast(MDN); std::string TypeName = Ty->getName(); - int64_t Imm = AccessOffsets[TypeName + ":" + GVar->getName().str()]; + int64_t Imm = AccessOffsets[GVar->getName().str()]; // Emit "mov ri, " for abstract member accesses. OutMI.setOpcode(BPF::MOV_ri); diff --git a/llvm/test/CodeGen/BPF/CORE/offset-reloc-access-str.ll b/llvm/test/CodeGen/BPF/CORE/offset-reloc-access-str.ll new file mode 100644 index 000000000000..5625bf99fa48 --- /dev/null +++ b/llvm/test/CodeGen/BPF/CORE/offset-reloc-access-str.ll @@ -0,0 +1,95 @@ +; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck %s +; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck %s +; +; Source code: +; struct s { int a; int b; }; +; struct t { int c; int d; }; +; #define _(x) (__builtin_preserve_access_index(x)) +; int get_value(const void *addr1, const void *addr2); +; int test(struct s *arg1, struct t *arg2) { +; return get_value(_(&arg1->b), _(&arg2->d)); +; } +; clang -target bpf -S -O2 -g -emit-llvm test.c + +%struct.s = type { i32, i32 } +%struct.t = type { i32, i32 } + +; Function Attrs: nounwind +define dso_local i32 @test(%struct.s* %arg1, %struct.t* %arg2) local_unnamed_addr #0 !dbg !7 { +entry: + call void @llvm.dbg.value(metadata %struct.s* %arg1, metadata !22, metadata !DIExpression()), !dbg !24 + call void @llvm.dbg.value(metadata %struct.t* %arg2, metadata !23, metadata !DIExpression()), !dbg !24 + %0 = tail call i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.ss(%struct.s* %arg1, i32 1, i32 1), !dbg !25, !llvm.preserve.access.index !12 + %1 = bitcast i32* %0 to i8*, !dbg !25 + %2 = tail call i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.ts(%struct.t* %arg2, i32 1, i32 1), !dbg !26, !llvm.preserve.access.index !17 + %3 = bitcast i32* %2 to i8*, !dbg !26 + %call = tail call i32 @get_value(i8* %1, i8* %3) #4, !dbg !27 + ret i32 %call, !dbg !28 +} + +; CHECK: .section .BTF,"",@progbits +; CHECK: .ascii ".text" # string offset=[[SEC_INDEX:[0-9]+]] +; CHECK-NEXT: .byte 0 +; CHECK: .ascii "0:1" # string offset=[[ACCESS_STR:[0-9]+]] +; CHECK-NEXT: .byte 0 +; CHECK: .section .BTF.ext,"",@progbits +; CHECK: .long 12 # OffsetReloc +; CHECK-NEXT: .long [[SEC_INDEX]] # Offset reloc section string offset=[[SEC_INDEX]] +; CHECK-NEXT: .long 2 +; CHECK-NEXT: .long .Ltmp{{[0-9]+}} +; CHECK-NEXT: .long {{[0-9]+}} +; CHECK-NEXT: .long [[ACCESS_STR]] +; CHECK-NEXT: .long .Ltmp{{[0-9]+}} +; CHECK-NEXT: .long {{[0-9]+}} +; CHECK-NEXT: .long [[ACCESS_STR]] + +declare dso_local i32 @get_value(i8*, i8*) local_unnamed_addr #1 + +; Function Attrs: nounwind readnone +declare i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.ss(%struct.s*, i32 immarg, i32 immarg) #2 + +; Function Attrs: nounwind readnone +declare i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.ts(%struct.t*, i32 immarg, i32 immarg) #2 + +; Function Attrs: nounwind readnone speculatable +declare void @llvm.dbg.value(metadata, metadata, metadata) #3 + +attributes #0 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #1 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #2 = { nounwind readnone } +attributes #3 = { nounwind readnone speculatable } +attributes #4 = { nounwind } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5} +!llvm.ident = !{!6} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 10.0.0 (trunk 366831) (llvm/trunk 366867)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None) +!1 = !DIFile(filename: "test.c", directory: "/tmp/home/yhs/work/tests/llvm/core-bugs") +!2 = !{} +!3 = !{i32 2, !"Dwarf Version", i32 4} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"wchar_size", i32 4} +!6 = !{!"clang version 10.0.0 (trunk 366831) (llvm/trunk 366867)"} +!7 = distinct !DISubprogram(name: "test", scope: !1, file: !1, line: 5, type: !8, scopeLine: 5, flags: DIFlagPrototyped, isDefinition: true, isOptimized: true, unit: !0, retainedNodes: !21) +!8 = !DISubroutineType(types: !9) +!9 = !{!10, !11, !16} +!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!11 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !12, size: 64) +!12 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "s", file: !1, line: 1, size: 64, elements: !13) +!13 = !{!14, !15} +!14 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !12, file: !1, line: 1, baseType: !10, size: 32) +!15 = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: !12, file: !1, line: 1, baseType: !10, size: 32, offset: 32) +!16 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !17, size: 64) +!17 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t", file: !1, line: 2, size: 64, elements: !18) +!18 = !{!19, !20} +!19 = !DIDerivedType(tag: DW_TAG_member, name: "c", scope: !17, file: !1, line: 2, baseType: !10, size: 32) +!20 = !DIDerivedType(tag: DW_TAG_member, name: "d", scope: !17, file: !1, line: 2, baseType: !10, size: 32, offset: 32) +!21 = !{!22, !23} +!22 = !DILocalVariable(name: "arg1", arg: 1, scope: !7, file: !1, line: 5, type: !11) +!23 = !DILocalVariable(name: "arg2", arg: 2, scope: !7, file: !1, line: 5, type: !16) +!24 = !DILocation(line: 0, scope: !7) +!25 = !DILocation(line: 6, column: 20, scope: !7) +!26 = !DILocation(line: 6, column: 33, scope: !7) +!27 = !DILocation(line: 6, column: 10, scope: !7) +!28 = !DILocation(line: 6, column: 3, scope: !7) From ccddca30dd820fa34f2535fabded6f15575e0f0a Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Mon, 29 Jul 2019 09:01:42 +0000 Subject: [PATCH 040/289] Merging r367062: ------------------------------------------------------------------------ r367062 | yhs | 2019-07-25 23:47:27 +0200 (Thu, 25 Jul 2019) | 30 lines [BPF] fix typedef issue for offset relocation Currently, the CO-RE offset relocation does not work if any struct/union member or array element is a typedef. For example, typedef const int arr_t[7]; struct input { arr_t a; }; func(...) { struct input *in = ...; ... __builtin_preserve_access_index(&in->a[1]) ... } The BPF backend calculated default offset is 0 while 4 is the correct answer. Similar issues exist for struct/union typedef's. When getting struct/union member or array element type, we should trace down to the type by skipping typedef and qualifiers const/volatile as this is what clang did to generate getelementptr instructions. (const/volatile member type qualifiers are already ignored by clang.) This patch fixed this issue, for each access index, skipping typedef and const/volatile/restrict BTF types. Signed-off-by: Yonghong Song Differential Revision: https://reviews.llvm.org/D65259 ------------------------------------------------------------------------ llvm-svn: 367211 --- llvm/lib/Target/BPF/BTFDebug.cpp | 41 +++++-- llvm/lib/Target/BPF/BTFDebug.h | 6 +- .../BPF/CORE/offset-reloc-typedef-array.ll | 97 +++++++++++++++ .../BPF/CORE/offset-reloc-typedef-struct.ll | 90 ++++++++++++++ .../BPF/CORE/offset-reloc-typedef-union.ll | 90 ++++++++++++++ .../CodeGen/BPF/CORE/offset-reloc-typedef.ll | 111 ++++++++++++++++++ 6 files changed, 426 insertions(+), 9 deletions(-) create mode 100644 llvm/test/CodeGen/BPF/CORE/offset-reloc-typedef-array.ll create mode 100644 llvm/test/CodeGen/BPF/CORE/offset-reloc-typedef-struct.ll create mode 100644 llvm/test/CodeGen/BPF/CORE/offset-reloc-typedef-union.ll create mode 100644 llvm/test/CodeGen/BPF/CORE/offset-reloc-typedef.ll diff --git a/llvm/lib/Target/BPF/BTFDebug.cpp b/llvm/lib/Target/BPF/BTFDebug.cpp index 3105eaec57ab..5c542e739088 100644 --- a/llvm/lib/Target/BPF/BTFDebug.cpp +++ b/llvm/lib/Target/BPF/BTFDebug.cpp @@ -30,6 +30,18 @@ static const char *BTFKindStr[] = { #include "BTF.def" }; +static const DIType * stripQualifiers(const DIType *Ty) { + while (const auto *DTy = dyn_cast(Ty)) { + unsigned Tag = DTy->getTag(); + if (Tag != dwarf::DW_TAG_typedef && Tag != dwarf::DW_TAG_const_type && + Tag != dwarf::DW_TAG_volatile_type && Tag != dwarf::DW_TAG_restrict_type) + break; + Ty = DTy->getBaseType(); + } + + return Ty; +} + /// Emit a BTF common type. void BTFTypeBase::emitType(MCStreamer &OS) { OS.AddComment(std::string(BTFKindStr[Kind]) + "(id = " + std::to_string(Id) + @@ -184,9 +196,9 @@ void BTFTypeEnum::emitType(MCStreamer &OS) { } } -BTFTypeArray::BTFTypeArray(uint32_t ElemTypeId, uint32_t ElemSize, - uint32_t NumElems) - : ElemSize(ElemSize) { +BTFTypeArray::BTFTypeArray(const DIType *Ty, uint32_t ElemTypeId, + uint32_t ElemSize, uint32_t NumElems) + : ElemTyNoQual(Ty), ElemSize(ElemSize) { Kind = BTF::BTF_KIND_ARRAY; BTFType.NameOff = 0; BTFType.Info = Kind << 24; @@ -207,6 +219,9 @@ void BTFTypeArray::completeType(BTFDebug &BDebug) { // created during initial type traversal. Just // retrieve that type id. ArrayInfo.IndexType = BDebug.getArrayIndexTypeId(); + + ElemTypeNoQual = ElemTyNoQual ? BDebug.getTypeId(ElemTyNoQual) + : ArrayInfo.ElemType; } void BTFTypeArray::emitType(MCStreamer &OS) { @@ -218,7 +233,7 @@ void BTFTypeArray::emitType(MCStreamer &OS) { void BTFTypeArray::getLocInfo(uint32_t Loc, uint32_t &LocOffset, uint32_t &ElementTypeId) { - ElementTypeId = ArrayInfo.ElemType; + ElementTypeId = ElemTypeNoQual; LocOffset = Loc * ElemSize; } @@ -251,7 +266,9 @@ void BTFTypeStruct::completeType(BTFDebug &BDebug) { } else { BTFMember.Offset = DDTy->getOffsetInBits(); } - BTFMember.Type = BDebug.getTypeId(DDTy->getBaseType()); + const auto *BaseTy = DDTy->getBaseType(); + BTFMember.Type = BDebug.getTypeId(BaseTy); + MemberTypeNoQual.push_back(BDebug.getTypeId(stripQualifiers(BaseTy))); Members.push_back(BTFMember); } } @@ -270,7 +287,7 @@ std::string BTFTypeStruct::getName() { return STy->getName(); } void BTFTypeStruct::getMemberInfo(uint32_t Loc, uint32_t &MemberOffset, uint32_t &MemberType) { - MemberType = Members[Loc].Type; + MemberType = MemberTypeNoQual[Loc]; MemberOffset = HasBitField ? Members[Loc].Offset & 0xffffff : Members[Loc].Offset; } @@ -492,10 +509,13 @@ void BTFDebug::visitArrayType(const DICompositeType *CTy, uint32_t &TypeId) { uint32_t ElemTypeId, ElemSize; const DIType *ElemType = CTy->getBaseType(); visitTypeEntry(ElemType, ElemTypeId, false, false); + + // Strip qualifiers from element type to get accurate element size. + ElemType = stripQualifiers(ElemType); ElemSize = ElemType->getSizeInBits() >> 3; if (!CTy->getSizeInBits()) { - auto TypeEntry = llvm::make_unique(ElemTypeId, 0, 0); + auto TypeEntry = llvm::make_unique(ElemType, ElemTypeId, 0, 0); ArrayTypes.push_back(TypeEntry.get()); ElemTypeId = addType(std::move(TypeEntry), CTy); } else { @@ -507,9 +527,11 @@ void BTFDebug::visitArrayType(const DICompositeType *CTy, uint32_t &TypeId) { const DISubrange *SR = cast(Element); auto *CI = SR->getCount().dyn_cast(); int64_t Count = CI->getSExtValue(); + const DIType *ArrayElemTy = (I == 0) ? ElemType : nullptr; auto TypeEntry = - llvm::make_unique(ElemTypeId, ElemSize, Count); + llvm::make_unique(ArrayElemTy, ElemTypeId, + ElemSize, Count); ArrayTypes.push_back(TypeEntry.get()); if (I == 0) ElemTypeId = addType(std::move(TypeEntry), CTy); @@ -1039,7 +1061,10 @@ void BTFDebug::generateOffsetReloc(const MachineInstr *MI, Offset += LocOffset; PrevArrayType = nullptr; setTypeFromId(ElementTypeId, &PrevStructType, &PrevArrayType); + } else { + llvm_unreachable("Internal Error: BTF offset relocation type traversal error"); } + Start = End + 1; End = Start; } diff --git a/llvm/lib/Target/BPF/BTFDebug.h b/llvm/lib/Target/BPF/BTFDebug.h index 6c0cdde17d9b..e210d18f941e 100644 --- a/llvm/lib/Target/BPF/BTFDebug.h +++ b/llvm/lib/Target/BPF/BTFDebug.h @@ -104,11 +104,14 @@ class BTFTypeEnum : public BTFTypeBase { /// Handle array type. class BTFTypeArray : public BTFTypeBase { + const DIType *ElemTyNoQual; uint32_t ElemSize; struct BTF::BTFArray ArrayInfo; + uint32_t ElemTypeNoQual; public: - BTFTypeArray(uint32_t ElemTypeId, uint32_t ElemSize, uint32_t NumElems); + BTFTypeArray(const DIType *Ty, uint32_t ElemTypeId, + uint32_t ElemSize, uint32_t NumElems); uint32_t getSize() { return BTFTypeBase::getSize() + BTF::BTFArraySize; } void completeType(BTFDebug &BDebug); void emitType(MCStreamer &OS); @@ -120,6 +123,7 @@ class BTFTypeStruct : public BTFTypeBase { const DICompositeType *STy; bool HasBitField; std::vector Members; + std::vector MemberTypeNoQual; public: BTFTypeStruct(const DICompositeType *STy, bool IsStruct, bool HasBitField, diff --git a/llvm/test/CodeGen/BPF/CORE/offset-reloc-typedef-array.ll b/llvm/test/CodeGen/BPF/CORE/offset-reloc-typedef-array.ll new file mode 100644 index 000000000000..7843c52c5ad8 --- /dev/null +++ b/llvm/test/CodeGen/BPF/CORE/offset-reloc-typedef-array.ll @@ -0,0 +1,97 @@ +; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck %s +; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck %s +; +; Source code: +; typedef const int arr_t[7]; +; typedef arr_t __arr; +; typedef __arr _arr; +; struct __s { _arr a; }; +; typedef struct __s s; +; #define _(x) (__builtin_preserve_access_index(x)) +; int get_value(const void *addr); +; int test(s *arg) { +; return get_value(_(&arg->a[1])); +; } +; clang -target bpf -S -O2 -g -emit-llvm test.c + +%struct.__s = type { [7 x i32] } + +; Function Attrs: nounwind +define dso_local i32 @test(%struct.__s* %arg) local_unnamed_addr #0 !dbg !7 { +entry: + call void @llvm.dbg.value(metadata %struct.__s* %arg, metadata !24, metadata !DIExpression()), !dbg !25 + %0 = tail call [7 x i32]* @llvm.preserve.struct.access.index.p0a7i32.p0s_struct.__ss(%struct.__s* %arg, i32 0, i32 0), !dbg !26, !llvm.preserve.access.index !13 + %1 = tail call i32* @llvm.preserve.array.access.index.p0i32.p0a7i32([7 x i32]* %0, i32 1, i32 1), !dbg !26 + %2 = bitcast i32* %1 to i8*, !dbg !26 + %call = tail call i32 @get_value(i8* %2) #4, !dbg !27 + ret i32 %call, !dbg !28 +} + +; CHECK: .cfi_startproc +; CHECK: [[RELOC:.Ltmp[0-9]+]]: +; CHECK: r2 = 4 +; CHECK: r1 += r2 +; CHECK: call get_value + +; CHECK: .long {{[0-9]+}} # BTF_KIND_STRUCT(id = [[TYPE_ID:[0-9]+]]) +; CHECK: .ascii ".text" # string offset=[[SEC_INDEX:[0-9]+]] +; CHECK-NEXT: .byte 0 +; CHECK: .ascii "0:0:1" # string offset=[[ACCESS_STR:[0-9]+]] +; CHECK-NEXT: .byte 0 +; CHECK: .long 12 # OffsetReloc +; CHECK-NEXT: .long [[SEC_INDEX]] # Offset reloc section string offset=[[SEC_INDEX]] +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long [[RELOC]] +; CHECK-NEXT: .long [[TYPE_ID]] +; CHECK-NEXT: .long [[ACCESS_STR]] + +declare dso_local i32 @get_value(i8*) local_unnamed_addr #1 + +; Function Attrs: nounwind readnone +declare [7 x i32]* @llvm.preserve.struct.access.index.p0a7i32.p0s_struct.__ss(%struct.__s*, i32 immarg, i32 immarg) #2 + +; Function Attrs: nounwind readnone +declare i32* @llvm.preserve.array.access.index.p0i32.p0a7i32([7 x i32]*, i32 immarg, i32 immarg) #2 + +; Function Attrs: nounwind readnone speculatable +declare void @llvm.dbg.value(metadata, metadata, metadata) #3 + +attributes #0 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #1 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #2 = { nounwind readnone } +attributes #3 = { nounwind readnone speculatable } +attributes #4 = { nounwind } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5} +!llvm.ident = !{!6} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 10.0.0 (trunk 366831) (llvm/trunk 366867)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None) +!1 = !DIFile(filename: "test.c", directory: "/tmp/home/yhs/work/tests/llvm/core-bugs") +!2 = !{} +!3 = !{i32 2, !"Dwarf Version", i32 4} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"wchar_size", i32 4} +!6 = !{!"clang version 10.0.0 (trunk 366831) (llvm/trunk 366867)"} +!7 = distinct !DISubprogram(name: "test", scope: !1, file: !1, line: 8, type: !8, scopeLine: 8, flags: DIFlagPrototyped, isDefinition: true, isOptimized: true, unit: !0, retainedNodes: !23) +!8 = !DISubroutineType(types: !9) +!9 = !{!10, !11} +!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!11 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !12, size: 64) +!12 = !DIDerivedType(tag: DW_TAG_typedef, name: "s", file: !1, line: 5, baseType: !13) +!13 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "__s", file: !1, line: 4, size: 224, elements: !14) +!14 = !{!15} +!15 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !13, file: !1, line: 4, baseType: !16, size: 224) +!16 = !DIDerivedType(tag: DW_TAG_typedef, name: "_arr", file: !1, line: 3, baseType: !17) +!17 = !DIDerivedType(tag: DW_TAG_typedef, name: "__arr", file: !1, line: 2, baseType: !18) +!18 = !DIDerivedType(tag: DW_TAG_typedef, name: "arr_t", file: !1, line: 1, baseType: !19) +!19 = !DICompositeType(tag: DW_TAG_array_type, baseType: !20, size: 224, elements: !21) +!20 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !10) +!21 = !{!22} +!22 = !DISubrange(count: 7) +!23 = !{!24} +!24 = !DILocalVariable(name: "arg", arg: 1, scope: !7, file: !1, line: 8, type: !11) +!25 = !DILocation(line: 0, scope: !7) +!26 = !DILocation(line: 9, column: 20, scope: !7) +!27 = !DILocation(line: 9, column: 10, scope: !7) +!28 = !DILocation(line: 9, column: 3, scope: !7) diff --git a/llvm/test/CodeGen/BPF/CORE/offset-reloc-typedef-struct.ll b/llvm/test/CodeGen/BPF/CORE/offset-reloc-typedef-struct.ll new file mode 100644 index 000000000000..a0d7532bf480 --- /dev/null +++ b/llvm/test/CodeGen/BPF/CORE/offset-reloc-typedef-struct.ll @@ -0,0 +1,90 @@ +; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck %s +; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck %s +; +; Source code: +; typedef int _int; +; typedef _int __int; +; struct __s { __int a; __int b; }; +; typedef struct __s _s; +; typedef _s s; +; #define _(x) (__builtin_preserve_access_index(x)) +; int get_value(const void *addr); +; int test(s *arg) { +; return get_value(_(&arg->b)); +; } +; clang -target bpf -S -O2 -g -emit-llvm test.c + +%struct.__s = type { i32, i32 } + +; Function Attrs: nounwind +define dso_local i32 @test(%struct.__s* %arg) local_unnamed_addr #0 !dbg !7 { +entry: + call void @llvm.dbg.value(metadata %struct.__s* %arg, metadata !21, metadata !DIExpression()), !dbg !22 + %0 = tail call i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.__ss(%struct.__s* %arg, i32 1, i32 1), !dbg !23, !llvm.preserve.access.index !14 + %1 = bitcast i32* %0 to i8*, !dbg !23 + %call = tail call i32 @get_value(i8* %1) #4, !dbg !24 + ret i32 %call, !dbg !25 +} + +; CHECK: .cfi_startproc +; CHECK: [[RELOC:.Ltmp[0-9]+]]: +; CHECK: r2 = 4 +; CHECK: r1 += r2 +; CHECK: call get_value + +; CHECK: .long {{[0-9]+}} # BTF_KIND_STRUCT(id = [[TYPE_ID:[0-9]+]]) +; CHECK: .ascii ".text" # string offset=[[SEC_STR:[0-9]+]] +; CHECK-NEXT: .byte 0 +; CHECK: .ascii "0:1" # string offset=[[ACCESS_STR:[0-9]+]] +; CHECK-NEXT: .byte 0 +; CHECK: .long 12 # OffsetReloc +; CHECK-NEXT: .long [[SEC_STR]] # Offset reloc section string offset={{[0-9]+}} +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long [[RELOC]] +; CHECK-NEXT: .long [[TYPE_ID]] +; CHECK-NEXT: .long [[ACCESS_STR]] + +declare dso_local i32 @get_value(i8*) local_unnamed_addr #1 + +; Function Attrs: nounwind readnone +declare i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.__ss(%struct.__s*, i32 immarg, i32 immarg) #2 + +; Function Attrs: nounwind readnone speculatable +declare void @llvm.dbg.value(metadata, metadata, metadata) #3 + +attributes #0 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #1 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #2 = { nounwind readnone } +attributes #3 = { nounwind readnone speculatable } +attributes #4 = { nounwind } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5} +!llvm.ident = !{!6} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 10.0.0 (trunk 366831) (llvm/trunk 366867)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None) +!1 = !DIFile(filename: "test.c", directory: "/tmp/home/yhs/work/tests/llvm/core-bugs") +!2 = !{} +!3 = !{i32 2, !"Dwarf Version", i32 4} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"wchar_size", i32 4} +!6 = !{!"clang version 10.0.0 (trunk 366831) (llvm/trunk 366867)"} +!7 = distinct !DISubprogram(name: "test", scope: !1, file: !1, line: 8, type: !8, scopeLine: 8, flags: DIFlagPrototyped, isDefinition: true, isOptimized: true, unit: !0, retainedNodes: !20) +!8 = !DISubroutineType(types: !9) +!9 = !{!10, !11} +!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!11 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !12, size: 64) +!12 = !DIDerivedType(tag: DW_TAG_typedef, name: "s", file: !1, line: 5, baseType: !13) +!13 = !DIDerivedType(tag: DW_TAG_typedef, name: "_s", file: !1, line: 4, baseType: !14) +!14 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "__s", file: !1, line: 3, size: 64, elements: !15) +!15 = !{!16, !19} +!16 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !14, file: !1, line: 3, baseType: !17, size: 32) +!17 = !DIDerivedType(tag: DW_TAG_typedef, name: "__int", file: !1, line: 2, baseType: !18) +!18 = !DIDerivedType(tag: DW_TAG_typedef, name: "_int", file: !1, line: 1, baseType: !10) +!19 = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: !14, file: !1, line: 3, baseType: !17, size: 32, offset: 32) +!20 = !{!21} +!21 = !DILocalVariable(name: "arg", arg: 1, scope: !7, file: !1, line: 8, type: !11) +!22 = !DILocation(line: 0, scope: !7) +!23 = !DILocation(line: 9, column: 20, scope: !7) +!24 = !DILocation(line: 9, column: 10, scope: !7) +!25 = !DILocation(line: 9, column: 3, scope: !7) diff --git a/llvm/test/CodeGen/BPF/CORE/offset-reloc-typedef-union.ll b/llvm/test/CodeGen/BPF/CORE/offset-reloc-typedef-union.ll new file mode 100644 index 000000000000..caefc2b4bc6a --- /dev/null +++ b/llvm/test/CodeGen/BPF/CORE/offset-reloc-typedef-union.ll @@ -0,0 +1,90 @@ +; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck %s +; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck %s +; +; Source code: +; typedef int _int; +; typedef _int __int; +; union __s { __int a; __int b; }; +; typedef union __s _s; +; typedef _s s; +; #define _(x) (__builtin_preserve_access_index(x)) +; int get_value(const void *addr); +; int test(s *arg) { +; return get_value(_(&arg->b)); +; } +; clang -target bpf -S -O2 -g -emit-llvm test.c + +%union.__s = type { i32 } + +; Function Attrs: nounwind +define dso_local i32 @test(%union.__s* %arg) local_unnamed_addr #0 !dbg !7 { +entry: + call void @llvm.dbg.value(metadata %union.__s* %arg, metadata !21, metadata !DIExpression()), !dbg !22 + %0 = tail call %union.__s* @llvm.preserve.union.access.index.p0s_union.__ss.p0s_union.__ss(%union.__s* %arg, i32 1), !dbg !23, !llvm.preserve.access.index !14 + %1 = bitcast %union.__s* %0 to i8*, !dbg !23 + %call = tail call i32 @get_value(i8* %1) #4, !dbg !24 + ret i32 %call, !dbg !25 +} + +; CHECK: .cfi_startproc +; CHECK: [[RELOC:.Ltmp[0-9]+]]: +; CHECK: r2 = 0 +; CHECK: r1 += r2 +; CHECK: call get_value + +; CHECK: .long {{[0-9]+}} # BTF_KIND_UNION(id = [[TYPE_ID:[0-9]+]]) +; CHECK: .ascii ".text" # string offset=[[SEC_INDEX:[0-9]+]] +; CHECK-NEXT: .byte 0 +; CHECK: .ascii "0:1" # string offset=[[ACCESS_STR:[0-9]+]] +; CHECK-NEXT: .byte 0 +; CHECK: .long 12 # OffsetReloc +; CHECK-NEXT: .long [[SEC_INDEX]] # Offset reloc section string offset=[[SEC_INDEX]] +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long [[RELOC]] +; CHECK-NEXT: .long [[TYPE_ID]] +; CHECK-NEXT: .long [[ACCESS_STR]] + +declare dso_local i32 @get_value(i8*) local_unnamed_addr #1 + +; Function Attrs: nounwind readnone +declare %union.__s* @llvm.preserve.union.access.index.p0s_union.__ss.p0s_union.__ss(%union.__s*, i32 immarg) #2 + +; Function Attrs: nounwind readnone speculatable +declare void @llvm.dbg.value(metadata, metadata, metadata) #3 + +attributes #0 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #1 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #2 = { nounwind readnone } +attributes #3 = { nounwind readnone speculatable } +attributes #4 = { nounwind } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5} +!llvm.ident = !{!6} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 10.0.0 (trunk 366831) (llvm/trunk 366867)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None) +!1 = !DIFile(filename: "test.c", directory: "/tmp/home/yhs/work/tests/llvm/core-bugs") +!2 = !{} +!3 = !{i32 2, !"Dwarf Version", i32 4} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"wchar_size", i32 4} +!6 = !{!"clang version 10.0.0 (trunk 366831) (llvm/trunk 366867)"} +!7 = distinct !DISubprogram(name: "test", scope: !1, file: !1, line: 8, type: !8, scopeLine: 8, flags: DIFlagPrototyped, isDefinition: true, isOptimized: true, unit: !0, retainedNodes: !20) +!8 = !DISubroutineType(types: !9) +!9 = !{!10, !11} +!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!11 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !12, size: 64) +!12 = !DIDerivedType(tag: DW_TAG_typedef, name: "s", file: !1, line: 5, baseType: !13) +!13 = !DIDerivedType(tag: DW_TAG_typedef, name: "_s", file: !1, line: 4, baseType: !14) +!14 = distinct !DICompositeType(tag: DW_TAG_union_type, name: "__s", file: !1, line: 3, size: 32, elements: !15) +!15 = !{!16, !19} +!16 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !14, file: !1, line: 3, baseType: !17, size: 32) +!17 = !DIDerivedType(tag: DW_TAG_typedef, name: "__int", file: !1, line: 2, baseType: !18) +!18 = !DIDerivedType(tag: DW_TAG_typedef, name: "_int", file: !1, line: 1, baseType: !10) +!19 = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: !14, file: !1, line: 3, baseType: !17, size: 32) +!20 = !{!21} +!21 = !DILocalVariable(name: "arg", arg: 1, scope: !7, file: !1, line: 8, type: !11) +!22 = !DILocation(line: 0, scope: !7) +!23 = !DILocation(line: 9, column: 20, scope: !7) +!24 = !DILocation(line: 9, column: 10, scope: !7) +!25 = !DILocation(line: 9, column: 3, scope: !7) diff --git a/llvm/test/CodeGen/BPF/CORE/offset-reloc-typedef.ll b/llvm/test/CodeGen/BPF/CORE/offset-reloc-typedef.ll new file mode 100644 index 000000000000..c09d97991d9e --- /dev/null +++ b/llvm/test/CodeGen/BPF/CORE/offset-reloc-typedef.ll @@ -0,0 +1,111 @@ +; RUN: llc -march=bpfel -filetype=asm -o - %s | FileCheck %s +; RUN: llc -march=bpfeb -filetype=asm -o - %s | FileCheck %s +; +; Source code: +; struct s { int a; int b; }; +; typedef struct s __s; +; union u { __s c; __s d; }; +; typedef union u __u; +; typedef __u arr_t[7]; +; typedef arr_t __arr; +; +; #define _(x) (__builtin_preserve_access_index(x)) +; int get_value(const void *addr); +; int test(__arr *arg) { +; return get_value(_(&arg[1]->d.b)); +; } +; clang -target bpf -S -O2 -g -emit-llvm test.c +; The offset reloc offset should be 12 from the base "arg". + +%union.u = type { %struct.s } +%struct.s = type { i32, i32 } + +; Function Attrs: nounwind +define dso_local i32 @test([7 x %union.u]* %arg) local_unnamed_addr #0 !dbg !7 { +entry: + call void @llvm.dbg.value(metadata [7 x %union.u]* %arg, metadata !28, metadata !DIExpression()), !dbg !29 + %0 = tail call [7 x %union.u]* @llvm.preserve.array.access.index.p0a7s_union.us.p0a7s_union.us([7 x %union.u]* %arg, i32 0, i32 1), !dbg !30 + %arraydecay = getelementptr inbounds [7 x %union.u], [7 x %union.u]* %0, i64 0, i64 0, !dbg !30 + %1 = tail call %union.u* @llvm.preserve.union.access.index.p0s_union.us.p0s_union.us(%union.u* %arraydecay, i32 1), !dbg !30, !llvm.preserve.access.index !16 + %d = getelementptr inbounds %union.u, %union.u* %1, i64 0, i32 0, !dbg !30 + %2 = tail call i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.ss(%struct.s* %d, i32 1, i32 1), !dbg !30, !llvm.preserve.access.index !20 + %3 = bitcast i32* %2 to i8*, !dbg !30 + %call = tail call i32 @get_value(i8* %3) #4, !dbg !31 + ret i32 %call, !dbg !32 +} + +; CHECK: .cfi_startproc +; CHECK: [[RELOC:.Ltmp[0-9]+]]: +; CHECK: r2 = 12 +; CHECK: r1 += r2 +; CHECK: call get_value + +; CHECK: .long {{[0-9]+}} # BTF_KIND_UNION(id = [[TYPE_ID:[0-9]+]]) +; CHECK: .ascii ".text" # string offset=[[SEC_STR:[0-9]+]] +; CHECK-NEXT: .byte 0 +; CHECK: .ascii "1:1:1" # string offset=[[ACCESS_STR:[0-9]+]] +; CHECK-NEXT: .byte 0 +; CHECK: .long 12 # OffsetReloc +; CHECK-NEXT: .long [[SEC_STR:[0-9]+]] # Offset reloc section string offset=[[SEC_STR:[0-9]+]] +; CHECK-NEXT: .long 1 +; CHECK-NEXT: .long [[RELOC:.Ltmp[0-9]+]] +; CHECK-NEXT: .long [[TYPE_ID:[0-9]+]] +; CHECK-NEXT: .long [[ACCESS_STR:[0-9]+]] + +declare dso_local i32 @get_value(i8*) local_unnamed_addr #1 + +; Function Attrs: nounwind readnone +declare [7 x %union.u]* @llvm.preserve.array.access.index.p0a7s_union.us.p0a7s_union.us([7 x %union.u]*, i32 immarg, i32 immarg) #2 + +; Function Attrs: nounwind readnone +declare %union.u* @llvm.preserve.union.access.index.p0s_union.us.p0s_union.us(%union.u*, i32 immarg) #2 + +; Function Attrs: nounwind readnone +declare i32* @llvm.preserve.struct.access.index.p0i32.p0s_struct.ss(%struct.s*, i32 immarg, i32 immarg) #2 + +; Function Attrs: nounwind readnone speculatable +declare void @llvm.dbg.value(metadata, metadata, metadata) #3 + +attributes #0 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #1 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="all" "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #2 = { nounwind readnone } +attributes #3 = { nounwind readnone speculatable } +attributes #4 = { nounwind } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5} +!llvm.ident = !{!6} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 10.0.0 (trunk 366831) (llvm/trunk 366867)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None) +!1 = !DIFile(filename: "test.c", directory: "/tmp/home/yhs/work/tests/llvm/core-bugs") +!2 = !{} +!3 = !{i32 2, !"Dwarf Version", i32 4} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"wchar_size", i32 4} +!6 = !{!"clang version 10.0.0 (trunk 366831) (llvm/trunk 366867)"} +!7 = distinct !DISubprogram(name: "test", scope: !1, file: !1, line: 10, type: !8, scopeLine: 10, flags: DIFlagPrototyped, isDefinition: true, isOptimized: true, unit: !0, retainedNodes: !27) +!8 = !DISubroutineType(types: !9) +!9 = !{!10, !11} +!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!11 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !12, size: 64) +!12 = !DIDerivedType(tag: DW_TAG_typedef, name: "__arr", file: !1, line: 6, baseType: !13) +!13 = !DIDerivedType(tag: DW_TAG_typedef, name: "arr_t", file: !1, line: 5, baseType: !14) +!14 = !DICompositeType(tag: DW_TAG_array_type, baseType: !15, size: 448, elements: !25) +!15 = !DIDerivedType(tag: DW_TAG_typedef, name: "__u", file: !1, line: 4, baseType: !16) +!16 = distinct !DICompositeType(tag: DW_TAG_union_type, name: "u", file: !1, line: 3, size: 64, elements: !17) +!17 = !{!18, !24} +!18 = !DIDerivedType(tag: DW_TAG_member, name: "c", scope: !16, file: !1, line: 3, baseType: !19, size: 64) +!19 = !DIDerivedType(tag: DW_TAG_typedef, name: "__s", file: !1, line: 2, baseType: !20) +!20 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "s", file: !1, line: 1, size: 64, elements: !21) +!21 = !{!22, !23} +!22 = !DIDerivedType(tag: DW_TAG_member, name: "a", scope: !20, file: !1, line: 1, baseType: !10, size: 32) +!23 = !DIDerivedType(tag: DW_TAG_member, name: "b", scope: !20, file: !1, line: 1, baseType: !10, size: 32, offset: 32) +!24 = !DIDerivedType(tag: DW_TAG_member, name: "d", scope: !16, file: !1, line: 3, baseType: !19, size: 64) +!25 = !{!26} +!26 = !DISubrange(count: 7) +!27 = !{!28} +!28 = !DILocalVariable(name: "arg", arg: 1, scope: !7, file: !1, line: 10, type: !11) +!29 = !DILocation(line: 0, scope: !7) +!30 = !DILocation(line: 11, column: 20, scope: !7) +!31 = !DILocation(line: 11, column: 10, scope: !7) +!32 = !DILocation(line: 11, column: 3, scope: !7) From a99af82ee07f218aea0285074e69d3fe3dd301fc Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Mon, 29 Jul 2019 09:16:42 +0000 Subject: [PATCH 041/289] UsersManual.rst: Update clang-cl command reference llvm-svn: 367212 --- clang/docs/UsersManual.rst | 103 +++++++++++++++++++++++-------------- 1 file changed, 63 insertions(+), 40 deletions(-) diff --git a/clang/docs/UsersManual.rst b/clang/docs/UsersManual.rst index 2fbb414f6820..f800e86e855c 100644 --- a/clang/docs/UsersManual.rst +++ b/clang/docs/UsersManual.rst @@ -2998,42 +2998,42 @@ Execute ``clang-cl /?`` to see a list of supported options: CL.EXE COMPATIBILITY OPTIONS: /? Display available options /arch: Set architecture for code generation - /Brepro- Emit an object file which cannot be reproduced over time - /Brepro Emit an object file which can be reproduced over time + /Brepro- Write current time into COFF output (default) + /Brepro Do not write current time into COFF output (breaks link.exe /incremental) /clang: Pass to the clang driver - /C Don't discard comments when preprocessing + /C Do not discard comments when preprocessing /c Compile only /d1PP Retain macro definitions in /E mode /d1reportAllClassLayout Dump record layout information - /diagnostics:caret Enable caret and column diagnostics (on by default) + /diagnostics:caret Enable caret and column diagnostics (default) /diagnostics:classic Disable column and caret diagnostics /diagnostics:column Disable caret diagnostics but keep column info /D Define macro - /EH Exception handling model + /EH Set exception handling model /EP Disable linemarker output and preprocess to stdout /execution-charset: - Runtime encoding, supports only UTF-8 + Set runtime encoding, supports only UTF-8 /E Preprocess to stdout /fallback Fall back to cl.exe if clang-cl fails to compile /FA Output assembly code file during compilation - /Fa Output assembly code to this file during compilation (with /FA) - /Fe Set output executable file or directory (ends in / or \) + /Fa Set assembly output file name (with /FA) + /Fe Set output executable file name /FI Include file before parsing /Fi Set preprocess output file name (with /P) - /Fo Set output object file, or directory (ends in / or \) (with /c) + /Fo Set output object file (with /c) /fp:except- /fp:except /fp:fast /fp:precise /fp:strict - /Fp Set pch filename (with /Yc and /Yu) + /Fp Set pch file name (with /Yc and /Yu) /GA Assume thread-local variables are defined in the executable /Gd Set __cdecl as a default calling convention /GF- Disable string pooling /GF Enable string pooling (default) - /GR- Disable emission of RTTI data + /GR- Do not emit RTTI data /Gregcall Set __regcall as a default calling convention - /GR Enable emission of RTTI data + /GR Emit RTTI data (default) /Gr Set __fastcall as a default calling convention /GS- Disable buffer security check /GS Enable buffer security check (default) @@ -3042,15 +3042,15 @@ Execute ``clang-cl /?`` to see a list of supported options: /guard: Enable Control Flow Guard with /guard:cf, or only the table with /guard:cf,nochecks /Gv Set __vectorcall as a default calling convention - /Gw- Don't put each data item in its own section + /Gw- Do not put each data item in its own section (default) /Gw Put each data item in its own section - /GX- Disable exception handling - /GX Enable exception handling - /Gy- Don't put each function in its own section (default) + /GX- Deprecated (like not passing /EH) + /GX Deprecated; use /EHsc + /Gy- Do not put each function in its own section (default) /Gy Put each function in its own section /Gz Set __stdcall as a default calling convention /help Display available options - /imsvc Add directory to system include search path, as if part of %INCLUDE% + /imsvc Add to system include search path, as if in %INCLUDE% /I Add directory to include search path /J Make char type unsigned /LDd Create debug DLL @@ -3060,11 +3060,10 @@ Execute ``clang-cl /?`` to see a list of supported options: /MD Use DLL run-time /MTd Use static debug run-time /MT Use static run-time - /O0 Disable optimization - /O1 Optimize for size (same as /Og /Os /Oy /Ob2 /GF /Gy) - /O2 Optimize for speed (same as /Og /Oi /Ot /Oy /Ob2 /GF /Gy) + /O1 Optimize for size (like /Og /Os /Oy /Ob2 /GF /Gy) + /O2 Optimize for speed (like /Og /Oi /Ot /Oy /Ob2 /GF /Gy) /Ob0 Disable function inlining - /Ob1 Only inline functions which are (explicitly or implicitly) marked inline + /Ob1 Only inline functions explicitly or implicitly marked inline /Ob2 Inline functions as deemed beneficial by the compiler /Od Disable optimization /Og No effect @@ -3072,23 +3071,23 @@ Execute ``clang-cl /?`` to see a list of supported options: /Oi Enable use of builtin functions /Os Optimize for size /Ot Optimize for speed - /Ox Deprecated (same as /Og /Oi /Ot /Oy /Ob2); use /O2 instead + /Ox Deprecated (like /Og /Oi /Ot /Oy /Ob2); use /O2 /Oy- Disable frame pointer omission (x86 only, default) /Oy Enable frame pointer omission (x86 only) /O Set multiple /O flags at once; e.g. '/O2y-' for '/O2 /Oy-' - /o Set output file or directory (ends in / or \) + /o Deprecated (set output file name); use /Fe or /Fe /P Preprocess to file /Qvec- Disable the loop vectorization passes /Qvec Enable the loop vectorization passes - /showFilenames- Don't print the name of each compiled file (default) + /showFilenames- Do not print the name of each compiled file (default) /showFilenames Print the name of each compiled file /showIncludes Print info about included files to stderr - /source-charset: Source encoding, supports only UTF-8 - /std: Language standard to compile for + /source-charset: Set source encoding, supports only UTF-8 + /std: Set C++ version (c++14,c++17,c++latest) /TC Treat all source files as C - /Tc Specify a C source file + /Tc Treat as C source file /TP Treat all source files as C++ - /Tp Specify a C++ source file + /Tp Treat as C++ source file /utf-8 Set source and runtime encoding to UTF-8 (default) /U Undefine macro /vd Control vtordisp placement @@ -3105,17 +3104,19 @@ Execute ``clang-cl /?`` to see a list of supported options: /W3 Enable -Wall /W4 Enable -Wall and -Wextra /Wall Enable -Weverything - /WX- Do not treat warnings as errors + /WX- Do not treat warnings as errors (default) /WX Treat warnings as errors /w Disable all warnings - /X Don't add %INCLUDE% to the include search path + /X Do not add %INCLUDE% to include search path /Y- Disable precompiled headers, overrides /Yc and /Yu /Yc Generate a pch file for all code up to and including /Yu Load a pch file and use it instead of all code up to and including /Z7 Enable CodeView debug information in object files - /Zc:char8_t Enable C++2a char8_t type - /Zc:char8_t- Disable C++2a char8_t type - /Zc:dllexportInlines- Don't dllexport/dllimport inline member functions of dllexport/import classes + /Zc:alignedNew- Disable C++17 aligned allocation functions + /Zc:alignedNew Enable C++17 aligned allocation functions + /Zc:char8_t- Disable char8_t from c++2a + /Zc:char8_t Enable char8_t from C++2a + /Zc:dllexportInlines- Do not dllexport/dllimport inline member functions of dllexport/import classes /Zc:dllexportInlines dllexport/dllimport inline member functions of dllexport/import classes (default) /Zc:sizedDealloc- Disable C++14 sized global deallocation functions /Zc:sizedDealloc Enable C++14 sized global deallocation functions @@ -3124,13 +3125,13 @@ Execute ``clang-cl /?`` to see a list of supported options: /Zc:threadSafeInit Enable thread-safe initialization of static variables /Zc:trigraphs- Disable trigraphs (default) /Zc:trigraphs Enable trigraphs - /Zc:twoPhase- Disable two-phase name lookup in templates + /Zc:twoPhase- Disable two-phase name lookup in templates (default) /Zc:twoPhase Enable two-phase name lookup in templates /Zd Emit debug line number tables only - /Zi Alias for /Z7. Does not produce PDBs. - /Zl Don't mention any default libraries in the object file - /Zp Set the default maximum struct packing alignment to 1 - /Zp Specify the default maximum struct packing alignment + /Zi Like /Z7 + /Zl Do not let object file auto-link default libraries + /Zp Set default maximum struct packing alignment to 1 + /Zp Set default maximum struct packing alignment /Zs Syntax-check only OPTIONS: @@ -3145,6 +3146,15 @@ Execute ``clang-cl /?`` to see a list of supported options: -fcomplete-member-pointers Require member pointer base types to be complete if they would be significant under the Microsoft ABI -fcoverage-mapping Generate coverage mapping to enable code coverage analysis + -fcs-profile-generate= + Generate instrumented code to collect context sensitive + execution counts into /default.profraw + (overridden by LLVM_PROFILE_FILE env var) + -fcs-profile-generate Generate instrumented code to collect context sensitive + execution counts into default.profraw + (overridden by LLVM_PROFILE_FILE env var) + -fdebug-compilation-dir + The compilation directory to embed in the debug info. -fdebug-macro Emit macro debug information -fdelayed-template-parsing Parse templated function definitions at the end of the translation unit @@ -3172,6 +3182,10 @@ Execute ``clang-cl /?`` to see a list of supported options: -fno-debug-macro Do not emit macro debug information -fno-delayed-template-parsing Disable delayed template parsing + -fno-profile-generate Disable generation of profile instrumentation. + -fno-profile-instr-generate + Disable generation of profile instrumentation. + -fno-profile-instr-use Disable using instrumentation data for profile-guided optimization -fno-sanitize-address-poison-custom-array-cookie Disable poisoning array cookies when using custom operator new[] in AddressSanitizer -fno-sanitize-address-use-after-scope @@ -3200,10 +3214,18 @@ Execute ``clang-cl /?`` to see a list of supported options: Disable trapping for specified sanitizers -fno-standalone-debug Limit debug information produced to reduce size of debug binary -fobjc-runtime= Specify the target Objective-C runtime kind and version + -forder-file-instrumentation + Generate instrumented code to collect order file into default.profraw + file (overridden by '=' form of option or LLVM_PROFILE_FILE env var) -fprofile-exclude-files= Instrument only functions from files where names don't match all the regexes separated by a semi-colon -fprofile-filter-files= Instrument only functions from files where names match any regex separated by a semi-colon + -fprofile-generate= + Generate instrumented code to collect execution counts into + /default.profraw (overridden by LLVM_PROFILE_FILE env var) + -fprofile-generate Generate instrumented code to collect execution counts into + default.profraw (overridden by LLVM_PROFILE_FILE env var) -fprofile-instr-generate= Generate instrumented code to collect execution counts into (overridden by LLVM_PROFILE_FILE env var) @@ -3252,10 +3274,10 @@ Execute ``clang-cl /?`` to see a list of supported options: -fsanitize-trap= Enable trapping for specified sanitizers -fsanitize-undefined-strip-path-components= Strip (or keep only, if negative) a given number of path components when emitting check metadata. - -fsanitize= Turn on runtime checks for various forms of undefined or suspicious - behavior. See user manual for available checks + -fsanitize= Turn on runtime checks for various forms of undefined or suspicious behavior. See user manual for available checks -fsplit-lto-unit Enables splitting of the LTO unit. -fstandalone-debug Emit full debug info for all types used by the program + -fthinlto-index= Perform ThinLTO importing using provided function summary index -fwhole-program-vtables Enables whole-program vtable optimization. Requires -flto -gcodeview-ghash Emit type record hashes in a .debug$H section -gcodeview Generate CodeView debug information @@ -3264,6 +3286,7 @@ Execute ``clang-cl /?`` to see a list of supported options: -miamcu Use Intel MCU ABI -mllvm Additional arguments to forward to LLVM's option processing -nobuiltininc Disable builtin #include directories + -print-supported-cpus Print supported cpu models for the given target (if target is not specified, it will print the supported cpus for the default target) -Qunused-arguments Don't emit warning for unused driver arguments -R Enable the specified remark --target= Generate code for the given target From 6aa75a25bdeea9cdc4b04cdd91e82e680444bf4b Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Mon, 29 Jul 2019 09:51:02 +0000 Subject: [PATCH 042/289] Merging r367215: ------------------------------------------------------------------------ r367215 | hans | 2019-07-29 11:49:04 +0200 (Mon, 29 Jul 2019) | 66 lines Mark test/MC/RISCV/rv{32,64}i-aliases-invalid.s unsupported also on Windows Because they fail there too. FAIL: LLVM :: MC/RISCV/rv32i-aliases-invalid.s (24397 of 32659) ******************** TEST 'LLVM :: MC/RISCV/rv32i-aliases-invalid.s' FAILED ******************** Script: -- : 'RUN: at line 2'; not c:\src\llvm.monorepo\build.release2\bin\llvm-mc.exe C:\src\llvm.monorepo\llvm\test\MC\RISCV\rv32i-aliases-invalid.s -triple=riscv32 -riscv-no-aliases 2>&1 | c:\src\llvm.monorepo\build.release2\bin\filecheck.exe C:\src\llvm.monorepo\llvm\test\MC\RISCV\rv32i-aliases-invalid.s : 'RUN: at line 3'; not c:\src\llvm.monorepo\build.release2\bin\llvm-mc.exe C:\src\llvm.monorepo\llvm\test\MC\RISCV\rv32i-aliases-invalid.s -triple=riscv32 2>&1 | c:\src\llvm.monorepo\build.release2\bin\filecheck.exe C:\src\llvm.monorepo\llvm\test\MC\RISCV\rv32i-aliases-invalid.s -- Exit Code: 1 Command Output (stdout): -- $ ":" "RUN: at line 2" $ "not" "c:\src\llvm.monorepo\build.release2\bin\llvm-mc.exe" "C:\src\llvm.monorepo\llvm\test\MC\RISCV\rv32i-aliases-invalid.s" "-triple=riscv32" "-riscv-no-aliases" $ "c:\src\llvm.monorepo\build.release2\bin\filecheck.exe" "C:\src\llvm.monorepo\llvm\test\MC\RISCV\rv32i-aliases-invalid.s" C:\src\llvm.monorepo\llvm\test\MC\RISCV\rv32i-aliases-invalid.s:10:21: error: CHECK: expected string not found in input li t4, foo # CHECK: :[[@LINE]]:8: error: immediate must be an integer in the range [-2147483648, 4294967295] ^ :5:1: note: scanning from here li x0, -2147483649 # CHECK: :[[@LINE]]:8: error: immediate must be an integer in the range [-2147483648, 4294967295] ^ :5:1: note: with "@LINE" equal to "10" li x0, -2147483649 # CHECK: :[[@LINE]]:8: error: immediate must be an integer in the range [-2147483648, 4294967295] ^ :5:38: note: possible intended match here li x0, -2147483649 # CHECK: :[[@LINE]]:8: error: immediate must be an integer in the range [-2147483648, 4294967295] ^ error: command failed with exit status: 1 -- -- ******************** Testing: 0 .. 10.. 20.. 30.. 40.. 50.. 60.. 70 FAIL: LLVM :: MC/RISCV/rv64i-aliases-invalid.s (24416 of 32659) ******************** TEST 'LLVM :: MC/RISCV/rv64i-aliases-invalid.s' FAILED ******************** Script: -- : 'RUN: at line 2'; not c:\src\llvm.monorepo\build.release2\bin\llvm-mc.exe C:\src\llvm.monorepo\llvm\test\MC\RISCV\rv64i-aliases-invalid.s -triple=riscv64 -riscv-no-aliases 2>&1 | c:\src\llvm.monorepo\build.release2\bin\filecheck.exe C:\src\llvm.monorepo\llvm\test\MC\RISCV\rv64i-aliases-invalid.s : 'RUN: at line 3'; not c:\src\llvm.monorepo\build.release2\bin\llvm-mc.exe C:\src\llvm.monorepo\llvm\test\MC\RISCV\rv64i-aliases-invalid.s -triple=riscv64 2>&1 | c:\src\llvm.monorepo\build.release2\bin\filecheck.exe C:\src\llvm.monorepo\llvm\test\MC\RISCV\rv64i-aliases-invalid.s -- Exit Code: 1 Command Output (stdout): -- $ ":" "RUN: at line 2" $ "not" "c:\src\llvm.monorepo\build.release2\bin\llvm-mc.exe" "C:\src\llvm.monorepo\llvm\test\MC\RISCV\rv64i-aliases-invalid.s" "-triple=riscv64" "-riscv-no-aliases" $ "c:\src\llvm.monorepo\build.release2\bin\filecheck.exe" "C:\src\llvm.monorepo\llvm\test\MC\RISCV\rv64i-aliases-invalid.s" C:\src\llvm.monorepo\llvm\test\MC\RISCV\rv64i-aliases-invalid.s:6:21: error: CHECK: expected string not found in input li t4, foo # CHECK: :[[@LINE]]:8: error: operand must be a constant 64-bit integer ^ :2:1: note: scanning from here li t5, 0x10000000000000000 # CHECK: :[[@LINE]]:8: error: unknown operand ^ :2:1: note: with "@LINE" equal to "6" li t5, 0x10000000000000000 # CHECK: :[[@LINE]]:8: error: unknown operand ^ :13:67: note: possible intended match here C:\src\llvm.monorepo\llvm\test\MC\RISCV\rv64i-aliases-invalid.s:12:13: error: immediate must be an integer in the range [0, 63] ^ error: command failed with exit status: 1 ------------------------------------------------------------------------ llvm-svn: 367217 --- llvm/test/MC/RISCV/rv32i-aliases-invalid.s | 1 + llvm/test/MC/RISCV/rv64i-aliases-invalid.s | 1 + 2 files changed, 2 insertions(+) diff --git a/llvm/test/MC/RISCV/rv32i-aliases-invalid.s b/llvm/test/MC/RISCV/rv32i-aliases-invalid.s index 4080d892a67e..ce603baa4fd0 100644 --- a/llvm/test/MC/RISCV/rv32i-aliases-invalid.s +++ b/llvm/test/MC/RISCV/rv32i-aliases-invalid.s @@ -1,3 +1,4 @@ +# UNSUPPORTED: linux, windows # RUN: not llvm-mc %s -triple=riscv32 -riscv-no-aliases 2>&1 | FileCheck %s # RUN: not llvm-mc %s -triple=riscv32 2>&1 | FileCheck %s diff --git a/llvm/test/MC/RISCV/rv64i-aliases-invalid.s b/llvm/test/MC/RISCV/rv64i-aliases-invalid.s index f3f2acc473dd..3e156b39f067 100644 --- a/llvm/test/MC/RISCV/rv64i-aliases-invalid.s +++ b/llvm/test/MC/RISCV/rv64i-aliases-invalid.s @@ -1,3 +1,4 @@ +# UNSUPPORTED: linux, windows # RUN: not llvm-mc %s -triple=riscv64 -riscv-no-aliases 2>&1 | FileCheck %s # RUN: not llvm-mc %s -triple=riscv64 2>&1 | FileCheck %s From f5744423e817a21e7603dddecda37c8301374570 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Tue, 30 Jul 2019 08:44:48 +0000 Subject: [PATCH 043/289] Merging r367008: ------------------------------------------------------------------------ r367008 | stulova | 2019-07-25 13:04:29 +0200 (Thu, 25 Jul 2019) | 12 lines [OpenCL] Rename lang mode flag for C++ mode Rename lang mode flag to -cl-std=clc++/-cl-std=CLC++ or -std=clc++/-std=CLC++. This aligns with OpenCL C conversion and removes ambiguity with OpenCL C++. Differential Revision: https://reviews.llvm.org/D65102 ------------------------------------------------------------------------ llvm-svn: 367300 --- clang/docs/LanguageExtensions.rst | 2 +- clang/docs/UsersManual.rst | 4 ++-- clang/include/clang/Driver/Options.td | 2 +- clang/include/clang/Frontend/LangStandards.def | 1 + clang/lib/Frontend/CompilerInvocation.cpp | 2 +- clang/test/CodeGenCXX/mangle-address-space.cpp | 4 ++-- clang/test/CodeGenOpenCL/builtins.cl | 2 +- clang/test/CodeGenOpenCL/images.cl | 2 +- clang/test/CodeGenOpenCL/logical-ops.cl | 2 +- clang/test/CodeGenOpenCL/pipe_builtin.cl | 2 +- clang/test/CodeGenOpenCL/sampler.cl | 2 +- clang/test/CodeGenOpenCL/spir_version.cl | 2 +- clang/test/CodeGenOpenCL/to_addr_builtin.cl | 2 +- clang/test/CodeGenOpenCLCXX/address-space-castoperators.cpp | 2 +- clang/test/CodeGenOpenCLCXX/address-space-deduction.cl | 4 ++-- clang/test/CodeGenOpenCLCXX/address-space-deduction2.cl | 2 +- clang/test/CodeGenOpenCLCXX/addrspace-conversion.cl | 2 +- clang/test/CodeGenOpenCLCXX/addrspace-derived-base.cl | 2 +- clang/test/CodeGenOpenCLCXX/addrspace-of-this.cl | 6 +++--- clang/test/CodeGenOpenCLCXX/addrspace-operators.cl | 2 +- clang/test/CodeGenOpenCLCXX/addrspace-references.cl | 2 +- clang/test/CodeGenOpenCLCXX/addrspace-with-class.cl | 4 ++-- clang/test/CodeGenOpenCLCXX/atexit.cl | 2 +- clang/test/CodeGenOpenCLCXX/global_init.cl | 2 +- clang/test/CodeGenOpenCLCXX/local_addrspace_init.cl | 2 +- .../test/CodeGenOpenCLCXX/method-overload-address-space.cl | 2 +- clang/test/CodeGenOpenCLCXX/template-address-spaces.cl | 2 +- clang/test/Driver/autocomplete.c | 6 ++++-- clang/test/Driver/opencl.cl | 4 ++-- clang/test/Frontend/opencl.cl | 2 +- clang/test/Frontend/stdlang.c | 3 ++- clang/test/Headers/opencl-c-header.cl | 2 +- clang/test/Parser/opencl-cxx-keywords.cl | 4 ++-- clang/test/Parser/opencl-cxx-virtual.cl | 2 +- clang/test/Preprocessor/predefined-macros.c | 2 +- clang/test/SemaOpenCL/address-spaces-conversions-cl2.0.cl | 6 +++--- clang/test/SemaOpenCL/address-spaces.cl | 2 +- clang/test/SemaOpenCL/builtin.cl | 2 +- clang/test/SemaOpenCL/clk_event_t.cl | 2 +- clang/test/SemaOpenCL/extension-version.cl | 4 ++-- clang/test/SemaOpenCL/extensions.cl | 2 +- clang/test/SemaOpenCL/invalid-image.cl | 2 +- clang/test/SemaOpenCL/invalid-pipes-cl2.0.cl | 2 +- clang/test/SemaOpenCLCXX/address-space-deduction.cl | 2 +- .../test/SemaOpenCLCXX/address-space-of-this-class-scope.cl | 2 +- clang/test/SemaOpenCLCXX/address-space-of-this.cl | 2 +- clang/test/SemaOpenCLCXX/address-space-references.cl | 2 +- clang/test/SemaOpenCLCXX/address-space-templates.cl | 2 +- clang/test/SemaOpenCLCXX/address_space_overloading.cl | 2 +- clang/test/SemaOpenCLCXX/kernel_invalid.cl | 2 +- clang/test/SemaOpenCLCXX/method-overload-address-space.cl | 2 +- clang/test/SemaOpenCLCXX/newdelete.cl | 2 +- clang/test/SemaOpenCLCXX/restricted.cl | 2 +- 53 files changed, 68 insertions(+), 64 deletions(-) diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst index cb72c459c1e5..616dce6c11c8 100644 --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -1779,7 +1779,7 @@ invoked. .. code-block:: console - clang -cl-std=c++ test.cl + clang -cl-std=clc++ test.cl If there are any global objects to be initialized the final binary will contain ``@_GLOBAL__sub_I_test.cl`` kernel to be enqueued. diff --git a/clang/docs/UsersManual.rst b/clang/docs/UsersManual.rst index f800e86e855c..aad4ebf6e4a5 100644 --- a/clang/docs/UsersManual.rst +++ b/clang/docs/UsersManual.rst @@ -2776,7 +2776,7 @@ restrictions from OpenCL C v2.0 will inherently apply. All OpenCL C builtin type and function libraries are supported and can be used in the new mode. To enable the new mode pass the following command line option when compiling ``.cl`` -file ``-cl-std=c++`` or ``-std=c++``. +file ``-cl-std=clc++``, ``-cl-std=CLC++``, ``-std=clc++`` or ``-std=CLC++``. .. code-block:: c++ @@ -2794,7 +2794,7 @@ file ``-cl-std=c++`` or ``-std=c++``. .. code-block:: console - clang -cl-std=c++ test.cl + clang -cl-std=clc++ test.cl .. _target_features: diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index dfd27fab796e..4ea8bfff0973 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -518,7 +518,7 @@ def cl_mad_enable : Flag<["-"], "cl-mad-enable">, Group, Flags<[CC def cl_no_signed_zeros : Flag<["-"], "cl-no-signed-zeros">, Group, Flags<[CC1Option]>, HelpText<"OpenCL only. Allow use of less precise no signed zeros computations in the generated binary.">; def cl_std_EQ : Joined<["-"], "cl-std=">, Group, Flags<[CC1Option]>, - HelpText<"OpenCL language standard to compile for.">, Values<"cl,CL,cl1.1,CL1.1,cl1.2,CL1.2,cl2.0,CL2.0,c++">; + HelpText<"OpenCL language standard to compile for.">, Values<"cl,CL,cl1.1,CL1.1,cl1.2,CL1.2,cl2.0,CL2.0,clc++,CLC++">; def cl_denorms_are_zero : Flag<["-"], "cl-denorms-are-zero">, Group, Flags<[CC1Option]>, HelpText<"OpenCL only. Allow denormals to be flushed to zero.">; def cl_fp32_correctly_rounded_divide_sqrt : Flag<["-"], "cl-fp32-correctly-rounded-divide-sqrt">, Group, Flags<[CC1Option]>, diff --git a/clang/include/clang/Frontend/LangStandards.def b/clang/include/clang/Frontend/LangStandards.def index 0964e9b90a03..72ea23562ebd 100644 --- a/clang/include/clang/Frontend/LangStandards.def +++ b/clang/include/clang/Frontend/LangStandards.def @@ -174,6 +174,7 @@ LANGSTANDARD_ALIAS_DEPR(opencl10, "CL") LANGSTANDARD_ALIAS_DEPR(opencl11, "CL1.1") LANGSTANDARD_ALIAS_DEPR(opencl12, "CL1.2") LANGSTANDARD_ALIAS_DEPR(opencl20, "CL2.0") +LANGSTANDARD_ALIAS_DEPR(openclcpp, "CLC++") // CUDA LANGSTANDARD(cuda, "cuda", CUDA, "NVIDIA CUDA(tm)", diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 8a9844096f08..bc54e38a1a63 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -2408,7 +2408,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, .Cases("cl1.1", "CL1.1", LangStandard::lang_opencl11) .Cases("cl1.2", "CL1.2", LangStandard::lang_opencl12) .Cases("cl2.0", "CL2.0", LangStandard::lang_opencl20) - .Case("c++", LangStandard::lang_openclcpp) + .Cases("clc++", "CLC++", LangStandard::lang_openclcpp) .Default(LangStandard::lang_unspecified); if (OpenCLLangStd == LangStandard::lang_unspecified) { diff --git a/clang/test/CodeGenCXX/mangle-address-space.cpp b/clang/test/CodeGenCXX/mangle-address-space.cpp index 549ae54dfbe4..2c5cdfc3dadb 100644 --- a/clang/test/CodeGenCXX/mangle-address-space.cpp +++ b/clang/test/CodeGenCXX/mangle-address-space.cpp @@ -1,7 +1,7 @@ // RUN: %clang_cc1 -emit-llvm -triple %itanium_abi_triple -o - %s | FileCheck %s --check-prefixes=CHECK,CHECKNOOCL // RUN: %clang_cc1 -emit-llvm -triple x86_64-windows-msvc -o - %s | FileCheck %s --check-prefixes=WIN,WINNOOCL -// RUN: %clang_cc1 -cl-std=c++ -emit-llvm -triple %itanium_abi_triple -o - %s | FileCheck %s --check-prefixes=CHECK,CHECKOCL -// RUN: %clang_cc1 -cl-std=c++ -emit-llvm -triple x86_64-windows-msvc -o - %s | FileCheck %s --check-prefixes=WIN,WINOCL +// RUN: %clang_cc1 -cl-std=clc++ -emit-llvm -triple %itanium_abi_triple -o - %s | FileCheck %s --check-prefixes=CHECK,CHECKOCL +// RUN: %clang_cc1 -cl-std=clc++ -emit-llvm -triple x86_64-windows-msvc -o - %s | FileCheck %s --check-prefixes=WIN,WINOCL // CHECKNOOCL-LABEL: define {{.*}}void @_Z2f0Pc // WINNOOCL-LABEL: define {{.*}}void @"?f0@@YAXPEAD@Z" diff --git a/clang/test/CodeGenOpenCL/builtins.cl b/clang/test/CodeGenOpenCL/builtins.cl index 1ef7d2a6d551..36a6fb6b664c 100644 --- a/clang/test/CodeGenOpenCL/builtins.cl +++ b/clang/test/CodeGenOpenCL/builtins.cl @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -finclude-default-header -cl-std=c++ -fblocks -O0 -emit-llvm -o - -triple "spir-unknown-unknown" | FileCheck %s +// RUN: %clang_cc1 %s -finclude-default-header -cl-std=clc++ -fblocks -O0 -emit-llvm -o - -triple "spir-unknown-unknown" | FileCheck %s void testBranchingOnEnqueueKernel(queue_t default_queue, unsigned flags, ndrange_t ndrange) { // Ensure `enqueue_kernel` can be branched upon. diff --git a/clang/test/CodeGenOpenCL/images.cl b/clang/test/CodeGenOpenCL/images.cl index baa919784706..326322d3d4a6 100644 --- a/clang/test/CodeGenOpenCL/images.cl +++ b/clang/test/CodeGenOpenCL/images.cl @@ -1,5 +1,5 @@ // RUN: %clang_cc1 %s -triple x86_64-unknown-linux-gnu -O0 -emit-llvm -o - | FileCheck %s -// RUN: %clang_cc1 %s -triple x86_64-unknown-linux-gnu -O0 -emit-llvm -o - -cl-std=c++ | FileCheck %s +// RUN: %clang_cc1 %s -triple x86_64-unknown-linux-gnu -O0 -emit-llvm -o - -cl-std=clc++ | FileCheck %s __attribute__((overloadable)) void read_image(read_only image1d_t img_ro); __attribute__((overloadable)) void read_image(write_only image1d_t img_wo); diff --git a/clang/test/CodeGenOpenCL/logical-ops.cl b/clang/test/CodeGenOpenCL/logical-ops.cl index 77334d3b37b7..f083a8580ee7 100644 --- a/clang/test/CodeGenOpenCL/logical-ops.cl +++ b/clang/test/CodeGenOpenCL/logical-ops.cl @@ -1,5 +1,5 @@ // RUN: %clang_cc1 %s -emit-llvm -o - -cl-std=CL1.2 -O1 -triple x86_64-unknown-linux-gnu | FileCheck %s -// RUN: %clang_cc1 %s -emit-llvm -o - -cl-std=c++ -O1 -triple x86_64-unknown-linux-gnu | FileCheck %s +// RUN: %clang_cc1 %s -emit-llvm -o - -cl-std=clc++ -O1 -triple x86_64-unknown-linux-gnu | FileCheck %s #pragma OPENCL EXTENSION cl_khr_fp64 : enable diff --git a/clang/test/CodeGenOpenCL/pipe_builtin.cl b/clang/test/CodeGenOpenCL/pipe_builtin.cl index 1a001f9bd61f..02b9669b7ab1 100644 --- a/clang/test/CodeGenOpenCL/pipe_builtin.cl +++ b/clang/test/CodeGenOpenCL/pipe_builtin.cl @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -cl-ext=+cl_khr_subgroups -O0 -cl-std=c++ -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -cl-ext=+cl_khr_subgroups -O0 -cl-std=clc++ -o - %s | FileCheck %s // FIXME: Add MS ABI manglings of OpenCL things and remove %itanium_abi_triple // above to support OpenCL in the MS C++ ABI. diff --git a/clang/test/CodeGenOpenCL/sampler.cl b/clang/test/CodeGenOpenCL/sampler.cl index 1ef1f538b256..ed3f32d6c53c 100644 --- a/clang/test/CodeGenOpenCL/sampler.cl +++ b/clang/test/CodeGenOpenCL/sampler.cl @@ -1,6 +1,6 @@ // RUN: %clang_cc1 %s -emit-llvm -triple spir-unknown-unknown -o - -O0 | FileCheck %s // RUN: %clang_cc1 %s -cl-std=CL2.0 -emit-llvm -triple spir-unknown-unknown -o - -O0 | FileCheck %s -// RUN: %clang_cc1 %s -cl-std=c++ -emit-llvm -triple spir-unknown-unknown -o - -O0 | FileCheck %s +// RUN: %clang_cc1 %s -cl-std=clc++ -emit-llvm -triple spir-unknown-unknown -o - -O0 | FileCheck %s // // This test covers 5 cases of sampler initialzation: // 1. function argument passing diff --git a/clang/test/CodeGenOpenCL/spir_version.cl b/clang/test/CodeGenOpenCL/spir_version.cl index 03f3f20885de..39893de0f56d 100644 --- a/clang/test/CodeGenOpenCL/spir_version.cl +++ b/clang/test/CodeGenOpenCL/spir_version.cl @@ -6,7 +6,7 @@ // RUN: %clang_cc1 %s -triple "spir64-unknown-unknown" -emit-llvm -o - -cl-std=CL2.0 | FileCheck %s --check-prefix=CHECK-SPIR-CL20 -// RUN: %clang_cc1 %s -triple "spir64-unknown-unknown" -emit-llvm -o - -cl-std=c++ | FileCheck %s --check-prefix=CHECK-SPIR-CL20 +// RUN: %clang_cc1 %s -triple "spir64-unknown-unknown" -emit-llvm -o - -cl-std=clc++ | FileCheck %s --check-prefix=CHECK-SPIR-CL20 // RUN: %clang_cc1 %s -triple "amdgcn--amdhsa" -emit-llvm -o - | FileCheck %s --check-prefix=CHECK-AMDGCN-CL10 // RUN: %clang_cc1 %s -triple "amdgcn--amdhsa" -emit-llvm -o - -cl-std=CL1.2 | FileCheck %s --check-prefix=CHECK-AMDGCN-CL12 diff --git a/clang/test/CodeGenOpenCL/to_addr_builtin.cl b/clang/test/CodeGenOpenCL/to_addr_builtin.cl index 19b8a107df33..52dd72f18a34 100644 --- a/clang/test/CodeGenOpenCL/to_addr_builtin.cl +++ b/clang/test/CodeGenOpenCL/to_addr_builtin.cl @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple spir-unknown-unknown -emit-llvm -O0 -cl-std=c++ -o - %s | FileCheck %s +// RUN: %clang_cc1 -triple spir-unknown-unknown -emit-llvm -O0 -cl-std=clc++ -o - %s | FileCheck %s // CHECK: %[[A:.*]] = type { float, float, float } typedef struct { diff --git a/clang/test/CodeGenOpenCLCXX/address-space-castoperators.cpp b/clang/test/CodeGenOpenCLCXX/address-space-castoperators.cpp index e5c3ee880ccc..61308323e82b 100644 --- a/clang/test/CodeGenOpenCLCXX/address-space-castoperators.cpp +++ b/clang/test/CodeGenOpenCLCXX/address-space-castoperators.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=c++ -emit-llvm -O0 -o - | FileCheck %s +// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=clc++ -emit-llvm -O0 -o - | FileCheck %s void test_reinterpret_cast(){ __private float x; diff --git a/clang/test/CodeGenOpenCLCXX/address-space-deduction.cl b/clang/test/CodeGenOpenCLCXX/address-space-deduction.cl index a6c8bc617ae1..a6ae5af01eba 100644 --- a/clang/test/CodeGenOpenCLCXX/address-space-deduction.cl +++ b/clang/test/CodeGenOpenCLCXX/address-space-deduction.cl @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=c++ -O0 -emit-llvm -o - | FileCheck %s -check-prefixes=COMMON,PTR -// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=c++ -O0 -emit-llvm -o - -DREF | FileCheck %s -check-prefixes=COMMON,REF +// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=clc++ -O0 -emit-llvm -o - | FileCheck %s -check-prefixes=COMMON,PTR +// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=clc++ -O0 -emit-llvm -o - -DREF | FileCheck %s -check-prefixes=COMMON,REF #ifdef REF #define PTR & diff --git a/clang/test/CodeGenOpenCLCXX/address-space-deduction2.cl b/clang/test/CodeGenOpenCLCXX/address-space-deduction2.cl index 6772cdcb11d0..36e89499c954 100644 --- a/clang/test/CodeGenOpenCLCXX/address-space-deduction2.cl +++ b/clang/test/CodeGenOpenCLCXX/address-space-deduction2.cl @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=c++ -O0 -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=clc++ -O0 -emit-llvm -o - | FileCheck %s class P { public: diff --git a/clang/test/CodeGenOpenCLCXX/addrspace-conversion.cl b/clang/test/CodeGenOpenCLCXX/addrspace-conversion.cl index 38422c24e859..a80662f72334 100644 --- a/clang/test/CodeGenOpenCLCXX/addrspace-conversion.cl +++ b/clang/test/CodeGenOpenCLCXX/addrspace-conversion.cl @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=c++ -emit-llvm -O0 -o - | FileCheck %s +// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=clc++ -emit-llvm -O0 -o - | FileCheck %s void bar(__generic volatile unsigned int* ptr) { diff --git a/clang/test/CodeGenOpenCLCXX/addrspace-derived-base.cl b/clang/test/CodeGenOpenCLCXX/addrspace-derived-base.cl index d5ffcbce99dc..916bb50ae822 100644 --- a/clang/test/CodeGenOpenCLCXX/addrspace-derived-base.cl +++ b/clang/test/CodeGenOpenCLCXX/addrspace-derived-base.cl @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -triple spir -cl-std=c++ -emit-llvm -O0 -o - | FileCheck %s +// RUN: %clang_cc1 %s -triple spir -cl-std=clc++ -emit-llvm -O0 -o - | FileCheck %s struct B { int mb; diff --git a/clang/test/CodeGenOpenCLCXX/addrspace-of-this.cl b/clang/test/CodeGenOpenCLCXX/addrspace-of-this.cl index 6780c5366c71..8a282ac21d4b 100644 --- a/clang/test/CodeGenOpenCLCXX/addrspace-of-this.cl +++ b/clang/test/CodeGenOpenCLCXX/addrspace-of-this.cl @@ -1,6 +1,6 @@ -// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=c++ -emit-llvm -pedantic -verify -O0 -o - -DDECL | FileCheck %s --check-prefixes="COMMON,EXPL" -// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=c++ -emit-llvm -pedantic -verify -O0 -o - -DDECL -DUSE_DEFLT | FileCheck %s --check-prefixes="COMMON,IMPL" -// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=c++ -emit-llvm -pedantic -verify -O0 -o - | FileCheck %s --check-prefixes="COMMON,IMPL" +// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=clc++ -emit-llvm -pedantic -verify -O0 -o - -DDECL | FileCheck %s --check-prefixes="COMMON,EXPL" +// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=clc++ -emit-llvm -pedantic -verify -O0 -o - -DDECL -DUSE_DEFLT | FileCheck %s --check-prefixes="COMMON,IMPL" +// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=clc++ -emit-llvm -pedantic -verify -O0 -o - | FileCheck %s --check-prefixes="COMMON,IMPL" // expected-no-diagnostics // Test that the 'this' pointer is in the __generic address space. diff --git a/clang/test/CodeGenOpenCLCXX/addrspace-operators.cl b/clang/test/CodeGenOpenCLCXX/addrspace-operators.cl index d26efcac4277..11a164a5f265 100644 --- a/clang/test/CodeGenOpenCLCXX/addrspace-operators.cl +++ b/clang/test/CodeGenOpenCLCXX/addrspace-operators.cl @@ -1,4 +1,4 @@ -//RUN: %clang_cc1 %s -triple spir -cl-std=c++ -emit-llvm -O0 -o - | FileCheck %s +//RUN: %clang_cc1 %s -triple spir -cl-std=clc++ -emit-llvm -O0 -o - | FileCheck %s enum E { a, diff --git a/clang/test/CodeGenOpenCLCXX/addrspace-references.cl b/clang/test/CodeGenOpenCLCXX/addrspace-references.cl index 303d75ad3e02..75a11c44395e 100644 --- a/clang/test/CodeGenOpenCLCXX/addrspace-references.cl +++ b/clang/test/CodeGenOpenCLCXX/addrspace-references.cl @@ -1,4 +1,4 @@ -//RUN: %clang_cc1 %s -cl-std=c++ -triple spir -emit-llvm -o - | FileCheck %s +//RUN: %clang_cc1 %s -cl-std=clc++ -triple spir -emit-llvm -o - | FileCheck %s int bar(const unsigned int &i); // CHECK-LABEL: define spir_func void @_Z3foov() diff --git a/clang/test/CodeGenOpenCLCXX/addrspace-with-class.cl b/clang/test/CodeGenOpenCLCXX/addrspace-with-class.cl index a477559c900b..9f19bfe5cc4f 100644 --- a/clang/test/CodeGenOpenCLCXX/addrspace-with-class.cl +++ b/clang/test/CodeGenOpenCLCXX/addrspace-with-class.cl @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=c++ -emit-llvm -O0 -o - | FileCheck %s -// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=c++ -emit-llvm -O0 -o - | FileCheck %s --check-prefix=CHECK-DEFINITIONS +// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=clc++ -emit-llvm -O0 -o - | FileCheck %s +// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=CLC++ -emit-llvm -O0 -o - | FileCheck %s --check-prefix=CHECK-DEFINITIONS // This test ensures the proper address spaces and address space cast are used // for constructors, member functions and destructors. diff --git a/clang/test/CodeGenOpenCLCXX/atexit.cl b/clang/test/CodeGenOpenCLCXX/atexit.cl index b4571f96a1a2..7bcaede2c2a1 100644 --- a/clang/test/CodeGenOpenCLCXX/atexit.cl +++ b/clang/test/CodeGenOpenCLCXX/atexit.cl @@ -1,4 +1,4 @@ -//RUN: %clang_cc1 %s -triple spir -cl-std=c++ -emit-llvm -O0 -o - | FileCheck %s +//RUN: %clang_cc1 %s -triple spir -cl-std=clc++ -emit-llvm -O0 -o - | FileCheck %s struct S { ~S(){}; diff --git a/clang/test/CodeGenOpenCLCXX/global_init.cl b/clang/test/CodeGenOpenCLCXX/global_init.cl index 9452cf6ca307..9f602beda5ba 100644 --- a/clang/test/CodeGenOpenCLCXX/global_init.cl +++ b/clang/test/CodeGenOpenCLCXX/global_init.cl @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -triple spir -cl-std=c++ -emit-llvm -O0 -o - | FileCheck %s +// RUN: %clang_cc1 %s -triple spir -cl-std=clc++ -emit-llvm -O0 -o - | FileCheck %s struct S { S() {} diff --git a/clang/test/CodeGenOpenCLCXX/local_addrspace_init.cl b/clang/test/CodeGenOpenCLCXX/local_addrspace_init.cl index 4424ff4ff2c8..e892e674ad14 100644 --- a/clang/test/CodeGenOpenCLCXX/local_addrspace_init.cl +++ b/clang/test/CodeGenOpenCLCXX/local_addrspace_init.cl @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -triple spir -cl-std=c++ -emit-llvm -O0 -o - | FileCheck %s +// RUN: %clang_cc1 %s -triple spir -cl-std=clc++ -emit-llvm -O0 -o - | FileCheck %s // Test that we don't initialize local address space objects. //CHECK: @_ZZ4testE1i = internal addrspace(3) global i32 undef diff --git a/clang/test/CodeGenOpenCLCXX/method-overload-address-space.cl b/clang/test/CodeGenOpenCLCXX/method-overload-address-space.cl index 6bec3fa33b01..d090c79ebf4a 100644 --- a/clang/test/CodeGenOpenCLCXX/method-overload-address-space.cl +++ b/clang/test/CodeGenOpenCLCXX/method-overload-address-space.cl @@ -1,4 +1,4 @@ -//RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=c++ -emit-llvm -O0 -o - | FileCheck %s +//RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=clc++ -emit-llvm -O0 -o - | FileCheck %s struct C { void foo() __local; diff --git a/clang/test/CodeGenOpenCLCXX/template-address-spaces.cl b/clang/test/CodeGenOpenCLCXX/template-address-spaces.cl index 7b553c2c0dcf..fcd8655eb9a0 100644 --- a/clang/test/CodeGenOpenCLCXX/template-address-spaces.cl +++ b/clang/test/CodeGenOpenCLCXX/template-address-spaces.cl @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -cl-std=c++ %s -emit-llvm -o - -O0 -triple spir-unknown-unknown | FileCheck %s +// RUN: %clang_cc1 -cl-std=clc++ %s -emit-llvm -o - -O0 -triple spir-unknown-unknown | FileCheck %s template struct S{ diff --git a/clang/test/Driver/autocomplete.c b/clang/test/Driver/autocomplete.c index 7805c3bc7894..5c0bfb69f9a3 100644 --- a/clang/test/Driver/autocomplete.c +++ b/clang/test/Driver/autocomplete.c @@ -34,8 +34,8 @@ // RUN: %clang --autocomplete=-cl-std=,CL2 | FileCheck %s -check-prefix=CLSTD // CLSTD: CL2.0 // RUN: %clang --autocomplete=-cl-std= | FileCheck %s -check-prefix=CLSTDALL -// CLSTDALL: c++ -// CLSTDALL-NEXT: cl + +// CLSTDALL: cl // CLSTDALL-NEXT: CL // CLSTDALL-NEXT: cl1.1 // CLSTDALL-NEXT: CL1.1 @@ -43,6 +43,8 @@ // CLSTDALL-NEXT: CL1.2 // CLSTDALL-NEXT: cl2.0 // CLSTDALL-NEXT: CL2.0 +// CLSTDALL-NEXT: clc++ +// CLSTDALL-NEXT: CLC++ // RUN: %clang --autocomplete=-fno-sanitize-coverage=,f | FileCheck %s -check-prefix=FNOSANICOVER // FNOSANICOVER: func // RUN: %clang --autocomplete=-fno-sanitize-coverage= | FileCheck %s -check-prefix=FNOSANICOVERALL diff --git a/clang/test/Driver/opencl.cl b/clang/test/Driver/opencl.cl index baff86fb9067..63b04bc1af41 100644 --- a/clang/test/Driver/opencl.cl +++ b/clang/test/Driver/opencl.cl @@ -2,7 +2,7 @@ // RUN: %clang -S -### -cl-std=CL1.1 %s 2>&1 | FileCheck --check-prefix=CHECK-CL11 %s // RUN: %clang -S -### -cl-std=CL1.2 %s 2>&1 | FileCheck --check-prefix=CHECK-CL12 %s // RUN: %clang -S -### -cl-std=CL2.0 %s 2>&1 | FileCheck --check-prefix=CHECK-CL20 %s -// RUN: %clang -S -### -cl-std=c++ %s 2>&1 | FileCheck --check-prefix=CHECK-CLCPP %s +// RUN: %clang -S -### -cl-std=clc++ %s 2>&1 | FileCheck --check-prefix=CHECK-CLCPP %s // RUN: %clang -S -### -cl-opt-disable %s 2>&1 | FileCheck --check-prefix=CHECK-OPT-DISABLE %s // RUN: %clang -S -### -cl-strict-aliasing %s 2>&1 | FileCheck --check-prefix=CHECK-STRICT-ALIASING %s // RUN: %clang -S -### -cl-single-precision-constant %s 2>&1 | FileCheck --check-prefix=CHECK-SINGLE-PRECISION-CONST %s @@ -22,7 +22,7 @@ // CHECK-CL11: "-cc1" {{.*}} "-cl-std=CL1.1" // CHECK-CL12: "-cc1" {{.*}} "-cl-std=CL1.2" // CHECK-CL20: "-cc1" {{.*}} "-cl-std=CL2.0" -// CHECK-CLCPP: "-cc1" {{.*}} "-cl-std=c++" +// CHECK-CLCPP: "-cc1" {{.*}} "-cl-std=clc++" // CHECK-OPT-DISABLE: "-cc1" {{.*}} "-cl-opt-disable" // CHECK-STRICT-ALIASING: "-cc1" {{.*}} "-cl-strict-aliasing" // CHECK-SINGLE-PRECISION-CONST: "-cc1" {{.*}} "-cl-single-precision-constant" diff --git a/clang/test/Frontend/opencl.cl b/clang/test/Frontend/opencl.cl index facc735330d4..ea7d3d4c8731 100644 --- a/clang/test/Frontend/opencl.cl +++ b/clang/test/Frontend/opencl.cl @@ -2,7 +2,7 @@ // RUN: %clang_cc1 %s -verify -fsyntax-only -cl-std=CL1.1 -DSYNTAX // RUN: %clang_cc1 %s -verify -fsyntax-only -cl-std=CL1.2 -DSYNTAX // RUN: %clang_cc1 %s -verify -fsyntax-only -cl-std=CL2.0 -DSYNTAX -// RUN: %clang_cc1 %s -verify -fsyntax-only -cl-std=c++ -DSYNTAX +// RUN: %clang_cc1 %s -verify -fsyntax-only -cl-std=clc++ -DSYNTAX // RUN: %clang_cc1 %s -verify -fsyntax-only -fblocks -DBLOCKS -DSYNTAX // RUN: %clang_cc1 %s -verify -fsyntax-only -cl-std=CL1.1 -fblocks -DBLOCKS -DSYNTAX // RUN: %clang_cc1 %s -verify -fsyntax-only -cl-std=CL1.2 -fblocks -DBLOCKS -DSYNTAX diff --git a/clang/test/Frontend/stdlang.c b/clang/test/Frontend/stdlang.c index 2b24c2dfea31..51484999e37a 100644 --- a/clang/test/Frontend/stdlang.c +++ b/clang/test/Frontend/stdlang.c @@ -4,11 +4,12 @@ // RUN: %clang_cc1 -x cl -cl-std=cl1.1 -DOPENCL %s // RUN: %clang_cc1 -x cl -cl-std=cl1.2 -DOPENCL %s // RUN: %clang_cc1 -x cl -cl-std=cl2.0 -DOPENCL %s -// RUN: %clang_cc1 -x cl -cl-std=c++ -DOPENCL %s +// RUN: %clang_cc1 -x cl -cl-std=clc++ -DOPENCL %s // RUN: %clang_cc1 -x cl -cl-std=CL -DOPENCL %s // RUN: %clang_cc1 -x cl -cl-std=CL1.1 -DOPENCL %s // RUN: %clang_cc1 -x cl -cl-std=CL1.2 -DOPENCL %s // RUN: %clang_cc1 -x cl -cl-std=CL2.0 -DOPENCL %s +// RUN: %clang_cc1 -x cl -cl-std=CLC++ -DOPENCL %s // RUN: not %clang_cc1 -x cl -std=c99 -DOPENCL %s 2>&1 | FileCheck --check-prefix=CHECK-C99 %s // RUN: not %clang_cc1 -x cl -cl-std=invalid -DOPENCL %s 2>&1 | FileCheck --check-prefix=CHECK-INVALID %s // CHECK-C99: error: invalid argument '-std=c99' not allowed with 'OpenCL' diff --git a/clang/test/Headers/opencl-c-header.cl b/clang/test/Headers/opencl-c-header.cl index 8183a8c1f79a..1b151ffdd16a 100644 --- a/clang/test/Headers/opencl-c-header.cl +++ b/clang/test/Headers/opencl-c-header.cl @@ -1,7 +1,7 @@ // RUN: %clang_cc1 -O0 -triple spir-unknown-unknown -internal-isystem ../../lib/Headers -include opencl-c.h -emit-llvm -o - %s -verify | FileCheck %s // RUN: %clang_cc1 -O0 -triple spir-unknown-unknown -internal-isystem ../../lib/Headers -include opencl-c.h -emit-llvm -o - %s -verify -cl-std=CL1.1 | FileCheck %s // RUN: %clang_cc1 -O0 -triple spir-unknown-unknown -internal-isystem ../../lib/Headers -include opencl-c.h -emit-llvm -o - %s -verify -cl-std=CL1.2 | FileCheck %s -// RUN: %clang_cc1 -O0 -triple spir-unknown-unknown -internal-isystem ../../lib/Headers -include opencl-c.h -emit-llvm -o - %s -verify -cl-std=c++ | FileCheck %s --check-prefix=CHECK20 +// RUN: %clang_cc1 -O0 -triple spir-unknown-unknown -internal-isystem ../../lib/Headers -include opencl-c.h -emit-llvm -o - %s -verify -cl-std=clc++ | FileCheck %s --check-prefix=CHECK20 // Test including the default header as a module. // The module should be compiled only once and loaded from cache afterwards. diff --git a/clang/test/Parser/opencl-cxx-keywords.cl b/clang/test/Parser/opencl-cxx-keywords.cl index 0cafcdf28f86..ddc84536f20a 100644 --- a/clang/test/Parser/opencl-cxx-keywords.cl +++ b/clang/test/Parser/opencl-cxx-keywords.cl @@ -1,5 +1,5 @@ -// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=c++ -verify -fsyntax-only -// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=c++ -verify -fsyntax-only -fexceptions -fcxx-exceptions +// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=clc++ -verify -fsyntax-only +// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=clc++ -verify -fsyntax-only -fexceptions -fcxx-exceptions // This test checks that various C++ and OpenCL C keywords are not available // in OpenCL. diff --git a/clang/test/Parser/opencl-cxx-virtual.cl b/clang/test/Parser/opencl-cxx-virtual.cl index 53befbc32120..f394a47fadb1 100644 --- a/clang/test/Parser/opencl-cxx-virtual.cl +++ b/clang/test/Parser/opencl-cxx-virtual.cl @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=c++ -fsyntax-only -verify +// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=clc++ -fsyntax-only -verify // Test that virtual functions and abstract classes are rejected. class virtual_functions { diff --git a/clang/test/Preprocessor/predefined-macros.c b/clang/test/Preprocessor/predefined-macros.c index 9296b1cf5a50..def105f4c52e 100644 --- a/clang/test/Preprocessor/predefined-macros.c +++ b/clang/test/Preprocessor/predefined-macros.c @@ -131,7 +131,7 @@ // RUN: | FileCheck -match-full-lines %s --check-prefix=CHECK-CL20 // RUN: %clang_cc1 %s -E -dM -o - -x cl -cl-fast-relaxed-math \ // RUN: | FileCheck -match-full-lines %s --check-prefix=CHECK-FRM -// RUN: %clang_cc1 %s -E -dM -o - -x cl -cl-std=c++ \ +// RUN: %clang_cc1 %s -E -dM -o - -x cl -cl-std=clc++ \ // RUN: | FileCheck -match-full-lines %s --check-prefix=CHECK-CLCPP10 // CHECK-CL10: #define CL_VERSION_1_0 100 // CHECK-CL10: #define CL_VERSION_1_1 110 diff --git a/clang/test/SemaOpenCL/address-spaces-conversions-cl2.0.cl b/clang/test/SemaOpenCL/address-spaces-conversions-cl2.0.cl index bbd3919b154b..89cf8e3a8124 100644 --- a/clang/test/SemaOpenCL/address-spaces-conversions-cl2.0.cl +++ b/clang/test/SemaOpenCL/address-spaces-conversions-cl2.0.cl @@ -1,9 +1,9 @@ // RUN: %clang_cc1 %s -ffake-address-space-map -verify -pedantic -fsyntax-only -DCONSTANT -cl-std=CL2.0 // RUN: %clang_cc1 %s -ffake-address-space-map -verify -pedantic -fsyntax-only -DGLOBAL -cl-std=CL2.0 // RUN: %clang_cc1 %s -ffake-address-space-map -verify -pedantic -fsyntax-only -DGENERIC -cl-std=CL2.0 -// RUN: %clang_cc1 %s -ffake-address-space-map -verify -pedantic -fsyntax-only -DCONSTANT -cl-std=c++ -// RUN: %clang_cc1 %s -ffake-address-space-map -verify -pedantic -fsyntax-only -DGLOBAL -cl-std=c++ -// RUN: %clang_cc1 %s -ffake-address-space-map -verify -pedantic -fsyntax-only -DGENERIC -cl-std=c++ +// RUN: %clang_cc1 %s -ffake-address-space-map -verify -pedantic -fsyntax-only -DCONSTANT -cl-std=clc++ +// RUN: %clang_cc1 %s -ffake-address-space-map -verify -pedantic -fsyntax-only -DGLOBAL -cl-std=clc++ +// RUN: %clang_cc1 %s -ffake-address-space-map -verify -pedantic -fsyntax-only -DGENERIC -cl-std=clc++ /* OpenCLC v2.0 adds a set of restrictions for conversions between pointers to * different address spaces, mainly described in Sections 6.5.5 and 6.5.6. diff --git a/clang/test/SemaOpenCL/address-spaces.cl b/clang/test/SemaOpenCL/address-spaces.cl index 13e9442b95c3..55a55dc75050 100644 --- a/clang/test/SemaOpenCL/address-spaces.cl +++ b/clang/test/SemaOpenCL/address-spaces.cl @@ -1,6 +1,6 @@ // RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only // RUN: %clang_cc1 %s -cl-std=CL2.0 -verify -pedantic -fsyntax-only -// RUN: %clang_cc1 %s -cl-std=c++ -verify -pedantic -fsyntax-only +// RUN: %clang_cc1 %s -cl-std=clc++ -verify -pedantic -fsyntax-only __constant int ci = 1; diff --git a/clang/test/SemaOpenCL/builtin.cl b/clang/test/SemaOpenCL/builtin.cl index 4669e3fbb381..b6f215668c87 100644 --- a/clang/test/SemaOpenCL/builtin.cl +++ b/clang/test/SemaOpenCL/builtin.cl @@ -1,5 +1,5 @@ // RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=CL1.2 -// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=c++ +// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=clc++ // expected-no-diagnostics diff --git a/clang/test/SemaOpenCL/clk_event_t.cl b/clang/test/SemaOpenCL/clk_event_t.cl index 4a884bcfa6c0..e9736eaa8f37 100644 --- a/clang/test/SemaOpenCL/clk_event_t.cl +++ b/clang/test/SemaOpenCL/clk_event_t.cl @@ -1,5 +1,5 @@ // RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=CL2.0 -// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=c++ +// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=clc++ // Taken from opencl-c.h #define CLK_NULL_EVENT (__builtin_astype(((void*)(__SIZE_MAX__)), clk_event_t)) diff --git a/clang/test/SemaOpenCL/extension-version.cl b/clang/test/SemaOpenCL/extension-version.cl index d976cfb3a435..19d088495350 100644 --- a/clang/test/SemaOpenCL/extension-version.cl +++ b/clang/test/SemaOpenCL/extension-version.cl @@ -2,12 +2,12 @@ // RUN: %clang_cc1 -x cl -cl-std=CL1.1 %s -verify -triple spir-unknown-unknown // RUN: %clang_cc1 -x cl -cl-std=CL1.2 %s -verify -triple spir-unknown-unknown // RUN: %clang_cc1 -x cl -cl-std=CL2.0 %s -verify -triple spir-unknown-unknown -// RUN: %clang_cc1 -x cl -cl-std=c++ %s -verify -triple spir-unknown-unknown +// RUN: %clang_cc1 -x cl -cl-std=clc++ %s -verify -triple spir-unknown-unknown // RUN: %clang_cc1 -x cl -cl-std=CL %s -verify -triple spir-unknown-unknown -Wpedantic-core-features -DTEST_CORE_FEATURES // RUN: %clang_cc1 -x cl -cl-std=CL1.1 %s -verify -triple spir-unknown-unknown -Wpedantic-core-features -DTEST_CORE_FEATURES // RUN: %clang_cc1 -x cl -cl-std=CL1.2 %s -verify -triple spir-unknown-unknown -Wpedantic-core-features -DTEST_CORE_FEATURES // RUN: %clang_cc1 -x cl -cl-std=CL2.0 %s -verify -triple spir-unknown-unknown -Wpedantic-core-features -DTEST_CORE_FEATURES -// RUN: %clang_cc1 -x cl -cl-std=c++ %s -verify -triple spir-unknown-unknown -Wpedantic-core-features -DTEST_CORE_FEATURES +// RUN: %clang_cc1 -x cl -cl-std=clc++ %s -verify -triple spir-unknown-unknown -Wpedantic-core-features -DTEST_CORE_FEATURES #if (defined(__OPENCL_CPP_VERSION__) || __OPENCL_C_VERSION__ >= 200) && !defined(TEST_CORE_FEATURES) // expected-no-diagnostics diff --git a/clang/test/SemaOpenCL/extensions.cl b/clang/test/SemaOpenCL/extensions.cl index e9dba69ecd7c..55dbd1d5eede 100644 --- a/clang/test/SemaOpenCL/extensions.cl +++ b/clang/test/SemaOpenCL/extensions.cl @@ -28,7 +28,7 @@ // enabled by default with -cl-std=CL2.0). // // RUN: %clang_cc1 %s -triple amdgcn-unknown-unknown -verify -pedantic -fsyntax-only -cl-std=CL2.0 -finclude-default-header -// RUN: %clang_cc1 %s -triple spir-unknown-unknown -verify -pedantic -fsyntax-only -cl-std=c++ +// RUN: %clang_cc1 %s -triple spir-unknown-unknown -verify -pedantic -fsyntax-only -cl-std=clc++ #ifdef _OPENCL_H_ // expected-no-diagnostics diff --git a/clang/test/SemaOpenCL/invalid-image.cl b/clang/test/SemaOpenCL/invalid-image.cl index 10c44cf4c281..9185cc371ebc 100644 --- a/clang/test/SemaOpenCL/invalid-image.cl +++ b/clang/test/SemaOpenCL/invalid-image.cl @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -verify -cl-std=c++ %s +// RUN: %clang_cc1 -verify -cl-std=clc++ %s // RUN: %clang_cc1 -verify %s // RUN: %clang_cc1 -verify -D=ATTR_TEST -fms-compatibility %s diff --git a/clang/test/SemaOpenCL/invalid-pipes-cl2.0.cl b/clang/test/SemaOpenCL/invalid-pipes-cl2.0.cl index afe5dc6a6085..69fa2b6da823 100644 --- a/clang/test/SemaOpenCL/invalid-pipes-cl2.0.cl +++ b/clang/test/SemaOpenCL/invalid-pipes-cl2.0.cl @@ -1,5 +1,5 @@ // RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=CL2.0 -// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=c++ +// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=clc++ global pipe int gp; // expected-error {{type '__global read_only pipe int' can only be used as a function parameter in OpenCL}} global reserve_id_t rid; // expected-error {{the '__global reserve_id_t' type cannot be used to declare a program scope variable}} diff --git a/clang/test/SemaOpenCLCXX/address-space-deduction.cl b/clang/test/SemaOpenCLCXX/address-space-deduction.cl index 4283ec41e635..0b64b5cdece9 100644 --- a/clang/test/SemaOpenCLCXX/address-space-deduction.cl +++ b/clang/test/SemaOpenCLCXX/address-space-deduction.cl @@ -1,4 +1,4 @@ -//RUN: %clang_cc1 %s -cl-std=c++ -pedantic -ast-dump -verify | FileCheck %s +//RUN: %clang_cc1 %s -cl-std=clc++ -pedantic -ast-dump -verify | FileCheck %s //expected-no-diagnostics diff --git a/clang/test/SemaOpenCLCXX/address-space-of-this-class-scope.cl b/clang/test/SemaOpenCLCXX/address-space-of-this-class-scope.cl index ebb76043bbd4..1c0cb3731bd5 100644 --- a/clang/test/SemaOpenCLCXX/address-space-of-this-class-scope.cl +++ b/clang/test/SemaOpenCLCXX/address-space-of-this-class-scope.cl @@ -1,4 +1,4 @@ -//RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=c++ -pedantic -verify +//RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=clc++ -pedantic -verify struct C { auto fGlob() __global -> decltype(this); diff --git a/clang/test/SemaOpenCLCXX/address-space-of-this.cl b/clang/test/SemaOpenCLCXX/address-space-of-this.cl index 7ae3aa63f407..ac79b3411928 100644 --- a/clang/test/SemaOpenCLCXX/address-space-of-this.cl +++ b/clang/test/SemaOpenCLCXX/address-space-of-this.cl @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=c++ -pedantic -verify -fsyntax-only +// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=clc++ -pedantic -verify -fsyntax-only // expected-no-diagnostics // Extract from PR38614 diff --git a/clang/test/SemaOpenCLCXX/address-space-references.cl b/clang/test/SemaOpenCLCXX/address-space-references.cl index 851d3023df29..a6c7c842da00 100644 --- a/clang/test/SemaOpenCLCXX/address-space-references.cl +++ b/clang/test/SemaOpenCLCXX/address-space-references.cl @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=c++ -pedantic -verify -fsyntax-only +// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=clc++ -pedantic -verify -fsyntax-only __global const int& f(__global float &ref) { return ref; // expected-error{{reference of type 'const __global int &' cannot bind to a temporary object because of address space mismatch}} diff --git a/clang/test/SemaOpenCLCXX/address-space-templates.cl b/clang/test/SemaOpenCLCXX/address-space-templates.cl index 3fb935766e94..0acc5145a632 100644 --- a/clang/test/SemaOpenCLCXX/address-space-templates.cl +++ b/clang/test/SemaOpenCLCXX/address-space-templates.cl @@ -1,4 +1,4 @@ -//RUN: %clang_cc1 %s -cl-std=c++ -pedantic -verify -fsyntax-only +//RUN: %clang_cc1 %s -cl-std=clc++ -pedantic -verify -fsyntax-only template struct S { diff --git a/clang/test/SemaOpenCLCXX/address_space_overloading.cl b/clang/test/SemaOpenCLCXX/address_space_overloading.cl index 6458ade56209..33337ef461df 100644 --- a/clang/test/SemaOpenCLCXX/address_space_overloading.cl +++ b/clang/test/SemaOpenCLCXX/address_space_overloading.cl @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=c++ +// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=clc++ // expected-no-diagnostics struct RetGlob { diff --git a/clang/test/SemaOpenCLCXX/kernel_invalid.cl b/clang/test/SemaOpenCLCXX/kernel_invalid.cl index 43e1243a55ef..2efdb756446d 100644 --- a/clang/test/SemaOpenCLCXX/kernel_invalid.cl +++ b/clang/test/SemaOpenCLCXX/kernel_invalid.cl @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -cl-std=c++ -pedantic -verify -fsyntax-only +// RUN: %clang_cc1 %s -cl-std=clc++ -pedantic -verify -fsyntax-only struct C { kernel void m(); //expected-error{{kernel functions cannot be class members}} diff --git a/clang/test/SemaOpenCLCXX/method-overload-address-space.cl b/clang/test/SemaOpenCLCXX/method-overload-address-space.cl index 64a279549cdd..7c428a570c2c 100644 --- a/clang/test/SemaOpenCLCXX/method-overload-address-space.cl +++ b/clang/test/SemaOpenCLCXX/method-overload-address-space.cl @@ -1,4 +1,4 @@ -//RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=c++ -pedantic -verify +//RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=clc++ -pedantic -verify struct C { void m1() __local __local; //expected-warning{{multiple identical address spaces specified for type}} diff --git a/clang/test/SemaOpenCLCXX/newdelete.cl b/clang/test/SemaOpenCLCXX/newdelete.cl index abc4c0fb6cbd..2ef27843d5ce 100644 --- a/clang/test/SemaOpenCLCXX/newdelete.cl +++ b/clang/test/SemaOpenCLCXX/newdelete.cl @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=c++ -pedantic -verify -fsyntax-only +// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=clc++ -pedantic -verify -fsyntax-only class A { public: diff --git a/clang/test/SemaOpenCLCXX/restricted.cl b/clang/test/SemaOpenCLCXX/restricted.cl index 2af4ae137c41..3487285b6081 100644 --- a/clang/test/SemaOpenCLCXX/restricted.cl +++ b/clang/test/SemaOpenCLCXX/restricted.cl @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=c++ -pedantic -verify -fsyntax-only +// RUN: %clang_cc1 %s -triple spir-unknown-unknown -cl-std=clc++ -pedantic -verify -fsyntax-only // This test checks that various C/C++/OpenCL C constructs are not available in // C++ for OpenCL. From 900b7dd0eaee48f571a0cc0626124f0d1c0d7328 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Tue, 30 Jul 2019 14:18:50 +0000 Subject: [PATCH 044/289] Merging r367314: ------------------------------------------------------------------------ r367314 | hans | 2019-07-30 16:17:58 +0200 (Tue, 30 Jul 2019) | 16 lines gn build: Use rebase_path on filename args to libcxx/utils/gen_link_script.py $ ninja -j800 [1/5] ACTION //libcxx/src:cxx_linker_script(//llvm/utils/gn/build/toolchain:stage2_unix) FAILED: lib/libc++.so python ../libcxx/utils/gen_link_script.py --input //build.gn/lib/libc++.so.0 --output //build.gn/lib/libc++.so c++abi unwind GENERATING SCRIPT: 'INPUT(libc++.so.0 -lc++abi -lunwind)' as file //build.gn/lib/libc++.so Traceback (most recent call last): File "../libcxx/utils/gen_link_script.py", line 57, in sys.exit(main()) File "../libcxx/utils/gen_link_script.py", line 50, in main with open(args.output, 'w') as f: IOError: [Errno 2] No such file or directory: '//build.gn/lib/libc++.so' ninja: build stopped: subcommand failed. Differential revision: https://reviews.llvm.org/D65449 ------------------------------------------------------------------------ llvm-svn: 367315 --- llvm/utils/gn/secondary/libcxx/src/BUILD.gn | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llvm/utils/gn/secondary/libcxx/src/BUILD.gn b/llvm/utils/gn/secondary/libcxx/src/BUILD.gn index 09b8947765be..8f5c1c31fbea 100644 --- a/llvm/utils/gn/secondary/libcxx/src/BUILD.gn +++ b/llvm/utils/gn/secondary/libcxx/src/BUILD.gn @@ -236,9 +236,9 @@ if (libcxx_enable_shared) { ] args = [ "--input", - "$runtimes_dir/libc++.so.0", + rebase_path("$runtimes_dir/libc++.so.0", root_build_dir), "--output", - "$runtimes_dir/libc++.so", + rebase_path("$runtimes_dir/libc++.so", root_build_dir), "c++abi", "unwind", ] From 6e08fdb3ccfd3e5ec0f98fabcfad0ddd02a0f42e Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Tue, 30 Jul 2019 14:39:19 +0000 Subject: [PATCH 045/289] Merging r366487: ------------------------------------------------------------------------ r366487 | pcc | 2019-07-18 22:14:16 +0200 (Thu, 18 Jul 2019) | 1 line gn build: Merge r366458. ------------------------------------------------------------------------ llvm-svn: 367317 --- llvm/utils/gn/secondary/clang-tools-extra/clangd/BUILD.gn | 1 + 1 file changed, 1 insertion(+) diff --git a/llvm/utils/gn/secondary/clang-tools-extra/clangd/BUILD.gn b/llvm/utils/gn/secondary/clang-tools-extra/clangd/BUILD.gn index e21727d22e34..44ebf4052388 100644 --- a/llvm/utils/gn/secondary/clang-tools-extra/clangd/BUILD.gn +++ b/llvm/utils/gn/secondary/clang-tools-extra/clangd/BUILD.gn @@ -105,6 +105,7 @@ static_library("clangd") { "URI.cpp", "XRefs.cpp", "index/Background.cpp", + "index/BackgroundIndexLoader.cpp", "index/BackgroundIndexStorage.cpp", "index/BackgroundQueue.cpp", "index/BackgroundRebuild.cpp", From 372334b3d334887b7699f5018e6532e31eb6cf40 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Wed, 31 Jul 2019 07:42:31 +0000 Subject: [PATCH 046/289] Merging r367340 and r367341: (Minus the linuxkernel part, which is not present on the branch.) ------------------------------------------------------------------------ r367340 | nico | 2019-07-30 20:16:55 +0200 (Tue, 30 Jul 2019) | 6 lines gn build: Fix check-clang-tools after r362702. r362702 added a test that requires clang-tidy to be linked into libclang, so add that to the gn build. Differential Revision: https://reviews.llvm.org/D65462 ------------------------------------------------------------------------ ------------------------------------------------------------------------ r367341 | nico | 2019-07-30 20:19:13 +0200 (Tue, 30 Jul 2019) | 1 line gn build: Update comment I failed to update in r367340 / D65462 ------------------------------------------------------------------------ llvm-svn: 367390 --- .../clang-include-fixer/plugin/BUILD.gn | 18 ++++++++++++++++++ .../clang-tidy/plugin/BUILD.gn | 3 +++ .../gn/secondary/clang/tools/libclang/BUILD.gn | 18 +++++++++++++++--- 3 files changed, 36 insertions(+), 3 deletions(-) create mode 100644 llvm/utils/gn/secondary/clang-tools-extra/clang-include-fixer/plugin/BUILD.gn diff --git a/llvm/utils/gn/secondary/clang-tools-extra/clang-include-fixer/plugin/BUILD.gn b/llvm/utils/gn/secondary/clang-tools-extra/clang-include-fixer/plugin/BUILD.gn new file mode 100644 index 000000000000..ce4617556bff --- /dev/null +++ b/llvm/utils/gn/secondary/clang-tools-extra/clang-include-fixer/plugin/BUILD.gn @@ -0,0 +1,18 @@ +static_library("plugin") { + output_name = "clangIncludeFixerPlugin" + configs += [ "//llvm/utils/gn/build:clang_code" ] + deps = [ + "//clang-tools-extra/clang-include-fixer", + "//clang/lib/AST", + "//clang/lib/Basic", + "//clang/lib/Frontend", + "//clang/lib/Parse", + "//clang/lib/Sema", + "//clang/lib/Tooling", + "//llvm/utils/gn/build/libs/pthread", + ] + + sources = [ + "IncludeFixerPlugin.cpp", + ] +} diff --git a/llvm/utils/gn/secondary/clang-tools-extra/clang-tidy/plugin/BUILD.gn b/llvm/utils/gn/secondary/clang-tools-extra/clang-tidy/plugin/BUILD.gn index 1d033e87ee52..ec6d4ce78871 100644 --- a/llvm/utils/gn/secondary/clang-tools-extra/clang-tidy/plugin/BUILD.gn +++ b/llvm/utils/gn/secondary/clang-tools-extra/clang-tidy/plugin/BUILD.gn @@ -1,3 +1,5 @@ +import("//clang/lib/StaticAnalyzer/Frontend/enable.gni") + static_library("plugin") { output_name = "clangTidyPlugin" configs += [ "//llvm/utils/gn/build:clang_code" ] @@ -16,6 +18,7 @@ static_library("plugin") { "//clang-tools-extra/clang-tidy/misc", "//clang-tools-extra/clang-tidy/modernize", "//clang-tools-extra/clang-tidy/objc", + "//clang-tools-extra/clang-tidy/openmp", "//clang-tools-extra/clang-tidy/performance", "//clang-tools-extra/clang-tidy/portability", "//clang-tools-extra/clang-tidy/readability", diff --git a/llvm/utils/gn/secondary/clang/tools/libclang/BUILD.gn b/llvm/utils/gn/secondary/clang/tools/libclang/BUILD.gn index 567588478e63..eb04b3071fad 100644 --- a/llvm/utils/gn/secondary/clang/tools/libclang/BUILD.gn +++ b/llvm/utils/gn/secondary/clang/tools/libclang/BUILD.gn @@ -3,8 +3,6 @@ import("//llvm/version.gni") # This build file is just enough to get check-clang to pass, it's missing # several things from the CMake build: -# - linking in clangTidyPlugin and clangIncludeFixerPlugin from -# clang-tools-extra (which doesn't have any GN build files yet) # - using libclang.exports # - a build target copying the Python bindings # - the GN linux build always builds without -fPIC (as if LLVM_ENABLE_PIC=OFF @@ -39,8 +37,22 @@ target(libclang_target_type, "libclang") { deps += [ "//clang/lib/ARCMigrate" ] } + defines = [] + + # FIXME: Once the GN build has a way to select which bits to build, + # only include this dependency if clang-tools-extra is part of the build. + # FIXME: libclang depending on anything in clang-tools-extra seems like + # a layering violation. + if (true) { + defines += [ "CLANG_TOOL_EXTRA_BUILD" ] + deps += [ + "//clang-tools-extra/clang-include-fixer/plugin", + "//clang-tools-extra/clang-tidy/plugin", + ] + } + if (host_os == "win") { - defines = [ "_CINDEX_LIB_" ] + defines += [ "_CINDEX_LIB_" ] } sources = [ From 5f32370064ad5bfcb7216abea49d2cb604ec193f Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Wed, 31 Jul 2019 14:20:16 +0000 Subject: [PATCH 047/289] Merging r366878 and r367301: ------------------------------------------------------------------------ r366878 | s.desmalen | 2019-07-24 10:42:34 +0200 (Wed, 24 Jul 2019) | 12 lines [SVE][Inline-Asm] Add support to specify SVE registers in the clobber list Adds the SVE vector and predicate registers to the list of known registers. Patch by Kerry McLaughlin. Reviewers: erichkeane, sdesmalen, rengolin Reviewed By: sdesmalen Differential Revision: https://reviews.llvm.org/D64739 ------------------------------------------------------------------------ ------------------------------------------------------------------------ r367301 | s.desmalen | 2019-07-30 12:14:39 +0200 (Tue, 30 Jul 2019) | 15 lines [AArch64] Disable __ARM_FEATURE_SVE without ACLE. The Arm C Language Extensions for SVE document specifies that __ARM_FEATURE_SVE should be set when the compiler supports SVE and implements all the extensions described in the document. This is currently not yet the case, so the feature should be disabled until the compiler can provide all the extensions as described. Reviewers: c-rhodes, rengolin, rovka, ktkachov Reviewed By: rengolin Differential Revision: https://reviews.llvm.org/D65404 ------------------------------------------------------------------------ llvm-svn: 367432 --- clang/lib/Basic/Targets/AArch64.cpp | 16 +++++++++++----- clang/test/CodeGen/aarch64-sve-inline-asm.c | 13 +++++++++++++ .../test/Preprocessor/aarch64-target-features.c | 2 +- 3 files changed, 25 insertions(+), 6 deletions(-) create mode 100644 clang/test/CodeGen/aarch64-sve-inline-asm.c diff --git a/clang/lib/Basic/Targets/AArch64.cpp b/clang/lib/Basic/Targets/AArch64.cpp index 74ac69ab8946..25f2b7b35f41 100644 --- a/clang/lib/Basic/Targets/AArch64.cpp +++ b/clang/lib/Basic/Targets/AArch64.cpp @@ -196,9 +196,6 @@ void AArch64TargetInfo::getTargetDefines(const LangOptions &Opts, Builder.defineMacro("__ARM_NEON_FP", "0xE"); } - if (FPU & SveMode) - Builder.defineMacro("__ARM_FEATURE_SVE", "1"); - if (HasCRC) Builder.defineMacro("__ARM_FEATURE_CRC32", "1"); @@ -351,10 +348,19 @@ const char *const AArch64TargetInfo::GCCRegNames[] = { "d12", "d13", "d14", "d15", "d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23", "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31", - // Vector registers + // Neon 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" + "v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31", + + // SVE vector registers + "z0", "z1", "z2", "z3", "z4", "z5", "z6", "z7", "z8", "z9", "z10", + "z11", "z12", "z13", "z14", "z15", "z16", "z17", "z18", "z19", "z20", "z21", + "z22", "z23", "z24", "z25", "z26", "z27", "z28", "z29", "z30", "z31", + + // SVE predicate registers + "p0", "p1", "p2", "p3", "p4", "p5", "p6", "p7", "p8", "p9", "p10", + "p11", "p12", "p13", "p14", "p15" }; ArrayRef AArch64TargetInfo::getGCCRegNames() const { diff --git a/clang/test/CodeGen/aarch64-sve-inline-asm.c b/clang/test/CodeGen/aarch64-sve-inline-asm.c new file mode 100644 index 000000000000..90e7777925b9 --- /dev/null +++ b/clang/test/CodeGen/aarch64-sve-inline-asm.c @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -emit-llvm -o - %s | FileCheck %s -check-prefix=CHECK + +void test_sve_asm() { + asm volatile( + "ptrue p0.d\n" + "ptrue p15.d\n" + "add z0.d, p0/m, z0.d, z0.d\n" + "add z31.d, p0/m, z31.d, z31.d\n" + : + : + : "z0", "z31", "p0", "p15"); + // CHECK: "~{z0},~{z31},~{p0},~{p15}" +} diff --git a/clang/test/Preprocessor/aarch64-target-features.c b/clang/test/Preprocessor/aarch64-target-features.c index 6964edc96f0b..922c0997d599 100644 --- a/clang/test/Preprocessor/aarch64-target-features.c +++ b/clang/test/Preprocessor/aarch64-target-features.c @@ -88,7 +88,7 @@ // RUN: %clang -target aarch64 -mtune=cyclone -### -c %s 2>&1 | FileCheck -check-prefix=CHECK-MTUNE-CYCLONE %s // RUN: %clang -target aarch64-none-linux-gnu -march=armv8-a+sve -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-SVE %s -// CHECK-SVE: __ARM_FEATURE_SVE 1 +// CHECK-SVE-NOT: __ARM_FEATURE_SVE 1 // RUN: %clang -target aarch64-none-linux-gnu -march=armv8.2a+dotprod -x c -E -dM %s -o - | FileCheck --check-prefix=CHECK-DOTPROD %s // CHECK-DOTPROD: __ARM_FEATURE_DOTPROD 1 From 77e8f41dc405410db2c1fc9a0e0cbc9630dce436 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Wed, 31 Jul 2019 14:27:24 +0000 Subject: [PATCH 048/289] Merging r367124, r367292, r367394, r367396, and r367398. ------------------------------------------------------------------------ r367124 | c-rhodes | 2019-07-26 17:57:50 +0200 (Fri, 26 Jul 2019) | 14 lines [AArch64][SVE2] Rename bitperm feature to sve2-bitperm Summary: The bitperm feature flag is now prefixed with SVE2, as it is for all other SVE2 extensions Patch by Maciej Gabka. Reviewers: sdesmalen, rovka, chill, SjoerdMeijer, rengolin Reviewed By: SjoerdMeijer, rengolin Differential Revision: https://reviews.llvm.org/D65327 ------------------------------------------------------------------------ ------------------------------------------------------------------------ r367292 | c-rhodes | 2019-07-30 09:47:48 +0200 (Tue, 30 Jul 2019) | 10 lines [AArch64][AsmParser] Remove SVE and SVE2 from ARMTargetParser Summary: Patch removes SVE and SVE2 features from ARMTargetParser as these features are not supported on ARM. Reviewed By: rengolin Differential Revision: https://reviews.llvm.org/D65385 ------------------------------------------------------------------------ ------------------------------------------------------------------------ r367394 | c-rhodes | 2019-07-31 10:45:57 +0200 (Wed, 31 Jul 2019) | 25 lines [AArch64][SVE2] Use destination register as source register Summary: This patch fixes a bug in the following instructions that should have been implemented as destructive. A destructive instruction is an instruction where one of the source registers also acts as the destination register. Therefore, the contents of the source register, when the instruction begins execution, are replaced by the result of the instruction when the instruction completes execution [1]: * SRI/SLI * EORBT/EORTB * TBX * Narrowing top instructions * FP convert precision instructions These changes are non-functional from the assembler/diassembler point-of-view but are necessary for correct codegen. [1] https://static.docs.arm.com/ddi0584/ae/DDI0584A_e_SVE_supp_armv8A.pdf Reviewed By: sdesmalen Differential Revision: https://reviews.llvm.org/D65389 ------------------------------------------------------------------------ ------------------------------------------------------------------------ r367396 | c-rhodes | 2019-07-31 10:58:16 +0200 (Wed, 31 Jul 2019) | 15 lines [AArch64][SVE2] Minor refactoring and cleanup Summary: * Clarify comment with SVE2 for predicated shifts and move next to other shift instructions. * Clarify comments for various instructions. * Move FCVTX instruction next to other fp conversions. * Move FLOGB to next to other fp instructions and fix description. * Remove "cons" from non-constructive multiclass for bitwise shift-right and accumulate instructions. Reviewed By: sdesmalen Differential Revision: https://reviews.llvm.org/D65390 ------------------------------------------------------------------------ ------------------------------------------------------------------------ r367398 | c-rhodes | 2019-07-31 11:10:36 +0200 (Wed, 31 Jul 2019) | 14 lines [AArch64][SVE2] Load/store instruction fixes Summary: * Loads and stores in SVE2 are gather/scatter not contiguous, fixed by renaming multiclasses to reflect this and also updated comments. * Remove aliases from load/store multiclasses that reflect the behaviour of the original form. * Fix bug in scatter store implementation, vector list should be used as input, not output. Reviewed By: sdesmalen Differential Revision: https://reviews.llvm.org/D65392 ------------------------------------------------------------------------ llvm-svn: 367434 --- .../llvm/Support/AArch64TargetParser.def | 58 ++-- .../llvm/Support/AArch64TargetParser.h | 2 +- llvm/include/llvm/Support/ARMTargetParser.h | 20 +- llvm/lib/Support/AArch64TargetParser.cpp | 4 +- llvm/lib/Target/AArch64/AArch64.td | 2 +- llvm/lib/Target/AArch64/AArch64InstrInfo.td | 2 +- .../lib/Target/AArch64/AArch64SVEInstrInfo.td | 164 ++++++------ .../AArch64/AsmParser/AArch64AsmParser.cpp | 2 +- llvm/lib/Target/AArch64/SVEInstrFormats.td | 248 +++++++++++++----- llvm/test/MC/AArch64/SVE2/bdep-diagnostics.s | 2 +- llvm/test/MC/AArch64/SVE2/bdep.s | 16 +- llvm/test/MC/AArch64/SVE2/bext-diagnostics.s | 2 +- llvm/test/MC/AArch64/SVE2/bext.s | 16 +- llvm/test/MC/AArch64/SVE2/bgrp-diagnostics.s | 2 +- llvm/test/MC/AArch64/SVE2/bgrp.s | 16 +- .../MC/AArch64/SVE2/directive-arch-negative.s | 6 +- llvm/test/MC/AArch64/SVE2/directive-arch.s | 2 +- .../SVE2/directive-arch_extension-negative.s | 6 +- .../AArch64/SVE2/directive-arch_extension.s | 2 +- .../MC/AArch64/SVE2/directive-cpu-negative.s | 6 +- llvm/test/MC/AArch64/SVE2/directive-cpu.s | 2 +- llvm/unittests/Support/TargetParserTest.cpp | 7 +- 22 files changed, 348 insertions(+), 239 deletions(-) diff --git a/llvm/include/llvm/Support/AArch64TargetParser.def b/llvm/include/llvm/Support/AArch64TargetParser.def index e152f383b3ec..5cdf190a9f19 100644 --- a/llvm/include/llvm/Support/AArch64TargetParser.def +++ b/llvm/include/llvm/Support/AArch64TargetParser.def @@ -50,35 +50,35 @@ AARCH64_ARCH("armv8.5-a", ARMV8_5A, "8.5-A", "v8.5a", #define AARCH64_ARCH_EXT_NAME(NAME, ID, FEATURE, NEGFEATURE) #endif // FIXME: This would be nicer were it tablegen -AARCH64_ARCH_EXT_NAME("invalid", AArch64::AEK_INVALID, nullptr, nullptr) -AARCH64_ARCH_EXT_NAME("none", AArch64::AEK_NONE, nullptr, nullptr) -AARCH64_ARCH_EXT_NAME("crc", AArch64::AEK_CRC, "+crc", "-crc") -AARCH64_ARCH_EXT_NAME("lse", AArch64::AEK_LSE, "+lse", "-lse") -AARCH64_ARCH_EXT_NAME("rdm", AArch64::AEK_RDM, "+rdm", "-rdm") -AARCH64_ARCH_EXT_NAME("crypto", AArch64::AEK_CRYPTO, "+crypto","-crypto") -AARCH64_ARCH_EXT_NAME("sm4", AArch64::AEK_SM4, "+sm4", "-sm4") -AARCH64_ARCH_EXT_NAME("sha3", AArch64::AEK_SHA3, "+sha3", "-sha3") -AARCH64_ARCH_EXT_NAME("sha2", AArch64::AEK_SHA2, "+sha2", "-sha2") -AARCH64_ARCH_EXT_NAME("aes", AArch64::AEK_AES, "+aes", "-aes") -AARCH64_ARCH_EXT_NAME("dotprod", AArch64::AEK_DOTPROD, "+dotprod","-dotprod") -AARCH64_ARCH_EXT_NAME("fp", AArch64::AEK_FP, "+fp-armv8", "-fp-armv8") -AARCH64_ARCH_EXT_NAME("simd", AArch64::AEK_SIMD, "+neon", "-neon") -AARCH64_ARCH_EXT_NAME("fp16", AArch64::AEK_FP16, "+fullfp16", "-fullfp16") -AARCH64_ARCH_EXT_NAME("fp16fml", AArch64::AEK_FP16FML, "+fp16fml", "-fp16fml") -AARCH64_ARCH_EXT_NAME("profile", AArch64::AEK_PROFILE, "+spe", "-spe") -AARCH64_ARCH_EXT_NAME("ras", AArch64::AEK_RAS, "+ras", "-ras") -AARCH64_ARCH_EXT_NAME("sve", AArch64::AEK_SVE, "+sve", "-sve") -AARCH64_ARCH_EXT_NAME("sve2", AArch64::AEK_SVE2, "+sve2", "-sve2") -AARCH64_ARCH_EXT_NAME("sve2-aes", AArch64::AEK_SVE2AES, "+sve2-aes", "-sve2-aes") -AARCH64_ARCH_EXT_NAME("sve2-sm4", AArch64::AEK_SVE2SM4, "+sve2-sm4", "-sve2-sm4") -AARCH64_ARCH_EXT_NAME("sve2-sha3", AArch64::AEK_SVE2SHA3, "+sve2-sha3", "-sve2-sha3") -AARCH64_ARCH_EXT_NAME("bitperm", AArch64::AEK_BITPERM, "+bitperm", "-bitperm") -AARCH64_ARCH_EXT_NAME("rcpc", AArch64::AEK_RCPC, "+rcpc", "-rcpc") -AARCH64_ARCH_EXT_NAME("rng", AArch64::AEK_RAND, "+rand", "-rand") -AARCH64_ARCH_EXT_NAME("memtag", AArch64::AEK_MTE, "+mte", "-mte") -AARCH64_ARCH_EXT_NAME("ssbs", AArch64::AEK_SSBS, "+ssbs", "-ssbs") -AARCH64_ARCH_EXT_NAME("sb", AArch64::AEK_SB, "+sb", "-sb") -AARCH64_ARCH_EXT_NAME("predres", AArch64::AEK_PREDRES, "+predres", "-predres") +AARCH64_ARCH_EXT_NAME("invalid", AArch64::AEK_INVALID, nullptr, nullptr) +AARCH64_ARCH_EXT_NAME("none", AArch64::AEK_NONE, nullptr, nullptr) +AARCH64_ARCH_EXT_NAME("crc", AArch64::AEK_CRC, "+crc", "-crc") +AARCH64_ARCH_EXT_NAME("lse", AArch64::AEK_LSE, "+lse", "-lse") +AARCH64_ARCH_EXT_NAME("rdm", AArch64::AEK_RDM, "+rdm", "-rdm") +AARCH64_ARCH_EXT_NAME("crypto", AArch64::AEK_CRYPTO, "+crypto","-crypto") +AARCH64_ARCH_EXT_NAME("sm4", AArch64::AEK_SM4, "+sm4", "-sm4") +AARCH64_ARCH_EXT_NAME("sha3", AArch64::AEK_SHA3, "+sha3", "-sha3") +AARCH64_ARCH_EXT_NAME("sha2", AArch64::AEK_SHA2, "+sha2", "-sha2") +AARCH64_ARCH_EXT_NAME("aes", AArch64::AEK_AES, "+aes", "-aes") +AARCH64_ARCH_EXT_NAME("dotprod", AArch64::AEK_DOTPROD, "+dotprod","-dotprod") +AARCH64_ARCH_EXT_NAME("fp", AArch64::AEK_FP, "+fp-armv8", "-fp-armv8") +AARCH64_ARCH_EXT_NAME("simd", AArch64::AEK_SIMD, "+neon", "-neon") +AARCH64_ARCH_EXT_NAME("fp16", AArch64::AEK_FP16, "+fullfp16", "-fullfp16") +AARCH64_ARCH_EXT_NAME("fp16fml", AArch64::AEK_FP16FML, "+fp16fml", "-fp16fml") +AARCH64_ARCH_EXT_NAME("profile", AArch64::AEK_PROFILE, "+spe", "-spe") +AARCH64_ARCH_EXT_NAME("ras", AArch64::AEK_RAS, "+ras", "-ras") +AARCH64_ARCH_EXT_NAME("sve", AArch64::AEK_SVE, "+sve", "-sve") +AARCH64_ARCH_EXT_NAME("sve2", AArch64::AEK_SVE2, "+sve2", "-sve2") +AARCH64_ARCH_EXT_NAME("sve2-aes", AArch64::AEK_SVE2AES, "+sve2-aes", "-sve2-aes") +AARCH64_ARCH_EXT_NAME("sve2-sm4", AArch64::AEK_SVE2SM4, "+sve2-sm4", "-sve2-sm4") +AARCH64_ARCH_EXT_NAME("sve2-sha3", AArch64::AEK_SVE2SHA3, "+sve2-sha3", "-sve2-sha3") +AARCH64_ARCH_EXT_NAME("sve2-bitperm", AArch64::AEK_SVE2BITPERM, "+sve2-bitperm", "-sve2-bitperm") +AARCH64_ARCH_EXT_NAME("rcpc", AArch64::AEK_RCPC, "+rcpc", "-rcpc") +AARCH64_ARCH_EXT_NAME("rng", AArch64::AEK_RAND, "+rand", "-rand") +AARCH64_ARCH_EXT_NAME("memtag", AArch64::AEK_MTE, "+mte", "-mte") +AARCH64_ARCH_EXT_NAME("ssbs", AArch64::AEK_SSBS, "+ssbs", "-ssbs") +AARCH64_ARCH_EXT_NAME("sb", AArch64::AEK_SB, "+sb", "-sb") +AARCH64_ARCH_EXT_NAME("predres", AArch64::AEK_PREDRES, "+predres", "-predres") #undef AARCH64_ARCH_EXT_NAME #ifndef AARCH64_CPU_NAME diff --git a/llvm/include/llvm/Support/AArch64TargetParser.h b/llvm/include/llvm/Support/AArch64TargetParser.h index 965d38535e74..a2d2cf32d715 100644 --- a/llvm/include/llvm/Support/AArch64TargetParser.h +++ b/llvm/include/llvm/Support/AArch64TargetParser.h @@ -53,7 +53,7 @@ enum ArchExtKind : unsigned { AEK_SVE2AES = 1 << 24, AEK_SVE2SM4 = 1 << 25, AEK_SVE2SHA3 = 1 << 26, - AEK_BITPERM = 1 << 27, + AEK_SVE2BITPERM = 1 << 27, }; enum class ArchKind { diff --git a/llvm/include/llvm/Support/ARMTargetParser.h b/llvm/include/llvm/Support/ARMTargetParser.h index 4b9070dea596..02d4c975129f 100644 --- a/llvm/include/llvm/Support/ARMTargetParser.h +++ b/llvm/include/llvm/Support/ARMTargetParser.h @@ -39,19 +39,13 @@ enum ArchExtKind : unsigned { AEK_DSP = 1 << 10, AEK_FP16 = 1 << 11, AEK_RAS = 1 << 12, - AEK_SVE = 1 << 13, - AEK_DOTPROD = 1 << 14, - AEK_SHA2 = 1 << 15, - AEK_AES = 1 << 16, - AEK_FP16FML = 1 << 17, - AEK_SB = 1 << 18, - AEK_SVE2 = 1 << 19, - AEK_SVE2AES = 1 << 20, - AEK_SVE2SM4 = 1 << 21, - AEK_SVE2SHA3 = 1 << 22, - AEK_BITPERM = 1 << 23, - AEK_FP_DP = 1 << 24, - AEK_LOB = 1 << 25, + AEK_DOTPROD = 1 << 13, + AEK_SHA2 = 1 << 14, + AEK_AES = 1 << 15, + AEK_FP16FML = 1 << 16, + AEK_SB = 1 << 17, + AEK_FP_DP = 1 << 18, + AEK_LOB = 1 << 19, // Unsupported extensions. AEK_OS = 0x8000000, AEK_IWMMXT = 0x10000000, diff --git a/llvm/lib/Support/AArch64TargetParser.cpp b/llvm/lib/Support/AArch64TargetParser.cpp index df4caa1f07fd..6f1d6d50eee2 100644 --- a/llvm/lib/Support/AArch64TargetParser.cpp +++ b/llvm/lib/Support/AArch64TargetParser.cpp @@ -96,8 +96,8 @@ bool AArch64::getExtensionFeatures(unsigned Extensions, Features.push_back("+sve2-sm4"); if (Extensions & AEK_SVE2SHA3) Features.push_back("+sve2-sha3"); - if (Extensions & AEK_BITPERM) - Features.push_back("+bitperm"); + if (Extensions & AEK_SVE2BITPERM) + Features.push_back("+sve2-bitperm"); if (Extensions & AEK_RCPC) Features.push_back("+rcpc"); diff --git a/llvm/lib/Target/AArch64/AArch64.td b/llvm/lib/Target/AArch64/AArch64.td index e39c6995e367..f54db0aa03b2 100644 --- a/llvm/lib/Target/AArch64/AArch64.td +++ b/llvm/lib/Target/AArch64/AArch64.td @@ -115,7 +115,7 @@ def FeatureSVE2SM4 : SubtargetFeature<"sve2-sm4", "HasSVE2SM4", "true", def FeatureSVE2SHA3 : SubtargetFeature<"sve2-sha3", "HasSVE2SHA3", "true", "Enable SHA3 SVE2 instructions", [FeatureSVE2, FeatureSHA3]>; -def FeatureSVE2BitPerm : SubtargetFeature<"bitperm", "HasSVE2BitPerm", "true", +def FeatureSVE2BitPerm : SubtargetFeature<"sve2-bitperm", "HasSVE2BitPerm", "true", "Enable bit permutation SVE2 instructions", [FeatureSVE2]>; def FeatureZCRegMove : SubtargetFeature<"zcm", "HasZeroCycleRegMove", "true", diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td index eed53f36d574..020035c7f6c3 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td @@ -116,7 +116,7 @@ def HasSVE2SM4 : Predicate<"Subtarget->hasSVE2SM4()">, def HasSVE2SHA3 : Predicate<"Subtarget->hasSVE2SHA3()">, AssemblerPredicate<"FeatureSVE2SHA3", "sve2-sha3">; def HasSVE2BitPerm : Predicate<"Subtarget->hasSVE2BitPerm()">, - AssemblerPredicate<"FeatureSVE2BitPerm", "bitperm">; + AssemblerPredicate<"FeatureSVE2BitPerm", "sve2-bitperm">; def HasRCPC : Predicate<"Subtarget->hasRCPC()">, AssemblerPredicate<"FeatureRCPC", "rcpc">; def HasAltNZCV : Predicate<"Subtarget->hasAlternativeNZCV()">, diff --git a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td index 79ab42f4c080..8e1ff999bd57 100644 --- a/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64SVEInstrInfo.td @@ -1164,6 +1164,13 @@ let Predicates = [HasSVE2] in { defm SQRSHLR_ZPmZ : sve2_int_arith_pred<0b011100, "sqrshlr">; defm UQRSHLR_ZPmZ : sve2_int_arith_pred<0b011110, "uqrshlr">; + // SVE2 predicated shifts + defm SQSHL_ZPmI : sve_int_bin_pred_shift_imm_left< 0b0110, "sqshl">; + defm UQSHL_ZPmI : sve_int_bin_pred_shift_imm_left< 0b0111, "uqshl">; + defm SRSHR_ZPmI : sve_int_bin_pred_shift_imm_right<0b1100, "srshr">; + defm URSHR_ZPmI : sve_int_bin_pred_shift_imm_right<0b1101, "urshr">; + defm SQSHLU_ZPmI : sve_int_bin_pred_shift_imm_left< 0b1111, "sqshlu">; + // SVE2 integer add/subtract long defm SADDLB_ZZZ : sve2_wide_int_arith_long<0b00000, "saddlb">; defm SADDLT_ZZZ : sve2_wide_int_arith_long<0b00001, "saddlt">; @@ -1199,14 +1206,14 @@ let Predicates = [HasSVE2] in { defm PMULLT_ZZZ : sve2_pmul_long<0b1, "pmullt">; // SVE2 bitwise shift and insert - defm SRI_ZZI : sve2_int_bin_cons_shift_imm_right<0b0, "sri">; - defm SLI_ZZI : sve2_int_bin_cons_shift_imm_left< 0b1, "sli">; + defm SRI_ZZI : sve2_int_bin_shift_imm_right<0b0, "sri">; + defm SLI_ZZI : sve2_int_bin_shift_imm_left< 0b1, "sli">; // SVE2 bitwise shift right and accumulate - defm SSRA_ZZI : sve2_int_bin_accum_cons_shift_imm_right<0b00, "ssra">; - defm USRA_ZZI : sve2_int_bin_accum_cons_shift_imm_right<0b01, "usra">; - defm SRSRA_ZZI : sve2_int_bin_accum_cons_shift_imm_right<0b10, "srsra">; - defm URSRA_ZZI : sve2_int_bin_accum_cons_shift_imm_right<0b11, "ursra">; + defm SSRA_ZZI : sve2_int_bin_accum_shift_imm_right<0b00, "ssra">; + defm USRA_ZZI : sve2_int_bin_accum_shift_imm_right<0b01, "usra">; + defm SRSRA_ZZI : sve2_int_bin_accum_shift_imm_right<0b10, "srsra">; + defm URSRA_ZZI : sve2_int_bin_accum_shift_imm_right<0b11, "ursra">; // SVE2 complex integer add defm CADD_ZZI : sve2_int_cadd<0b0, "cadd">; @@ -1228,41 +1235,47 @@ let Predicates = [HasSVE2] in { defm SBCLB_ZZZ : sve2_int_addsub_long_carry<0b10, "sbclb">; defm SBCLT_ZZZ : sve2_int_addsub_long_carry<0b11, "sbclt">; - // SVE2 bitwise shift right narrow - defm SQSHRUNB_ZZI : sve2_int_bin_cons_shift_imm_right_narrow<0b0000, "sqshrunb">; - defm SQSHRUNT_ZZI : sve2_int_bin_cons_shift_imm_right_narrow<0b0001, "sqshrunt">; - defm SQRSHRUNB_ZZI : sve2_int_bin_cons_shift_imm_right_narrow<0b0010, "sqrshrunb">; - defm SQRSHRUNT_ZZI : sve2_int_bin_cons_shift_imm_right_narrow<0b0011, "sqrshrunt">; - defm SHRNB_ZZI : sve2_int_bin_cons_shift_imm_right_narrow<0b0100, "shrnb">; - defm SHRNT_ZZI : sve2_int_bin_cons_shift_imm_right_narrow<0b0101, "shrnt">; - defm RSHRNB_ZZI : sve2_int_bin_cons_shift_imm_right_narrow<0b0110, "rshrnb">; - defm RSHRNT_ZZI : sve2_int_bin_cons_shift_imm_right_narrow<0b0111, "rshrnt">; - defm SQSHRNB_ZZI : sve2_int_bin_cons_shift_imm_right_narrow<0b1000, "sqshrnb">; - defm SQSHRNT_ZZI : sve2_int_bin_cons_shift_imm_right_narrow<0b1001, "sqshrnt">; - defm SQRSHRNB_ZZI : sve2_int_bin_cons_shift_imm_right_narrow<0b1010, "sqrshrnb">; - defm SQRSHRNT_ZZI : sve2_int_bin_cons_shift_imm_right_narrow<0b1011, "sqrshrnt">; - defm UQSHRNB_ZZI : sve2_int_bin_cons_shift_imm_right_narrow<0b1100, "uqshrnb">; - defm UQSHRNT_ZZI : sve2_int_bin_cons_shift_imm_right_narrow<0b1101, "uqshrnt">; - defm UQRSHRNB_ZZI : sve2_int_bin_cons_shift_imm_right_narrow<0b1110, "uqrshrnb">; - defm UQRSHRNT_ZZI : sve2_int_bin_cons_shift_imm_right_narrow<0b1111, "uqrshrnt">; - - // SVE2 integer add/subtract narrow high part - defm ADDHNB_ZZZ : sve2_int_addsub_narrow_high<0b000, "addhnb">; - defm ADDHNT_ZZZ : sve2_int_addsub_narrow_high<0b001, "addhnt">; - defm RADDHNB_ZZZ : sve2_int_addsub_narrow_high<0b010, "raddhnb">; - defm RADDHNT_ZZZ : sve2_int_addsub_narrow_high<0b011, "raddhnt">; - defm SUBHNB_ZZZ : sve2_int_addsub_narrow_high<0b100, "subhnb">; - defm SUBHNT_ZZZ : sve2_int_addsub_narrow_high<0b101, "subhnt">; - defm RSUBHNB_ZZZ : sve2_int_addsub_narrow_high<0b110, "rsubhnb">; - defm RSUBHNT_ZZZ : sve2_int_addsub_narrow_high<0b111, "rsubhnt">; - - // SVE2 saturating extract narrow - defm SQXTNB_ZZ : sve2_int_sat_extract_narrow<0b000, "sqxtnb">; - defm SQXTNT_ZZ : sve2_int_sat_extract_narrow<0b001, "sqxtnt">; - defm UQXTNB_ZZ : sve2_int_sat_extract_narrow<0b010, "uqxtnb">; - defm UQXTNT_ZZ : sve2_int_sat_extract_narrow<0b011, "uqxtnt">; - defm SQXTUNB_ZZ : sve2_int_sat_extract_narrow<0b100, "sqxtunb">; - defm SQXTUNT_ZZ : sve2_int_sat_extract_narrow<0b101, "sqxtunt">; + // SVE2 bitwise shift right narrow (bottom) + defm SQSHRUNB_ZZI : sve2_int_bin_shift_imm_right_narrow_bottom<0b000, "sqshrunb">; + defm SQRSHRUNB_ZZI : sve2_int_bin_shift_imm_right_narrow_bottom<0b001, "sqrshrunb">; + defm SHRNB_ZZI : sve2_int_bin_shift_imm_right_narrow_bottom<0b010, "shrnb">; + defm RSHRNB_ZZI : sve2_int_bin_shift_imm_right_narrow_bottom<0b011, "rshrnb">; + defm SQSHRNB_ZZI : sve2_int_bin_shift_imm_right_narrow_bottom<0b100, "sqshrnb">; + defm SQRSHRNB_ZZI : sve2_int_bin_shift_imm_right_narrow_bottom<0b101, "sqrshrnb">; + defm UQSHRNB_ZZI : sve2_int_bin_shift_imm_right_narrow_bottom<0b110, "uqshrnb">; + defm UQRSHRNB_ZZI : sve2_int_bin_shift_imm_right_narrow_bottom<0b111, "uqrshrnb">; + + // SVE2 bitwise shift right narrow (top) + defm SQSHRUNT_ZZI : sve2_int_bin_shift_imm_right_narrow_top<0b000, "sqshrunt">; + defm SQRSHRUNT_ZZI : sve2_int_bin_shift_imm_right_narrow_top<0b001, "sqrshrunt">; + defm SHRNT_ZZI : sve2_int_bin_shift_imm_right_narrow_top<0b010, "shrnt">; + defm RSHRNT_ZZI : sve2_int_bin_shift_imm_right_narrow_top<0b011, "rshrnt">; + defm SQSHRNT_ZZI : sve2_int_bin_shift_imm_right_narrow_top<0b100, "sqshrnt">; + defm SQRSHRNT_ZZI : sve2_int_bin_shift_imm_right_narrow_top<0b101, "sqrshrnt">; + defm UQSHRNT_ZZI : sve2_int_bin_shift_imm_right_narrow_top<0b110, "uqshrnt">; + defm UQRSHRNT_ZZI : sve2_int_bin_shift_imm_right_narrow_top<0b111, "uqrshrnt">; + + // SVE2 integer add/subtract narrow high part (bottom) + defm ADDHNB_ZZZ : sve2_int_addsub_narrow_high_bottom<0b00, "addhnb">; + defm RADDHNB_ZZZ : sve2_int_addsub_narrow_high_bottom<0b01, "raddhnb">; + defm SUBHNB_ZZZ : sve2_int_addsub_narrow_high_bottom<0b10, "subhnb">; + defm RSUBHNB_ZZZ : sve2_int_addsub_narrow_high_bottom<0b11, "rsubhnb">; + + // SVE2 integer add/subtract narrow high part (top) + defm ADDHNT_ZZZ : sve2_int_addsub_narrow_high_top<0b00, "addhnt">; + defm RADDHNT_ZZZ : sve2_int_addsub_narrow_high_top<0b01, "raddhnt">; + defm SUBHNT_ZZZ : sve2_int_addsub_narrow_high_top<0b10, "subhnt">; + defm RSUBHNT_ZZZ : sve2_int_addsub_narrow_high_top<0b11, "rsubhnt">; + + // SVE2 saturating extract narrow (bottom) + defm SQXTNB_ZZ : sve2_int_sat_extract_narrow_bottom<0b00, "sqxtnb">; + defm UQXTNB_ZZ : sve2_int_sat_extract_narrow_bottom<0b01, "uqxtnb">; + defm SQXTUNB_ZZ : sve2_int_sat_extract_narrow_bottom<0b10, "sqxtunb">; + + // SVE2 saturating extract narrow (top) + defm SQXTNT_ZZ : sve2_int_sat_extract_narrow_top<0b00, "sqxtnt">; + defm UQXTNT_ZZ : sve2_int_sat_extract_narrow_top<0b01, "uqxtnt">; + defm SQXTUNT_ZZ : sve2_int_sat_extract_narrow_top<0b10, "sqxtunt">; // SVE2 character match defm MATCH_PPzZZ : sve2_char_match<0b0, "match">; @@ -1289,10 +1302,14 @@ let Predicates = [HasSVE2] in { // SVE2 histogram generation (vector) defm HISTCNT_ZPzZZ : sve2_hist_gen_vector<"histcnt">; + // SVE2 floating-point base 2 logarithm as integer + defm FLOGB_ZPmZ : sve2_fp_flogb<"flogb">; + // SVE2 floating-point convert precision defm FCVTXNT_ZPmZ : sve2_fp_convert_down_odd_rounding<"fcvtxnt">; defm FCVTNT_ZPmZ : sve2_fp_convert_down_narrow<"fcvtnt">; defm FCVTLT_ZPmZ : sve2_fp_convert_up_long<"fcvtlt">; + def FCVTX_ZPmZ_DtoS : sve_fp_2op_p_zd<0b0001010, "fcvtx", ZPR64, ZPR32, ElementSizeD>; // SVE2 floating-point pairwise operations defm FADDP_ZPmZZ : sve2_fp_pairwise_pred<0b000, "faddp">; @@ -1321,58 +1338,45 @@ let Predicates = [HasSVE2] in { def BSL2N_ZZZZ_D : sve2_int_bitwise_ternary_op_d<0b101, "bsl2n">; def NBSL_ZZZZ_D : sve2_int_bitwise_ternary_op_d<0b111, "nbsl">; - // sve_int_rotate_imm + // SVE2 bitwise xor and rotate right by immediate defm XAR_ZZZI : sve2_int_rotate_right_imm<"xar">; // SVE2 extract vector (immediate offset, constructive) def EXT_ZZI_B : sve2_int_perm_extract_i_cons<"ext">; - // SVE floating-point convert precision - def FCVTX_ZPmZ_DtoS : sve_fp_2op_p_zd<0b0001010, "fcvtx", ZPR64, ZPR32, ElementSizeD>; - - // SVE floating-point convert to integer - defm FLOGB_ZPmZ : sve2_fp_flogb<"flogb">; - - // Non-temporal contiguous loads (vector + register) - defm LDNT1SB_ZZR_S : sve2_mem_cldnt_vs<0b00000, "ldnt1sb", Z_s, ZPR32>; - defm LDNT1B_ZZR_S : sve2_mem_cldnt_vs<0b00001, "ldnt1b", Z_s, ZPR32>; - defm LDNT1SH_ZZR_S : sve2_mem_cldnt_vs<0b00100, "ldnt1sh", Z_s, ZPR32>; - defm LDNT1H_ZZR_S : sve2_mem_cldnt_vs<0b00101, "ldnt1h", Z_s, ZPR32>; - defm LDNT1W_ZZR_S : sve2_mem_cldnt_vs<0b01001, "ldnt1w", Z_s, ZPR32>; - - defm LDNT1SB_ZZR_D : sve2_mem_cldnt_vs<0b10000, "ldnt1sb", Z_d, ZPR64>; - defm LDNT1B_ZZR_D : sve2_mem_cldnt_vs<0b10010, "ldnt1b", Z_d, ZPR64>; - defm LDNT1SH_ZZR_D : sve2_mem_cldnt_vs<0b10100, "ldnt1sh", Z_d, ZPR64>; - defm LDNT1H_ZZR_D : sve2_mem_cldnt_vs<0b10110, "ldnt1h", Z_d, ZPR64>; - defm LDNT1SW_ZZR_D : sve2_mem_cldnt_vs<0b11000, "ldnt1sw", Z_d, ZPR64>; - defm LDNT1W_ZZR_D : sve2_mem_cldnt_vs<0b11010, "ldnt1w", Z_d, ZPR64>; - defm LDNT1D_ZZR_D : sve2_mem_cldnt_vs<0b11110, "ldnt1d", Z_d, ZPR64>; + // SVE2 non-temporal gather loads + defm LDNT1SB_ZZR_S : sve2_mem_gldnt_vs<0b00000, "ldnt1sb", Z_s, ZPR32>; + defm LDNT1B_ZZR_S : sve2_mem_gldnt_vs<0b00001, "ldnt1b", Z_s, ZPR32>; + defm LDNT1SH_ZZR_S : sve2_mem_gldnt_vs<0b00100, "ldnt1sh", Z_s, ZPR32>; + defm LDNT1H_ZZR_S : sve2_mem_gldnt_vs<0b00101, "ldnt1h", Z_s, ZPR32>; + defm LDNT1W_ZZR_S : sve2_mem_gldnt_vs<0b01001, "ldnt1w", Z_s, ZPR32>; + + defm LDNT1SB_ZZR_D : sve2_mem_gldnt_vs<0b10000, "ldnt1sb", Z_d, ZPR64>; + defm LDNT1B_ZZR_D : sve2_mem_gldnt_vs<0b10010, "ldnt1b", Z_d, ZPR64>; + defm LDNT1SH_ZZR_D : sve2_mem_gldnt_vs<0b10100, "ldnt1sh", Z_d, ZPR64>; + defm LDNT1H_ZZR_D : sve2_mem_gldnt_vs<0b10110, "ldnt1h", Z_d, ZPR64>; + defm LDNT1SW_ZZR_D : sve2_mem_gldnt_vs<0b11000, "ldnt1sw", Z_d, ZPR64>; + defm LDNT1W_ZZR_D : sve2_mem_gldnt_vs<0b11010, "ldnt1w", Z_d, ZPR64>; + defm LDNT1D_ZZR_D : sve2_mem_gldnt_vs<0b11110, "ldnt1d", Z_d, ZPR64>; // SVE2 vector splice (constructive) defm SPLICE_ZPZZ : sve2_int_perm_splice_cons<"splice">; - // Predicated shifts - defm SQSHL_ZPmI : sve_int_bin_pred_shift_imm_left< 0b0110, "sqshl">; - defm UQSHL_ZPmI : sve_int_bin_pred_shift_imm_left< 0b0111, "uqshl">; - defm SRSHR_ZPmI : sve_int_bin_pred_shift_imm_right<0b1100, "srshr">; - defm URSHR_ZPmI : sve_int_bin_pred_shift_imm_right<0b1101, "urshr">; - defm SQSHLU_ZPmI : sve_int_bin_pred_shift_imm_left< 0b1111, "sqshlu">; - - // Non-temporal contiguous stores (vector + register) - defm STNT1B_ZZR_S : sve2_mem_cstnt_vs<0b001, "stnt1b", Z_s, ZPR32>; - defm STNT1H_ZZR_S : sve2_mem_cstnt_vs<0b011, "stnt1h", Z_s, ZPR32>; - defm STNT1W_ZZR_S : sve2_mem_cstnt_vs<0b101, "stnt1w", Z_s, ZPR32>; + // SVE2 non-temporal scatter stores + defm STNT1B_ZZR_S : sve2_mem_sstnt_vs<0b001, "stnt1b", Z_s, ZPR32>; + defm STNT1H_ZZR_S : sve2_mem_sstnt_vs<0b011, "stnt1h", Z_s, ZPR32>; + defm STNT1W_ZZR_S : sve2_mem_sstnt_vs<0b101, "stnt1w", Z_s, ZPR32>; - defm STNT1B_ZZR_D : sve2_mem_cstnt_vs<0b000, "stnt1b", Z_d, ZPR64>; - defm STNT1H_ZZR_D : sve2_mem_cstnt_vs<0b010, "stnt1h", Z_d, ZPR64>; - defm STNT1W_ZZR_D : sve2_mem_cstnt_vs<0b100, "stnt1w", Z_d, ZPR64>; - defm STNT1D_ZZR_D : sve2_mem_cstnt_vs<0b110, "stnt1d", Z_d, ZPR64>; + defm STNT1B_ZZR_D : sve2_mem_sstnt_vs<0b000, "stnt1b", Z_d, ZPR64>; + defm STNT1H_ZZR_D : sve2_mem_sstnt_vs<0b010, "stnt1h", Z_d, ZPR64>; + defm STNT1W_ZZR_D : sve2_mem_sstnt_vs<0b100, "stnt1w", Z_d, ZPR64>; + defm STNT1D_ZZR_D : sve2_mem_sstnt_vs<0b110, "stnt1d", Z_d, ZPR64>; - // SVE table lookup (three sources) + // SVE2 table lookup (three sources) defm TBL_ZZZZ : sve2_int_perm_tbl<"tbl">; defm TBX_ZZZ : sve2_int_perm_tbx<"tbx">; - // SVE integer compare scalar count and limit + // SVE2 integer compare scalar count and limit defm WHILEGE_PWW : sve_int_while4_rr<0b000, "whilege">; defm WHILEGT_PWW : sve_int_while4_rr<0b001, "whilegt">; defm WHILEHS_PWW : sve_int_while4_rr<0b100, "whilehs">; @@ -1383,7 +1387,7 @@ let Predicates = [HasSVE2] in { defm WHILEHS_PXX : sve_int_while8_rr<0b100, "whilehs">; defm WHILEHI_PXX : sve_int_while8_rr<0b101, "whilehi">; - // SVE pointer conflict compare + // SVE2 pointer conflict compare defm WHILEWR_PXX : sve2_int_while_rr<0b0, "whilewr">; defm WHILERW_PXX : sve2_int_while_rr<0b1, "whilerw">; } diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp index f4c55d48d215..09b42811f786 100644 --- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp +++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp @@ -2840,7 +2840,7 @@ static const struct Extension { {"sve2-aes", {AArch64::FeatureSVE2AES}}, {"sve2-sm4", {AArch64::FeatureSVE2SM4}}, {"sve2-sha3", {AArch64::FeatureSVE2SHA3}}, - {"bitperm", {AArch64::FeatureSVE2BitPerm}}, + {"sve2-bitperm", {AArch64::FeatureSVE2BitPerm}}, // FIXME: Unsupported extensions {"pan", {}}, {"lor", {}}, diff --git a/llvm/lib/Target/AArch64/SVEInstrFormats.td b/llvm/lib/Target/AArch64/SVEInstrFormats.td index 808e59467081..3f698f5762b6 100644 --- a/llvm/lib/Target/AArch64/SVEInstrFormats.td +++ b/llvm/lib/Target/AArch64/SVEInstrFormats.td @@ -744,7 +744,7 @@ multiclass sve2_int_perm_tbl { } class sve2_int_perm_tbx sz8_64, string asm, ZPRRegOp zprty> -: I<(outs zprty:$Zd), (ins zprty:$Zn, zprty:$Zm), +: I<(outs zprty:$Zd), (ins zprty:$_Zd, zprty:$Zn, zprty:$Zm), asm, "\t$Zd, $Zn, $Zm", "", []>, Sched<[]> { @@ -758,6 +758,8 @@ class sve2_int_perm_tbx sz8_64, string asm, ZPRRegOp zprty> let Inst{15-10} = 0b001011; let Inst{9-5} = Zn; let Inst{4-0} = Zd; + + let Constraints = "$Zd = $_Zd"; } multiclass sve2_int_perm_tbx { @@ -1489,7 +1491,7 @@ multiclass sve_fp_fcadd { class sve2_fp_convert_precision opc, string asm, ZPRRegOp zprty1, ZPRRegOp zprty2> -: I<(outs zprty1:$Zd), (ins PPR3bAny:$Pg, zprty2:$Zn), +: I<(outs zprty1:$Zd), (ins zprty1:$_Zd, PPR3bAny:$Pg, zprty2:$Zn), asm, "\t$Zd, $Pg/m, $Zn", "", []>, Sched<[]> { @@ -1504,6 +1506,8 @@ class sve2_fp_convert_precision opc, string asm, let Inst{12-10} = Pg; let Inst{9-5} = Zn; let Inst{4-0} = Zd; + + let Constraints = "$Zd = $_Zd"; } multiclass sve2_fp_convert_down_narrow { @@ -2399,21 +2403,40 @@ multiclass sve2_misc_bitwise opc, string asm> { def _D : sve2_misc<0b11, opc, asm, ZPR64, ZPR64>; } -multiclass sve2_bitwise_xor_interleaved { - let DestructiveInstType = Destructive, ElementSize = ElementSizeNone in { - def _B : sve2_misc<0b00, { 0b010, opc }, asm, ZPR8, ZPR8>; - def _H : sve2_misc<0b01, { 0b010, opc }, asm, ZPR16, ZPR16>; - def _S : sve2_misc<0b10, { 0b010, opc }, asm, ZPR32, ZPR32>; - def _D : sve2_misc<0b11, { 0b010, opc }, asm, ZPR64, ZPR64>; - } -} - multiclass sve2_misc_int_addsub_long_interleaved opc, string asm> { def _H : sve2_misc<0b01, { 0b00, opc }, asm, ZPR16, ZPR8>; def _S : sve2_misc<0b10, { 0b00, opc }, asm, ZPR32, ZPR16>; def _D : sve2_misc<0b11, { 0b00, opc }, asm, ZPR64, ZPR32>; } +class sve2_bitwise_xor_interleaved sz, bits<1> opc, string asm, + ZPRRegOp zprty1, ZPRRegOp zprty2> +: I<(outs zprty1:$Zd), (ins zprty1:$_Zd, zprty2:$Zn, zprty2:$Zm), + asm, "\t$Zd, $Zn, $Zm", "", []>, Sched<[]> { + bits<5> Zd; + bits<5> Zn; + bits<5> Zm; + let Inst{31-24} = 0b01000101; + let Inst{23-22} = sz; + let Inst{21} = 0b0; + let Inst{20-16} = Zm; + let Inst{15-11} = 0b10010; + let Inst{10} = opc; + let Inst{9-5} = Zn; + let Inst{4-0} = Zd; + + let Constraints = "$Zd = $_Zd"; + let DestructiveInstType = Destructive; + let ElementSize = ElementSizeNone; +} + +multiclass sve2_bitwise_xor_interleaved { + def _B : sve2_bitwise_xor_interleaved<0b00, opc, asm, ZPR8, ZPR8>; + def _H : sve2_bitwise_xor_interleaved<0b01, opc, asm, ZPR16, ZPR16>; + def _S : sve2_bitwise_xor_interleaved<0b10, opc, asm, ZPR32, ZPR32>; + def _D : sve2_bitwise_xor_interleaved<0b11, opc, asm, ZPR64, ZPR64>; +} + class sve2_bitwise_shift_left_long tsz8_64, bits<2> opc, string asm, ZPRRegOp zprty1, ZPRRegOp zprty2, Operand immtype> @@ -2451,9 +2474,9 @@ multiclass sve2_bitwise_shift_left_long opc, string asm> { // SVE2 Accumulate Group //===----------------------------------------------------------------------===// -class sve2_int_bin_cons_shift_imm tsz8_64, bit opc, string asm, - ZPRRegOp zprty, Operand immtype> -: I<(outs zprty:$Zd), (ins zprty:$Zn, immtype:$imm), +class sve2_int_bin_shift_imm tsz8_64, bit opc, string asm, + ZPRRegOp zprty, Operand immtype> +: I<(outs zprty:$Zd), (ins zprty:$_Zd, zprty:$Zn, immtype:$imm), asm, "\t$Zd, $Zn, $imm", "", []>, Sched<[]> { bits<5> Zd; @@ -2468,38 +2491,40 @@ class sve2_int_bin_cons_shift_imm tsz8_64, bit opc, string asm, let Inst{10} = opc; let Inst{9-5} = Zn; let Inst{4-0} = Zd; + + let Constraints = "$Zd = $_Zd"; } -multiclass sve2_int_bin_cons_shift_imm_left { - def _B : sve2_int_bin_cons_shift_imm<{0,0,0,1}, opc, asm, ZPR8, vecshiftL8>; - def _H : sve2_int_bin_cons_shift_imm<{0,0,1,?}, opc, asm, ZPR16, vecshiftL16> { +multiclass sve2_int_bin_shift_imm_left { + def _B : sve2_int_bin_shift_imm<{0,0,0,1}, opc, asm, ZPR8, vecshiftL8>; + def _H : sve2_int_bin_shift_imm<{0,0,1,?}, opc, asm, ZPR16, vecshiftL16> { let Inst{19} = imm{3}; } - def _S : sve2_int_bin_cons_shift_imm<{0,1,?,?}, opc, asm, ZPR32, vecshiftL32> { + def _S : sve2_int_bin_shift_imm<{0,1,?,?}, opc, asm, ZPR32, vecshiftL32> { let Inst{20-19} = imm{4-3}; } - def _D : sve2_int_bin_cons_shift_imm<{1,?,?,?}, opc, asm, ZPR64, vecshiftL64> { + def _D : sve2_int_bin_shift_imm<{1,?,?,?}, opc, asm, ZPR64, vecshiftL64> { let Inst{22} = imm{5}; let Inst{20-19} = imm{4-3}; } } -multiclass sve2_int_bin_cons_shift_imm_right { - def _B : sve2_int_bin_cons_shift_imm<{0,0,0,1}, opc, asm, ZPR8, vecshiftR8>; - def _H : sve2_int_bin_cons_shift_imm<{0,0,1,?}, opc, asm, ZPR16, vecshiftR16> { +multiclass sve2_int_bin_shift_imm_right { + def _B : sve2_int_bin_shift_imm<{0,0,0,1}, opc, asm, ZPR8, vecshiftR8>; + def _H : sve2_int_bin_shift_imm<{0,0,1,?}, opc, asm, ZPR16, vecshiftR16> { let Inst{19} = imm{3}; } - def _S : sve2_int_bin_cons_shift_imm<{0,1,?,?}, opc, asm, ZPR32, vecshiftR32> { + def _S : sve2_int_bin_shift_imm<{0,1,?,?}, opc, asm, ZPR32, vecshiftR32> { let Inst{20-19} = imm{4-3}; } - def _D : sve2_int_bin_cons_shift_imm<{1,?,?,?}, opc, asm, ZPR64, vecshiftR64> { + def _D : sve2_int_bin_shift_imm<{1,?,?,?}, opc, asm, ZPR64, vecshiftR64> { let Inst{22} = imm{5}; let Inst{20-19} = imm{4-3}; } } -class sve2_int_bin_accum_cons_shift_imm tsz8_64, bits<2> opc, string asm, - ZPRRegOp zprty, Operand immtype> +class sve2_int_bin_accum_shift_imm tsz8_64, bits<2> opc, string asm, + ZPRRegOp zprty, Operand immtype> : I<(outs zprty:$Zda), (ins zprty:$_Zda, zprty:$Zn, immtype:$imm), asm, "\t$Zda, $Zn, $imm", "", []>, Sched<[]> { @@ -2521,15 +2546,15 @@ class sve2_int_bin_accum_cons_shift_imm tsz8_64, bits<2> opc, string asm let ElementSize = ElementSizeNone; } -multiclass sve2_int_bin_accum_cons_shift_imm_right opc, string asm> { - def _B : sve2_int_bin_accum_cons_shift_imm<{0,0,0,1}, opc, asm, ZPR8, vecshiftR8>; - def _H : sve2_int_bin_accum_cons_shift_imm<{0,0,1,?}, opc, asm, ZPR16, vecshiftR16> { +multiclass sve2_int_bin_accum_shift_imm_right opc, string asm> { + def _B : sve2_int_bin_accum_shift_imm<{0,0,0,1}, opc, asm, ZPR8, vecshiftR8>; + def _H : sve2_int_bin_accum_shift_imm<{0,0,1,?}, opc, asm, ZPR16, vecshiftR16> { let Inst{19} = imm{3}; } - def _S : sve2_int_bin_accum_cons_shift_imm<{0,1,?,?}, opc, asm, ZPR32, vecshiftR32> { + def _S : sve2_int_bin_accum_shift_imm<{0,1,?,?}, opc, asm, ZPR32, vecshiftR32> { let Inst{20-19} = imm{4-3}; } - def _D : sve2_int_bin_accum_cons_shift_imm<{1,?,?,?}, opc, asm, ZPR64, vecshiftR64> { + def _D : sve2_int_bin_accum_shift_imm<{1,?,?,?}, opc, asm, ZPR64, vecshiftR64> { let Inst{22} = imm{5}; let Inst{20-19} = imm{4-3}; } @@ -2607,9 +2632,9 @@ multiclass sve2_int_addsub_long_carry opc, string asm> { // SVE2 Narrowing Group //===----------------------------------------------------------------------===// -class sve2_int_bin_cons_shift_imm_narrow tsz8_64, bits<4> opc, - string asm, ZPRRegOp zprty1, - ZPRRegOp zprty2, Operand immtype> +class sve2_int_bin_shift_imm_narrow_bottom tsz8_64, bits<3> opc, + string asm, ZPRRegOp zprty1, + ZPRRegOp zprty2, Operand immtype> : I<(outs zprty1:$Zd), (ins zprty2:$Zn, immtype:$imm), asm, "\t$Zd, $Zn, $imm", "", []>, Sched<[]> { @@ -2622,26 +2647,63 @@ class sve2_int_bin_cons_shift_imm_narrow tsz8_64, bits<4> opc, let Inst{20-19} = tsz8_64{1-0}; let Inst{18-16} = imm{2-0}; // imm3 let Inst{15-14} = 0b00; - let Inst{13-10} = opc; + let Inst{13-11} = opc; + let Inst{10} = 0b0; let Inst{9-5} = Zn; let Inst{4-0} = Zd; } -multiclass sve2_int_bin_cons_shift_imm_right_narrow opc, string asm> { - def _B : sve2_int_bin_cons_shift_imm_narrow<{0,0,1}, opc, asm, ZPR8, ZPR16, - vecshiftR8>; - def _H : sve2_int_bin_cons_shift_imm_narrow<{0,1,?}, opc, asm, ZPR16, ZPR32, - vecshiftR16> { +multiclass sve2_int_bin_shift_imm_right_narrow_bottom opc, string asm> { + def _B : sve2_int_bin_shift_imm_narrow_bottom<{0,0,1}, opc, asm, ZPR8, ZPR16, + vecshiftR8>; + def _H : sve2_int_bin_shift_imm_narrow_bottom<{0,1,?}, opc, asm, ZPR16, ZPR32, + vecshiftR16> { let Inst{19} = imm{3}; } - def _S : sve2_int_bin_cons_shift_imm_narrow<{1,?,?}, opc, asm, ZPR32, ZPR64, - vecshiftR32> { + def _S : sve2_int_bin_shift_imm_narrow_bottom<{1,?,?}, opc, asm, ZPR32, ZPR64, + vecshiftR32> { let Inst{20-19} = imm{4-3}; } } -class sve2_int_addsub_narrow_high sz, bits<3> opc, string asm, - ZPRRegOp zprty1, ZPRRegOp zprty2> +class sve2_int_bin_shift_imm_narrow_top tsz8_64, bits<3> opc, + string asm, ZPRRegOp zprty1, + ZPRRegOp zprty2, Operand immtype> +: I<(outs zprty1:$Zd), (ins zprty1:$_Zd, zprty2:$Zn, immtype:$imm), + asm, "\t$Zd, $Zn, $imm", + "", []>, Sched<[]> { + bits<5> Zd; + bits<5> Zn; + bits<5> imm; + let Inst{31-23} = 0b010001010; + let Inst{22} = tsz8_64{2}; + let Inst{21} = 0b1; + let Inst{20-19} = tsz8_64{1-0}; + let Inst{18-16} = imm{2-0}; // imm3 + let Inst{15-14} = 0b00; + let Inst{13-11} = opc; + let Inst{10} = 0b1; + let Inst{9-5} = Zn; + let Inst{4-0} = Zd; + + let Constraints = "$Zd = $_Zd"; +} + +multiclass sve2_int_bin_shift_imm_right_narrow_top opc, string asm> { + def _B : sve2_int_bin_shift_imm_narrow_top<{0,0,1}, opc, asm, ZPR8, ZPR16, + vecshiftR8>; + def _H : sve2_int_bin_shift_imm_narrow_top<{0,1,?}, opc, asm, ZPR16, ZPR32, + vecshiftR16> { + let Inst{19} = imm{3}; + } + def _S : sve2_int_bin_shift_imm_narrow_top<{1,?,?}, opc, asm, ZPR32, ZPR64, + vecshiftR32> { + let Inst{20-19} = imm{4-3}; + } +} + +class sve2_int_addsub_narrow_high_bottom sz, bits<2> opc, string asm, + ZPRRegOp zprty1, ZPRRegOp zprty2> : I<(outs zprty1:$Zd), (ins zprty2:$Zn, zprty2:$Zm), asm, "\t$Zd, $Zn, $Zm", "", []>, Sched<[]> { bits<5> Zd; @@ -2652,19 +2714,46 @@ class sve2_int_addsub_narrow_high sz, bits<3> opc, string asm, let Inst{21} = 0b1; let Inst{20-16} = Zm; let Inst{15-13} = 0b011; - let Inst{12-10} = opc; // S, R, T + let Inst{12-11} = opc; // S, R + let Inst{10} = 0b0; // Top let Inst{9-5} = Zn; let Inst{4-0} = Zd; } -multiclass sve2_int_addsub_narrow_high opc, string asm> { - def _B : sve2_int_addsub_narrow_high<0b01, opc, asm, ZPR8, ZPR16>; - def _H : sve2_int_addsub_narrow_high<0b10, opc, asm, ZPR16, ZPR32>; - def _S : sve2_int_addsub_narrow_high<0b11, opc, asm, ZPR32, ZPR64>; +multiclass sve2_int_addsub_narrow_high_bottom opc, string asm> { + def _B : sve2_int_addsub_narrow_high_bottom<0b01, opc, asm, ZPR8, ZPR16>; + def _H : sve2_int_addsub_narrow_high_bottom<0b10, opc, asm, ZPR16, ZPR32>; + def _S : sve2_int_addsub_narrow_high_bottom<0b11, opc, asm, ZPR32, ZPR64>; } -class sve2_int_sat_extract_narrow tsz8_64, bits<3> opc, string asm, - ZPRRegOp zprty1, ZPRRegOp zprty2> +class sve2_int_addsub_narrow_high_top sz, bits<2> opc, string asm, + ZPRRegOp zprty1, ZPRRegOp zprty2> +: I<(outs zprty1:$Zd), (ins zprty1:$_Zd, zprty2:$Zn, zprty2:$Zm), + asm, "\t$Zd, $Zn, $Zm", "", []>, Sched<[]> { + bits<5> Zd; + bits<5> Zn; + bits<5> Zm; + let Inst{31-24} = 0b01000101; + let Inst{23-22} = sz; + let Inst{21} = 0b1; + let Inst{20-16} = Zm; + let Inst{15-13} = 0b011; + let Inst{12-11} = opc; // S, R + let Inst{10} = 0b1; // Top + let Inst{9-5} = Zn; + let Inst{4-0} = Zd; + + let Constraints = "$Zd = $_Zd"; +} + +multiclass sve2_int_addsub_narrow_high_top opc, string asm> { + def _B : sve2_int_addsub_narrow_high_top<0b01, opc, asm, ZPR8, ZPR16>; + def _H : sve2_int_addsub_narrow_high_top<0b10, opc, asm, ZPR16, ZPR32>; + def _S : sve2_int_addsub_narrow_high_top<0b11, opc, asm, ZPR32, ZPR64>; +} + +class sve2_int_sat_extract_narrow_bottom tsz8_64, bits<2> opc, string asm, + ZPRRegOp zprty1, ZPRRegOp zprty2> : I<(outs zprty1:$Zd), (ins zprty2:$Zn), asm, "\t$Zd, $Zn", "", []>, Sched<[]> { bits<5> Zd; @@ -2674,15 +2763,41 @@ class sve2_int_sat_extract_narrow tsz8_64, bits<3> opc, string asm, let Inst{21} = 0b1; let Inst{20-19} = tsz8_64{1-0}; let Inst{18-13} = 0b000010; - let Inst{12-10} = opc; + let Inst{12-11} = opc; + let Inst{10} = 0b0; + let Inst{9-5} = Zn; + let Inst{4-0} = Zd; +} + +multiclass sve2_int_sat_extract_narrow_bottom opc, string asm> { + def _B : sve2_int_sat_extract_narrow_bottom<0b001, opc, asm, ZPR8, ZPR16>; + def _H : sve2_int_sat_extract_narrow_bottom<0b010, opc, asm, ZPR16, ZPR32>; + def _S : sve2_int_sat_extract_narrow_bottom<0b100, opc, asm, ZPR32, ZPR64>; +} + +class sve2_int_sat_extract_narrow_top tsz8_64, bits<2> opc, string asm, + ZPRRegOp zprty1, ZPRRegOp zprty2> +: I<(outs zprty1:$Zd), (ins zprty1:$_Zd, zprty2:$Zn), + asm, "\t$Zd, $Zn", "", []>, Sched<[]> { + bits<5> Zd; + bits<5> Zn; + let Inst{31-23} = 0b010001010; + let Inst{22} = tsz8_64{2}; + let Inst{21} = 0b1; + let Inst{20-19} = tsz8_64{1-0}; + let Inst{18-13} = 0b000010; + let Inst{12-11} = opc; + let Inst{10} = 0b1; let Inst{9-5} = Zn; let Inst{4-0} = Zd; + + let Constraints = "$Zd = $_Zd"; } -multiclass sve2_int_sat_extract_narrow opc, string asm> { - def _B : sve2_int_sat_extract_narrow<0b001, opc, asm, ZPR8, ZPR16>; - def _H : sve2_int_sat_extract_narrow<0b010, opc, asm, ZPR16, ZPR32>; - def _S : sve2_int_sat_extract_narrow<0b100, opc, asm, ZPR32, ZPR64>; +multiclass sve2_int_sat_extract_narrow_top opc, string asm> { + def _B : sve2_int_sat_extract_narrow_top<0b001, opc, asm, ZPR8, ZPR16>; + def _H : sve2_int_sat_extract_narrow_top<0b010, opc, asm, ZPR16, ZPR32>; + def _S : sve2_int_sat_extract_narrow_top<0b100, opc, asm, ZPR32, ZPR64>; } //===----------------------------------------------------------------------===// @@ -3886,9 +4001,9 @@ multiclass sve_mem_cstnt_ss msz, string asm, RegisterOperand listty, (!cast(NAME) zprty:$Zt, PPR3bAny:$Pg, GPR64sp:$Rn, gprty:$Rm), 0>; } -class sve2_mem_cstnt_vs_base opc, dag iops, string asm, - RegisterOperand VecList> -: I<(outs VecList:$Zt), iops, +class sve2_mem_sstnt_vs_base opc, string asm, + RegisterOperand listty, ZPRRegOp zprty> +: I<(outs), (ins listty:$Zt, PPR3bAny:$Pg, zprty:$Zn, GPR64:$Rm), asm, "\t$Zt, $Pg, [$Zn, $Rm]", "", []>, Sched<[]> { @@ -3908,17 +4023,14 @@ class sve2_mem_cstnt_vs_base opc, dag iops, string asm, let mayStore = 1; } -multiclass sve2_mem_cstnt_vs opc, string asm, +multiclass sve2_mem_sstnt_vs opc, string asm, RegisterOperand listty, ZPRRegOp zprty> { - def _REAL : sve2_mem_cstnt_vs_base; + def _REAL : sve2_mem_sstnt_vs_base; def : InstAlias(NAME # _REAL) zprty:$Zt, PPR3bAny:$Pg, zprty:$Zn, GPR64:$Rm), 0>; def : InstAlias(NAME # _REAL) zprty:$Zt, PPR3bAny:$Pg, zprty:$Zn, XZR), 0>; - def : InstAlias(NAME # _REAL) listty:$Zt, PPR3bAny:$Pg, zprty:$Zn, GPR64:$Rm), 0>; def : InstAlias(NAME # _REAL) listty:$Zt, PPR3bAny:$Pg, zprty:$Zn, XZR), 1>; } @@ -5094,7 +5206,7 @@ multiclass sve_mem_p_fill { (!cast(NAME) PPRAny:$Pt, GPR64sp:$Rn, 0), 1>; } -class sve2_mem_cldnt_vs_base opc, dag iops, string asm, +class sve2_mem_gldnt_vs_base opc, dag iops, string asm, RegisterOperand VecList> : I<(outs VecList:$Zt), iops, asm, "\t$Zt, $Pg/z, [$Zn, $Rm]", @@ -5119,17 +5231,15 @@ class sve2_mem_cldnt_vs_base opc, dag iops, string asm, let mayLoad = 1; } -multiclass sve2_mem_cldnt_vs opc, string asm, +multiclass sve2_mem_gldnt_vs opc, string asm, RegisterOperand listty, ZPRRegOp zprty> { - def _REAL : sve2_mem_cldnt_vs_base; def : InstAlias(NAME # _REAL) zprty:$Zt, PPR3bAny:$Pg, zprty:$Zn, GPR64:$Rm), 0>; def : InstAlias(NAME # _REAL) zprty:$Zt, PPR3bAny:$Pg, zprty:$Zn, XZR), 0>; - def : InstAlias(NAME # _REAL) listty:$Zt, PPR3bAny:$Pg, zprty:$Zn, GPR64:$Rm), 0>; def : InstAlias(NAME # _REAL) listty:$Zt, PPR3bAny:$Pg, zprty:$Zn, XZR), 1>; } diff --git a/llvm/test/MC/AArch64/SVE2/bdep-diagnostics.s b/llvm/test/MC/AArch64/SVE2/bdep-diagnostics.s index f6dce7958672..08a589e1f963 100644 --- a/llvm/test/MC/AArch64/SVE2/bdep-diagnostics.s +++ b/llvm/test/MC/AArch64/SVE2/bdep-diagnostics.s @@ -1,4 +1,4 @@ -// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+bitperm 2>&1 < %s| FileCheck %s +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2-bitperm 2>&1 < %s| FileCheck %s // ------------------------------------------------------------------------- // diff --git a/llvm/test/MC/AArch64/SVE2/bdep.s b/llvm/test/MC/AArch64/SVE2/bdep.s index 9d68b5a673c8..0bc935226373 100644 --- a/llvm/test/MC/AArch64/SVE2/bdep.s +++ b/llvm/test/MC/AArch64/SVE2/bdep.s @@ -1,32 +1,32 @@ -// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+bitperm < %s \ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2-bitperm < %s \ // RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST // RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ // RUN: | FileCheck %s --check-prefix=CHECK-ERROR -// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+bitperm < %s \ -// RUN: | llvm-objdump -d -mattr=+bitperm - | FileCheck %s --check-prefix=CHECK-INST -// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+bitperm < %s \ +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2-bitperm < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2-bitperm - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2-bitperm < %s \ // RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN bdep z0.b, z1.b, z31.b // CHECK-INST: bdep z0.b, z1.b, z31.b // CHECK-ENCODING: [0x20,0xb4,0x1f,0x45] -// CHECK-ERROR: instruction requires: bitperm +// CHECK-ERROR: instruction requires: sve2-bitperm // CHECK-UNKNOWN: 20 b4 1f 45 bdep z0.h, z1.h, z31.h // CHECK-INST: bdep z0.h, z1.h, z31.h // CHECK-ENCODING: [0x20,0xb4,0x5f,0x45] -// CHECK-ERROR: instruction requires: bitperm +// CHECK-ERROR: instruction requires: sve2-bitperm // CHECK-UNKNOWN: 20 b4 5f 45 bdep z0.s, z1.s, z31.s // CHECK-INST: bdep z0.s, z1.s, z31.s // CHECK-ENCODING: [0x20,0xb4,0x9f,0x45] -// CHECK-ERROR: instruction requires: bitperm +// CHECK-ERROR: instruction requires: sve2-bitperm // CHECK-UNKNOWN: 20 b4 9f 45 bdep z0.d, z1.d, z31.d // CHECK-INST: bdep z0.d, z1.d, z31.d // CHECK-ENCODING: [0x20,0xb4,0xdf,0x45] -// CHECK-ERROR: instruction requires: bitperm +// CHECK-ERROR: instruction requires: sve2-bitperm // CHECK-UNKNOWN: 20 b4 df 45 diff --git a/llvm/test/MC/AArch64/SVE2/bext-diagnostics.s b/llvm/test/MC/AArch64/SVE2/bext-diagnostics.s index 7ffe1449cc2c..5faadbcb8f4a 100644 --- a/llvm/test/MC/AArch64/SVE2/bext-diagnostics.s +++ b/llvm/test/MC/AArch64/SVE2/bext-diagnostics.s @@ -1,4 +1,4 @@ -// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+bitperm 2>&1 < %s| FileCheck %s +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2-bitperm 2>&1 < %s| FileCheck %s // ------------------------------------------------------------------------- // diff --git a/llvm/test/MC/AArch64/SVE2/bext.s b/llvm/test/MC/AArch64/SVE2/bext.s index 2c23bd9b2af4..ae3d0bfbff5e 100644 --- a/llvm/test/MC/AArch64/SVE2/bext.s +++ b/llvm/test/MC/AArch64/SVE2/bext.s @@ -1,32 +1,32 @@ -// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+bitperm < %s \ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2-bitperm < %s \ // RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST // RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ // RUN: | FileCheck %s --check-prefix=CHECK-ERROR -// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+bitperm < %s \ -// RUN: | llvm-objdump -d -mattr=+bitperm - | FileCheck %s --check-prefix=CHECK-INST -// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+bitperm < %s \ +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2-bitperm < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2-bitperm - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2-bitperm < %s \ // RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN bext z0.b, z1.b, z31.b // CHECK-INST: bext z0.b, z1.b, z31.b // CHECK-ENCODING: [0x20,0xb0,0x1f,0x45] -// CHECK-ERROR: instruction requires: bitperm +// CHECK-ERROR: instruction requires: sve2-bitperm // CHECK-UNKNOWN: 20 b0 1f 45 bext z0.h, z1.h, z31.h // CHECK-INST: bext z0.h, z1.h, z31.h // CHECK-ENCODING: [0x20,0xb0,0x5f,0x45] -// CHECK-ERROR: instruction requires: bitperm +// CHECK-ERROR: instruction requires: sve2-bitperm // CHECK-UNKNOWN: 20 b0 5f 45 bext z0.s, z1.s, z31.s // CHECK-INST: bext z0.s, z1.s, z31.s // CHECK-ENCODING: [0x20,0xb0,0x9f,0x45] -// CHECK-ERROR: instruction requires: bitperm +// CHECK-ERROR: instruction requires: sve2-bitperm // CHECK-UNKNOWN: 20 b0 9f 45 bext z0.d, z1.d, z31.d // CHECK-INST: bext z0.d, z1.d, z31.d // CHECK-ENCODING: [0x20,0xb0,0xdf,0x45] -// CHECK-ERROR: instruction requires: bitperm +// CHECK-ERROR: instruction requires: sve2-bitperm // CHECK-UNKNOWN: 20 b0 df 45 diff --git a/llvm/test/MC/AArch64/SVE2/bgrp-diagnostics.s b/llvm/test/MC/AArch64/SVE2/bgrp-diagnostics.s index 9c05a0c6918d..2ae32c04b78e 100644 --- a/llvm/test/MC/AArch64/SVE2/bgrp-diagnostics.s +++ b/llvm/test/MC/AArch64/SVE2/bgrp-diagnostics.s @@ -1,4 +1,4 @@ -// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+bitperm 2>&1 < %s| FileCheck %s +// RUN: not llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2-bitperm 2>&1 < %s| FileCheck %s // ------------------------------------------------------------------------- // diff --git a/llvm/test/MC/AArch64/SVE2/bgrp.s b/llvm/test/MC/AArch64/SVE2/bgrp.s index b2e7f98a4303..3d994c0a3648 100644 --- a/llvm/test/MC/AArch64/SVE2/bgrp.s +++ b/llvm/test/MC/AArch64/SVE2/bgrp.s @@ -1,32 +1,32 @@ -// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+bitperm < %s \ +// RUN: llvm-mc -triple=aarch64 -show-encoding -mattr=+sve2-bitperm < %s \ // RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST // RUN: not llvm-mc -triple=aarch64 -show-encoding < %s 2>&1 \ // RUN: | FileCheck %s --check-prefix=CHECK-ERROR -// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+bitperm < %s \ -// RUN: | llvm-objdump -d -mattr=+bitperm - | FileCheck %s --check-prefix=CHECK-INST -// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+bitperm < %s \ +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2-bitperm < %s \ +// RUN: | llvm-objdump -d -mattr=+sve2-bitperm - | FileCheck %s --check-prefix=CHECK-INST +// RUN: llvm-mc -triple=aarch64 -filetype=obj -mattr=+sve2-bitperm < %s \ // RUN: | llvm-objdump -d - | FileCheck %s --check-prefix=CHECK-UNKNOWN bgrp z0.b, z1.b, z31.b // CHECK-INST: bgrp z0.b, z1.b, z31.b // CHECK-ENCODING: [0x20,0xb8,0x1f,0x45] -// CHECK-ERROR: instruction requires: bitperm +// CHECK-ERROR: instruction requires: sve2-bitperm // CHECK-UNKNOWN: 20 b8 1f 45 bgrp z0.h, z1.h, z31.h // CHECK-INST: bgrp z0.h, z1.h, z31.h // CHECK-ENCODING: [0x20,0xb8,0x5f,0x45] -// CHECK-ERROR: instruction requires: bitperm +// CHECK-ERROR: instruction requires: sve2-bitperm // CHECK-UNKNOWN: 20 b8 5f 45 bgrp z0.s, z1.s, z31.s // CHECK-INST: bgrp z0.s, z1.s, z31.s // CHECK-ENCODING: [0x20,0xb8,0x9f,0x45] -// CHECK-ERROR: instruction requires: bitperm +// CHECK-ERROR: instruction requires: sve2-bitperm // CHECK-UNKNOWN: 20 b8 9f 45 bgrp z0.d, z1.d, z31.d // CHECK-INST: bgrp z0.d, z1.d, z31.d // CHECK-ENCODING: [0x20,0xb8,0xdf,0x45] -// CHECK-ERROR: instruction requires: bitperm +// CHECK-ERROR: instruction requires: sve2-bitperm // CHECK-UNKNOWN: 20 b8 df 45 diff --git a/llvm/test/MC/AArch64/SVE2/directive-arch-negative.s b/llvm/test/MC/AArch64/SVE2/directive-arch-negative.s index 4b2ba039dc38..51775ee5379b 100644 --- a/llvm/test/MC/AArch64/SVE2/directive-arch-negative.s +++ b/llvm/test/MC/AArch64/SVE2/directive-arch-negative.s @@ -24,8 +24,8 @@ rax1 z0.d, z0.d, z0.d // CHECK: error: instruction requires: sve2-sha3 // CHECK-NEXT: rax1 z0.d, z0.d, z0.d -.arch armv8-a+bitperm -.arch armv8-a+nobitperm +.arch armv8-a+sve2-bitperm +.arch armv8-a+nosve2-bitperm bgrp z21.s, z10.s, z21.s -// CHECK: error: instruction requires: bitperm +// CHECK: error: instruction requires: sve2-bitperm // CHECK-NEXT: bgrp z21.s, z10.s, z21.s diff --git a/llvm/test/MC/AArch64/SVE2/directive-arch.s b/llvm/test/MC/AArch64/SVE2/directive-arch.s index 94ef64700755..4e2e71dbb732 100644 --- a/llvm/test/MC/AArch64/SVE2/directive-arch.s +++ b/llvm/test/MC/AArch64/SVE2/directive-arch.s @@ -16,6 +16,6 @@ sm4e z0.s, z0.s, z0.s rax1 z0.d, z0.d, z0.d // CHECK: rax1 z0.d, z0.d, z0.d -.arch armv8-a+bitperm +.arch armv8-a+sve2-bitperm bgrp z21.s, z10.s, z21.s // CHECK: bgrp z21.s, z10.s, z21.s diff --git a/llvm/test/MC/AArch64/SVE2/directive-arch_extension-negative.s b/llvm/test/MC/AArch64/SVE2/directive-arch_extension-negative.s index 5db80e11a910..1a1f81ae7ffb 100644 --- a/llvm/test/MC/AArch64/SVE2/directive-arch_extension-negative.s +++ b/llvm/test/MC/AArch64/SVE2/directive-arch_extension-negative.s @@ -24,8 +24,8 @@ rax1 z0.d, z0.d, z0.d // CHECK: error: instruction requires: sve2-sha3 // CHECK-NEXT: rax1 z0.d, z0.d, z0.d -.arch_extension bitperm -.arch_extension nobitperm +.arch_extension sve2-bitperm +.arch_extension nosve2-bitperm bgrp z21.s, z10.s, z21.s -// CHECK: error: instruction requires: bitperm +// CHECK: error: instruction requires: sve2-bitperm // CHECK-NEXT: bgrp z21.s, z10.s, z21.s diff --git a/llvm/test/MC/AArch64/SVE2/directive-arch_extension.s b/llvm/test/MC/AArch64/SVE2/directive-arch_extension.s index 257f5721d720..90f5bec07d54 100644 --- a/llvm/test/MC/AArch64/SVE2/directive-arch_extension.s +++ b/llvm/test/MC/AArch64/SVE2/directive-arch_extension.s @@ -16,6 +16,6 @@ sm4e z0.s, z0.s, z0.s rax1 z0.d, z0.d, z0.d // CHECK: rax1 z0.d, z0.d, z0.d -.arch_extension bitperm +.arch_extension sve2-bitperm bgrp z21.s, z10.s, z21.s // CHECK: bgrp z21.s, z10.s, z21.s diff --git a/llvm/test/MC/AArch64/SVE2/directive-cpu-negative.s b/llvm/test/MC/AArch64/SVE2/directive-cpu-negative.s index 542a6f692ca3..97d4c3d1ca6d 100644 --- a/llvm/test/MC/AArch64/SVE2/directive-cpu-negative.s +++ b/llvm/test/MC/AArch64/SVE2/directive-cpu-negative.s @@ -24,8 +24,8 @@ rax1 z0.d, z0.d, z0.d // CHECK: error: instruction requires: sve2-sha3 // CHECK-NEXT: rax1 z0.d, z0.d, z0.d -.cpu generic+bitperm -.cpu generic+nobitperm +.cpu generic+sve2-bitperm +.cpu generic+nosve2-bitperm bgrp z21.s, z10.s, z21.s -// CHECK: error: instruction requires: bitperm +// CHECK: error: instruction requires: sve2-bitperm // CHECK-NEXT: bgrp z21.s, z10.s, z21.s diff --git a/llvm/test/MC/AArch64/SVE2/directive-cpu.s b/llvm/test/MC/AArch64/SVE2/directive-cpu.s index a8ca7b389e94..b3cacc46c1dd 100644 --- a/llvm/test/MC/AArch64/SVE2/directive-cpu.s +++ b/llvm/test/MC/AArch64/SVE2/directive-cpu.s @@ -16,6 +16,6 @@ sm4e z0.s, z0.s, z0.s rax1 z0.d, z0.d, z0.d // CHECK: rax1 z0.d, z0.d, z0.d -.cpu generic+bitperm +.cpu generic+sve2-bitperm bgrp z21.s, z10.s, z21.s // CHECK: bgrp z21.s, z10.s, z21.s diff --git a/llvm/unittests/Support/TargetParserTest.cpp b/llvm/unittests/Support/TargetParserTest.cpp index 34c7a8a4fd1c..04ee379d344a 100644 --- a/llvm/unittests/Support/TargetParserTest.cpp +++ b/llvm/unittests/Support/TargetParserTest.cpp @@ -1048,7 +1048,7 @@ TEST(TargetParserTest, AArch64ExtensionFeatures) { AArch64::AEK_RDM, AArch64::AEK_DOTPROD, AArch64::AEK_SVE, AArch64::AEK_SVE2, AArch64::AEK_SVE2AES, AArch64::AEK_SVE2SM4, - AArch64::AEK_SVE2SHA3, AArch64::AEK_BITPERM, + AArch64::AEK_SVE2SHA3, AArch64::AEK_SVE2BITPERM, AArch64::AEK_RCPC, AArch64::AEK_FP16FML }; std::vector Features; @@ -1083,7 +1083,7 @@ TEST(TargetParserTest, AArch64ExtensionFeatures) { EXPECT_TRUE(std::find(B, E, "+sve2-aes") != E); EXPECT_TRUE(std::find(B, E, "+sve2-sm4") != E); EXPECT_TRUE(std::find(B, E, "+sve2-sha3") != E); - EXPECT_TRUE(std::find(B, E, "+bitperm") != E); + EXPECT_TRUE(std::find(B, E, "+sve2-bitperm") != E); } TEST(TargetParserTest, AArch64ArchFeatures) { @@ -1114,7 +1114,8 @@ TEST(TargetParserTest, AArch64ArchExtFeature) { "-sve2-sm4"}, {"sve2-sha3", "nosve2-sha3", "+sve2-sha3", "-sve2-sha3"}, - {"bitperm", "nobitperm", "+bitperm", "-bitperm"}, + {"sve2-bitperm", "nosve2-bitperm", + "+sve2-bitperm", "-sve2-bitperm"}, {"dotprod", "nodotprod", "+dotprod", "-dotprod"}, {"rcpc", "norcpc", "+rcpc", "-rcpc" }, {"rng", "norng", "+rand", "-rand"}, From 4f1869c35afab79b90cae4d0198fe6ce9bfc7423 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Thu, 1 Aug 2019 08:21:51 +0000 Subject: [PATCH 049/289] Merging r367414: ------------------------------------------------------------------------ r367414 | tkrasnukha | 2019-07-31 14:00:30 +0200 (Wed, 31 Jul 2019) | 7 lines [ProcessWindows] Choose a register context file by preprocessor Replaced Cmake option based check with the preprocessor macro as CMAKE_SYSTEM_PROCESSOR doesn't work as expected on Windows. Fixes llvm.org/pr42724 Differential Revision: https://reviews.llvm.org/D65409 ------------------------------------------------------------------------ llvm-svn: 367523 --- .../Plugins/Process/Windows/Common/CMakeLists.txt | 13 +++---------- .../Common/x64/RegisterContextWindows_x64.cpp | 4 ++++ .../Windows/Common/x64/RegisterContextWindows_x64.h | 4 ++++ .../Common/x86/RegisterContextWindows_x86.cpp | 4 ++++ .../Windows/Common/x86/RegisterContextWindows_x86.h | 4 ++++ 5 files changed, 19 insertions(+), 10 deletions(-) diff --git a/lldb/source/Plugins/Process/Windows/Common/CMakeLists.txt b/lldb/source/Plugins/Process/Windows/Common/CMakeLists.txt index 68486c1d9905..1d7b8ccd49ad 100644 --- a/lldb/source/Plugins/Process/Windows/Common/CMakeLists.txt +++ b/lldb/source/Plugins/Process/Windows/Common/CMakeLists.txt @@ -7,6 +7,9 @@ add_lldb_library(lldbPluginProcessWindowsCommon PLUGIN ProcessWindowsLog.cpp RegisterContextWindows.cpp TargetThreadWindows.cpp + x64/RegisterContextWindows_x64.cpp + x86/RegisterContextWindows_x86.cpp + # TODO add support for ARM (NT) and ARM64 LINK_LIBS lldbCore @@ -20,13 +23,3 @@ add_lldb_library(lldbPluginProcessWindowsCommon PLUGIN LINK_COMPONENTS Support ) - -# TODO add support for ARM (NT) and ARM64 -# TODO build these unconditionally as we cannot do cross-debugging or WoW -if(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|AMD64") - target_sources(lldbPluginProcessWindowsCommon PRIVATE - x64/RegisterContextWindows_x64.cpp) -elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "i?86|X86") - target_sources(lldbPluginProcessWindowsCommon PRIVATE - x86/RegisterContextWindows_x86.cpp) -endif() diff --git a/lldb/source/Plugins/Process/Windows/Common/x64/RegisterContextWindows_x64.cpp b/lldb/source/Plugins/Process/Windows/Common/x64/RegisterContextWindows_x64.cpp index 4101aa1f1b5e..11f72c002115 100644 --- a/lldb/source/Plugins/Process/Windows/Common/x64/RegisterContextWindows_x64.cpp +++ b/lldb/source/Plugins/Process/Windows/Common/x64/RegisterContextWindows_x64.cpp @@ -6,6 +6,8 @@ // //===----------------------------------------------------------------------===// +#if defined(__x86_64__) || defined(__amd64__) || defined(_M_X64) || defined(_M_AMD64) + #include "lldb/Host/windows/HostThreadWindows.h" #include "lldb/Host/windows/windows.h" #include "lldb/Utility/RegisterValue.h" @@ -534,3 +536,5 @@ bool RegisterContextWindows_x64::WriteRegister(const RegisterInfo *reg_info, return ::SetThreadContext( wthread.GetHostThread().GetNativeThread().GetSystemHandle(), &m_context); } + +#endif // defined(__x86_64__) || defined(__amd64__) || defined(_M_X64) || defined(_M_AMD64) diff --git a/lldb/source/Plugins/Process/Windows/Common/x64/RegisterContextWindows_x64.h b/lldb/source/Plugins/Process/Windows/Common/x64/RegisterContextWindows_x64.h index 5f252e162934..20d2cb90ece3 100644 --- a/lldb/source/Plugins/Process/Windows/Common/x64/RegisterContextWindows_x64.h +++ b/lldb/source/Plugins/Process/Windows/Common/x64/RegisterContextWindows_x64.h @@ -9,6 +9,8 @@ #ifndef liblldb_RegisterContextWindows_x64_H_ #define liblldb_RegisterContextWindows_x64_H_ +#if defined(__x86_64__) || defined(__amd64__) || defined(_M_X64) || defined(_M_AMD64) + #include "RegisterContextWindows.h" #include "lldb/lldb-forward.h" @@ -40,4 +42,6 @@ class RegisterContextWindows_x64 : public RegisterContextWindows { }; } +#endif // defined(__x86_64__) || defined(__amd64__) || defined(_M_X64) || defined(_M_AMD64) + #endif // #ifndef liblldb_RegisterContextWindows_x64_H_ diff --git a/lldb/source/Plugins/Process/Windows/Common/x86/RegisterContextWindows_x86.cpp b/lldb/source/Plugins/Process/Windows/Common/x86/RegisterContextWindows_x86.cpp index 0c25853e1c16..b8f7bb46181d 100644 --- a/lldb/source/Plugins/Process/Windows/Common/x86/RegisterContextWindows_x86.cpp +++ b/lldb/source/Plugins/Process/Windows/Common/x86/RegisterContextWindows_x86.cpp @@ -6,6 +6,8 @@ // //===----------------------------------------------------------------------===// +#if defined(__i386__) || defined(_M_IX86) + #include "lldb/Host/windows/HostThreadWindows.h" #include "lldb/Host/windows/windows.h" #include "lldb/Utility/RegisterValue.h" @@ -282,3 +284,5 @@ bool RegisterContextWindows_x86::ReadRegisterHelper( reg_value.SetUInt32(value); return true; } + +#endif // defined(__i386__) || defined(_M_IX86) diff --git a/lldb/source/Plugins/Process/Windows/Common/x86/RegisterContextWindows_x86.h b/lldb/source/Plugins/Process/Windows/Common/x86/RegisterContextWindows_x86.h index 8dca1dc995b1..6517de0bbdfc 100644 --- a/lldb/source/Plugins/Process/Windows/Common/x86/RegisterContextWindows_x86.h +++ b/lldb/source/Plugins/Process/Windows/Common/x86/RegisterContextWindows_x86.h @@ -9,6 +9,8 @@ #ifndef liblldb_RegisterContextWindows_x86_H_ #define liblldb_RegisterContextWindows_x86_H_ +#if defined(__i386__) || defined(_M_IX86) + #include "RegisterContextWindows.h" #include "lldb/lldb-forward.h" @@ -44,4 +46,6 @@ class RegisterContextWindows_x86 : public RegisterContextWindows { }; } +#endif // defined(__i386__) || defined(_M_IX86) + #endif // #ifndef liblldb_RegisterContextWindows_x86_H_ From b980ebe4769d52e78fdf5a8df792af4ec71483d5 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Thu, 1 Aug 2019 08:32:39 +0000 Subject: [PATCH 050/289] Merging r367442: ------------------------------------------------------------------------ r367442 | arichardson | 2019-07-31 18:31:55 +0200 (Wed, 31 Jul 2019) | 30 lines [Sanitizer][ASAN][MSAN] Fix infinite recursion on FreeBSD Summary: MSAN was broken on FreeBSD by https://reviews.llvm.org/D55703: after this change accesses to the key variable call __tls_get_addr, which is intercepted. The interceptor then calls GetCurrentThread which calls MsanTSDGet which again calls __tls_get_addr, etc... Using the default implementation in the SANITIZER_FREEBSD case fixes MSAN for me. I then applied the same change to ASAN (introduced in https://reviews.llvm.org/D55596) but that did not work yet. In the ASAN case, we get infinite recursion again during initialization, this time because calling pthread_key_create() early on results in infinite recursion. pthread_key_create() calls sysctlbyname() which is intercepted but COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED returns true, so the interceptor calls internal_sysctlbyname() which then ends up calling the interceptor again. I fixed this issue by using dlsym() to get the libc version of sysctlbyname() instead. This fixes https://llvm.org/PR40761 Reviewers: vitalybuka, krytarowski, devnexen, dim, bsdjhb, #sanitizers, MaskRay Reviewed By: MaskRay Subscribers: MaskRay, emaste, kubamracek, jfb, #sanitizers, llvm-commits Tags: #sanitizers, #llvm Differential Revision: https://reviews.llvm.org/D65221 ------------------------------------------------------------------------ llvm-svn: 367524 --- compiler-rt/lib/asan/asan_posix.cc | 4 ++-- compiler-rt/lib/msan/msan_linux.cc | 4 ++-- compiler-rt/lib/sanitizer_common/sanitizer_linux.cc | 6 +++++- compiler-rt/test/asan/TestCases/Posix/fread_fwrite.cc | 3 --- compiler-rt/test/asan/TestCases/Posix/tsd_dtor_leak.cc | 2 -- compiler-rt/test/msan/tzset.cc | 1 - 6 files changed, 9 insertions(+), 11 deletions(-) diff --git a/compiler-rt/lib/asan/asan_posix.cc b/compiler-rt/lib/asan/asan_posix.cc index 5c5e0359ad6c..f3fbda07ac5e 100644 --- a/compiler-rt/lib/asan/asan_posix.cc +++ b/compiler-rt/lib/asan/asan_posix.cc @@ -39,8 +39,8 @@ void AsanOnDeadlySignal(int signo, void *siginfo, void *context) { // ---------------------- TSD ---------------- {{{1 -#if SANITIZER_NETBSD || SANITIZER_FREEBSD -// Thread Static Data cannot be used in early init on NetBSD and FreeBSD. +#if SANITIZER_NETBSD +// Thread Static Data cannot be used in early init on NetBSD. // Reuse the Asan TSD API for compatibility with existing code // with an alternative implementation. diff --git a/compiler-rt/lib/msan/msan_linux.cc b/compiler-rt/lib/msan/msan_linux.cc index 3b6e6cb85f33..056783088225 100644 --- a/compiler-rt/lib/msan/msan_linux.cc +++ b/compiler-rt/lib/msan/msan_linux.cc @@ -174,8 +174,8 @@ void InstallAtExitHandler() { // ---------------------- TSD ---------------- {{{1 -#if SANITIZER_NETBSD || SANITIZER_FREEBSD -// Thread Static Data cannot be used in early init on NetBSD and FreeBSD. +#if SANITIZER_NETBSD +// Thread Static Data cannot be used in early init on NetBSD. // Reuse the MSan TSD API for compatibility with existing code // with an alternative implementation. diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc index 88ab0979bb05..455fd4c861de 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc @@ -779,7 +779,11 @@ int internal_sysctl(const int *name, unsigned int namelen, void *oldp, #if SANITIZER_FREEBSD int internal_sysctlbyname(const char *sname, void *oldp, uptr *oldlenp, const void *newp, uptr newlen) { - return sysctlbyname(sname, oldp, (size_t *)oldlenp, newp, (size_t)newlen); + static decltype(sysctlbyname) *real = nullptr; + if (!real) + real = (decltype(sysctlbyname) *)dlsym(RTLD_NEXT, "sysctlbyname"); + CHECK(real); + return real(sname, oldp, (size_t *)oldlenp, newp, (size_t)newlen); } #endif #endif diff --git a/compiler-rt/test/asan/TestCases/Posix/fread_fwrite.cc b/compiler-rt/test/asan/TestCases/Posix/fread_fwrite.cc index 640248860179..c0629260418a 100644 --- a/compiler-rt/test/asan/TestCases/Posix/fread_fwrite.cc +++ b/compiler-rt/test/asan/TestCases/Posix/fread_fwrite.cc @@ -1,9 +1,6 @@ // RUN: %clangxx_asan -g %s -o %t // RUN: not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-FWRITE // RUN: not %run %t 1 2>&1 | FileCheck %s --check-prefix=CHECK-FREAD -// -// On FreeBSD stack overflow error instead -// XFAIL: freebsd #include #include diff --git a/compiler-rt/test/asan/TestCases/Posix/tsd_dtor_leak.cc b/compiler-rt/test/asan/TestCases/Posix/tsd_dtor_leak.cc index 26109fe1a5f4..860f3459e5a8 100644 --- a/compiler-rt/test/asan/TestCases/Posix/tsd_dtor_leak.cc +++ b/compiler-rt/test/asan/TestCases/Posix/tsd_dtor_leak.cc @@ -3,8 +3,6 @@ // RUN: %clangxx_asan -O1 %s -pthread -o %t // RUN: %env_asan_opts=quarantine_size_mb=0 %run %t // XFAIL: x86_64-netbsd -// Assertion fails -// XFAIL: x86_64-freebsd #include #include #include diff --git a/compiler-rt/test/msan/tzset.cc b/compiler-rt/test/msan/tzset.cc index 86805cd56c5d..05915e047e15 100644 --- a/compiler-rt/test/msan/tzset.cc +++ b/compiler-rt/test/msan/tzset.cc @@ -1,5 +1,4 @@ // RUN: %clangxx_msan -O0 %s -o %t && %run %t -// XFAIL: freebsd #include #include From 9a3e9c7d7d46de9fa74063ec3247c437f43dac93 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Thu, 1 Aug 2019 08:40:43 +0000 Subject: [PATCH 051/289] Merging r367323: ------------------------------------------------------------------------ r367323 | dmajor | 2019-07-30 17:32:49 +0200 (Tue, 30 Jul 2019) | 9 lines [COFF][ARM64] Reorder handling of aarch64 MSVC builtins In `CodeGenFunction::EmitAArch64BuiltinExpr()`, bulk move all of the aarch64 MSVC-builtin cases to an earlier point in the function (the `// Handle non-overloaded intrinsics first` switch block) in order to avoid an unreachable in `GetNeonType()`. The NEON type-overloading logic is not appropriate for the Windows builtins. Fixes https://llvm.org/pr42775 Differential Revision: https://reviews.llvm.org/D65403 ------------------------------------------------------------------------ llvm-svn: 367525 --- clang/lib/CodeGen/CGBuiltin.cpp | 290 +++++++++--------- .../test/CodeGen/arm64-microsoft-intrinsics.c | 4 + 2 files changed, 149 insertions(+), 145 deletions(-) diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index a300bab49f9c..cadce507412b 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -8011,6 +8011,151 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID, return Builder.CreateExtractElement(Ops[0], EmitScalarExpr(E->getArg(1)), "vgetq_lane"); } + case AArch64::BI_BitScanForward: + case AArch64::BI_BitScanForward64: + return EmitMSVCBuiltinExpr(MSVCIntrin::_BitScanForward, E); + case AArch64::BI_BitScanReverse: + case AArch64::BI_BitScanReverse64: + return EmitMSVCBuiltinExpr(MSVCIntrin::_BitScanReverse, E); + case AArch64::BI_InterlockedAnd64: + return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedAnd, E); + case AArch64::BI_InterlockedExchange64: + return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchange, E); + case AArch64::BI_InterlockedExchangeAdd64: + return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchangeAdd, E); + case AArch64::BI_InterlockedExchangeSub64: + return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchangeSub, E); + case AArch64::BI_InterlockedOr64: + return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedOr, E); + case AArch64::BI_InterlockedXor64: + return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedXor, E); + case AArch64::BI_InterlockedDecrement64: + return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedDecrement, E); + case AArch64::BI_InterlockedIncrement64: + return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedIncrement, E); + case AArch64::BI_InterlockedExchangeAdd8_acq: + case AArch64::BI_InterlockedExchangeAdd16_acq: + case AArch64::BI_InterlockedExchangeAdd_acq: + case AArch64::BI_InterlockedExchangeAdd64_acq: + return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchangeAdd_acq, E); + case AArch64::BI_InterlockedExchangeAdd8_rel: + case AArch64::BI_InterlockedExchangeAdd16_rel: + case AArch64::BI_InterlockedExchangeAdd_rel: + case AArch64::BI_InterlockedExchangeAdd64_rel: + return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchangeAdd_rel, E); + case AArch64::BI_InterlockedExchangeAdd8_nf: + case AArch64::BI_InterlockedExchangeAdd16_nf: + case AArch64::BI_InterlockedExchangeAdd_nf: + case AArch64::BI_InterlockedExchangeAdd64_nf: + return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchangeAdd_nf, E); + case AArch64::BI_InterlockedExchange8_acq: + case AArch64::BI_InterlockedExchange16_acq: + case AArch64::BI_InterlockedExchange_acq: + case AArch64::BI_InterlockedExchange64_acq: + return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchange_acq, E); + case AArch64::BI_InterlockedExchange8_rel: + case AArch64::BI_InterlockedExchange16_rel: + case AArch64::BI_InterlockedExchange_rel: + case AArch64::BI_InterlockedExchange64_rel: + return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchange_rel, E); + case AArch64::BI_InterlockedExchange8_nf: + case AArch64::BI_InterlockedExchange16_nf: + case AArch64::BI_InterlockedExchange_nf: + case AArch64::BI_InterlockedExchange64_nf: + return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchange_nf, E); + case AArch64::BI_InterlockedCompareExchange8_acq: + case AArch64::BI_InterlockedCompareExchange16_acq: + case AArch64::BI_InterlockedCompareExchange_acq: + case AArch64::BI_InterlockedCompareExchange64_acq: + return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedCompareExchange_acq, E); + case AArch64::BI_InterlockedCompareExchange8_rel: + case AArch64::BI_InterlockedCompareExchange16_rel: + case AArch64::BI_InterlockedCompareExchange_rel: + case AArch64::BI_InterlockedCompareExchange64_rel: + return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedCompareExchange_rel, E); + case AArch64::BI_InterlockedCompareExchange8_nf: + case AArch64::BI_InterlockedCompareExchange16_nf: + case AArch64::BI_InterlockedCompareExchange_nf: + case AArch64::BI_InterlockedCompareExchange64_nf: + return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedCompareExchange_nf, E); + case AArch64::BI_InterlockedOr8_acq: + case AArch64::BI_InterlockedOr16_acq: + case AArch64::BI_InterlockedOr_acq: + case AArch64::BI_InterlockedOr64_acq: + return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedOr_acq, E); + case AArch64::BI_InterlockedOr8_rel: + case AArch64::BI_InterlockedOr16_rel: + case AArch64::BI_InterlockedOr_rel: + case AArch64::BI_InterlockedOr64_rel: + return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedOr_rel, E); + case AArch64::BI_InterlockedOr8_nf: + case AArch64::BI_InterlockedOr16_nf: + case AArch64::BI_InterlockedOr_nf: + case AArch64::BI_InterlockedOr64_nf: + return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedOr_nf, E); + case AArch64::BI_InterlockedXor8_acq: + case AArch64::BI_InterlockedXor16_acq: + case AArch64::BI_InterlockedXor_acq: + case AArch64::BI_InterlockedXor64_acq: + return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedXor_acq, E); + case AArch64::BI_InterlockedXor8_rel: + case AArch64::BI_InterlockedXor16_rel: + case AArch64::BI_InterlockedXor_rel: + case AArch64::BI_InterlockedXor64_rel: + return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedXor_rel, E); + case AArch64::BI_InterlockedXor8_nf: + case AArch64::BI_InterlockedXor16_nf: + case AArch64::BI_InterlockedXor_nf: + case AArch64::BI_InterlockedXor64_nf: + return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedXor_nf, E); + case AArch64::BI_InterlockedAnd8_acq: + case AArch64::BI_InterlockedAnd16_acq: + case AArch64::BI_InterlockedAnd_acq: + case AArch64::BI_InterlockedAnd64_acq: + return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedAnd_acq, E); + case AArch64::BI_InterlockedAnd8_rel: + case AArch64::BI_InterlockedAnd16_rel: + case AArch64::BI_InterlockedAnd_rel: + case AArch64::BI_InterlockedAnd64_rel: + return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedAnd_rel, E); + case AArch64::BI_InterlockedAnd8_nf: + case AArch64::BI_InterlockedAnd16_nf: + case AArch64::BI_InterlockedAnd_nf: + case AArch64::BI_InterlockedAnd64_nf: + return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedAnd_nf, E); + case AArch64::BI_InterlockedIncrement16_acq: + case AArch64::BI_InterlockedIncrement_acq: + case AArch64::BI_InterlockedIncrement64_acq: + return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedIncrement_acq, E); + case AArch64::BI_InterlockedIncrement16_rel: + case AArch64::BI_InterlockedIncrement_rel: + case AArch64::BI_InterlockedIncrement64_rel: + return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedIncrement_rel, E); + case AArch64::BI_InterlockedIncrement16_nf: + case AArch64::BI_InterlockedIncrement_nf: + case AArch64::BI_InterlockedIncrement64_nf: + return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedIncrement_nf, E); + case AArch64::BI_InterlockedDecrement16_acq: + case AArch64::BI_InterlockedDecrement_acq: + case AArch64::BI_InterlockedDecrement64_acq: + return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedDecrement_acq, E); + case AArch64::BI_InterlockedDecrement16_rel: + case AArch64::BI_InterlockedDecrement_rel: + case AArch64::BI_InterlockedDecrement64_rel: + return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedDecrement_rel, E); + case AArch64::BI_InterlockedDecrement16_nf: + case AArch64::BI_InterlockedDecrement_nf: + case AArch64::BI_InterlockedDecrement64_nf: + return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedDecrement_nf, E); + + case AArch64::BI_InterlockedAdd: { + Value *Arg0 = EmitScalarExpr(E->getArg(0)); + Value *Arg1 = EmitScalarExpr(E->getArg(1)); + AtomicRMWInst *RMWI = Builder.CreateAtomicRMW( + AtomicRMWInst::Add, Arg0, Arg1, + llvm::AtomicOrdering::SequentiallyConsistent); + return Builder.CreateAdd(RMWI, Arg1); + } } llvm::VectorType *VTy = GetNeonType(this, Type); @@ -9128,151 +9273,6 @@ Value *CodeGenFunction::EmitAArch64BuiltinExpr(unsigned BuiltinID, Int = Intrinsic::aarch64_neon_suqadd; return EmitNeonCall(CGM.getIntrinsic(Int, Ty), Ops, "vuqadd"); } - case AArch64::BI_BitScanForward: - case AArch64::BI_BitScanForward64: - return EmitMSVCBuiltinExpr(MSVCIntrin::_BitScanForward, E); - case AArch64::BI_BitScanReverse: - case AArch64::BI_BitScanReverse64: - return EmitMSVCBuiltinExpr(MSVCIntrin::_BitScanReverse, E); - case AArch64::BI_InterlockedAnd64: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedAnd, E); - case AArch64::BI_InterlockedExchange64: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchange, E); - case AArch64::BI_InterlockedExchangeAdd64: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchangeAdd, E); - case AArch64::BI_InterlockedExchangeSub64: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchangeSub, E); - case AArch64::BI_InterlockedOr64: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedOr, E); - case AArch64::BI_InterlockedXor64: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedXor, E); - case AArch64::BI_InterlockedDecrement64: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedDecrement, E); - case AArch64::BI_InterlockedIncrement64: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedIncrement, E); - case AArch64::BI_InterlockedExchangeAdd8_acq: - case AArch64::BI_InterlockedExchangeAdd16_acq: - case AArch64::BI_InterlockedExchangeAdd_acq: - case AArch64::BI_InterlockedExchangeAdd64_acq: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchangeAdd_acq, E); - case AArch64::BI_InterlockedExchangeAdd8_rel: - case AArch64::BI_InterlockedExchangeAdd16_rel: - case AArch64::BI_InterlockedExchangeAdd_rel: - case AArch64::BI_InterlockedExchangeAdd64_rel: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchangeAdd_rel, E); - case AArch64::BI_InterlockedExchangeAdd8_nf: - case AArch64::BI_InterlockedExchangeAdd16_nf: - case AArch64::BI_InterlockedExchangeAdd_nf: - case AArch64::BI_InterlockedExchangeAdd64_nf: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchangeAdd_nf, E); - case AArch64::BI_InterlockedExchange8_acq: - case AArch64::BI_InterlockedExchange16_acq: - case AArch64::BI_InterlockedExchange_acq: - case AArch64::BI_InterlockedExchange64_acq: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchange_acq, E); - case AArch64::BI_InterlockedExchange8_rel: - case AArch64::BI_InterlockedExchange16_rel: - case AArch64::BI_InterlockedExchange_rel: - case AArch64::BI_InterlockedExchange64_rel: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchange_rel, E); - case AArch64::BI_InterlockedExchange8_nf: - case AArch64::BI_InterlockedExchange16_nf: - case AArch64::BI_InterlockedExchange_nf: - case AArch64::BI_InterlockedExchange64_nf: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedExchange_nf, E); - case AArch64::BI_InterlockedCompareExchange8_acq: - case AArch64::BI_InterlockedCompareExchange16_acq: - case AArch64::BI_InterlockedCompareExchange_acq: - case AArch64::BI_InterlockedCompareExchange64_acq: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedCompareExchange_acq, E); - case AArch64::BI_InterlockedCompareExchange8_rel: - case AArch64::BI_InterlockedCompareExchange16_rel: - case AArch64::BI_InterlockedCompareExchange_rel: - case AArch64::BI_InterlockedCompareExchange64_rel: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedCompareExchange_rel, E); - case AArch64::BI_InterlockedCompareExchange8_nf: - case AArch64::BI_InterlockedCompareExchange16_nf: - case AArch64::BI_InterlockedCompareExchange_nf: - case AArch64::BI_InterlockedCompareExchange64_nf: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedCompareExchange_nf, E); - case AArch64::BI_InterlockedOr8_acq: - case AArch64::BI_InterlockedOr16_acq: - case AArch64::BI_InterlockedOr_acq: - case AArch64::BI_InterlockedOr64_acq: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedOr_acq, E); - case AArch64::BI_InterlockedOr8_rel: - case AArch64::BI_InterlockedOr16_rel: - case AArch64::BI_InterlockedOr_rel: - case AArch64::BI_InterlockedOr64_rel: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedOr_rel, E); - case AArch64::BI_InterlockedOr8_nf: - case AArch64::BI_InterlockedOr16_nf: - case AArch64::BI_InterlockedOr_nf: - case AArch64::BI_InterlockedOr64_nf: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedOr_nf, E); - case AArch64::BI_InterlockedXor8_acq: - case AArch64::BI_InterlockedXor16_acq: - case AArch64::BI_InterlockedXor_acq: - case AArch64::BI_InterlockedXor64_acq: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedXor_acq, E); - case AArch64::BI_InterlockedXor8_rel: - case AArch64::BI_InterlockedXor16_rel: - case AArch64::BI_InterlockedXor_rel: - case AArch64::BI_InterlockedXor64_rel: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedXor_rel, E); - case AArch64::BI_InterlockedXor8_nf: - case AArch64::BI_InterlockedXor16_nf: - case AArch64::BI_InterlockedXor_nf: - case AArch64::BI_InterlockedXor64_nf: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedXor_nf, E); - case AArch64::BI_InterlockedAnd8_acq: - case AArch64::BI_InterlockedAnd16_acq: - case AArch64::BI_InterlockedAnd_acq: - case AArch64::BI_InterlockedAnd64_acq: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedAnd_acq, E); - case AArch64::BI_InterlockedAnd8_rel: - case AArch64::BI_InterlockedAnd16_rel: - case AArch64::BI_InterlockedAnd_rel: - case AArch64::BI_InterlockedAnd64_rel: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedAnd_rel, E); - case AArch64::BI_InterlockedAnd8_nf: - case AArch64::BI_InterlockedAnd16_nf: - case AArch64::BI_InterlockedAnd_nf: - case AArch64::BI_InterlockedAnd64_nf: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedAnd_nf, E); - case AArch64::BI_InterlockedIncrement16_acq: - case AArch64::BI_InterlockedIncrement_acq: - case AArch64::BI_InterlockedIncrement64_acq: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedIncrement_acq, E); - case AArch64::BI_InterlockedIncrement16_rel: - case AArch64::BI_InterlockedIncrement_rel: - case AArch64::BI_InterlockedIncrement64_rel: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedIncrement_rel, E); - case AArch64::BI_InterlockedIncrement16_nf: - case AArch64::BI_InterlockedIncrement_nf: - case AArch64::BI_InterlockedIncrement64_nf: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedIncrement_nf, E); - case AArch64::BI_InterlockedDecrement16_acq: - case AArch64::BI_InterlockedDecrement_acq: - case AArch64::BI_InterlockedDecrement64_acq: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedDecrement_acq, E); - case AArch64::BI_InterlockedDecrement16_rel: - case AArch64::BI_InterlockedDecrement_rel: - case AArch64::BI_InterlockedDecrement64_rel: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedDecrement_rel, E); - case AArch64::BI_InterlockedDecrement16_nf: - case AArch64::BI_InterlockedDecrement_nf: - case AArch64::BI_InterlockedDecrement64_nf: - return EmitMSVCBuiltinExpr(MSVCIntrin::_InterlockedDecrement_nf, E); - - case AArch64::BI_InterlockedAdd: { - Value *Arg0 = EmitScalarExpr(E->getArg(0)); - Value *Arg1 = EmitScalarExpr(E->getArg(1)); - AtomicRMWInst *RMWI = Builder.CreateAtomicRMW( - AtomicRMWInst::Add, Arg0, Arg1, - llvm::AtomicOrdering::SequentiallyConsistent); - return Builder.CreateAdd(RMWI, Arg1); - } } } diff --git a/clang/test/CodeGen/arm64-microsoft-intrinsics.c b/clang/test/CodeGen/arm64-microsoft-intrinsics.c index eeb09e89727d..4a9642e173c1 100644 --- a/clang/test/CodeGen/arm64-microsoft-intrinsics.c +++ b/clang/test/CodeGen/arm64-microsoft-intrinsics.c @@ -8,6 +8,10 @@ long test_InterlockedAdd(long volatile *Addend, long Value) { return _InterlockedAdd(Addend, Value); } +long test_InterlockedAdd_constant(long volatile *Addend) { + return _InterlockedAdd(Addend, -1); +} + // CHECK-LABEL: define {{.*}} i32 @test_InterlockedAdd(i32* %Addend, i32 %Value) {{.*}} { // CHECK-MSVC: %[[OLDVAL:[0-9]+]] = atomicrmw add i32* %1, i32 %2 seq_cst // CHECK-MSVC: %[[NEWVAL:[0-9]+]] = add i32 %[[OLDVAL:[0-9]+]], %2 From ecb5f95a0ed47924b7a2bf922f95a5a557af4832 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Thu, 1 Aug 2019 08:47:45 +0000 Subject: [PATCH 052/289] Merging r367304: ------------------------------------------------------------------------ r367304 | ro | 2019-07-30 12:33:20 +0200 (Tue, 30 Jul 2019) | 10 lines [CMake] Define _FILE_OFFSET_BITS=64 on Solaris This is the compantion patch to https://reviews.llvm.org/D64482, needed to ensure that builds with host compilers that don't yet predefine _FILE_OFFSET_BITS=64 on Solaris succeed by always making the host and freshly built clang consistent. Tested on x86_64-pc-solaris2.11. Differential Revision: https://reviews.llvm.org/D64483 ------------------------------------------------------------------------ llvm-svn: 367526 --- llvm/CMakeLists.txt | 5 +++++ llvm/cmake/config-ix.cmake | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/llvm/CMakeLists.txt b/llvm/CMakeLists.txt index 8d71dee98f48..7daabb428fc7 100644 --- a/llvm/CMakeLists.txt +++ b/llvm/CMakeLists.txt @@ -831,6 +831,11 @@ if (UNIX AND ${CMAKE_SYSTEM_NAME} MATCHES "AIX") add_definitions("-D_LARGE_FILE_API") endif() +# Build with _FILE_OFFSET_BITS=64 on Solaris to match g++ >= 9. +if (UNIX AND ${CMAKE_SYSTEM_NAME} MATCHES "SunOS") + add_definitions("-D_FILE_OFFSET_BITS=64") +endif() + # Work around a broken bfd ld behavior. When linking a binary with a # foo.so library, it will try to find any library that foo.so uses and # check its symbols. This is wasteful (the check was done when foo.so diff --git a/llvm/cmake/config-ix.cmake b/llvm/cmake/config-ix.cmake index 0218d42eb891..4c585b8fd5a2 100644 --- a/llvm/cmake/config-ix.cmake +++ b/llvm/cmake/config-ix.cmake @@ -30,6 +30,12 @@ if (UNIX AND ${CMAKE_SYSTEM_NAME} MATCHES "AIX") list(APPEND CMAKE_REQUIRED_DEFINITIONS "-D_LARGE_FILE_API") endif() +# Do checks with _FILE_OFFSET_BITS=64 on Solaris, because we will build +# with those too. +if (UNIX AND ${CMAKE_SYSTEM_NAME} MATCHES "SunOS") + list(APPEND CMAKE_REQUIRED_DEFINITIONS "-D_FILE_OFFSET_BITS=64") +endif() + # include checks check_include_file(dlfcn.h HAVE_DLFCN_H) check_include_file(errno.h HAVE_ERRNO_H) From e3cbac740113f383382be0df6aaa3b451d9e99aa Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Thu, 1 Aug 2019 08:49:35 +0000 Subject: [PATCH 053/289] Merging r367305: ------------------------------------------------------------------------ r367305 | ro | 2019-07-30 12:38:41 +0200 (Tue, 30 Jul 2019) | 32 lines [Driver] Define _FILE_OFFSET_BITS=64 on Solaris make check-all currently fails on x86_64-pc-solaris2.11 when building with GCC 9: Undefined first referenced symbol in file _ZN11__sanitizer14internal_lseekEimi SANITIZER_TEST_OBJECTS.sanitizer_libc_test.cc.i386.o _ZN11__sanitizer23MapWritableFileToMemoryEPvmim SANITIZER_TEST_OBJECTS.sanitizer_libc_test.cc.i386.o ld: fatal: symbol referencing errors clang-9: error: linker command failed with exit code 1 (use -v to see invocation) make[3]: *** [projects/compiler-rt/lib/sanitizer_common/tests/CMakeFiles/TSanitizer-i386-Test.dir/build.make:92: projects/compiler-rt/lib/sanitizer_common/tests/Sanitizer-i386-Test] Error 1 While e.g. __sanitizer::internal_lseek is defined in sanitizer_solaris.cc, g++ 9 predefines _FILE_OFFSET_BITS=64 while clang++ currently does not. This patch resolves this inconsistency by following the gcc lead, which allows make check-all to finish successfully. There's one caveat: gcc defines _LARGEFILE_SOURCE and _LARGEFILE64_SOURCE for C++ only, while clang has long been doing it for all languages. I'd like to keep it this way because those macros do is to make declarations of fseek/ftello (_LARGEFILE_SOURCE) resp. the 64-bit versions of largefile functions (*64 with _LARGEFILE64_SOURCE) visible additionally. However, _FILE_OFFSET_BITS=64 changes all affected functions to be largefile-aware. I'd like to restrict this to C++, just like gcc does. To avoid a similar inconsistence with host compilers that don't predefine _FILE_OFFSET_BITS=64 (e.g. clang < 9, gcc < 9), this needs a compantion patch https://reviews.llvm.org/D64483. Tested on x86_64-pc-solaris2.11. Differential Revision: https://reviews.llvm.org/D64482 ------------------------------------------------------------------------ llvm-svn: 367527 --- clang/lib/Basic/Targets/OSTargets.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/clang/lib/Basic/Targets/OSTargets.h b/clang/lib/Basic/Targets/OSTargets.h index 8542311ffa41..c0373ffaa444 100644 --- a/clang/lib/Basic/Targets/OSTargets.h +++ b/clang/lib/Basic/Targets/OSTargets.h @@ -618,8 +618,11 @@ class LLVM_LIBRARY_VISIBILITY SolarisTargetInfo : public OSTargetInfo { Builder.defineMacro("_XOPEN_SOURCE", "600"); else Builder.defineMacro("_XOPEN_SOURCE", "500"); - if (Opts.CPlusPlus) + if (Opts.CPlusPlus) { Builder.defineMacro("__C99FEATURES__"); + Builder.defineMacro("_FILE_OFFSET_BITS", "64"); + } + // GCC restricts the next two to C++. Builder.defineMacro("_LARGEFILE_SOURCE"); Builder.defineMacro("_LARGEFILE64_SOURCE"); Builder.defineMacro("__EXTENSIONS__"); From ddea81c67c8de177fa265035d3e0e5f9ed9470a0 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Thu, 1 Aug 2019 09:03:00 +0000 Subject: [PATCH 054/289] Merging r367387: ------------------------------------------------------------------------ r367387 | jdoerfert | 2019-07-31 07:16:38 +0200 (Wed, 31 Jul 2019) | 26 lines [Fix] Customize warnings for missing built-in types If we detect a built-in declaration for which we cannot derive a type matching the pattern in the Builtins.def file, we currently emit a warning that the respective header is needed. However, this is not necessarily the behavior we want as it has no connection to the location of the declaration (which can actually be in the header in question). Instead, this warning is generated - if we could not build the type for the pattern on file (for some reason). Here we should make the reason explicit. The actual problem is otherwise circumvented as the warning is misleading, see [0] for an example. - if we could not build the type for the pattern because we do not have a type on record, possible since D55483, we should not emit any warning. See [1] for a legitimate problem. This patch address both cases. For the "setjmp" family a new warning is introduced and for built-ins without type on record, so far "pthread_create", we do not emit the warning anymore. Also see: PR40692 [0] https://lkml.org/lkml/2019/1/11/718 [1] https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=235583 Differential Revision: https://reviews.llvm.org/D58091 ------------------------------------------------------------------------ llvm-svn: 367528 --- .../clang/Basic/DiagnosticSemaKinds.td | 4 ++++ clang/lib/Sema/SemaDecl.cpp | 23 ++++++++++++++++--- clang/test/Analysis/retain-release.m | 4 ++-- clang/test/Sema/builtin-setjmp.c | 10 ++++++++ clang/test/Sema/implicit-builtin-decl.c | 9 +++++--- 5 files changed, 42 insertions(+), 8 deletions(-) create mode 100644 clang/test/Sema/builtin-setjmp.c diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index effcbad78b23..275c4e4365d1 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -598,6 +598,10 @@ def ext_implicit_lib_function_decl : ExtWarn< def note_include_header_or_declare : Note< "include the header <%0> or explicitly provide a declaration for '%1'">; def note_previous_builtin_declaration : Note<"%0 is a builtin with type %1">; +def warn_implicit_decl_no_jmp_buf + : Warning<"declaration of built-in function '%0' requires the declaration" + " of the 'jmp_buf' type, commonly provided in the header .">, + InGroup>; def warn_implicit_decl_requires_sysheader : Warning< "declaration of built-in function '%1' requires inclusion of the header <%0>">, InGroup; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index cf8ad9c90551..8f19edbc4f36 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -1984,10 +1984,27 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID, ASTContext::GetBuiltinTypeError Error; QualType R = Context.GetBuiltinType(ID, Error); if (Error) { - if (ForRedeclaration) - Diag(Loc, diag::warn_implicit_decl_requires_sysheader) - << getHeaderName(Context.BuiltinInfo, ID, Error) + if (!ForRedeclaration) + return nullptr; + + // If we have a builtin without an associated type we should not emit a + // warning when we were not able to find a type for it. + if (Error == ASTContext::GE_Missing_type) + return nullptr; + + // If we could not find a type for setjmp it is because the jmp_buf type was + // not defined prior to the setjmp declaration. + if (Error == ASTContext::GE_Missing_setjmp) { + Diag(Loc, diag::warn_implicit_decl_no_jmp_buf) << Context.BuiltinInfo.getName(ID); + return nullptr; + } + + // Generally, we emit a warning that the declaration requires the + // appropriate header. + Diag(Loc, diag::warn_implicit_decl_requires_sysheader) + << getHeaderName(Context.BuiltinInfo, ID, Error) + << Context.BuiltinInfo.getName(ID); return nullptr; } diff --git a/clang/test/Analysis/retain-release.m b/clang/test/Analysis/retain-release.m index ad79d72d1aa1..e459fb7a0b85 100644 --- a/clang/test/Analysis/retain-release.m +++ b/clang/test/Analysis/retain-release.m @@ -2,7 +2,7 @@ // RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10\ // RUN: -analyzer-checker=core,osx.coreFoundation.CFRetainRelease\ // RUN: -analyzer-checker=osx.cocoa.ClassRelease,osx.cocoa.RetainCount\ -// RUN: -analyzer-checker=debug.ExprInspection -fblocks -verify=expected,C %s\ +// RUN: -analyzer-checker=debug.ExprInspection -fblocks -verify %s\ // RUN: -Wno-objc-root-class -analyzer-output=plist -o %t.objc.plist // RUN: %clang_analyze_cc1 -triple x86_64-apple-darwin10\ // RUN: -analyzer-checker=core,osx.coreFoundation.CFRetainRelease\ @@ -1231,7 +1231,7 @@ void rdar_7184450_pos(CGContextRef myContext, CGFloat x, CGPoint myStartPoint, typedef unsigned long __darwin_pthread_key_t; typedef __darwin_pthread_key_t pthread_key_t; -int pthread_create(pthread_t *, const pthread_attr_t *, // C-warning{{declaration of built-in function 'pthread_create' requires inclusion of the header }} +int pthread_create(pthread_t *, const pthread_attr_t *, void *(*)(void *), void *); int pthread_setspecific(pthread_key_t key, const void *value); diff --git a/clang/test/Sema/builtin-setjmp.c b/clang/test/Sema/builtin-setjmp.c new file mode 100644 index 000000000000..f8770d88e731 --- /dev/null +++ b/clang/test/Sema/builtin-setjmp.c @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsyntax-only -verify -DNO_JMP_BUF %s +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsyntax-only -verify %s + +#ifdef NO_JMP_BUF +extern long setjmp(long *); // expected-warning {{declaration of built-in function 'setjmp' requires the declaration of the 'jmp_buf' type, commonly provided in the header .}} +#else +typedef long jmp_buf; +extern int setjmp(char); // expected-warning@8 {{incompatible redeclaration of library function 'setjmp'}} + // expected-note@8 {{'setjmp' is a builtin with type 'int (jmp_buf)' (aka 'int (long)')}} +#endif diff --git a/clang/test/Sema/implicit-builtin-decl.c b/clang/test/Sema/implicit-builtin-decl.c index 3c2ff94984c0..3a3dfa935ac1 100644 --- a/clang/test/Sema/implicit-builtin-decl.c +++ b/clang/test/Sema/implicit-builtin-decl.c @@ -55,14 +55,17 @@ main(int argc, char *argv[]) void snprintf() { } -// PR8316 -void longjmp(); // expected-warning{{declaration of built-in function 'longjmp' requires inclusion of the header }} +// PR8316 & PR40692 +void longjmp(); // expected-warning{{declaration of built-in function 'longjmp' requires the declaration of the 'jmp_buf' type, commonly provided in the header .}} extern float fmaxf(float, float); struct __jmp_buf_tag {}; -void sigsetjmp(struct __jmp_buf_tag[1], int); // expected-warning{{declaration of built-in function 'sigsetjmp' requires inclusion of the header }} +void sigsetjmp(struct __jmp_buf_tag[1], int); // expected-warning{{declaration of built-in function 'sigsetjmp' requires the declaration of the 'jmp_buf' type, commonly provided in the header .}} // CHECK: FunctionDecl {{.*}} col:6 sigsetjmp ' // CHECK-NOT: FunctionDecl // CHECK: ReturnsTwiceAttr {{.*}} <{{.*}}> Implicit + +// PR40692 +void pthread_create(); // no warning expected From f08bb47ab4f6fc3a753b7807a3663168dec71cda Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Thu, 1 Aug 2019 09:11:01 +0000 Subject: [PATCH 055/289] Merging r367417: ------------------------------------------------------------------------ r367417 | lebedevri | 2019-07-31 14:06:38 +0200 (Wed, 31 Jul 2019) | 38 lines [DivRemPairs] Avoid RAUW pitfalls (PR42823) Summary: `DivRemPairs` internally creates two maps: * {sign, divident, divisor} -> div instruction * {sign, divident, divisor} -> rem instruction Then it iterates over rem map, and looks if there is an entry in div map with the same key. Then depending on some internal logic it may RAUW rem instruction with something else. But if that rem instruction is an input to other div/rem, then it was used as a key in these maps, so the old value (used in key) is now dandling, because RAUW didn't update those maps. And we can't even RAUW map keys in general, there's `ValueMap`, but we don't have a single `Value` as key... The bug was discovered via D65298, and the test there exists. Now, i'm not sure how to expose this issue in trunk. The bug is clearly there if i change the map keys to be `AssertingVH`/`PoisoningVH`, but i guess this didn't miscompiled anything thus far? I really don't think this is benin without that patch. The fix is actually rather straight-forward - instead of trying to somehow shoe-horn `ValueMap` here (doesn't fit, key isn't just `Value`), or writing a new `ValueMap` with key being a struct of `Value`s, we can just have an intermediate data structure - a vector, each entry containing matching `Div, Rem` pair, and pre-filling it before doing any modifications. This way we won't need to query map after doing RAUW, so no bug is possible. Reviewers: spatel, bogner, RKSimon, craig.topper Reviewed By: spatel Subscribers: hiraditya, hans, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D65451 ------------------------------------------------------------------------ llvm-svn: 367531 --- .../Transforms/Utils/BypassSlowDivision.h | 11 +- llvm/lib/Transforms/Scalar/DivRemPairs.cpp | 114 +++++++++--- .../PowerPC/div-expanded-rem-pair.ll | 172 ++++++++++++++++++ .../DivRemPairs/PowerPC/div-rem-pairs.ll | 168 ++++++++++------- .../DivRemPairs/X86/div-expanded-rem-pair.ll | 170 +++++++++++++++++ .../DivRemPairs/X86/div-rem-pairs.ll | 146 +++++++++------ 6 files changed, 639 insertions(+), 142 deletions(-) create mode 100644 llvm/test/Transforms/DivRemPairs/PowerPC/div-expanded-rem-pair.ll create mode 100644 llvm/test/Transforms/DivRemPairs/X86/div-expanded-rem-pair.ll diff --git a/llvm/include/llvm/Transforms/Utils/BypassSlowDivision.h b/llvm/include/llvm/Transforms/Utils/BypassSlowDivision.h index 471055921fa8..994b6ec9c229 100644 --- a/llvm/include/llvm/Transforms/Utils/BypassSlowDivision.h +++ b/llvm/include/llvm/Transforms/Utils/BypassSlowDivision.h @@ -19,6 +19,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseMapInfo.h" +#include "llvm/IR/ValueHandle.h" #include namespace llvm { @@ -28,8 +29,8 @@ class Value; struct DivRemMapKey { bool SignedOp; - Value *Dividend; - Value *Divisor; + AssertingVH Dividend; + AssertingVH Divisor; DivRemMapKey(bool InSignedOp, Value *InDividend, Value *InDivisor) : SignedOp(InSignedOp), Dividend(InDividend), Divisor(InDivisor) {} @@ -50,8 +51,10 @@ template <> struct DenseMapInfo { } static unsigned getHashValue(const DivRemMapKey &Val) { - return (unsigned)(reinterpret_cast(Val.Dividend) ^ - reinterpret_cast(Val.Divisor)) ^ + return (unsigned)(reinterpret_cast( + static_cast(Val.Dividend)) ^ + reinterpret_cast( + static_cast(Val.Divisor))) ^ (unsigned)Val.SignedOp; } }; diff --git a/llvm/lib/Transforms/Scalar/DivRemPairs.cpp b/llvm/lib/Transforms/Scalar/DivRemPairs.cpp index 876681b4f9de..e64651d97495 100644 --- a/llvm/lib/Transforms/Scalar/DivRemPairs.cpp +++ b/llvm/lib/Transforms/Scalar/DivRemPairs.cpp @@ -23,6 +23,7 @@ #include "llvm/Support/DebugCounter.h" #include "llvm/Transforms/Scalar.h" #include "llvm/Transforms/Utils/BypassSlowDivision.h" + using namespace llvm; #define DEBUG_TYPE "div-rem-pairs" @@ -32,24 +33,44 @@ STATISTIC(NumDecomposed, "Number of instructions decomposed"); DEBUG_COUNTER(DRPCounter, "div-rem-pairs-transform", "Controls transformations in div-rem-pairs pass"); -/// Find matching pairs of integer div/rem ops (they have the same numerator, -/// denominator, and signedness). If they exist in different basic blocks, bring -/// them together by hoisting or replace the common division operation that is -/// implicit in the remainder: -/// X % Y <--> X - ((X / Y) * Y). -/// -/// We can largely ignore the normal safety and cost constraints on speculation -/// of these ops when we find a matching pair. This is because we are already -/// guaranteed that any exceptions and most cost are already incurred by the -/// first member of the pair. -/// -/// Note: This transform could be an oddball enhancement to EarlyCSE, GVN, or -/// SimplifyCFG, but it's split off on its own because it's different enough -/// that it doesn't quite match the stated objectives of those passes. -static bool optimizeDivRem(Function &F, const TargetTransformInfo &TTI, - const DominatorTree &DT) { - bool Changed = false; +/// A thin wrapper to store two values that we matched as div-rem pair. +/// We want this extra indirection to avoid dealing with RAUW'ing the map keys. +struct DivRemPairWorklistEntry { + /// The actual udiv/sdiv instruction. Source of truth. + AssertingVH DivInst; + + /// The instruction that we have matched as a remainder instruction. + /// Should only be used as Value, don't introspect it. + AssertingVH RemInst; + + DivRemPairWorklistEntry(Instruction *DivInst_, Instruction *RemInst_) + : DivInst(DivInst_), RemInst(RemInst_) { + assert((DivInst->getOpcode() == Instruction::UDiv || + DivInst->getOpcode() == Instruction::SDiv) && + "Not a division."); + assert(DivInst->getType() == RemInst->getType() && "Types should match."); + // We can't check anything else about remainder instruction, + // it's not strictly required to be a urem/srem. + } + /// The type for this pair, identical for both the div and rem. + Type *getType() const { return DivInst->getType(); } + + /// Is this pair signed or unsigned? + bool isSigned() const { return DivInst->getOpcode() == Instruction::SDiv; } + + /// In this pair, what are the divident and divisor? + Value *getDividend() const { return DivInst->getOperand(0); } + Value *getDivisor() const { return DivInst->getOperand(1); } +}; +using DivRemWorklistTy = SmallVector; + +/// Find matching pairs of integer div/rem ops (they have the same numerator, +/// denominator, and signedness). Place those pairs into a worklist for further +/// processing. This indirection is needed because we have to use TrackingVH<> +/// because we will be doing RAUW, and if one of the rem instructions we change +/// happens to be an input to another div/rem in the maps, we'd have problems. +static DivRemWorklistTy getWorklist(Function &F) { // Insert all divide and remainder instructions into maps keyed by their // operands and opcode (signed or unsigned). DenseMap DivMap; @@ -69,6 +90,9 @@ static bool optimizeDivRem(Function &F, const TargetTransformInfo &TTI, } } + // We'll accumulate the matching pairs of div-rem instructions here. + DivRemWorklistTy Worklist; + // We can iterate over either map because we are only looking for matched // pairs. Choose remainders for efficiency because they are usually even more // rare than division. @@ -78,12 +102,45 @@ static bool optimizeDivRem(Function &F, const TargetTransformInfo &TTI, if (!DivInst) continue; - // We have a matching pair of div/rem instructions. If one dominates the - // other, hoist and/or replace one. + // We have a matching pair of div/rem instructions. NumPairs++; Instruction *RemInst = RemPair.second; - bool IsSigned = DivInst->getOpcode() == Instruction::SDiv; - bool HasDivRemOp = TTI.hasDivRemOp(DivInst->getType(), IsSigned); + + // Place it in the worklist. + Worklist.emplace_back(DivInst, RemInst); + } + + return Worklist; +} + +/// Find matching pairs of integer div/rem ops (they have the same numerator, +/// denominator, and signedness). If they exist in different basic blocks, bring +/// them together by hoisting or replace the common division operation that is +/// implicit in the remainder: +/// X % Y <--> X - ((X / Y) * Y). +/// +/// We can largely ignore the normal safety and cost constraints on speculation +/// of these ops when we find a matching pair. This is because we are already +/// guaranteed that any exceptions and most cost are already incurred by the +/// first member of the pair. +/// +/// Note: This transform could be an oddball enhancement to EarlyCSE, GVN, or +/// SimplifyCFG, but it's split off on its own because it's different enough +/// that it doesn't quite match the stated objectives of those passes. +static bool optimizeDivRem(Function &F, const TargetTransformInfo &TTI, + const DominatorTree &DT) { + bool Changed = false; + + // Get the matching pairs of div-rem instructions. We want this extra + // indirection to avoid dealing with having to RAUW the keys of the maps. + DivRemWorklistTy Worklist = getWorklist(F); + + // Process each entry in the worklist. + for (DivRemPairWorklistEntry &E : Worklist) { + bool HasDivRemOp = TTI.hasDivRemOp(E.getType(), E.isSigned()); + + auto &DivInst = E.DivInst; + auto &RemInst = E.RemInst; // If the target supports div+rem and the instructions are in the same block // already, there's nothing to do. The backend should handle this. If the @@ -110,8 +167,8 @@ static bool optimizeDivRem(Function &F, const TargetTransformInfo &TTI, // The target does not have a single div/rem operation. Decompose the // remainder calculation as: // X % Y --> X - ((X / Y) * Y). - Value *X = RemInst->getOperand(0); - Value *Y = RemInst->getOperand(1); + Value *X = E.getDividend(); + Value *Y = E.getDivisor(); Instruction *Mul = BinaryOperator::CreateMul(DivInst, Y); Instruction *Sub = BinaryOperator::CreateSub(X, Mul); @@ -152,8 +209,13 @@ static bool optimizeDivRem(Function &F, const TargetTransformInfo &TTI, // Now kill the explicit remainder. We have replaced it with: // (sub X, (mul (div X, Y), Y) - RemInst->replaceAllUsesWith(Sub); - RemInst->eraseFromParent(); + Sub->setName(RemInst->getName() + ".decomposed"); + Instruction *OrigRemInst = RemInst; + // Update AssertingVH<> with new instruction so it doesn't assert. + RemInst = Sub; + // And replace the original instruction with the new one. + OrigRemInst->replaceAllUsesWith(Sub); + OrigRemInst->eraseFromParent(); NumDecomposed++; } Changed = true; @@ -188,7 +250,7 @@ struct DivRemPairsLegacyPass : public FunctionPass { return optimizeDivRem(F, TTI, DT); } }; -} +} // namespace char DivRemPairsLegacyPass::ID = 0; INITIALIZE_PASS_BEGIN(DivRemPairsLegacyPass, "div-rem-pairs", diff --git a/llvm/test/Transforms/DivRemPairs/PowerPC/div-expanded-rem-pair.ll b/llvm/test/Transforms/DivRemPairs/PowerPC/div-expanded-rem-pair.ll new file mode 100644 index 000000000000..04a8a7721e91 --- /dev/null +++ b/llvm/test/Transforms/DivRemPairs/PowerPC/div-expanded-rem-pair.ll @@ -0,0 +1,172 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -div-rem-pairs -S -mtriple=powerpc64-unknown-unknown | FileCheck %s + +declare void @foo(i32, i32) + +define void @decompose_illegal_srem_same_block(i32 %a, i32 %b) { +; CHECK-LABEL: @decompose_illegal_srem_same_block( +; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[T0:%.*]] = mul i32 [[DIV]], [[B]] +; CHECK-NEXT: [[REM:%.*]] = sub i32 [[A]], [[T0]] +; CHECK-NEXT: call void @foo(i32 [[REM]], i32 [[DIV]]) +; CHECK-NEXT: ret void +; + %div = sdiv i32 %a, %b + %t0 = mul i32 %div, %b + %rem = sub i32 %a, %t0 + call void @foo(i32 %rem, i32 %div) + ret void +} + +define void @decompose_illegal_urem_same_block(i32 %a, i32 %b) { +; CHECK-LABEL: @decompose_illegal_urem_same_block( +; CHECK-NEXT: [[DIV:%.*]] = udiv i32 [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[T0:%.*]] = mul i32 [[DIV]], [[B]] +; CHECK-NEXT: [[REM:%.*]] = sub i32 [[A]], [[T0]] +; CHECK-NEXT: call void @foo(i32 [[REM]], i32 [[DIV]]) +; CHECK-NEXT: ret void +; + %div = udiv i32 %a, %b + %t0 = mul i32 %div, %b + %rem = sub i32 %a, %t0 + call void @foo(i32 %rem, i32 %div) + ret void +} + +; Recompose and hoist the srem if it's safe and free, otherwise keep as-is.. + +define i16 @hoist_srem(i16 %a, i16 %b) { +; CHECK-LABEL: @hoist_srem( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[DIV:%.*]] = sdiv i16 [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i16 [[DIV]], 42 +; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]] +; CHECK: if: +; CHECK-NEXT: [[T0:%.*]] = mul i16 [[DIV]], [[B]] +; CHECK-NEXT: [[REM:%.*]] = sub i16 [[A]], [[T0]] +; CHECK-NEXT: br label [[END]] +; CHECK: end: +; CHECK-NEXT: [[RET:%.*]] = phi i16 [ [[REM]], [[IF]] ], [ 3, [[ENTRY:%.*]] ] +; CHECK-NEXT: ret i16 [[RET]] +; +entry: + %div = sdiv i16 %a, %b + %cmp = icmp eq i16 %div, 42 + br i1 %cmp, label %if, label %end + +if: + %t0 = mul i16 %div, %b + %rem = sub i16 %a, %t0 + br label %end + +end: + %ret = phi i16 [ %rem, %if ], [ 3, %entry ] + ret i16 %ret +} + +; Recompose and hoist the urem if it's safe and free, otherwise keep as-is.. + +define i8 @hoist_urem(i8 %a, i8 %b) { +; CHECK-LABEL: @hoist_urem( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[DIV:%.*]] = udiv i8 [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[DIV]], 42 +; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]] +; CHECK: if: +; CHECK-NEXT: [[T0:%.*]] = mul i8 [[DIV]], [[B]] +; CHECK-NEXT: [[REM:%.*]] = sub i8 [[A]], [[T0]] +; CHECK-NEXT: br label [[END]] +; CHECK: end: +; CHECK-NEXT: [[RET:%.*]] = phi i8 [ [[REM]], [[IF]] ], [ 3, [[ENTRY:%.*]] ] +; CHECK-NEXT: ret i8 [[RET]] +; +entry: + %div = udiv i8 %a, %b + %cmp = icmp eq i8 %div, 42 + br i1 %cmp, label %if, label %end + +if: + %t0 = mul i8 %div, %b + %rem = sub i8 %a, %t0 + br label %end + +end: + %ret = phi i8 [ %rem, %if ], [ 3, %entry ] + ret i8 %ret +} + +; Be careful with RAUW/invalidation if this is a srem-of-srem. + +define i32 @srem_of_srem_unexpanded(i32 %X, i32 %Y, i32 %Z) { +; CHECK-LABEL: @srem_of_srem_unexpanded( +; CHECK-NEXT: [[T0:%.*]] = mul nsw i32 [[Z:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[T1:%.*]] = sdiv i32 [[X:%.*]], [[T0]] +; CHECK-NEXT: [[T2:%.*]] = mul nsw i32 [[T0]], [[T1]] +; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[T1]], [[T0]] +; CHECK-NEXT: [[T3_DECOMPOSED:%.*]] = sub i32 [[X]], [[TMP1]] +; CHECK-NEXT: [[T4:%.*]] = sdiv i32 [[T3_DECOMPOSED]], [[Y]] +; CHECK-NEXT: [[T5:%.*]] = mul nsw i32 [[T4]], [[Y]] +; CHECK-NEXT: [[TMP2:%.*]] = mul i32 [[T4]], [[Y]] +; CHECK-NEXT: [[T6_DECOMPOSED:%.*]] = sub i32 [[T3_DECOMPOSED]], [[TMP2]] +; CHECK-NEXT: ret i32 [[T6_DECOMPOSED]] +; + %t0 = mul nsw i32 %Z, %Y + %t1 = sdiv i32 %X, %t0 + %t2 = mul nsw i32 %t0, %t1 + %t3 = srem i32 %X, %t0 + %t4 = sdiv i32 %t3, %Y + %t5 = mul nsw i32 %t4, %Y + %t6 = srem i32 %t3, %Y + ret i32 %t6 +} +define i32 @srem_of_srem_expanded(i32 %X, i32 %Y, i32 %Z) { +; CHECK-LABEL: @srem_of_srem_expanded( +; CHECK-NEXT: [[T0:%.*]] = mul nsw i32 [[Z:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[T1:%.*]] = sdiv i32 [[X:%.*]], [[T0]] +; CHECK-NEXT: [[T2:%.*]] = mul nsw i32 [[T0]], [[T1]] +; CHECK-NEXT: [[T3:%.*]] = sub nsw i32 [[X]], [[T2]] +; CHECK-NEXT: [[T4:%.*]] = sdiv i32 [[T3]], [[Y]] +; CHECK-NEXT: [[T5:%.*]] = mul nsw i32 [[T4]], [[Y]] +; CHECK-NEXT: [[T6:%.*]] = sub nsw i32 [[T3]], [[T5]] +; CHECK-NEXT: ret i32 [[T6]] +; + %t0 = mul nsw i32 %Z, %Y + %t1 = sdiv i32 %X, %t0 + %t2 = mul nsw i32 %t0, %t1 + %t3 = sub nsw i32 %X, %t2 + %t4 = sdiv i32 %t3, %Y + %t5 = mul nsw i32 %t4, %Y + %t6 = sub nsw i32 %t3, %t5 + ret i32 %t6 +} + +; If the target doesn't have a unified div/rem op for the type, keep decomposed rem + +define i128 @dont_hoist_urem(i128 %a, i128 %b) { +; CHECK-LABEL: @dont_hoist_urem( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[DIV:%.*]] = udiv i128 [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i128 [[DIV]], 42 +; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]] +; CHECK: if: +; CHECK-NEXT: [[T0:%.*]] = mul i128 [[DIV]], [[B]] +; CHECK-NEXT: [[REM:%.*]] = sub i128 [[A]], [[T0]] +; CHECK-NEXT: br label [[END]] +; CHECK: end: +; CHECK-NEXT: [[RET:%.*]] = phi i128 [ [[REM]], [[IF]] ], [ 3, [[ENTRY:%.*]] ] +; CHECK-NEXT: ret i128 [[RET]] +; +entry: + %div = udiv i128 %a, %b + %cmp = icmp eq i128 %div, 42 + br i1 %cmp, label %if, label %end + +if: + %t0 = mul i128 %div, %b + %rem = sub i128 %a, %t0 + br label %end + +end: + %ret = phi i128 [ %rem, %if ], [ 3, %entry ] + ret i128 %ret +} diff --git a/llvm/test/Transforms/DivRemPairs/PowerPC/div-rem-pairs.ll b/llvm/test/Transforms/DivRemPairs/PowerPC/div-rem-pairs.ll index c82360c9ba05..4e95e0e399ef 100644 --- a/llvm/test/Transforms/DivRemPairs/PowerPC/div-rem-pairs.ll +++ b/llvm/test/Transforms/DivRemPairs/PowerPC/div-rem-pairs.ll @@ -1,13 +1,14 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt < %s -div-rem-pairs -S -mtriple=powerpc64-unknown-unknown | FileCheck %s declare void @foo(i32, i32) define void @decompose_illegal_srem_same_block(i32 %a, i32 %b) { ; CHECK-LABEL: @decompose_illegal_srem_same_block( -; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 %a, %b -; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[DIV]], %b -; CHECK-NEXT: [[TMP2:%.*]] = sub i32 %a, [[TMP1]] -; CHECK-NEXT: call void @foo(i32 [[TMP2]], i32 [[DIV]]) +; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[DIV]], [[B]] +; CHECK-NEXT: [[REM_DECOMPOSED:%.*]] = sub i32 [[A]], [[TMP1]] +; CHECK-NEXT: call void @foo(i32 [[REM_DECOMPOSED]], i32 [[DIV]]) ; CHECK-NEXT: ret void ; %rem = srem i32 %a, %b @@ -18,10 +19,10 @@ define void @decompose_illegal_srem_same_block(i32 %a, i32 %b) { define void @decompose_illegal_urem_same_block(i32 %a, i32 %b) { ; CHECK-LABEL: @decompose_illegal_urem_same_block( -; CHECK-NEXT: [[DIV:%.*]] = udiv i32 %a, %b -; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[DIV]], %b -; CHECK-NEXT: [[TMP2:%.*]] = sub i32 %a, [[TMP1]] -; CHECK-NEXT: call void @foo(i32 [[TMP2]], i32 [[DIV]]) +; CHECK-NEXT: [[DIV:%.*]] = udiv i32 [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[DIV]], [[B]] +; CHECK-NEXT: [[REM_DECOMPOSED:%.*]] = sub i32 [[A]], [[TMP1]] +; CHECK-NEXT: call void @foo(i32 [[REM_DECOMPOSED]], i32 [[DIV]]) ; CHECK-NEXT: ret void ; %div = udiv i32 %a, %b @@ -36,15 +37,15 @@ define void @decompose_illegal_urem_same_block(i32 %a, i32 %b) { define i32 @hoist_sdiv(i32 %a, i32 %b) { ; CHECK-LABEL: @hoist_sdiv( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 %a, %b -; CHECK-NEXT: [[TMP0:%.*]] = mul i32 [[DIV]], %b -; CHECK-NEXT: [[TMP1:%.*]] = sub i32 %a, [[TMP0]] -; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[TMP1]], 42 -; CHECK-NEXT: br i1 [[CMP]], label %if, label %end +; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[TMP0:%.*]] = mul i32 [[DIV]], [[B]] +; CHECK-NEXT: [[REM_DECOMPOSED:%.*]] = sub i32 [[A]], [[TMP0]] +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[REM_DECOMPOSED]], 42 +; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]] ; CHECK: if: -; CHECK-NEXT: br label %end +; CHECK-NEXT: br label [[END]] ; CHECK: end: -; CHECK-NEXT: [[RET:%.*]] = phi i32 [ [[DIV]], %if ], [ 3, %entry ] +; CHECK-NEXT: [[RET:%.*]] = phi i32 [ [[DIV]], [[IF]] ], [ 3, [[ENTRY:%.*]] ] ; CHECK-NEXT: ret i32 [[RET]] ; entry: @@ -66,15 +67,15 @@ end: define i64 @hoist_udiv(i64 %a, i64 %b) { ; CHECK-LABEL: @hoist_udiv( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[DIV:%.*]] = udiv i64 %a, %b -; CHECK-NEXT: [[TMP0:%.*]] = mul i64 [[DIV]], %b -; CHECK-NEXT: [[TMP1:%.*]] = sub i64 %a, [[TMP0]] -; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[TMP1]], 42 -; CHECK-NEXT: br i1 [[CMP]], label %if, label %end +; CHECK-NEXT: [[DIV:%.*]] = udiv i64 [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[TMP0:%.*]] = mul i64 [[DIV]], [[B]] +; CHECK-NEXT: [[REM_DECOMPOSED:%.*]] = sub i64 [[A]], [[TMP0]] +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[REM_DECOMPOSED]], 42 +; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]] ; CHECK: if: -; CHECK-NEXT: br label %end +; CHECK-NEXT: br label [[END]] ; CHECK: end: -; CHECK-NEXT: [[RET:%.*]] = phi i64 [ [[DIV]], %if ], [ 3, %entry ] +; CHECK-NEXT: [[RET:%.*]] = phi i64 [ [[DIV]], [[IF]] ], [ 3, [[ENTRY:%.*]] ] ; CHECK-NEXT: ret i64 [[RET]] ; entry: @@ -96,15 +97,15 @@ end: define i16 @hoist_srem(i16 %a, i16 %b) { ; CHECK-LABEL: @hoist_srem( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[DIV:%.*]] = sdiv i16 %a, %b +; CHECK-NEXT: [[DIV:%.*]] = sdiv i16 [[A:%.*]], [[B:%.*]] ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i16 [[DIV]], 42 -; CHECK-NEXT: br i1 [[CMP]], label %if, label %end +; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]] ; CHECK: if: -; CHECK-NEXT: [[TMP0:%.*]] = mul i16 [[DIV]], %b -; CHECK-NEXT: [[TMP1:%.*]] = sub i16 %a, [[TMP0]] -; CHECK-NEXT: br label %end +; CHECK-NEXT: [[TMP0:%.*]] = mul i16 [[DIV]], [[B]] +; CHECK-NEXT: [[REM_DECOMPOSED:%.*]] = sub i16 [[A]], [[TMP0]] +; CHECK-NEXT: br label [[END]] ; CHECK: end: -; CHECK-NEXT: [[RET:%.*]] = phi i16 [ [[TMP1]], %if ], [ 3, %entry ] +; CHECK-NEXT: [[RET:%.*]] = phi i16 [ [[REM_DECOMPOSED]], [[IF]] ], [ 3, [[ENTRY:%.*]] ] ; CHECK-NEXT: ret i16 [[RET]] ; entry: @@ -126,15 +127,15 @@ end: define i8 @hoist_urem(i8 %a, i8 %b) { ; CHECK-LABEL: @hoist_urem( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[DIV:%.*]] = udiv i8 %a, %b +; CHECK-NEXT: [[DIV:%.*]] = udiv i8 [[A:%.*]], [[B:%.*]] ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[DIV]], 42 -; CHECK-NEXT: br i1 [[CMP]], label %if, label %end +; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]] ; CHECK: if: -; CHECK-NEXT: [[TMP0:%.*]] = mul i8 [[DIV]], %b -; CHECK-NEXT: [[TMP1:%.*]] = sub i8 %a, [[TMP0]] -; CHECK-NEXT: br label %end +; CHECK-NEXT: [[TMP0:%.*]] = mul i8 [[DIV]], [[B]] +; CHECK-NEXT: [[REM_DECOMPOSED:%.*]] = sub i8 [[A]], [[TMP0]] +; CHECK-NEXT: br label [[END]] ; CHECK: end: -; CHECK-NEXT: [[RET:%.*]] = phi i8 [ [[TMP1]], %if ], [ 3, %entry ] +; CHECK-NEXT: [[RET:%.*]] = phi i8 [ [[REM_DECOMPOSED]], [[IF]] ], [ 3, [[ENTRY:%.*]] ] ; CHECK-NEXT: ret i8 [[RET]] ; entry: @@ -151,19 +152,64 @@ end: ret i8 %ret } +; Be careful with RAUW/invalidation if this is a srem-of-srem. + +define i32 @srem_of_srem_unexpanded(i32 %X, i32 %Y, i32 %Z) { +; CHECK-LABEL: @srem_of_srem_unexpanded( +; CHECK-NEXT: [[T0:%.*]] = mul nsw i32 [[Z:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[T1:%.*]] = sdiv i32 [[X:%.*]], [[T0]] +; CHECK-NEXT: [[T2:%.*]] = mul nsw i32 [[T0]], [[T1]] +; CHECK-NEXT: [[TMP1:%.*]] = mul i32 [[T1]], [[T0]] +; CHECK-NEXT: [[T3_DECOMPOSED:%.*]] = sub i32 [[X]], [[TMP1]] +; CHECK-NEXT: [[T4:%.*]] = sdiv i32 [[T3_DECOMPOSED]], [[Y]] +; CHECK-NEXT: [[T5:%.*]] = mul nsw i32 [[T4]], [[Y]] +; CHECK-NEXT: [[TMP2:%.*]] = mul i32 [[T4]], [[Y]] +; CHECK-NEXT: [[T6_DECOMPOSED:%.*]] = sub i32 [[T3_DECOMPOSED]], [[TMP2]] +; CHECK-NEXT: ret i32 [[T6_DECOMPOSED]] +; + %t0 = mul nsw i32 %Z, %Y + %t1 = sdiv i32 %X, %t0 + %t2 = mul nsw i32 %t0, %t1 + %t3 = srem i32 %X, %t0 + %t4 = sdiv i32 %t3, %Y + %t5 = mul nsw i32 %t4, %Y + %t6 = srem i32 %t3, %Y + ret i32 %t6 +} +define i32 @srem_of_srem_expanded(i32 %X, i32 %Y, i32 %Z) { +; CHECK-LABEL: @srem_of_srem_expanded( +; CHECK-NEXT: [[T0:%.*]] = mul nsw i32 [[Z:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[T1:%.*]] = sdiv i32 [[X:%.*]], [[T0]] +; CHECK-NEXT: [[T2:%.*]] = mul nsw i32 [[T0]], [[T1]] +; CHECK-NEXT: [[T3:%.*]] = sub nsw i32 [[X]], [[T2]] +; CHECK-NEXT: [[T4:%.*]] = sdiv i32 [[T3]], [[Y]] +; CHECK-NEXT: [[T5:%.*]] = mul nsw i32 [[T4]], [[Y]] +; CHECK-NEXT: [[T6:%.*]] = sub nsw i32 [[T3]], [[T5]] +; CHECK-NEXT: ret i32 [[T6]] +; + %t0 = mul nsw i32 %Z, %Y + %t1 = sdiv i32 %X, %t0 + %t2 = mul nsw i32 %t0, %t1 + %t3 = sub nsw i32 %X, %t2 + %t4 = sdiv i32 %t3, %Y + %t5 = mul nsw i32 %t4, %Y + %t6 = sub nsw i32 %t3, %t5 + ret i32 %t6 +} + ; If the ops don't match, don't do anything: signedness. define i32 @dont_hoist_udiv(i32 %a, i32 %b) { ; CHECK-LABEL: @dont_hoist_udiv( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[REM:%.*]] = srem i32 %a, %b +; CHECK-NEXT: [[REM:%.*]] = srem i32 [[A:%.*]], [[B:%.*]] ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[REM]], 42 -; CHECK-NEXT: br i1 [[CMP]], label %if, label %end +; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]] ; CHECK: if: -; CHECK-NEXT: [[DIV:%.*]] = udiv i32 %a, %b -; CHECK-NEXT: br label %end +; CHECK-NEXT: [[DIV:%.*]] = udiv i32 [[A]], [[B]] +; CHECK-NEXT: br label [[END]] ; CHECK: end: -; CHECK-NEXT: [[RET:%.*]] = phi i32 [ [[DIV]], %if ], [ 3, %entry ] +; CHECK-NEXT: [[RET:%.*]] = phi i32 [ [[DIV]], [[IF]] ], [ 3, [[ENTRY:%.*]] ] ; CHECK-NEXT: ret i32 [[RET]] ; entry: @@ -185,14 +231,14 @@ end: define i32 @dont_hoist_srem(i32 %a, i32 %b) { ; CHECK-LABEL: @dont_hoist_srem( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[REM:%.*]] = urem i32 %a, %b +; CHECK-NEXT: [[REM:%.*]] = urem i32 [[A:%.*]], [[B:%.*]] ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[REM]], 42 -; CHECK-NEXT: br i1 [[CMP]], label %if, label %end +; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]] ; CHECK: if: -; CHECK-NEXT: [[REM2:%.*]] = srem i32 %a, %b -; CHECK-NEXT: br label %end +; CHECK-NEXT: [[REM2:%.*]] = srem i32 [[A]], [[B]] +; CHECK-NEXT: br label [[END]] ; CHECK: end: -; CHECK-NEXT: [[RET:%.*]] = phi i32 [ [[REM2]], %if ], [ 3, %entry ] +; CHECK-NEXT: [[RET:%.*]] = phi i32 [ [[REM2]], [[IF]] ], [ 3, [[ENTRY:%.*]] ] ; CHECK-NEXT: ret i32 [[RET]] ; entry: @@ -214,14 +260,14 @@ end: define i32 @dont_hoist_sdiv(i32 %a, i32 %b, i32 %c) { ; CHECK-LABEL: @dont_hoist_sdiv( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[REM:%.*]] = srem i32 %a, %b +; CHECK-NEXT: [[REM:%.*]] = srem i32 [[A:%.*]], [[B:%.*]] ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[REM]], 42 -; CHECK-NEXT: br i1 [[CMP]], label %if, label %end +; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]] ; CHECK: if: -; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 %a, %c -; CHECK-NEXT: br label %end +; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[A]], [[C:%.*]] +; CHECK-NEXT: br label [[END]] ; CHECK: end: -; CHECK-NEXT: [[RET:%.*]] = phi i32 [ [[DIV]], %if ], [ 3, %entry ] +; CHECK-NEXT: [[RET:%.*]] = phi i32 [ [[DIV]], [[IF]] ], [ 3, [[ENTRY:%.*]] ] ; CHECK-NEXT: ret i32 [[RET]] ; entry: @@ -243,15 +289,15 @@ end: define i128 @dont_hoist_urem(i128 %a, i128 %b) { ; CHECK-LABEL: @dont_hoist_urem( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[DIV:%.*]] = udiv i128 %a, %b +; CHECK-NEXT: [[DIV:%.*]] = udiv i128 [[A:%.*]], [[B:%.*]] ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i128 [[DIV]], 42 -; CHECK-NEXT: br i1 [[CMP]], label %if, label %end +; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]] ; CHECK: if: -; CHECK-NEXT: [[TMP0:%.*]] = mul i128 [[DIV]], %b -; CHECK-NEXT: [[TMP1:%.*]] = sub i128 %a, [[TMP0]] -; CHECK-NEXT: br label %end +; CHECK-NEXT: [[TMP0:%.*]] = mul i128 [[DIV]], [[B]] +; CHECK-NEXT: [[REM_DECOMPOSED:%.*]] = sub i128 [[A]], [[TMP0]] +; CHECK-NEXT: br label [[END]] ; CHECK: end: -; CHECK-NEXT: [[RET:%.*]] = phi i128 [ [[TMP1]], %if ], [ 3, %entry ] +; CHECK-NEXT: [[RET:%.*]] = phi i128 [ [[REM_DECOMPOSED]], [[IF]] ], [ 3, [[ENTRY:%.*]] ] ; CHECK-NEXT: ret i128 [[RET]] ; entry: @@ -274,15 +320,15 @@ end: define i32 @no_domination(i1 %cmp, i32 %a, i32 %b) { ; CHECK-LABEL: @no_domination( ; CHECK-NEXT: entry: -; CHECK-NEXT: br i1 %cmp, label %if, label %else +; CHECK-NEXT: br i1 [[CMP:%.*]], label [[IF:%.*]], label [[ELSE:%.*]] ; CHECK: if: -; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 %a, %b -; CHECK-NEXT: br label %end +; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: br label [[END:%.*]] ; CHECK: else: -; CHECK-NEXT: [[REM:%.*]] = srem i32 %a, %b -; CHECK-NEXT: br label %end +; CHECK-NEXT: [[REM:%.*]] = srem i32 [[A]], [[B]] +; CHECK-NEXT: br label [[END]] ; CHECK: end: -; CHECK-NEXT: [[RET:%.*]] = phi i32 [ [[DIV]], %if ], [ [[REM]], %else ] +; CHECK-NEXT: [[RET:%.*]] = phi i32 [ [[DIV]], [[IF]] ], [ [[REM]], [[ELSE]] ] ; CHECK-NEXT: ret i32 [[RET]] ; entry: diff --git a/llvm/test/Transforms/DivRemPairs/X86/div-expanded-rem-pair.ll b/llvm/test/Transforms/DivRemPairs/X86/div-expanded-rem-pair.ll new file mode 100644 index 000000000000..b0cb92a394fd --- /dev/null +++ b/llvm/test/Transforms/DivRemPairs/X86/div-expanded-rem-pair.ll @@ -0,0 +1,170 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -div-rem-pairs -S -mtriple=x86_64-unknown-unknown | FileCheck %s + +declare void @foo(i32, i32) + +define void @decompose_illegal_srem_same_block(i32 %a, i32 %b) { +; CHECK-LABEL: @decompose_illegal_srem_same_block( +; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[T0:%.*]] = mul i32 [[DIV]], [[B]] +; CHECK-NEXT: [[REM:%.*]] = sub i32 [[A]], [[T0]] +; CHECK-NEXT: call void @foo(i32 [[REM]], i32 [[DIV]]) +; CHECK-NEXT: ret void +; + %div = sdiv i32 %a, %b + %t0 = mul i32 %div, %b + %rem = sub i32 %a, %t0 + call void @foo(i32 %rem, i32 %div) + ret void +} + +define void @decompose_illegal_urem_same_block(i32 %a, i32 %b) { +; CHECK-LABEL: @decompose_illegal_urem_same_block( +; CHECK-NEXT: [[DIV:%.*]] = udiv i32 [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[T0:%.*]] = mul i32 [[DIV]], [[B]] +; CHECK-NEXT: [[REM:%.*]] = sub i32 [[A]], [[T0]] +; CHECK-NEXT: call void @foo(i32 [[REM]], i32 [[DIV]]) +; CHECK-NEXT: ret void +; + %div = udiv i32 %a, %b + %t0 = mul i32 %div, %b + %rem = sub i32 %a, %t0 + call void @foo(i32 %rem, i32 %div) + ret void +} + +; Recompose and hoist the srem if it's safe and free, otherwise keep as-is.. + +define i16 @hoist_srem(i16 %a, i16 %b) { +; CHECK-LABEL: @hoist_srem( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[DIV:%.*]] = sdiv i16 [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i16 [[DIV]], 42 +; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]] +; CHECK: if: +; CHECK-NEXT: [[T0:%.*]] = mul i16 [[DIV]], [[B]] +; CHECK-NEXT: [[REM:%.*]] = sub i16 [[A]], [[T0]] +; CHECK-NEXT: br label [[END]] +; CHECK: end: +; CHECK-NEXT: [[RET:%.*]] = phi i16 [ [[REM]], [[IF]] ], [ 3, [[ENTRY:%.*]] ] +; CHECK-NEXT: ret i16 [[RET]] +; +entry: + %div = sdiv i16 %a, %b + %cmp = icmp eq i16 %div, 42 + br i1 %cmp, label %if, label %end + +if: + %t0 = mul i16 %div, %b + %rem = sub i16 %a, %t0 + br label %end + +end: + %ret = phi i16 [ %rem, %if ], [ 3, %entry ] + ret i16 %ret +} + +; Recompose and hoist the urem if it's safe and free, otherwise keep as-is.. + +define i8 @hoist_urem(i8 %a, i8 %b) { +; CHECK-LABEL: @hoist_urem( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[DIV:%.*]] = udiv i8 [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[DIV]], 42 +; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]] +; CHECK: if: +; CHECK-NEXT: [[T0:%.*]] = mul i8 [[DIV]], [[B]] +; CHECK-NEXT: [[REM:%.*]] = sub i8 [[A]], [[T0]] +; CHECK-NEXT: br label [[END]] +; CHECK: end: +; CHECK-NEXT: [[RET:%.*]] = phi i8 [ [[REM]], [[IF]] ], [ 3, [[ENTRY:%.*]] ] +; CHECK-NEXT: ret i8 [[RET]] +; +entry: + %div = udiv i8 %a, %b + %cmp = icmp eq i8 %div, 42 + br i1 %cmp, label %if, label %end + +if: + %t0 = mul i8 %div, %b + %rem = sub i8 %a, %t0 + br label %end + +end: + %ret = phi i8 [ %rem, %if ], [ 3, %entry ] + ret i8 %ret +} + +; Be careful with RAUW/invalidation if this is a srem-of-srem. + +define i32 @srem_of_srem_unexpanded(i32 %X, i32 %Y, i32 %Z) { +; CHECK-LABEL: @srem_of_srem_unexpanded( +; CHECK-NEXT: [[T0:%.*]] = mul nsw i32 [[Z:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[T1:%.*]] = sdiv i32 [[X:%.*]], [[T0]] +; CHECK-NEXT: [[T2:%.*]] = mul nsw i32 [[T0]], [[T1]] +; CHECK-NEXT: [[T3:%.*]] = srem i32 [[X]], [[T0]] +; CHECK-NEXT: [[T4:%.*]] = sdiv i32 [[T3]], [[Y]] +; CHECK-NEXT: [[T5:%.*]] = mul nsw i32 [[T4]], [[Y]] +; CHECK-NEXT: [[T6:%.*]] = srem i32 [[T3]], [[Y]] +; CHECK-NEXT: ret i32 [[T6]] +; + %t0 = mul nsw i32 %Z, %Y + %t1 = sdiv i32 %X, %t0 + %t2 = mul nsw i32 %t0, %t1 + %t3 = srem i32 %X, %t0 + %t4 = sdiv i32 %t3, %Y + %t5 = mul nsw i32 %t4, %Y + %t6 = srem i32 %t3, %Y + ret i32 %t6 +} +define i32 @srem_of_srem_expanded(i32 %X, i32 %Y, i32 %Z) { +; CHECK-LABEL: @srem_of_srem_expanded( +; CHECK-NEXT: [[T0:%.*]] = mul nsw i32 [[Z:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[T1:%.*]] = sdiv i32 [[X:%.*]], [[T0]] +; CHECK-NEXT: [[T2:%.*]] = mul nsw i32 [[T0]], [[T1]] +; CHECK-NEXT: [[T3:%.*]] = sub nsw i32 [[X]], [[T2]] +; CHECK-NEXT: [[T4:%.*]] = sdiv i32 [[T3]], [[Y]] +; CHECK-NEXT: [[T5:%.*]] = mul nsw i32 [[T4]], [[Y]] +; CHECK-NEXT: [[T6:%.*]] = sub nsw i32 [[T3]], [[T5]] +; CHECK-NEXT: ret i32 [[T6]] +; + %t0 = mul nsw i32 %Z, %Y + %t1 = sdiv i32 %X, %t0 + %t2 = mul nsw i32 %t0, %t1 + %t3 = sub nsw i32 %X, %t2 + %t4 = sdiv i32 %t3, %Y + %t5 = mul nsw i32 %t4, %Y + %t6 = sub nsw i32 %t3, %t5 + ret i32 %t6 +} + +; If the target doesn't have a unified div/rem op for the type, keep decomposed rem + +define i128 @dont_hoist_urem(i128 %a, i128 %b) { +; CHECK-LABEL: @dont_hoist_urem( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[DIV:%.*]] = udiv i128 [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i128 [[DIV]], 42 +; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]] +; CHECK: if: +; CHECK-NEXT: [[T0:%.*]] = mul i128 [[DIV]], [[B]] +; CHECK-NEXT: [[REM:%.*]] = sub i128 [[A]], [[T0]] +; CHECK-NEXT: br label [[END]] +; CHECK: end: +; CHECK-NEXT: [[RET:%.*]] = phi i128 [ [[REM]], [[IF]] ], [ 3, [[ENTRY:%.*]] ] +; CHECK-NEXT: ret i128 [[RET]] +; +entry: + %div = udiv i128 %a, %b + %cmp = icmp eq i128 %div, 42 + br i1 %cmp, label %if, label %end + +if: + %t0 = mul i128 %div, %b + %rem = sub i128 %a, %t0 + br label %end + +end: + %ret = phi i128 [ %rem, %if ], [ 3, %entry ] + ret i128 %ret +} diff --git a/llvm/test/Transforms/DivRemPairs/X86/div-rem-pairs.ll b/llvm/test/Transforms/DivRemPairs/X86/div-rem-pairs.ll index 74c8e6e209d4..711790004c15 100644 --- a/llvm/test/Transforms/DivRemPairs/X86/div-rem-pairs.ll +++ b/llvm/test/Transforms/DivRemPairs/X86/div-rem-pairs.ll @@ -1,11 +1,12 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt < %s -div-rem-pairs -S -mtriple=x86_64-unknown-unknown | FileCheck %s declare void @foo(i32, i32) define void @decompose_illegal_srem_same_block(i32 %a, i32 %b) { ; CHECK-LABEL: @decompose_illegal_srem_same_block( -; CHECK-NEXT: [[REM:%.*]] = srem i32 %a, %b -; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 %a, %b +; CHECK-NEXT: [[REM:%.*]] = srem i32 [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[A]], [[B]] ; CHECK-NEXT: call void @foo(i32 [[REM]], i32 [[DIV]]) ; CHECK-NEXT: ret void ; @@ -17,8 +18,8 @@ define void @decompose_illegal_srem_same_block(i32 %a, i32 %b) { define void @decompose_illegal_urem_same_block(i32 %a, i32 %b) { ; CHECK-LABEL: @decompose_illegal_urem_same_block( -; CHECK-NEXT: [[DIV:%.*]] = udiv i32 %a, %b -; CHECK-NEXT: [[REM:%.*]] = urem i32 %a, %b +; CHECK-NEXT: [[DIV:%.*]] = udiv i32 [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[REM:%.*]] = urem i32 [[A]], [[B]] ; CHECK-NEXT: call void @foo(i32 [[REM]], i32 [[DIV]]) ; CHECK-NEXT: ret void ; @@ -34,14 +35,14 @@ define void @decompose_illegal_urem_same_block(i32 %a, i32 %b) { define i32 @hoist_sdiv(i32 %a, i32 %b) { ; CHECK-LABEL: @hoist_sdiv( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[REM:%.*]] = srem i32 %a, %b -; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 %a, %b +; CHECK-NEXT: [[REM:%.*]] = srem i32 [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[A]], [[B]] ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[REM]], 42 -; CHECK-NEXT: br i1 [[CMP]], label %if, label %end +; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]] ; CHECK: if: -; CHECK-NEXT: br label %end +; CHECK-NEXT: br label [[END]] ; CHECK: end: -; CHECK-NEXT: [[RET:%.*]] = phi i32 [ [[DIV]], %if ], [ 3, %entry ] +; CHECK-NEXT: [[RET:%.*]] = phi i32 [ [[DIV]], [[IF]] ], [ 3, [[ENTRY:%.*]] ] ; CHECK-NEXT: ret i32 [[RET]] ; entry: @@ -63,14 +64,14 @@ end: define i64 @hoist_udiv(i64 %a, i64 %b) { ; CHECK-LABEL: @hoist_udiv( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[REM:%.*]] = urem i64 %a, %b -; CHECK-NEXT: [[DIV:%.*]] = udiv i64 %a, %b +; CHECK-NEXT: [[REM:%.*]] = urem i64 [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[DIV:%.*]] = udiv i64 [[A]], [[B]] ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[REM]], 42 -; CHECK-NEXT: br i1 [[CMP]], label %if, label %end +; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]] ; CHECK: if: -; CHECK-NEXT: br label %end +; CHECK-NEXT: br label [[END]] ; CHECK: end: -; CHECK-NEXT: [[RET:%.*]] = phi i64 [ [[DIV]], %if ], [ 3, %entry ] +; CHECK-NEXT: [[RET:%.*]] = phi i64 [ [[DIV]], [[IF]] ], [ 3, [[ENTRY:%.*]] ] ; CHECK-NEXT: ret i64 [[RET]] ; entry: @@ -92,14 +93,14 @@ end: define i16 @hoist_srem(i16 %a, i16 %b) { ; CHECK-LABEL: @hoist_srem( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[DIV:%.*]] = sdiv i16 %a, %b -; CHECK-NEXT: [[REM:%.*]] = srem i16 %a, %b +; CHECK-NEXT: [[DIV:%.*]] = sdiv i16 [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[REM:%.*]] = srem i16 [[A]], [[B]] ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i16 [[DIV]], 42 -; CHECK-NEXT: br i1 [[CMP]], label %if, label %end +; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]] ; CHECK: if: -; CHECK-NEXT: br label %end +; CHECK-NEXT: br label [[END]] ; CHECK: end: -; CHECK-NEXT: [[RET:%.*]] = phi i16 [ [[REM]], %if ], [ 3, %entry ] +; CHECK-NEXT: [[RET:%.*]] = phi i16 [ [[REM]], [[IF]] ], [ 3, [[ENTRY:%.*]] ] ; CHECK-NEXT: ret i16 [[RET]] ; entry: @@ -121,14 +122,14 @@ end: define i8 @hoist_urem(i8 %a, i8 %b) { ; CHECK-LABEL: @hoist_urem( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[DIV:%.*]] = udiv i8 %a, %b -; CHECK-NEXT: [[REM:%.*]] = urem i8 %a, %b +; CHECK-NEXT: [[DIV:%.*]] = udiv i8 [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[REM:%.*]] = urem i8 [[A]], [[B]] ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[DIV]], 42 -; CHECK-NEXT: br i1 [[CMP]], label %if, label %end +; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]] ; CHECK: if: -; CHECK-NEXT: br label %end +; CHECK-NEXT: br label [[END]] ; CHECK: end: -; CHECK-NEXT: [[RET:%.*]] = phi i8 [ [[REM]], %if ], [ 3, %entry ] +; CHECK-NEXT: [[RET:%.*]] = phi i8 [ [[REM]], [[IF]] ], [ 3, [[ENTRY:%.*]] ] ; CHECK-NEXT: ret i8 [[RET]] ; entry: @@ -145,19 +146,62 @@ end: ret i8 %ret } +; Be careful with RAUW/invalidation if this is a srem-of-srem. + +define i32 @srem_of_srem_unexpanded(i32 %X, i32 %Y, i32 %Z) { +; CHECK-LABEL: @srem_of_srem_unexpanded( +; CHECK-NEXT: [[T0:%.*]] = mul nsw i32 [[Z:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[T1:%.*]] = sdiv i32 [[X:%.*]], [[T0]] +; CHECK-NEXT: [[T2:%.*]] = mul nsw i32 [[T0]], [[T1]] +; CHECK-NEXT: [[T3:%.*]] = srem i32 [[X]], [[T0]] +; CHECK-NEXT: [[T4:%.*]] = sdiv i32 [[T3]], [[Y]] +; CHECK-NEXT: [[T5:%.*]] = mul nsw i32 [[T4]], [[Y]] +; CHECK-NEXT: [[T6:%.*]] = srem i32 [[T3]], [[Y]] +; CHECK-NEXT: ret i32 [[T6]] +; + %t0 = mul nsw i32 %Z, %Y + %t1 = sdiv i32 %X, %t0 + %t2 = mul nsw i32 %t0, %t1 + %t3 = srem i32 %X, %t0 + %t4 = sdiv i32 %t3, %Y + %t5 = mul nsw i32 %t4, %Y + %t6 = srem i32 %t3, %Y + ret i32 %t6 +} +define i32 @srem_of_srem_expanded(i32 %X, i32 %Y, i32 %Z) { +; CHECK-LABEL: @srem_of_srem_expanded( +; CHECK-NEXT: [[T0:%.*]] = mul nsw i32 [[Z:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[T1:%.*]] = sdiv i32 [[X:%.*]], [[T0]] +; CHECK-NEXT: [[T2:%.*]] = mul nsw i32 [[T0]], [[T1]] +; CHECK-NEXT: [[T3:%.*]] = sub nsw i32 [[X]], [[T2]] +; CHECK-NEXT: [[T4:%.*]] = sdiv i32 [[T3]], [[Y]] +; CHECK-NEXT: [[T5:%.*]] = mul nsw i32 [[T4]], [[Y]] +; CHECK-NEXT: [[T6:%.*]] = sub nsw i32 [[T3]], [[T5]] +; CHECK-NEXT: ret i32 [[T6]] +; + %t0 = mul nsw i32 %Z, %Y + %t1 = sdiv i32 %X, %t0 + %t2 = mul nsw i32 %t0, %t1 + %t3 = sub nsw i32 %X, %t2 + %t4 = sdiv i32 %t3, %Y + %t5 = mul nsw i32 %t4, %Y + %t6 = sub nsw i32 %t3, %t5 + ret i32 %t6 +} + ; If the ops don't match, don't do anything: signedness. define i32 @dont_hoist_udiv(i32 %a, i32 %b) { ; CHECK-LABEL: @dont_hoist_udiv( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[REM:%.*]] = srem i32 %a, %b +; CHECK-NEXT: [[REM:%.*]] = srem i32 [[A:%.*]], [[B:%.*]] ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[REM]], 42 -; CHECK-NEXT: br i1 [[CMP]], label %if, label %end +; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]] ; CHECK: if: -; CHECK-NEXT: [[DIV:%.*]] = udiv i32 %a, %b -; CHECK-NEXT: br label %end +; CHECK-NEXT: [[DIV:%.*]] = udiv i32 [[A]], [[B]] +; CHECK-NEXT: br label [[END]] ; CHECK: end: -; CHECK-NEXT: [[RET:%.*]] = phi i32 [ [[DIV]], %if ], [ 3, %entry ] +; CHECK-NEXT: [[RET:%.*]] = phi i32 [ [[DIV]], [[IF]] ], [ 3, [[ENTRY:%.*]] ] ; CHECK-NEXT: ret i32 [[RET]] ; entry: @@ -179,14 +223,14 @@ end: define i32 @dont_hoist_srem(i32 %a, i32 %b) { ; CHECK-LABEL: @dont_hoist_srem( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[REM:%.*]] = urem i32 %a, %b +; CHECK-NEXT: [[REM:%.*]] = urem i32 [[A:%.*]], [[B:%.*]] ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[REM]], 42 -; CHECK-NEXT: br i1 [[CMP]], label %if, label %end +; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]] ; CHECK: if: -; CHECK-NEXT: [[REM2:%.*]] = srem i32 %a, %b -; CHECK-NEXT: br label %end +; CHECK-NEXT: [[REM2:%.*]] = srem i32 [[A]], [[B]] +; CHECK-NEXT: br label [[END]] ; CHECK: end: -; CHECK-NEXT: [[RET:%.*]] = phi i32 [ [[REM2]], %if ], [ 3, %entry ] +; CHECK-NEXT: [[RET:%.*]] = phi i32 [ [[REM2]], [[IF]] ], [ 3, [[ENTRY:%.*]] ] ; CHECK-NEXT: ret i32 [[RET]] ; entry: @@ -208,14 +252,14 @@ end: define i32 @dont_hoist_sdiv(i32 %a, i32 %b, i32 %c) { ; CHECK-LABEL: @dont_hoist_sdiv( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[REM:%.*]] = srem i32 %a, %b +; CHECK-NEXT: [[REM:%.*]] = srem i32 [[A:%.*]], [[B:%.*]] ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[REM]], 42 -; CHECK-NEXT: br i1 [[CMP]], label %if, label %end +; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]] ; CHECK: if: -; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 %a, %c -; CHECK-NEXT: br label %end +; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[A]], [[C:%.*]] +; CHECK-NEXT: br label [[END]] ; CHECK: end: -; CHECK-NEXT: [[RET:%.*]] = phi i32 [ [[DIV]], %if ], [ 3, %entry ] +; CHECK-NEXT: [[RET:%.*]] = phi i32 [ [[DIV]], [[IF]] ], [ 3, [[ENTRY:%.*]] ] ; CHECK-NEXT: ret i32 [[RET]] ; entry: @@ -237,15 +281,15 @@ end: define i128 @dont_hoist_urem(i128 %a, i128 %b) { ; CHECK-LABEL: @dont_hoist_urem( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[DIV:%.*]] = udiv i128 %a, %b +; CHECK-NEXT: [[DIV:%.*]] = udiv i128 [[A:%.*]], [[B:%.*]] ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i128 [[DIV]], 42 -; CHECK-NEXT: br i1 [[CMP]], label %if, label %end +; CHECK-NEXT: br i1 [[CMP]], label [[IF:%.*]], label [[END:%.*]] ; CHECK: if: -; CHECK-NEXT: [[TMP0:%.*]] = mul i128 [[DIV]], %b -; CHECK-NEXT: [[TMP1:%.*]] = sub i128 %a, [[TMP0]] -; CHECK-NEXT: br label %end +; CHECK-NEXT: [[TMP0:%.*]] = mul i128 [[DIV]], [[B]] +; CHECK-NEXT: [[REM_DECOMPOSED:%.*]] = sub i128 [[A]], [[TMP0]] +; CHECK-NEXT: br label [[END]] ; CHECK: end: -; CHECK-NEXT: [[RET:%.*]] = phi i128 [ [[TMP1]], %if ], [ 3, %entry ] +; CHECK-NEXT: [[RET:%.*]] = phi i128 [ [[REM_DECOMPOSED]], [[IF]] ], [ 3, [[ENTRY:%.*]] ] ; CHECK-NEXT: ret i128 [[RET]] ; entry: @@ -268,15 +312,15 @@ end: define i32 @no_domination(i1 %cmp, i32 %a, i32 %b) { ; CHECK-LABEL: @no_domination( ; CHECK-NEXT: entry: -; CHECK-NEXT: br i1 %cmp, label %if, label %else +; CHECK-NEXT: br i1 [[CMP:%.*]], label [[IF:%.*]], label [[ELSE:%.*]] ; CHECK: if: -; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 %a, %b -; CHECK-NEXT: br label %end +; CHECK-NEXT: [[DIV:%.*]] = sdiv i32 [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: br label [[END:%.*]] ; CHECK: else: -; CHECK-NEXT: [[REM:%.*]] = srem i32 %a, %b -; CHECK-NEXT: br label %end +; CHECK-NEXT: [[REM:%.*]] = srem i32 [[A]], [[B]] +; CHECK-NEXT: br label [[END]] ; CHECK: end: -; CHECK-NEXT: [[RET:%.*]] = phi i32 [ [[DIV]], %if ], [ [[REM]], %else ] +; CHECK-NEXT: [[RET:%.*]] = phi i32 [ [[DIV]], [[IF]] ], [ [[REM]], [[ELSE]] ] ; CHECK-NEXT: ret i32 [[RET]] ; entry: From c023a03a754fe838f776322a62aa0e1d77a16003 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Thu, 1 Aug 2019 09:40:07 +0000 Subject: [PATCH 056/289] Merging r367308: ------------------------------------------------------------------------ r367308 | teemperor | 2019-07-30 14:31:24 +0200 (Tue, 30 Jul 2019) | 27 lines [lldb] Fix crash when tab-completing in multi-line expr Summary: Tab completing inside the multiline expression command can cause LLDB to crash. The easiest way to do this is to go inside a frame with at least one local variable and then try to complete: (lldb) expr 1. a[tab] Reason for this was some mixup when we calculate the cursor position. Obviously we should calculate the offset inside the string by doing 'end - start', but we are doing 'start - end' (which causes the offset to become -1 which will lead to some out-of-bounds reading). Fixes rdar://51754005 I don't see any way to test this as the *multiline* expression completion is completely untested at the moment and I don't think we have any existing code for testing infrastructure for it. Reviewers: shafik, davide, labath Reviewed By: labath Subscribers: abidh, lldb-commits, davide, clayborg, labath Tags: #lldb Differential Revision: https://reviews.llvm.org/D64995 ------------------------------------------------------------------------ llvm-svn: 367534 --- .../multiline-completion/Makefile | 3 ++ .../TestMultilineCompletion.py | 52 +++++++++++++++++++ .../multiline-completion/main.c | 5 ++ lldb/source/Core/IOHandler.cpp | 2 +- 4 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 lldb/packages/Python/lldbsuite/test/expression_command/multiline-completion/Makefile create mode 100644 lldb/packages/Python/lldbsuite/test/expression_command/multiline-completion/TestMultilineCompletion.py create mode 100644 lldb/packages/Python/lldbsuite/test/expression_command/multiline-completion/main.c diff --git a/lldb/packages/Python/lldbsuite/test/expression_command/multiline-completion/Makefile b/lldb/packages/Python/lldbsuite/test/expression_command/multiline-completion/Makefile new file mode 100644 index 000000000000..f5a47fcc46cc --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/expression_command/multiline-completion/Makefile @@ -0,0 +1,3 @@ +LEVEL = ../../make +C_SOURCES := main.c +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/expression_command/multiline-completion/TestMultilineCompletion.py b/lldb/packages/Python/lldbsuite/test/expression_command/multiline-completion/TestMultilineCompletion.py new file mode 100644 index 000000000000..2d75fc471d58 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/expression_command/multiline-completion/TestMultilineCompletion.py @@ -0,0 +1,52 @@ +""" +Test completion for multiline expressions. +""" + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * + +class MultilineCompletionTest(TestBase): + + mydir = TestBase.compute_mydir(__file__) + NO_DEBUG_INFO_TESTCASE = True + + def setUp(self): + TestBase.setUp(self) + self.source = 'main.c' + + def expect_string(self, string): + import pexpect + """This expects for "string", with timeout & EOF being test fails.""" + try: + self.child.expect_exact(string) + except pexpect.EOF: + self.fail("Got EOF waiting for '%s'" % (string)) + except pexpect.TIMEOUT: + self.fail("Timed out waiting for '%s'" % (string)) + + @expectedFailureAll( + oslist=["windows"], + bugnumber="llvm.org/pr22274: need a pexpect replacement for windows") + def test_basic_completion(self): + """Test that we can complete a simple multiline expression""" + self.build() + self.setTearDownCleanup() + + import pexpect + exe = self.getBuildArtifact("a.out") + prompt = "(lldb) " + + run_commands = ' -o "b main" -o "r"' + self.child = pexpect.spawn( + '%s %s %s %s' % + (lldbtest_config.lldbExec, self.lldbOption, run_commands, exe)) + child = self.child + + self.expect_string(prompt) + self.child.sendline("expr") + self.expect_string("terminate with an empty line to evaluate") + self.child.send("to_\t") + self.expect_string("to_complete") + + self.deletePexpectChild() diff --git a/lldb/packages/Python/lldbsuite/test/expression_command/multiline-completion/main.c b/lldb/packages/Python/lldbsuite/test/expression_command/multiline-completion/main.c new file mode 100644 index 000000000000..03350dd8299a --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/expression_command/multiline-completion/main.c @@ -0,0 +1,5 @@ +int main(int argc, char **argv) { + lldb_enable_attach(); + int to_complete = 0; + return to_complete; +} diff --git a/lldb/source/Core/IOHandler.cpp b/lldb/source/Core/IOHandler.cpp index b30308490cca..c3c722019faa 100644 --- a/lldb/source/Core/IOHandler.cpp +++ b/lldb/source/Core/IOHandler.cpp @@ -233,7 +233,7 @@ int IOHandlerDelegate::IOHandlerComplete( matches, descriptions); case Completion::Expression: { CompletionResult result; - CompletionRequest request(current_line, current_line - cursor, + CompletionRequest request(current_line, cursor - current_line, skip_first_n_matches, max_matches, result); CommandCompletions::InvokeCommonCompletionCallbacks( io_handler.GetDebugger().GetCommandInterpreter(), From f94a258ec4a09727db889a6f6ba70cf5657f894c Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Thu, 1 Aug 2019 14:47:07 +0000 Subject: [PATCH 057/289] Merging r366545: ------------------------------------------------------------------------ r366545 | kadircet | 2019-07-19 11:08:22 +0200 (Fri, 19 Jul 2019) | 17 lines [clangd] Handle windows line endings in QueryDriver Summary: The previous patch did not fix the end mark. D64789 fixes second case of https://github.com/clangd/clangd/issues/93 Patch by @lh123 ! Reviewers: sammccall, kadircet Reviewed By: kadircet Subscribers: MaskRay, ilya-biryukov, jkorous, arphaman, cfe-commits Tags: #clang-tools-extra, #clang Differential Revision: https://reviews.llvm.org/D64970 ------------------------------------------------------------------------ llvm-svn: 367571 --- clang-tools-extra/clangd/QueryDriverDatabase.cpp | 6 ++++-- clang-tools-extra/clangd/test/system-include-extractor.test | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/clang-tools-extra/clangd/QueryDriverDatabase.cpp b/clang-tools-extra/clangd/QueryDriverDatabase.cpp index 28596dafb601..bec6ea7186b2 100644 --- a/clang-tools-extra/clangd/QueryDriverDatabase.cpp +++ b/clang-tools-extra/clangd/QueryDriverDatabase.cpp @@ -59,7 +59,7 @@ namespace { std::vector parseDriverOutput(llvm::StringRef Output) { std::vector SystemIncludes; const char SIS[] = "#include <...> search starts here:"; - constexpr char const *SIE = "End of search list."; + const char SIE[] = "End of search list."; llvm::SmallVector Lines; Output.split(Lines, '\n', /*MaxSplit=*/-1, /*KeepEmpty=*/false); @@ -70,7 +70,9 @@ std::vector parseDriverOutput(llvm::StringRef Output) { return {}; } ++StartIt; - const auto EndIt = std::find(StartIt, Lines.end(), SIE); + const auto EndIt = + llvm::find_if(llvm::make_range(StartIt, Lines.end()), + [SIE](llvm::StringRef Line) { return Line.trim() == SIE; }); if (EndIt == Lines.end()) { elog("System include extraction: end marker missing: {0}", Output); return {}; diff --git a/clang-tools-extra/clangd/test/system-include-extractor.test b/clang-tools-extra/clangd/test/system-include-extractor.test index 8f99db9122a6..9f1a3de48bc5 100644 --- a/clang-tools-extra/clangd/test/system-include-extractor.test +++ b/clang-tools-extra/clangd/test/system-include-extractor.test @@ -8,7 +8,7 @@ # RUN: echo 'echo -e "#include <...> search starts here:\r" >&2' >> %t.dir/my_driver.sh # RUN: echo 'echo %t.dir/my/dir/ >&2' >> %t.dir/my_driver.sh # RUN: echo 'echo %t.dir/my/dir2/ >&2' >> %t.dir/my_driver.sh -# RUN: echo 'echo End of search list. >&2' >> %t.dir/my_driver.sh +# RUN: echo 'echo -e "End of search list.\r" >&2' >> %t.dir/my_driver.sh # RUN: chmod +x %t.dir/my_driver.sh # Create header files my/dir/a.h and my/dir2/b.h From 64dfe8807f6f26c1957e1548b8dd85f03be4347a Mon Sep 17 00:00:00 2001 From: Martin Storsjo Date: Thu, 1 Aug 2019 20:43:59 +0000 Subject: [PATCH 058/289] Update release notes for things I've done since the last release llvm-svn: 367609 --- llvm/docs/ReleaseNotes.rst | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst index e1481f9f1389..37a3c9f4b39e 100644 --- a/llvm/docs/ReleaseNotes.rst +++ b/llvm/docs/ReleaseNotes.rst @@ -49,6 +49,9 @@ Non-comprehensive list of changes in this release ``EP_FullLinkTimeOptimizationLast`` are available for plugins to specialize the legacy pass manager full LTO pipeline. +* **llvm-objcopy/llvm-strip** got support for COFF object files/executables, + supporting the most common copying/stripping options. + .. NOTE If you would like to document a larger change, then you can add a subsection about it right here. You can copy the following boilerplate @@ -127,7 +130,7 @@ Changes to the SystemZ Target Changes to the X86 Target ------------------------- - During this release ... +* Fixed a bug in generating DWARF unwind information for 32 bit MinGW Changes to the AMDGPU Target ----------------------------- From 7f1bcc1770abb337cfb82d53d1c4f7ec6ab7d290 Mon Sep 17 00:00:00 2001 From: Martin Storsjo Date: Thu, 1 Aug 2019 20:44:45 +0000 Subject: [PATCH 059/289] Update release notes for things I've done since the last release llvm-svn: 367610 --- clang/docs/ReleaseNotes.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index c94868a39ed4..425fbfcb445b 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -102,6 +102,12 @@ Windows Support ``clang-cl /diagnostic:caret /c test.cc`` for example now produces ``clang: error: no such file or directory: '/diagnostic:caret'; did you mean '/diagnostics:caret'?`` +- The ``-print-search-dirs`` option now separates elements with semicolons, + as is the norm for path lists on Windows + +- Improved handling of dllexport in conjunction with explicit template + instantiations for MinGW, to allow building a shared libc++ for MinGW + without ``--export-all-symbols`` to override the dllexport attributes C Language Changes in Clang From b359686b8dbcde0ce625e060b263d3d13c05a631 Mon Sep 17 00:00:00 2001 From: Martin Storsjo Date: Thu, 1 Aug 2019 20:45:27 +0000 Subject: [PATCH 060/289] Update release notes for things I've done since the last release llvm-svn: 367611 --- lld/docs/ReleaseNotes.rst | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/lld/docs/ReleaseNotes.rst b/lld/docs/ReleaseNotes.rst index 76207fec11ac..bccef8165f82 100644 --- a/lld/docs/ReleaseNotes.rst +++ b/lld/docs/ReleaseNotes.rst @@ -53,6 +53,14 @@ COFF Improvements * Several speed and memory usage improvements. +* Range extension thunks are now created for ARM64, if needed + +* lld-link now supports resource object files created by GNU windres and + MS cvtres, not only llvm-cvtres + +* The generated thunks for delayimports now share the majority of code + among thunks, significantly reducing the overhead of using delayimport + * ... MinGW Improvements @@ -62,6 +70,17 @@ MinGW Improvements terminators for the sections such as .eh_frame properly, fixing DWARF exception handling with libgcc and gcc's crtend.o. +* lld now also handles DWARF unwind info generated by GCC, when linking + with libgcc + +* Many more GNU ld options are now supported, which e.g. allows the lld + MinGW frontend to be called by GCC + +* PDB output can be requested without manually specifying the PDB file + name, with the new option ``-pdb=`` with an empty value to the option. + (The old existing syntax ``-pdb `` was more cumbersome to use + with an empty parameter value.) + MachO Improvements ------------------ From 18de8ea36f73bf9f522becb7897b1b67579ee302 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Fri, 2 Aug 2019 13:39:28 +0000 Subject: [PATCH 061/289] Merging r367530: ------------------------------------------------------------------------ r367530 | ibiryukov | 2019-08-01 11:10:37 +0200 (Thu, 01 Aug 2019) | 17 lines [Preprocessor] Always discard body of #define if we failed to parse it Summary: Preivously we would only discard it if we failed to parse parameter lists. If we do not consume the body, parser sees tokens inside directive. In turn, this leads to spurious diagnostics and a crash in TokenBuffer, see the added tests. Reviewers: sammccall Reviewed By: sammccall Subscribers: cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D65517 ------------------------------------------------------------------------ llvm-svn: 367681 --- clang/lib/Lex/PPDirectives.cpp | 14 +++++++++----- clang/test/Preprocessor/stringize_skipped.c | 5 +++++ clang/unittests/Tooling/Syntax/TokensTest.cpp | 15 +++++++++++++++ 3 files changed, 29 insertions(+), 5 deletions(-) create mode 100644 clang/test/Preprocessor/stringize_skipped.c diff --git a/clang/lib/Lex/PPDirectives.cpp b/clang/lib/Lex/PPDirectives.cpp index 2756042f23eb..5658f46c99de 100644 --- a/clang/lib/Lex/PPDirectives.cpp +++ b/clang/lib/Lex/PPDirectives.cpp @@ -33,6 +33,7 @@ #include "clang/Lex/Token.h" #include "clang/Lex/VariadicMacroSupport.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/ScopeExit.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/STLExtras.h" @@ -2399,6 +2400,13 @@ MacroInfo *Preprocessor::ReadOptionalMacroParameterListAndBody( Token Tok; LexUnexpandedToken(Tok); + // Ensure we consume the rest of the macro body if errors occur. + auto _ = llvm::make_scope_exit([&]() { + // The flag indicates if we are still waiting for 'eod'. + if (CurLexer->ParsingPreprocessorDirective) + DiscardUntilEndOfDirective(); + }); + // Used to un-poison and then re-poison identifiers of the __VA_ARGS__ ilk // within their appropriate context. VariadicMacroScopeGuard VariadicMacroScopeGuard(*this); @@ -2420,12 +2428,8 @@ MacroInfo *Preprocessor::ReadOptionalMacroParameterListAndBody( } else if (Tok.is(tok::l_paren)) { // This is a function-like macro definition. Read the argument list. MI->setIsFunctionLike(); - if (ReadMacroParameterList(MI, LastTok)) { - // Throw away the rest of the line. - if (CurPPLexer->ParsingPreprocessorDirective) - DiscardUntilEndOfDirective(); + if (ReadMacroParameterList(MI, LastTok)) return nullptr; - } // If this is a definition of an ISO C/C++ variadic function-like macro (not // using the GNU named varargs extension) inform our variadic scope guard diff --git a/clang/test/Preprocessor/stringize_skipped.c b/clang/test/Preprocessor/stringize_skipped.c new file mode 100644 index 000000000000..e9395fbbb4b3 --- /dev/null +++ b/clang/test/Preprocessor/stringize_skipped.c @@ -0,0 +1,5 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// Ensure we see the error from PP and do not see errors from the parser. + +// expected-error@+1{{'#' is not followed by a macro parameter}} +#define INVALID() #B 10+10 diff --git a/clang/unittests/Tooling/Syntax/TokensTest.cpp b/clang/unittests/Tooling/Syntax/TokensTest.cpp index 24adba28a294..a1398bd55688 100644 --- a/clang/unittests/Tooling/Syntax/TokensTest.cpp +++ b/clang/unittests/Tooling/Syntax/TokensTest.cpp @@ -298,6 +298,21 @@ file './input.cpp' spelled tokens: no mappings. +)"}, + // Should not crash on errors inside '#define' directives. Error is that + // stringification (#B) does not refer to a macro parameter. + { + R"cpp( +a +#define MACRO() A #B +)cpp", + R"(expanded tokens: + a +file './input.cpp' + spelled tokens: + a # define MACRO ( ) A # B + mappings: + ['#'_1, ''_9) => [''_1, ''_1) )"}}; for (auto &Test : TestCases) EXPECT_EQ(collectAndDump(Test.first), Test.second) From 7750339a6609b863d55678291430a4cc13c0d2a3 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Mon, 5 Aug 2019 07:27:39 +0000 Subject: [PATCH 062/289] Merging r367520: ------------------------------------------------------------------------ r367520 | hans | 2019-08-01 10:01:09 +0200 (Thu, 01 Aug 2019) | 15 lines Delay emitting dllexport explicitly defaulted members until the class is fully parsed (PR40006) This is similar to r245139, but that only addressed dllexported classes. It was still possible to run into the same problem with dllexported members in an otherwise normal class (see bug). This uses the same strategy to fix: delay defining the method until the whole class has been parsed. (The easiest way to see the ordering problem is in Parser::ParseCXXMemberSpecification(): it calls ParseLexedMemberInitializers() *after* ActOnFinishCXXMemberDecls(), which was trying to define the dllexport method. Now we delay it to ActOnFinishCXXNonNestedClass() which is called after both of those.) Differential revision: https://reviews.llvm.org/D65511 ------------------------------------------------------------------------ llvm-svn: 367804 --- clang/include/clang/Sema/Sema.h | 1 + clang/lib/Sema/Sema.cpp | 1 + clang/lib/Sema/SemaDeclCXX.cpp | 13 +++++++++++-- clang/test/CodeGenCXX/dllexport.cpp | 9 +++++++++ 4 files changed, 22 insertions(+), 2 deletions(-) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index af762f74d745..e6c63fd9c015 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -11165,6 +11165,7 @@ class Sema { // Emitting members of dllexported classes is delayed until the class // (including field initializers) is fully parsed. SmallVector DelayedDllExportClasses; + SmallVector DelayedDllExportMemberFunctions; private: class SavePendingParsedClassStateRAII { diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index 11fed28b52db..485d39e2c9e8 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -961,6 +961,7 @@ void Sema::ActOnEndOfTranslationUnit() { // All dllexport classes should have been processed already. assert(DelayedDllExportClasses.empty()); + assert(DelayedDllExportMemberFunctions.empty()); // Remove file scoped decls that turned out to be used. UnusedFileScopedDecls.erase( diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 9a6385f28319..3d4c7fc3e056 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -6165,8 +6165,8 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) { M->dropAttr(); if (M->hasAttr()) { - DefineImplicitSpecialMember(*this, M, M->getLocation()); - ActOnFinishInlineFunctionDef(M); + // Define after any fields with in-class initializers have been parsed. + DelayedDllExportMemberFunctions.push_back(M); } } }; @@ -11419,6 +11419,15 @@ void Sema::ActOnFinishCXXMemberDecls() { void Sema::ActOnFinishCXXNonNestedClass(Decl *D) { referenceDLLExportedClassMethods(); + + if (!DelayedDllExportMemberFunctions.empty()) { + SmallVector WorkList; + std::swap(DelayedDllExportMemberFunctions, WorkList); + for (CXXMethodDecl *M : WorkList) { + DefineImplicitSpecialMember(*this, M, M->getLocation()); + ActOnFinishInlineFunctionDef(M); + } + } } void Sema::referenceDLLExportedClassMethods() { diff --git a/clang/test/CodeGenCXX/dllexport.cpp b/clang/test/CodeGenCXX/dllexport.cpp index 16cfb8465845..5d4523f2ea61 100644 --- a/clang/test/CodeGenCXX/dllexport.cpp +++ b/clang/test/CodeGenCXX/dllexport.cpp @@ -851,6 +851,15 @@ struct __declspec(dllexport) Baz { // Baz's operator=, causing instantiation of Foo after which // ActOnFinishCXXNonNestedClass is called, and we would bite our own tail. // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc dereferenceable(1) %"struct.InClassInits::Baz"* @"??4Baz@InClassInits@@QAEAAU01@ABU01@@Z" + +// Trying to define the explicitly defaulted ctor must be delayed until the +// in-class initializer for x has been processed. +struct PR40006 { + __declspec(dllexport) PR40006() = default; + int x = 42; +}; +// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc %"struct.InClassInits::PR40006"* @"??0PR40006@InClassInits@@QAE@XZ" + } // We had an issue where instantiating A would force emission of B's delayed From 8aaba9f96bced4c70cc3ec81cd8de0e3416391af Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Mon, 5 Aug 2019 07:31:33 +0000 Subject: [PATCH 063/289] Merging r367661: ------------------------------------------------------------------------ r367661 | hans | 2019-08-02 09:51:41 +0200 (Fri, 02 Aug 2019) | 5 lines Don't try emitting dllexported explicitly defaulted non-trivial ctors twice during explicit template instantiation definition (PR42857) Trying to emit the definition twice triggers an assert. Differential revision: https://reviews.llvm.org/D65579 ------------------------------------------------------------------------ llvm-svn: 367805 --- clang/lib/Sema/SemaDeclCXX.cpp | 8 +++++++- clang/test/CodeGenCXX/dllexport.cpp | 7 +++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 3d4c7fc3e056..2ffb0b4892a1 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -11425,7 +11425,13 @@ void Sema::ActOnFinishCXXNonNestedClass(Decl *D) { std::swap(DelayedDllExportMemberFunctions, WorkList); for (CXXMethodDecl *M : WorkList) { DefineImplicitSpecialMember(*this, M, M->getLocation()); - ActOnFinishInlineFunctionDef(M); + + // Pass the method to the consumer to get emitted. This is not necessary + // for explicit instantiation definitions, as they will get emitted + // anyway. + if (M->getParent()->getTemplateSpecializationKind() != + TSK_ExplicitInstantiationDefinition) + ActOnFinishInlineFunctionDef(M); } } } diff --git a/clang/test/CodeGenCXX/dllexport.cpp b/clang/test/CodeGenCXX/dllexport.cpp index 5d4523f2ea61..59ba6d854883 100644 --- a/clang/test/CodeGenCXX/dllexport.cpp +++ b/clang/test/CodeGenCXX/dllexport.cpp @@ -860,6 +860,13 @@ struct PR40006 { }; // M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc %"struct.InClassInits::PR40006"* @"??0PR40006@InClassInits@@QAE@XZ" +// PR42857: Clang would try to emit the non-trivial explicitly defaulted +// dllexport ctor twice when doing an explicit instantiation definition. +struct Qux { Qux(); }; +template struct PR42857 { __declspec(dllexport) PR42857() = default; Qux q; }; +template struct PR42857; +// M32-DAG: define weak_odr dso_local dllexport x86_thiscallcc %"struct.InClassInits::PR42857"* @"??0?$PR42857@H@InClassInits@@QAE@XZ" + } // We had an issue where instantiating A would force emission of B's delayed From 6c8e44e84a8510f94eb636a0cf50fad2c89da0e3 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Mon, 5 Aug 2019 07:35:49 +0000 Subject: [PATCH 064/289] Merge r367599 - [COFF] Fix wholearchive with thin archives (PR42388, D65565) llvm-svn: 367806 --- lld/COFF/Driver.cpp | 4 +++- lld/test/COFF/Inputs/mangled-symbol.s | 9 ++++++++ lld/test/COFF/thin-archive.s | 32 +++++++++++++++++++++++++++ 3 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 lld/test/COFF/Inputs/mangled-symbol.s create mode 100644 lld/test/COFF/thin-archive.s diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp index d7af50b9318f..7214d12bde8a 100644 --- a/lld/COFF/Driver.cpp +++ b/lld/COFF/Driver.cpp @@ -184,8 +184,10 @@ void LinkerDriver::addBuffer(std::unique_ptr mb, if (wholeArchive) { std::unique_ptr file = CHECK(Archive::create(mbref), filename + ": failed to parse archive"); + Archive *archive = file.get(); + make>(std::move(file)); // take ownership - for (MemoryBufferRef m : getArchiveMembers(file.get())) + for (MemoryBufferRef m : getArchiveMembers(archive)) addArchiveBuffer(m, "", filename, 0); return; } diff --git a/lld/test/COFF/Inputs/mangled-symbol.s b/lld/test/COFF/Inputs/mangled-symbol.s new file mode 100644 index 000000000000..d393236768ed --- /dev/null +++ b/lld/test/COFF/Inputs/mangled-symbol.s @@ -0,0 +1,9 @@ + .text + + .def "?f@@YAHXZ" + .scl 2 + .type 32 + .endef + .global "?f@@YAHXZ" +"?f@@YAHXZ": + retq $0 diff --git a/lld/test/COFF/thin-archive.s b/lld/test/COFF/thin-archive.s new file mode 100644 index 000000000000..f24911de401a --- /dev/null +++ b/lld/test/COFF/thin-archive.s @@ -0,0 +1,32 @@ +# REQUIRES: x86 + +# RUN: llvm-mc -filetype=obj -triple=x86_64-windows-msvc -o %t.main.obj %s + +# RUN: llvm-mc -filetype=obj -triple=x86_64-windows-msvc -o %t.lib.obj \ +# RUN: %S/Inputs/mangled-symbol.s +# RUN: lld-link /lib /out:%t.lib %t.lib.obj +# RUN: lld-link /lib /llvmlibthin /out:%t_thin.lib %t.lib.obj + +# RUN: lld-link /entry:main %t.main.obj %t.lib /out:%t.exe 2>&1 | \ +# RUN: FileCheck --allow-empty %s +# RUN: lld-link /entry:main %t.main.obj %t_thin.lib /out:%t.exe 2>&1 | \ +# RUN: FileCheck --allow-empty %s +# RUN: lld-link /entry:main %t.main.obj /wholearchive:%t_thin.lib /out:%t.exe 2>&1 | \ +# RUN: FileCheck --allow-empty %s + +# RUN: rm %t.lib.obj +# RUN: lld-link /entry:main %t.main.obj %t.lib /out:%t.exe 2>&1 | \ +# RUN: FileCheck --allow-empty %s + +# CHECK-NOT: error: could not get the buffer for the member defining + + .text + + .def main + .scl 2 + .type 32 + .endef + .global main +main: + call "?f@@YAHXZ" + retq $0 From 1475909e282a421e5cf6915dfe5d56a56b1ba612 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Mon, 5 Aug 2019 07:43:25 +0000 Subject: [PATCH 065/289] Merging r367687: ------------------------------------------------------------------------ r367687 | ibiryukov | 2019-08-02 17:23:04 +0200 (Fri, 02 Aug 2019) | 16 lines [clangd] Fix a crash when presenting values for Hover Summary: We should pass the expression type, not a variable type when printing the resulting value. Variable type may be different from what the pretty-printing function expects, e.g. have references. Reviewers: sammccall Reviewed By: sammccall Subscribers: MaskRay, jkorous, arphaman, kadircet, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D65655 ------------------------------------------------------------------------ llvm-svn: 367807 --- clang-tools-extra/clangd/XRefs.cpp | 2 +- clang-tools-extra/clangd/unittests/XRefsTests.cpp | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/clang-tools-extra/clangd/XRefs.cpp b/clang-tools-extra/clangd/XRefs.cpp index 6339f8643f74..77c975870c01 100644 --- a/clang-tools-extra/clangd/XRefs.cpp +++ b/clang-tools-extra/clangd/XRefs.cpp @@ -716,7 +716,7 @@ static HoverInfo getHoverContents(const Decl *D, const SymbolIndex *Index) { HI.Value.emplace(); llvm::raw_string_ostream ValueOS(*HI.Value); Result.Val.printPretty(ValueOS, const_cast(Ctx), - Var->getType()); + Init->getType()); } } } diff --git a/clang-tools-extra/clangd/unittests/XRefsTests.cpp b/clang-tools-extra/clangd/unittests/XRefsTests.cpp index 3439bc7d15d3..4a95a9935f2f 100644 --- a/clang-tools-extra/clangd/unittests/XRefsTests.cpp +++ b/clang-tools-extra/clangd/unittests/XRefsTests.cpp @@ -1793,6 +1793,16 @@ TEST(Hover, All) { "int\n" "]", }, + { + R"cpp(// Should not crash when evaluating the initializer. + struct Test {}; + void test() { Test && te^st = {}; } + )cpp", + "text[Declared in]code[test]\n" + "codeblock(cpp) [\n" + "struct Test &&test = {}\n" + "]", + }, }; // Create a tiny index, so tests above can verify documentation is fetched. From 4e21661a8c9c9fc4f154a8c74d2536de05af00eb Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Mon, 5 Aug 2019 07:49:21 +0000 Subject: [PATCH 066/289] Merging r367753: ------------------------------------------------------------------------ r367753 | nikic | 2019-08-03 08:47:23 +0200 (Sat, 03 Aug 2019) | 12 lines [Thumb] Fix invalid symbol redefinition due to duplicated jumptable (PR42760) Fix for https://bugs.llvm.org/show_bug.cgi?id=42760. A tBR_JTr instruction is duplicated by tail duplication, which results in the same jumptable with the same label being emitted twice. Fix this by marking tBR_JTr as not duplicable. The corresponding ARM/Thumb instructions are already marked as not duplicable. Additionally also mark tTBB_JT and tTBH_JT to be consistent with Thumb2, even though this shouldn't be strictly necessary. Differential Revision: https://reviews.llvm.org/D65606 ------------------------------------------------------------------------ llvm-svn: 367808 --- llvm/lib/Target/ARM/ARMInstrThumb.td | 3 +- llvm/test/CodeGen/Thumb/pr42760.ll | 56 ++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 llvm/test/CodeGen/Thumb/pr42760.ll diff --git a/llvm/lib/Target/ARM/ARMInstrThumb.td b/llvm/lib/Target/ARM/ARMInstrThumb.td index cfeb13c6acb6..fa266c41080c 100644 --- a/llvm/lib/Target/ARM/ARMInstrThumb.td +++ b/llvm/lib/Target/ARM/ARMInstrThumb.td @@ -592,6 +592,7 @@ let isBranch = 1, isTerminator = 1, isBarrier = 1 in { [(ARMbrjt tGPR:$target, tjumptable:$jt)]>, Sched<[WriteBrTbl]> { let Size = 2; + let isNotDuplicable = 1; list Predicates = [IsThumb, IsThumb1Only]; } } @@ -1465,7 +1466,7 @@ def tLEApcrelJT : tPseudoInst<(outs tGPR:$Rd), // Thumb-1 doesn't have the TBB or TBH instructions, but we can synthesize them // and make use of the same compressed jump table format as Thumb-2. let Size = 2, isBranch = 1, isTerminator = 1, isBarrier = 1, - isIndirectBranch = 1 in { + isIndirectBranch = 1, isNotDuplicable = 1 in { def tTBB_JT : tPseudoInst<(outs), (ins tGPRwithpc:$base, tGPR:$index, i32imm:$jt, i32imm:$pclbl), 0, IIC_Br, []>, Sched<[WriteBr]>; diff --git a/llvm/test/CodeGen/Thumb/pr42760.ll b/llvm/test/CodeGen/Thumb/pr42760.ll new file mode 100644 index 000000000000..fc9a18bb3342 --- /dev/null +++ b/llvm/test/CodeGen/Thumb/pr42760.ll @@ -0,0 +1,56 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=thumbv6m-none-unknown-eabi -tail-dup-placement-threshold=3 < %s | FileCheck %s + +define hidden void @test() { +; CHECK-LABEL: test: +; CHECK: @ %bb.0: @ %entry +; CHECK-NEXT: movs r0, #1 +; CHECK-NEXT: lsls r1, r0, #2 +; CHECK-NEXT: b .LBB0_2 +; CHECK-NEXT: .LBB0_1: @ %bb2 +; CHECK-NEXT: @ in Loop: Header=BB0_2 Depth=1 +; CHECK-NEXT: cmp r0, #0 +; CHECK-NEXT: bne .LBB0_6 +; CHECK-NEXT: .LBB0_2: @ %switch +; CHECK-NEXT: @ =>This Inner Loop Header: Depth=1 +; CHECK-NEXT: adr r2, .LJTI0_0 +; CHECK-NEXT: ldr r2, [r2, r1] +; CHECK-NEXT: mov pc, r2 +; CHECK-NEXT: @ %bb.3: +; CHECK-NEXT: .p2align 2 +; CHECK-NEXT: .LJTI0_0: +; CHECK-NEXT: .long .LBB0_6+1 +; CHECK-NEXT: .long .LBB0_4+1 +; CHECK-NEXT: .long .LBB0_6+1 +; CHECK-NEXT: .long .LBB0_5+1 +; CHECK-NEXT: .LBB0_4: @ %switch +; CHECK-NEXT: @ in Loop: Header=BB0_2 Depth=1 +; CHECK-NEXT: b .LBB0_1 +; CHECK-NEXT: .LBB0_5: @ %bb +; CHECK-NEXT: @ in Loop: Header=BB0_2 Depth=1 +; CHECK-NEXT: cmp r0, #0 +; CHECK-NEXT: beq .LBB0_1 +; CHECK-NEXT: .LBB0_6: @ %dead +entry: + br label %switch + +switch: ; preds = %bb2, %entry + switch i32 undef, label %dead2 [ + i32 0, label %dead + i32 1, label %bb2 + i32 2, label %dead + i32 3, label %bb + ] + +dead: ; preds = %bb2, %bb, %switch, %switch + unreachable + +dead2: ; preds = %switch + unreachable + +bb: ; preds = %switch + br i1 undef, label %dead, label %bb2 + +bb2: ; preds = %bb, %switch + br i1 undef, label %dead, label %switch +} From 9d9021d8d6d77281b249d496afc949bec5edf1fa Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Mon, 5 Aug 2019 08:10:53 +0000 Subject: [PATCH 067/289] Merging r366868: ------------------------------------------------------------------------ r366868 | rogfer01 | 2019-07-24 07:33:46 +0200 (Wed, 24 Jul 2019) | 6 lines [RISCV] Implement benchmark::cycleclock::Now This is a cherrypick of D64237 onto llvm/utils/benchmark and libcxx/utils/google-benchmark. Differential Revision: https://reviews.llvm.org/D65142 ------------------------------------------------------------------------ llvm-svn: 367810 --- llvm/utils/benchmark/README.LLVM | 2 ++ llvm/utils/benchmark/src/cycleclock.h | 15 +++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/llvm/utils/benchmark/README.LLVM b/llvm/utils/benchmark/README.LLVM index c493ff4f5c64..d2aa87e86e79 100644 --- a/llvm/utils/benchmark/README.LLVM +++ b/llvm/utils/benchmark/README.LLVM @@ -23,3 +23,5 @@ Changes: is applied to disable exceptions in Microsoft STL when exceptions are disabled * Disabled CMake get_git_version as it is meaningless for this in-tree build, and hardcoded a null version +* https://github.com/google/benchmark/commit/4abdfbb802d1b514703223f5f852ce4a507d32d2 + is applied on top of v1.4.1 to add RISC-V timer support. diff --git a/llvm/utils/benchmark/src/cycleclock.h b/llvm/utils/benchmark/src/cycleclock.h index e1f18cc64d20..7b54b2530378 100644 --- a/llvm/utils/benchmark/src/cycleclock.h +++ b/llvm/utils/benchmark/src/cycleclock.h @@ -164,6 +164,21 @@ inline BENCHMARK_ALWAYS_INLINE int64_t Now() { uint64_t tsc; asm("stck %0" : "=Q" (tsc) : : "cc"); return tsc; +#elif defined(__riscv) // RISC-V + // Use RDCYCLE (and RDCYCLEH on riscv32) +#if __riscv_xlen == 32 + uint64_t cycles_low, cycles_hi0, cycles_hi1; + asm("rdcycleh %0" : "=r"(cycles_hi0)); + asm("rdcycle %0" : "=r"(cycles_lo)); + asm("rdcycleh %0" : "=r"(cycles_hi1)); + // This matches the PowerPC overflow detection, above + cycles_lo &= -static_cast(cycles_hi0 == cycles_hi1); + return (cycles_hi1 << 32) | cycles_lo; +#else + uint64_t cycles; + asm("rdcycle %0" : "=r"(cycles)); + return cycles; +#endif #else // The soft failover to a generic implementation is automatic only for ARM. // For other platforms the developer is expected to make an attempt to create From d4bdcb45a7d6dbfd362ed079ec44fb34a2ffb08c Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Mon, 5 Aug 2019 08:14:21 +0000 Subject: [PATCH 068/289] Merging r366868: ------------------------------------------------------------------------ r366868 | rogfer01 | 2019-07-24 07:33:46 +0200 (Wed, 24 Jul 2019) | 6 lines [RISCV] Implement benchmark::cycleclock::Now This is a cherrypick of D64237 onto llvm/utils/benchmark and libcxx/utils/google-benchmark. Differential Revision: https://reviews.llvm.org/D65142 ------------------------------------------------------------------------ llvm-svn: 367813 --- libcxx/utils/google-benchmark/README.LLVM | 6 ++++++ libcxx/utils/google-benchmark/src/cycleclock.h | 15 +++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/libcxx/utils/google-benchmark/README.LLVM b/libcxx/utils/google-benchmark/README.LLVM index e51e2571bf62..6b81ddf873a8 100644 --- a/libcxx/utils/google-benchmark/README.LLVM +++ b/libcxx/utils/google-benchmark/README.LLVM @@ -4,3 +4,9 @@ LLVM notes This directory contains the Google Benchmark source code with some unnecessary files removed. Note that this directory is under a different license than libc++. + +Changes: +* https://github.com/google/benchmark/commit/4abdfbb802d1b514703223f5f852ce4a507d32d2 + is applied on top of + https://github.com/google/benchmark/commit/4528c76b718acc9b57956f63069c699ae21edcab + to add RISC-V timer support. diff --git a/libcxx/utils/google-benchmark/src/cycleclock.h b/libcxx/utils/google-benchmark/src/cycleclock.h index f5e37b011b9f..d5d62c4c7fe1 100644 --- a/libcxx/utils/google-benchmark/src/cycleclock.h +++ b/libcxx/utils/google-benchmark/src/cycleclock.h @@ -164,6 +164,21 @@ inline BENCHMARK_ALWAYS_INLINE int64_t Now() { uint64_t tsc; asm("stck %0" : "=Q"(tsc) : : "cc"); return tsc; +#elif defined(__riscv) // RISC-V + // Use RDCYCLE (and RDCYCLEH on riscv32) +#if __riscv_xlen == 32 + uint64_t cycles_low, cycles_hi0, cycles_hi1; + asm("rdcycleh %0" : "=r"(cycles_hi0)); + asm("rdcycle %0" : "=r"(cycles_lo)); + asm("rdcycleh %0" : "=r"(cycles_hi1)); + // This matches the PowerPC overflow detection, above + cycles_lo &= -static_cast(cycles_hi0 == cycles_hi1); + return (cycles_hi1 << 32) | cycles_lo; +#else + uint64_t cycles; + asm("rdcycle %0" : "=r"(cycles)); + return cycles; +#endif #else // The soft failover to a generic implementation is automatic only for ARM. // For other platforms the developer is expected to make an attempt to create From 6fb930d55aefa467a81fcc424088af50d3a6afc3 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Mon, 5 Aug 2019 09:02:29 +0000 Subject: [PATCH 069/289] Merging r367662: ------------------------------------------------------------------------ r367662 | psmith | 2019-08-02 10:05:14 +0200 (Fri, 02 Aug 2019) | 17 lines [AliasAnalysis] Initialize a member variable that may be used by unit test. The unit tests in BasicAliasAnalysisTest use the alias analysis API directly and do not call setAAResults to initalize AAR. This gives a valgrind error "Conditional Jump depends on unitialized variable". On most buildbots the variable is nullptr, but in some cases it can be non nullptr leading to seemingly random failures. These tests were disabled in r366986. With the initialization they can be enabled again. Fixes PR42719 Differential Revision: https://reviews.llvm.org/D65568 ------------------------------------------------------------------------ llvm-svn: 367818 --- llvm/include/llvm/Analysis/AliasAnalysis.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/include/llvm/Analysis/AliasAnalysis.h b/llvm/include/llvm/Analysis/AliasAnalysis.h index 948341554f23..282142f51bb3 100644 --- a/llvm/include/llvm/Analysis/AliasAnalysis.h +++ b/llvm/include/llvm/Analysis/AliasAnalysis.h @@ -949,7 +949,7 @@ template class AAResultBase { /// A pointer to the AAResults object that this AAResult is /// aggregated within. May be null if not aggregated. - AAResults *AAR; + AAResults *AAR = nullptr; /// Helper to dispatch calls back through the derived type. DerivedT &derived() { return static_cast(*this); } From fa658316f63d59b099ccbe8605e23d2a7acea02c Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Mon, 5 Aug 2019 13:10:20 +0000 Subject: [PATCH 070/289] Merging r367846 and r367847: ------------------------------------------------------------------------ r367846 | hans | 2019-08-05 15:04:07 +0200 (Mon, 05 Aug 2019) | 1 line Write the RequiredLibraries for 'all' in LibraryDependencies.inc in a deterministic order (PR42739) ------------------------------------------------------------------------ ------------------------------------------------------------------------ r367847 | hans | 2019-08-05 15:04:12 +0200 (Mon, 05 Aug 2019) | 8 lines test-release.sh: Perform the sed substitution on both files (PR42739) The comparison would otherwise fail if Phase2 occurrs naturally in the object file. It would get replaced with Phase3 in the one .o, but not in the other. We were already running both files through sed to have them processed in this same way; this is a logical extension of that. ------------------------------------------------------------------------ llvm-svn: 367848 --- llvm/utils/llvm-build/llvmbuild/main.py | 2 +- llvm/utils/release/test-release.sh | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/llvm/utils/llvm-build/llvmbuild/main.py b/llvm/utils/llvm-build/llvmbuild/main.py index 9a9726424d40..99b82ad5e20c 100644 --- a/llvm/utils/llvm-build/llvmbuild/main.py +++ b/llvm/utils/llvm-build/llvmbuild/main.py @@ -359,7 +359,7 @@ def write_library_table(self, output_path, enabled_optional_components): root_entries = set(e[0] for e in entries) for _,_,deps,_ in entries: root_entries -= set(deps) - entries.append(('all', None, root_entries, True)) + entries.append(('all', None, sorted(root_entries), True)) entries.sort() diff --git a/llvm/utils/release/test-release.sh b/llvm/utils/release/test-release.sh index 558e01d2eabc..031687f6e4ba 100755 --- a/llvm/utils/release/test-release.sh +++ b/llvm/utils/release/test-release.sh @@ -591,11 +591,12 @@ for Flavor in $Flavors ; do for p2 in `find $llvmCore_phase2_objdir -name '*.o'` ; do p3=`echo $p2 | sed -e 's,Phase2,Phase3,'` # Substitute 'Phase2' for 'Phase3' in the Phase 2 object file in - # case there are build paths in the debug info. On some systems, - # sed adds a newline to the output, so pass $p3 through sed too. + # case there are build paths in the debug info. Do the same sub- + # stitution on both files in case the string occurrs naturally. if ! cmp -s \ <(env LC_CTYPE=C sed -e 's,Phase2,Phase3,g' -e 's,Phase1,Phase2,g' $p2) \ - <(env LC_CTYPE=C sed -e '' $p3) 16 16; then + <(env LC_CTYPE=C sed -e 's,Phase2,Phase3,g' -e 's,Phase1,Phase2,g' $p3) \ + 16 16; then echo "file `basename $p2` differs between phase 2 and phase 3" fi done From a4972dc5568114b170ae2ad3da4eb3e277376b0f Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Tue, 6 Aug 2019 07:47:52 +0000 Subject: [PATCH 071/289] Merging r367836: ------------------------------------------------------------------------ r367836 | mstorsjo | 2019-08-05 13:57:00 +0200 (Mon, 05 Aug 2019) | 17 lines [COFF] Omit automatically imported symbols from the symbol table These symbols actually point to the symbol's IAT entry, which obviously is different from the symbol itself (which is imported from a different module and doesn't exist in the current one). Omitting this symbol helps gdb inspect automatically imported symbols, see https://sourceware.org/bugzilla/show_bug.cgi?id=24574 for discussion on the matter. Surprisingly, those extra symbols don't seem to be an issue for gdb when the sources have been built with clang, only with gcc. The actual logic in gdb that this depends on still is unknown, but omitting these symbols from the symbol table is the right thing to do in any case. Differential Revision: https://reviews.llvm.org/D65727 ------------------------------------------------------------------------ llvm-svn: 367986 --- lld/COFF/Writer.cpp | 7 +++++++ lld/test/COFF/autoimport-gnu-implib.s | 7 ++++++- lld/test/COFF/autoimport-x86.s | 9 +++++++-- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp index 3da8b98d3d22..cc75db0f519c 100644 --- a/lld/COFF/Writer.cpp +++ b/lld/COFF/Writer.cpp @@ -1095,6 +1095,13 @@ Optional Writer::createSymbol(Defined *def) { } } + // Symbols that are runtime pseudo relocations don't point to the actual + // symbol data itself (as they are imported), but points to the IAT entry + // instead. Avoid emitting them to the symbol table, as they can confuse + // debuggers. + if (def->isRuntimePseudoReloc) + return None; + StringRef name = def->getName(); if (name.size() > COFF::NameSize) { sym.Name.Offset.Zeroes = 0; diff --git a/lld/test/COFF/autoimport-gnu-implib.s b/lld/test/COFF/autoimport-gnu-implib.s index e6e0ed207c0b..d7d4ed626e83 100644 --- a/lld/test/COFF/autoimport-gnu-implib.s +++ b/lld/test/COFF/autoimport-gnu-implib.s @@ -7,9 +7,10 @@ # RUN: llvm-ar rcs %t-implib.a %t-dabcdh.o %t-dabcds00000.o %t-dabcdt.o # RUN: llvm-mc -triple=x86_64-windows-gnu %s -filetype=obj -o %t.obj -# RUN: lld-link -lldmingw -out:%t.exe -entry:main %t.obj %t-implib.a -verbose +# RUN: lld-link -lldmingw -debug:symtab -out:%t.exe -entry:main %t.obj %t-implib.a -verbose # RUN: llvm-readobj --coff-imports %t.exe | FileCheck -check-prefix=IMPORTS %s +# RUN: llvm-nm %t.exe | FileCheck -check-prefix=SYMBOLS %s # IMPORTS: Import { # IMPORTS-NEXT: Name: foo.dll @@ -18,6 +19,10 @@ # IMPORTS-NEXT: Symbol: data (0) # IMPORTS-NEXT: } +# Check that the automatically imported symbol "data" is not listed in +# the symbol table. +# SYMBOLS-NOT: {{ }}data + .global main .text main: diff --git a/lld/test/COFF/autoimport-x86.s b/lld/test/COFF/autoimport-x86.s index 400cec71173e..9e0ae1ead189 100644 --- a/lld/test/COFF/autoimport-x86.s +++ b/lld/test/COFF/autoimport-x86.s @@ -5,11 +5,12 @@ # RUN: lld-link -out:%t-lib.dll -dll -entry:DllMainCRTStartup %t-lib.obj -lldmingw -implib:%t-lib.lib # RUN: llvm-mc -triple=x86_64-windows-gnu %s -filetype=obj -o %t.obj -# RUN: lld-link -lldmingw -out:%t.exe -entry:main %t.obj %t-lib.lib -verbose +# RUN: lld-link -lldmingw -debug:symtab -out:%t.exe -entry:main %t.obj %t-lib.lib -verbose # RUN: llvm-readobj --coff-imports %t.exe | FileCheck -check-prefix=IMPORTS %s # RUN: llvm-objdump -d %t.exe | FileCheck -check-prefix=DISASM %s # RUN: llvm-objdump -s %t.exe | FileCheck -check-prefix=CONTENTS %s +# RUN: llvm-nm %t.exe | FileCheck -check-prefix=SYMBOLS %s # IMPORTS: Import { # IMPORTS-NEXT: Name: autoimport-x86.s.tmp-lib.dll @@ -20,7 +21,7 @@ # DISASM: Disassembly of section .text: # DISASM-EMPTY: -# DISASM: .text: +# DISASM: main: # Relative offset at 0x1002 pointing at the IAT at 0x2080. # DISASM: 140001000: 8b 05 7a 10 00 00 movl 4218(%rip), %eax # DISASM: 140001006: c3 retq @@ -41,6 +42,10 @@ # CONTENTS: 140003000 80200040 01000000 00200040 01000000 # CONTENTS: 140003010 24200040 01000000 +# Check that the automatically imported symbol "variable" is not listed in +# the symbol table. +# SYMBOLS-NOT: variable + .global main .text main: From af8b0746d5e1cebac934c6e02ef76c41f0415c08 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Tue, 6 Aug 2019 07:59:51 +0000 Subject: [PATCH 072/289] Merging r367675 and r367823: ------------------------------------------------------------------------ r367675 | stulova | 2019-08-02 13:19:35 +0200 (Fri, 02 Aug 2019) | 10 lines [OpenCL] Allow OpenCL C style vector initialization in C++ Allow creating vector literals from other vectors. float4 a = (float4)(1.0f, 2.0f, 3.0f, 4.0f); float4 v = (float4)(a.s23, a.s01); Differential revision: https://reviews.llvm.org/D65286 ------------------------------------------------------------------------ ------------------------------------------------------------------------ r367823 | stulova | 2019-08-05 11:50:28 +0200 (Mon, 05 Aug 2019) | 6 lines [OpenCL] Fix vector literal test broken in rL367675. Avoid checking alignment unnecessary that is not portable among targets. ------------------------------------------------------------------------ llvm-svn: 367987 --- clang/lib/Sema/SemaInit.cpp | 14 +++- .../CodeGenOpenCL/vector_literals_nested.cl | 23 ------ .../CodeGenOpenCL/vector_literals_valid.cl | 75 +++++++++++++++---- clang/test/SemaCXX/vector.cpp | 8 ++ .../test/SemaOpenCL/vector_literals_const.cl | 27 ------- 5 files changed, 78 insertions(+), 69 deletions(-) delete mode 100644 clang/test/CodeGenOpenCL/vector_literals_nested.cl delete mode 100644 clang/test/SemaOpenCL/vector_literals_const.cl diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index bc1069609336..85af4bc492ce 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -1289,7 +1289,16 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity, // FIXME: Better EqualLoc? InitializationKind Kind = InitializationKind::CreateCopy(expr->getBeginLoc(), SourceLocation()); - InitializationSequence Seq(SemaRef, Entity, Kind, expr, + + // Vector elements can be initialized from other vectors in which case + // we need initialization entity with a type of a vector (and not a vector + // element!) initializing multiple vector elements. + auto TmpEntity = + (ElemType->isExtVectorType() && !Entity.getType()->isExtVectorType()) + ? InitializedEntity::InitializeTemporary(ElemType) + : Entity; + + InitializationSequence Seq(SemaRef, TmpEntity, Kind, expr, /*TopLevelOfInitList*/ true); // C++14 [dcl.init.aggr]p13: @@ -1300,8 +1309,7 @@ void InitListChecker::CheckSubElementType(const InitializedEntity &Entity, // assignment-expression. if (Seq || isa(expr)) { if (!VerifyOnly) { - ExprResult Result = - Seq.Perform(SemaRef, Entity, Kind, expr); + ExprResult Result = Seq.Perform(SemaRef, TmpEntity, Kind, expr); if (Result.isInvalid()) hadError = true; diff --git a/clang/test/CodeGenOpenCL/vector_literals_nested.cl b/clang/test/CodeGenOpenCL/vector_literals_nested.cl deleted file mode 100644 index b9013d0482f9..000000000000 --- a/clang/test/CodeGenOpenCL/vector_literals_nested.cl +++ /dev/null @@ -1,23 +0,0 @@ -// RUN: %clang_cc1 %s -emit-llvm -O3 -o - | FileCheck %s - -typedef int int2 __attribute((ext_vector_type(2))); -typedef int int4 __attribute((ext_vector_type(4))); - -__constant const int4 itest1 = (int4)(1, 2, ((int2)(3, 4))); -// CHECK: constant <4 x i32> -__constant const int4 itest2 = (int4)(1, 2, ((int2)(3))); -// CHECK: constant <4 x i32> - -typedef float float2 __attribute((ext_vector_type(2))); -typedef float float4 __attribute((ext_vector_type(4))); - -void ftest1(float4 *p) { - *p = (float4)(1.1f, 1.2f, ((float2)(1.3f, 1.4f))); -// CHECK: store <4 x float> -} - -float4 ftest2(float4 *p) { - *p = (float4)(1.1f, 1.2f, ((float2)(1.3f))); -// CHECK: store <4 x float> -} - diff --git a/clang/test/CodeGenOpenCL/vector_literals_valid.cl b/clang/test/CodeGenOpenCL/vector_literals_valid.cl index bba5b23e23bd..249c95cd756d 100644 --- a/clang/test/CodeGenOpenCL/vector_literals_valid.cl +++ b/clang/test/CodeGenOpenCL/vector_literals_valid.cl @@ -1,22 +1,65 @@ -// RUN: %clang_cc1 -emit-llvm %s -o %t +// RUN: %clang_cc1 -emit-llvm %s -o - -O0 | FileCheck %s +// RUN: %clang_cc1 -emit-llvm %s -o - -cl-std=clc++ -O0 | FileCheck %s -typedef __attribute__(( ext_vector_type(2) )) int int2; -typedef __attribute__(( ext_vector_type(3) )) int int3; -typedef __attribute__(( ext_vector_type(4) )) int int4; -typedef __attribute__(( ext_vector_type(8) )) int int8; -typedef __attribute__(( ext_vector_type(4) )) float float4; +typedef __attribute__((ext_vector_type(2))) int int2; +typedef __attribute__((ext_vector_type(3))) int int3; +typedef __attribute__((ext_vector_type(4))) int int4; +typedef __attribute__((ext_vector_type(8))) int int8; +typedef __attribute__((ext_vector_type(4))) float float4; + +__constant const int4 c1 = (int4)(1, 2, ((int2)(3))); +// CHECK: constant <4 x i32> + +__constant const int4 c2 = (int4)(1, 2, ((int2)(3, 4))); +// CHECK: constant <4 x i32> void vector_literals_valid() { - int4 a_1_1_1_1 = (int4)(1,2,3,4); - int4 a_2_1_1 = (int4)((int2)(1,2),3,4); - int4 a_1_2_1 = (int4)(1,(int2)(2,3),4); - int4 a_1_1_2 = (int4)(1,2,(int2)(3,4)); - int4 a_2_2 = (int4)((int2)(1,2),(int2)(3,4)); - int4 a_3_1 = (int4)((int3)(1,2,3),4); - int4 a_1_3 = (int4)(1,(int3)(2,3,4)); + //CHECK: insertelement <4 x i32> , i32 %{{.+}}, i32 2 + //CHECK: insertelement <4 x i32> %{{.+}}, i32 %{{.+}}, i32 3 + int4 a_1_1_1_1 = (int4)(1, 2, c1.s2, c2.s3); + + //CHECK: store <2 x i32> , <2 x i32>* + //CHECK: shufflevector <2 x i32> %{{[0-9]+}}, <2 x i32> undef, <4 x i32> + //CHECK: shufflevector <4 x i32> %{{.+}}, <4 x i32> undef, <4 x i32> + //CHECK: insertelement <4 x i32> %{{.+}}, i32 3, i32 2 + //CHECK: insertelement <4 x i32> %{{.+}}, i32 4, i32 3 + int4 a_2_1_1 = (int4)((int2)(1, 2), 3, 4); + + //CHECK: store <2 x i32> , <2 x i32>* + //CHECK: shufflevector <2 x i32> %{{[0-9]+}}, <2 x i32> undef, <4 x i32> + //CHECK: shufflevector <4 x i32> , <4 x i32> %{{.+}}, <4 x i32> + //CHECK: insertelement <4 x i32> %{{.+}}, i32 4, i32 3 + int4 a_1_2_1 = (int4)(1, (int2)(2, 3), 4); + + //CHECK: store <2 x i32> , <2 x i32>* + //CHECK: shufflevector <2 x i32> %{{[0-9]+}}, <2 x i32> undef, <4 x i32> + //CHECK: shufflevector <4 x i32> , <4 x i32> %{{.+}}, <4 x i32> + int4 a_1_1_2 = (int4)(1, 2, (int2)(3, 4)); + + //CHECK: store <2 x i32> , <2 x i32>* + //CHECK: shufflevector <2 x i32> %{{[0-9]+}}, <2 x i32> undef, <4 x i32> + //CHECK: shufflevector <4 x i32> %{{.+}}, <4 x i32> undef, <4 x i32> + //CHECK: shufflevector <4 x i32> %{{.+}}, <4 x i32> , <4 x i32> + int4 a_2_2 = (int4)((int2)(1, 2), (int2)(3)); + + //CHECK: store <4 x i32> , <4 x i32>* + //CHECK: shufflevector <4 x i32> %{{.+}}, <4 x i32> undef, <3 x i32> + //CHECK: shufflevector <3 x i32> %{{.+}}, <3 x i32> undef, <4 x i32> + //CHECK: shufflevector <4 x i32> , <4 x i32> %{{.+}}, <4 x i32> + int4 a_1_3 = (int4)(1, (int3)(2, 3, 4)); + + //CHECK: store <4 x i32> , <4 x i32>* %a int4 a = (int4)(1); - int8 b = (int8)(1,2,a.xy,a); - float4 V2 = (float4) (1); -} + //CHECK: load <4 x i32>, <4 x i32>* %a + //CHECK: shufflevector <4 x i32> %{{[0-9]+}}, <4 x i32> undef, <2 x i32> + //CHECK: shufflevector <2 x i32> %{{[0-9]+}}, <2 x i32> undef, <8 x i32> + //CHECK: shufflevector <8 x i32> , <8 x i32> %{{.+}}, <8 x i32> + //CHECK: load <4 x i32>, <4 x i32>* %a + //CHECK: shufflevector <4 x i32> %{{[0-9]+}}, <4 x i32> undef, <8 x i32> + //CHECK: shufflevector <8 x i32> %{{.+}}, <8 x i32> %{{.+}}, <8 x i32> + int8 b = (int8)(1, 2, a.xy, a); + //CHECK: store <4 x float> , <4 x float>* %V2 + float4 V2 = (float4)(1); +} diff --git a/clang/test/SemaCXX/vector.cpp b/clang/test/SemaCXX/vector.cpp index a6a4ceb0e535..40dcd35c1bb6 100644 --- a/clang/test/SemaCXX/vector.cpp +++ b/clang/test/SemaCXX/vector.cpp @@ -334,3 +334,11 @@ void Init() { } } // namespace Templates + +typedef int inte2 __attribute__((__ext_vector_type__(2))); + +void test_vector_literal(inte4 res) { + inte2 a = (inte2)(1, 2); //expected-warning{{expression result unused}} + inte4 b = (inte4)(a, a); //expected-error{{C-style cast from vector 'inte2' (vector of 2 'int' values) to vector 'inte4' (vector of 4 'int' values) of different size}} //expected-warning{{expression result unused}} +} + diff --git a/clang/test/SemaOpenCL/vector_literals_const.cl b/clang/test/SemaOpenCL/vector_literals_const.cl deleted file mode 100644 index ee5ae2002a3c..000000000000 --- a/clang/test/SemaOpenCL/vector_literals_const.cl +++ /dev/null @@ -1,27 +0,0 @@ -// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -// expected-no-diagnostics - -typedef int int2 __attribute((ext_vector_type(2))); -typedef int int3 __attribute((ext_vector_type(3))); -typedef int int4 __attribute((ext_vector_type(4))); - -__constant int4 i_1_1_1_1 = (int4)(1,2,3,4); -__constant int4 i_2_1_1 = (int4)((int2)(1,2),3,4); -__constant int4 i_1_2_1 = (int4)(1,(int2)(2,3),4); -__constant int4 i_1_1_2 = (int4)(1,2,(int2)(3,4)); -__constant int4 i_2_2 = (int4)((int2)(1,2),(int2)(3,4)); -__constant int4 i_3_1 = (int4)((int3)(1,2,3),4); -__constant int4 i_1_3 = (int4)(1,(int3)(2,3,4)); - -typedef float float2 __attribute((ext_vector_type(2))); -typedef float float3 __attribute((ext_vector_type(3))); -typedef float float4 __attribute((ext_vector_type(4))); - -__constant float4 f_1_1_1_1 = (float4)(1,2,3,4); -__constant float4 f_2_1_1 = (float4)((float2)(1,2),3,4); -__constant float4 f_1_2_1 = (float4)(1,(float2)(2,3),4); -__constant float4 f_1_1_2 = (float4)(1,2,(float2)(3,4)); -__constant float4 f_2_2 = (float4)((float2)(1,2),(float2)(3,4)); -__constant float4 f_3_1 = (float4)((float3)(1,2,3),4); -__constant float4 f_1_3 = (float4)(1,(float3)(2,3,4)); - From 4445e5fbe1855dcdbb091b4ffd0bf763d6bc0dc8 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Tue, 6 Aug 2019 08:08:11 +0000 Subject: [PATCH 073/289] Merging r366660 and r367306: ------------------------------------------------------------------------ r366660 | rksimon | 2019-07-21 21:04:44 +0200 (Sun, 21 Jul 2019) | 3 lines [X86] SimplifyDemandedVectorEltsForTargetNode - Move SUBV_BROADCAST narrowing handling. NFCI. Move the narrowing of SUBV_BROADCAST to where we handle all the other opcodes. ------------------------------------------------------------------------ ------------------------------------------------------------------------ r367306 | rksimon | 2019-07-30 13:35:13 +0200 (Tue, 30 Jul 2019) | 5 lines [X86][AVX] SimplifyDemandedVectorElts - handle extraction from X86ISD::SUBV_BROADCAST source (PR42819) PR42819 showed an issue that we couldn't handle the case where we demanded a 'sub-sub-vector' of the SUBV_BROADCAST 'sub-vector' source. This patch recognizes these cases and extracts the sub-sub-vector instead of trying to broadcast to a type smaller than the 'sub-vector' source. ------------------------------------------------------------------------ llvm-svn: 367991 --- llvm/lib/Target/X86/X86ISelLowering.cpp | 34 +++++++++++-------------- llvm/test/CodeGen/X86/oddsubvector.ll | 32 +++++++++++++++++++++++ 2 files changed, 47 insertions(+), 19 deletions(-) diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index 0b4bf687e6cf..a03ce7988580 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -34062,25 +34062,6 @@ bool X86TargetLowering::SimplifyDemandedVectorEltsForTargetNode( return true; break; } - case X86ISD::SUBV_BROADCAST: { - // Reduce size of broadcast if we don't need the upper half. - unsigned HalfElts = NumElts / 2; - if (DemandedElts.extractBits(HalfElts, HalfElts).isNullValue()) { - SDValue Src = Op.getOperand(0); - MVT SrcVT = Src.getSimpleValueType(); - - SDValue Half = Src; - if (SrcVT.getVectorNumElements() != HalfElts) { - MVT HalfVT = MVT::getVectorVT(SrcVT.getScalarType(), HalfElts); - Half = TLO.DAG.getNode(X86ISD::SUBV_BROADCAST, SDLoc(Op), HalfVT, Src); - } - - return TLO.CombineTo(Op, insertSubVector(TLO.DAG.getUNDEF(VT), Half, 0, - TLO.DAG, SDLoc(Op), - Half.getValueSizeInBits())); - } - break; - } case X86ISD::VPERMV: { SDValue Mask = Op.getOperand(0); APInt MaskUndef, MaskZero; @@ -34134,6 +34115,21 @@ bool X86TargetLowering::SimplifyDemandedVectorEltsForTargetNode( SDValue Insert = insertSubVector(UndefVec, ExtOp, 0, TLO.DAG, DL, ExtSizeInBits); return TLO.CombineTo(Op, Insert); + } + // Subvector broadcast. + case X86ISD::SUBV_BROADCAST: { + SDLoc DL(Op); + SDValue Src = Op.getOperand(0); + if (Src.getValueSizeInBits() > ExtSizeInBits) + Src = extractSubVector(Src, 0, TLO.DAG, DL, ExtSizeInBits); + else if (Src.getValueSizeInBits() < ExtSizeInBits) { + MVT SrcSVT = Src.getSimpleValueType().getScalarType(); + MVT SrcVT = + MVT::getVectorVT(SrcSVT, ExtSizeInBits / SrcSVT.getSizeInBits()); + Src = TLO.DAG.getNode(X86ISD::SUBV_BROADCAST, DL, SrcVT, Src); + } + return TLO.CombineTo(Op, insertSubVector(TLO.DAG.getUNDEF(VT), Src, 0, + TLO.DAG, DL, ExtSizeInBits)); } // Byte shifts by immediate. case X86ISD::VSHLDQ: diff --git a/llvm/test/CodeGen/X86/oddsubvector.ll b/llvm/test/CodeGen/X86/oddsubvector.ll index 9bc6c0f380a0..bb384e118dca 100644 --- a/llvm/test/CodeGen/X86/oddsubvector.ll +++ b/llvm/test/CodeGen/X86/oddsubvector.ll @@ -158,3 +158,35 @@ define void @PR40815(%struct.Mat4* nocapture readonly dereferenceable(64), %stru store <4 x float> %5, <4 x float>* %13, align 16 ret void } + +define <16 x i32> @PR42819(<8 x i32>* %a0) { +; SSE-LABEL: PR42819: +; SSE: # %bb.0: +; SSE-NEXT: movdqu (%rdi), %xmm3 +; SSE-NEXT: pslldq {{.*#+}} xmm3 = zero,zero,zero,zero,xmm3[0,1,2,3,4,5,6,7,8,9,10,11] +; SSE-NEXT: xorps %xmm0, %xmm0 +; SSE-NEXT: xorps %xmm1, %xmm1 +; SSE-NEXT: xorps %xmm2, %xmm2 +; SSE-NEXT: retq +; +; AVX-LABEL: PR42819: +; AVX: # %bb.0: +; AVX-NEXT: vpermilps {{.*#+}} xmm0 = mem[0,0,1,2] +; AVX-NEXT: vinsertf128 $1, %xmm0, %ymm0, %ymm0 +; AVX-NEXT: vxorps %xmm1, %xmm1, %xmm1 +; AVX-NEXT: vblendps {{.*#+}} ymm1 = ymm1[0,1,2,3,4],ymm0[5,6,7] +; AVX-NEXT: vxorps %xmm0, %xmm0, %xmm0 +; AVX-NEXT: retq +; +; AVX512-LABEL: PR42819: +; AVX512: # %bb.0: +; AVX512-NEXT: vmovdqu (%rdi), %xmm0 +; AVX512-NEXT: movw $-8192, %ax # imm = 0xE000 +; AVX512-NEXT: kmovw %eax, %k1 +; AVX512-NEXT: vpexpandd %zmm0, %zmm0 {%k1} {z} +; AVX512-NEXT: retq + %1 = load <8 x i32>, <8 x i32>* %a0, align 4 + %2 = shufflevector <8 x i32> %1, <8 x i32> undef, <16 x i32> + %3 = shufflevector <16 x i32> zeroinitializer, <16 x i32> %2, <16 x i32> + ret <16 x i32> %3 +} From 7bfdcec8561b4737e15a1fb30a3c3586b9d7807a Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Tue, 6 Aug 2019 08:11:14 +0000 Subject: [PATCH 074/289] lit: Bump version to 0.9.0 llvm-svn: 367992 --- llvm/utils/lit/lit/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/utils/lit/lit/__init__.py b/llvm/utils/lit/lit/__init__.py index 0d849d16f076..8c4586ccbc4d 100644 --- a/llvm/utils/lit/lit/__init__.py +++ b/llvm/utils/lit/lit/__init__.py @@ -2,7 +2,7 @@ __author__ = 'Daniel Dunbar' __email__ = 'daniel@minormatter.com' -__versioninfo__ = (0, 8, 0) +__versioninfo__ = (0, 9, 0) __version__ = '.'.join(str(v) for v in __versioninfo__) + 'dev' __all__ = [] From df0dd0366ff935ceb5e5d9bad2f2d711298ae761 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Tue, 6 Aug 2019 08:18:29 +0000 Subject: [PATCH 075/289] Merge r367730 for PR42812 > [lit] Fix 42812: lit test suite can no longer be run stand-alone > > Summary: > This change updates the lit.cfg file to use llvm_config when it is available, but when it is not, it directly modifies the config object. This makes it possible to run the lit tests standalone without having built llvm (as long as the correct binaries are present in the path such as FileCheck and not). > > Because the lit tests don't take a hard dependency on llvm_config, some features such as system-windows have to have definitions in lit's cfg file as well. This is a potential issue as the os features sometimes change names (for example, we went from windows to system-windows, etc.). This can cause drift between lit's tests and the rest of the llvm tests. > > Reviewers: probinson, mgorny > > Reviewed By: mgorny > > Subscribers: delcypher, llvm-commits, asmith > > Tags: #llvm > > Differential Revision: https://reviews.llvm.org/D65674 llvm-svn: 367993 --- llvm/utils/lit/tests/lit.cfg | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/llvm/utils/lit/tests/lit.cfg b/llvm/utils/lit/tests/lit.cfg index 4648b1bfc9c3..56670323474d 100644 --- a/llvm/utils/lit/tests/lit.cfg +++ b/llvm/utils/lit/tests/lit.cfg @@ -35,9 +35,13 @@ else: lit_path = os.path.join(config.test_source_root, '..') # Required because some tests import the lit module -llvm_config.with_environment('PYTHONPATH', lit_path, append_path=True) +if llvm_config: + llvm_config.with_environment('PYTHONPATH', lit_path, append_path=True) +else: + config.environment['PYTHONPATH'] = os.pathsep.join([lit_path]) # Add llvm and lit tools directories if this config is being loaded indirectly. +# In this case, we can also expect llvm_config to have been imported correctly. for attribute in ('llvm_tools_dir', 'lit_tools_dir'): directory = getattr(config, attribute, None) if directory: @@ -63,3 +67,10 @@ try: except ImportError: lit_config.warning('Could not import psutil. Some tests will be skipped and' ' the --timeout command line argument will not work.') + +# When running the lit tests standalone, we want to define the same features +# that the llvm_config defines. This means that the 'system-windows' feature +# (and any others) need to match the names in llvm_config for consistency +if not llvm_config: + if sys.platform.startswith('win') or sys.platform.startswith('cygwin'): + config.available_features.add('system-windows') From c3007c61b9ba4f4ccad967c72d099f828dd548c3 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Tue, 6 Aug 2019 08:22:46 +0000 Subject: [PATCH 076/289] Merging r367906: ------------------------------------------------------------------------ r367906 | jkorous | 2019-08-05 20:44:07 +0200 (Mon, 05 Aug 2019) | 5 lines [DirectoryWatcher][linux] Fix build for older kernels Apparently kernel support for IN_EXCL_UNLINK in inotify_add_watch() doesn't imply it's defined in sys/inotify.h. https://bugs.llvm.org/show_bug.cgi?id=42824 ------------------------------------------------------------------------ llvm-svn: 367995 --- clang/lib/DirectoryWatcher/linux/DirectoryWatcher-linux.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/clang/lib/DirectoryWatcher/linux/DirectoryWatcher-linux.cpp b/clang/lib/DirectoryWatcher/linux/DirectoryWatcher-linux.cpp index 6d7d69da4db5..1a66faeb3239 100644 --- a/clang/lib/DirectoryWatcher/linux/DirectoryWatcher-linux.cpp +++ b/clang/lib/DirectoryWatcher/linux/DirectoryWatcher-linux.cpp @@ -24,7 +24,6 @@ #include #include -#include #include #include #include @@ -335,7 +334,7 @@ std::unique_ptr clang::DirectoryWatcher::create( InotifyFD, Path.str().c_str(), IN_CREATE | IN_DELETE | IN_DELETE_SELF | IN_MODIFY | IN_MOVED_FROM | IN_MOVE_SELF | IN_MOVED_TO | IN_ONLYDIR | IN_IGNORED -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36) +#ifdef IN_EXCL_UNLINK | IN_EXCL_UNLINK #endif ); From a93571098f502e291d8c1c701262a171ce20db15 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Tue, 6 Aug 2019 08:26:06 +0000 Subject: [PATCH 077/289] Merging r367929: ------------------------------------------------------------------------ r367929 | echristo | 2019-08-05 23:25:59 +0200 (Mon, 05 Aug 2019) | 5 lines BMI2 support is indicated in bit eight of EBX, not nine. See Intel SDM, Vol 2A, Table 3-8: https://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-vol-2a-manual.pdf#page=296 Differential Revision: https://reviews.llvm.org/D65766 ------------------------------------------------------------------------ llvm-svn: 367996 --- compiler-rt/lib/builtins/cpu_model.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler-rt/lib/builtins/cpu_model.c b/compiler-rt/lib/builtins/cpu_model.c index f953aed959e5..940c5938fef5 100644 --- a/compiler-rt/lib/builtins/cpu_model.c +++ b/compiler-rt/lib/builtins/cpu_model.c @@ -543,7 +543,7 @@ static void getAvailableFeatures(unsigned ECX, unsigned EDX, unsigned MaxLeaf, setFeature(FEATURE_BMI); if (HasLeaf7 && ((EBX >> 5) & 1) && HasAVX) setFeature(FEATURE_AVX2); - if (HasLeaf7 && ((EBX >> 9) & 1)) + if (HasLeaf7 && ((EBX >> 8) & 1)) setFeature(FEATURE_BMI2); if (HasLeaf7 && ((EBX >> 16) & 1) && HasAVX512Save) setFeature(FEATURE_AVX512F); From 1b8baf20728852336082e73f30b86929f495888d Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Tue, 6 Aug 2019 08:30:56 +0000 Subject: [PATCH 078/289] Merging r367941: ------------------------------------------------------------------------ r367941 | reames | 2019-08-06 00:34:59 +0200 (Tue, 06 Aug 2019) | 5 lines Add a note to the release not about a potentially breaking optimization This has come up twice already (once in pr42763 and once in the commit thread), so give warning of a new way in which UB can result in unexpected program behavior. ------------------------------------------------------------------------ llvm-svn: 367997 --- llvm/docs/ReleaseNotes.rst | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst index 37a3c9f4b39e..67da442abbd5 100644 --- a/llvm/docs/ReleaseNotes.rst +++ b/llvm/docs/ReleaseNotes.rst @@ -62,6 +62,19 @@ Non-comprehensive list of changes in this release Makes programs 10x faster by doing Special New Thing. +Noteworthy optimizations +------------------------ + +* LLVM will now remove stores to constant memory (since this is a + contradiction) under the assumption the code in question must be dead. This + has proven to be problematic for some C/C++ code bases which expect to be + able to cast away 'const'. This is (and has always been) undefined + behavior, but up until now had not been actively utilized for optimization + purposes in this exact way. For more information, please see: + `bug 42763 _` and + `post commit discussion _`. + + Changes to the LLVM IR ---------------------- From a628617c561845f85799f1246124f190e21163d7 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Tue, 6 Aug 2019 09:30:53 +0000 Subject: [PATCH 079/289] Merging r368004: ------------------------------------------------------------------------ r368004 | hans | 2019-08-06 11:30:10 +0200 (Tue, 06 Aug 2019) | 1 line test-release.sh: Reorder sed commands for the binary comparison ------------------------------------------------------------------------ llvm-svn: 368005 --- llvm/utils/release/test-release.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llvm/utils/release/test-release.sh b/llvm/utils/release/test-release.sh index 031687f6e4ba..8f691ccfb87a 100755 --- a/llvm/utils/release/test-release.sh +++ b/llvm/utils/release/test-release.sh @@ -594,8 +594,8 @@ for Flavor in $Flavors ; do # case there are build paths in the debug info. Do the same sub- # stitution on both files in case the string occurrs naturally. if ! cmp -s \ - <(env LC_CTYPE=C sed -e 's,Phase2,Phase3,g' -e 's,Phase1,Phase2,g' $p2) \ - <(env LC_CTYPE=C sed -e 's,Phase2,Phase3,g' -e 's,Phase1,Phase2,g' $p3) \ + <(env LC_CTYPE=C sed -e 's,Phase1,Phase2,g' -e 's,Phase2,Phase3,g' $p2) \ + <(env LC_CTYPE=C sed -e 's,Phase1,Phase2,g' -e 's,Phase2,Phase3,g' $p3) \ 16 16; then echo "file `basename $p2` differs between phase 2 and phase 3" fi From 13c43456a9a81293549e292c31cd29e9aaa67ead Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Tue, 6 Aug 2019 11:04:11 +0000 Subject: [PATCH 080/289] Merging r367898: ------------------------------------------------------------------------ r367898 | evandro | 2019-08-05 20:09:14 +0200 (Mon, 05 Aug 2019) | 22 lines [AArch64] Expand bcmp() for small block lengths Patch D56593 by @courbet results in calls to `bcmp()` in some cases, should the target support the it. Unless `TTI::MemCmpExpansionOptions()` is overridden by the target. In a proprietary benchmark we see a performance drop of about 12% on PNG compression before this patch, though it passes all tests. This patch mirrors X86 for AArch64 and initializes `TTI::MemCmpExpansionOptions()` to then expand calls to `bcmp()` when appropriate. No tuning of the parameters was performed, but, at this point, it's enough to recover the performance drop above. This problem also exists on ARM. Once a consensus is reached for AArch64, we can work to fix ARM as well. Authors: - Evandro Menezes (@evandro) - Brian Rzycki (@brzycki) Differential revision: https://reviews.llvm.org/D64805 ------------------------------------------------------------------------ llvm-svn: 368017 --- .../Target/AArch64/AArch64ISelLowering.cpp | 4 ++ .../AArch64/AArch64TargetTransformInfo.cpp | 13 ++++++ .../AArch64/AArch64TargetTransformInfo.h | 3 ++ .../test/CodeGen/AArch64/bcmp-inline-small.ll | 44 +++++++++++++++++++ 4 files changed, 64 insertions(+) create mode 100644 llvm/test/CodeGen/AArch64/bcmp-inline-small.ll diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp index 7becc99fb5c7..816db6f919bf 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -606,6 +606,10 @@ AArch64TargetLowering::AArch64TargetLowering(const TargetMachine &TM, MaxStoresPerMemmoveOptSize = MaxStoresPerMemmove = 4; + MaxLoadsPerMemcmpOptSize = 4; + MaxLoadsPerMemcmp = Subtarget->requiresStrictAlign() + ? MaxLoadsPerMemcmpOptSize : 8; + setStackPointerRegisterToSaveRestore(AArch64::SP); setSchedulingPreference(Sched::Hybrid); diff --git a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp index a4b78f2a7d6b..301bf72d5239 100644 --- a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp +++ b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp @@ -618,6 +618,19 @@ int AArch64TTIImpl::getCmpSelInstrCost(unsigned Opcode, Type *ValTy, return BaseT::getCmpSelInstrCost(Opcode, ValTy, CondTy, I); } +AArch64TTIImpl::TTI::MemCmpExpansionOptions +AArch64TTIImpl::enableMemCmpExpansion(bool OptSize, bool IsZeroCmp) const { + TTI::MemCmpExpansionOptions Options; + Options.AllowOverlappingLoads = !ST->requiresStrictAlign(); + Options.MaxNumLoads = TLI->getMaxExpandSizeMemcmp(OptSize); + Options.NumLoadsPerBlock = Options.MaxNumLoads; + // TODO: Though vector loads usually perform well on AArch64, in some targets + // they may wake up the FP unit, which raises the power consumption. Perhaps + // they could be used with no holds barred (-O3). + Options.LoadSizes = {8, 4, 2, 1}; + return Options; +} + int AArch64TTIImpl::getMemoryOpCost(unsigned Opcode, Type *Ty, unsigned Alignment, unsigned AddressSpace, const Instruction *I) { diff --git a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.h b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.h index 10c15a139b4c..95cda63b0174 100644 --- a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.h +++ b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.h @@ -130,6 +130,9 @@ class AArch64TTIImpl : public BasicTTIImplBase { int getCmpSelInstrCost(unsigned Opcode, Type *ValTy, Type *CondTy, const Instruction *I = nullptr); + TTI::MemCmpExpansionOptions enableMemCmpExpansion(bool OptSize, + bool IsZeroCmp) const; + int getMemoryOpCost(unsigned Opcode, Type *Src, unsigned Alignment, unsigned AddressSpace, const Instruction *I = nullptr); diff --git a/llvm/test/CodeGen/AArch64/bcmp-inline-small.ll b/llvm/test/CodeGen/AArch64/bcmp-inline-small.ll new file mode 100644 index 000000000000..da42b1d6863c --- /dev/null +++ b/llvm/test/CodeGen/AArch64/bcmp-inline-small.ll @@ -0,0 +1,44 @@ +; RUN: llc -O2 < %s -mtriple=aarch64-linux-gnu | FileCheck %s --check-prefixes=CHECK,CHECKN +; RUN: llc -O2 < %s -mtriple=aarch64-linux-gnu -mattr=strict-align | FileCheck %s --check-prefixes=CHECK,CHECKS + +declare i32 @bcmp(i8*, i8*, i64) nounwind readonly +declare i32 @memcmp(i8*, i8*, i64) nounwind readonly + +define i1 @bcmp_b2(i8* %s1, i8* %s2) { +entry: + %bcmp = call i32 @bcmp(i8* %s1, i8* %s2, i64 15) + %ret = icmp eq i32 %bcmp, 0 + ret i1 %ret + +; CHECK-LABEL: bcmp_b2: +; CHECK-NOT: bl bcmp +; CHECKN: ldr x +; CHECKN-NEXT: ldr x +; CHECKN-NEXT: ldur x +; CHECKN-NEXT: ldur x +; CHECKS: ldr x +; CHECKS-NEXT: ldr x +; CHECKS-NEXT: ldr w +; CHECKS-NEXT: ldr w +; CHECKS-NEXT: ldrh w +; CHECKS-NEXT: ldrh w +; CHECKS-NEXT: ldrb w +; CHECKS-NEXT: ldrb w +} + +define i1 @bcmp_bs(i8* %s1, i8* %s2) optsize { +entry: + %memcmp = call i32 @memcmp(i8* %s1, i8* %s2, i64 31) + %ret = icmp eq i32 %memcmp, 0 + ret i1 %ret + +; CHECK-LABEL: bcmp_bs: +; CHECKN-NOT: bl memcmp +; CHECKN: ldp x +; CHECKN-NEXT: ldp x +; CHECKN-NEXT: ldr x +; CHECKN-NEXT: ldr x +; CHECKN-NEXT: ldur x +; CHECKN-NEXT: ldur x +; CHECKS: bl memcmp +} From 8df6d06f1e72dc31d63afd1dd5c415b7cb668c4d Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Wed, 7 Aug 2019 08:31:37 +0000 Subject: [PATCH 081/289] Merging r368019: ------------------------------------------------------------------------ r368019 | ibiryukov | 2019-08-06 13:37:50 +0200 (Tue, 06 Aug 2019) | 28 lines [clangd] Compute scopes eagerly in IncludeFixer Summary: Computing lazily leads to crashes. In particular, computing scopes may produce diagnostics (from inside template instantiations) and we currently do it when processing another diagnostic, which leads to crashes. Moreover, we remember and access 'Scope*' when computing scopes. This might lead to invalid memory access if the Scope is deleted by the time we run the delayed computation. We did not actually construct an example when this happens, though. From the VCS and review history, it seems the optimization was introduced in the initial version without a mention of any performance benchmarks justifying the performance gains. This led me to a conclusion that the optimization was premature, so removing it to avoid crashes seems like the right trade-off at that point. Reviewers: sammccall Reviewed By: sammccall Subscribers: MaskRay, jkorous, arphaman, kadircet, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D65796 ------------------------------------------------------------------------ llvm-svn: 368133 --- clang-tools-extra/clangd/IncludeFixer.cpp | 69 ++++++++++--------- clang-tools-extra/clangd/IncludeFixer.h | 4 +- .../clangd/unittests/DiagnosticsTests.cpp | 21 ++++++ 3 files changed, 57 insertions(+), 37 deletions(-) diff --git a/clang-tools-extra/clangd/IncludeFixer.cpp b/clang-tools-extra/clangd/IncludeFixer.cpp index edf86504d139..eb525f40e257 100644 --- a/clang-tools-extra/clangd/IncludeFixer.cpp +++ b/clang-tools-extra/clangd/IncludeFixer.cpp @@ -16,6 +16,7 @@ #include "index/Symbol.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclBase.h" +#include "clang/AST/DeclarationName.h" #include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/Type.h" #include "clang/Basic/Diagnostic.h" @@ -34,6 +35,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/None.h" #include "llvm/ADT/Optional.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSet.h" #include "llvm/Support/Error.h" @@ -301,6 +303,24 @@ llvm::Optional extractUnresolvedNameCheaply( return Result; } +/// Returns all namespace scopes that the unqualified lookup would visit. +std::vector +collectAccessibleScopes(Sema &Sem, const DeclarationNameInfo &Typo, Scope *S, + Sema::LookupNameKind LookupKind) { + std::vector Scopes; + VisitedContextCollector Collector; + Sem.LookupVisibleDecls(S, LookupKind, Collector, + /*IncludeGlobalScope=*/false, + /*LoadExternal=*/false); + + Scopes.push_back(""); + for (const auto *Ctx : Collector.takeVisitedContexts()) { + if (isa(Ctx)) + Scopes.push_back(printNamespaceScope(*Ctx)); + } + return Scopes; +} + class IncludeFixer::UnresolvedNameRecorder : public ExternalSemaSource { public: UnresolvedNameRecorder(llvm::Optional &LastUnresolvedName) @@ -321,48 +341,30 @@ class IncludeFixer::UnresolvedNameRecorder : public ExternalSemaSource { if (!SemaPtr->SourceMgr.isWrittenInMainFile(Typo.getLoc())) return clang::TypoCorrection(); - // This is not done lazily because `SS` can get out of scope and it's - // relatively cheap. auto Extracted = extractUnresolvedNameCheaply( SemaPtr->SourceMgr, Typo, SS, SemaPtr->LangOpts, static_cast(LookupKind) == Sema::LookupNameKind::LookupNestedNameSpecifierName); if (!Extracted) return TypoCorrection(); - auto CheapUnresolved = std::move(*Extracted); + UnresolvedName Unresolved; - Unresolved.Name = CheapUnresolved.Name; + Unresolved.Name = Extracted->Name; Unresolved.Loc = Typo.getBeginLoc(); - - if (!CheapUnresolved.ResolvedScope && !S) // Give up if no scope available. + if (!Extracted->ResolvedScope && !S) // Give up if no scope available. return TypoCorrection(); - auto *Sem = SemaPtr; // Avoid capturing `this`. - Unresolved.GetScopes = [Sem, CheapUnresolved, S, LookupKind]() { - std::vector Scopes; - if (CheapUnresolved.ResolvedScope) { - Scopes.push_back(*CheapUnresolved.ResolvedScope); - } else { - assert(S); - // No scope specifier is specified. Collect all accessible scopes in the - // context. - VisitedContextCollector Collector; - Sem->LookupVisibleDecls( - S, static_cast(LookupKind), Collector, - /*IncludeGlobalScope=*/false, - /*LoadExternal=*/false); - - Scopes.push_back(""); - for (const auto *Ctx : Collector.takeVisitedContexts()) - if (isa(Ctx)) - Scopes.push_back(printNamespaceScope(*Ctx)); - } + if (Extracted->ResolvedScope) + Unresolved.Scopes.push_back(*Extracted->ResolvedScope); + else // no qualifier or qualifier is unresolved. + Unresolved.Scopes = collectAccessibleScopes( + *SemaPtr, Typo, S, static_cast(LookupKind)); + + if (Extracted->UnresolvedScope) { + for (std::string &Scope : Unresolved.Scopes) + Scope += *Extracted->UnresolvedScope; + } - if (CheapUnresolved.UnresolvedScope) - for (auto &Scope : Scopes) - Scope.append(*CheapUnresolved.UnresolvedScope); - return Scopes; - }; LastUnresolvedName = std::move(Unresolved); // Never return a valid correction to try to recover. Our suggested fixes @@ -384,14 +386,13 @@ IncludeFixer::unresolvedNameRecorder() { std::vector IncludeFixer::fixUnresolvedName() const { assert(LastUnresolvedName.hasValue()); auto &Unresolved = *LastUnresolvedName; - std::vector Scopes = Unresolved.GetScopes(); vlog("Trying to fix unresolved name \"{0}\" in scopes: [{1}]", - Unresolved.Name, llvm::join(Scopes.begin(), Scopes.end(), ", ")); + Unresolved.Name, llvm::join(Unresolved.Scopes, ", ")); FuzzyFindRequest Req; Req.AnyScope = false; Req.Query = Unresolved.Name; - Req.Scopes = Scopes; + Req.Scopes = Unresolved.Scopes; Req.RestrictForCodeCompletion = true; Req.Limit = 100; diff --git a/clang-tools-extra/clangd/IncludeFixer.h b/clang-tools-extra/clangd/IncludeFixer.h index aafb384bfe9a..ba2a59fb3fb5 100644 --- a/clang-tools-extra/clangd/IncludeFixer.h +++ b/clang-tools-extra/clangd/IncludeFixer.h @@ -58,9 +58,7 @@ class IncludeFixer { struct UnresolvedName { std::string Name; // E.g. "X" in foo::X. SourceLocation Loc; // Start location of the unresolved name. - // Lazily get the possible scopes of the unresolved name. `Sema` must be - // alive when this is called. - std::function()> GetScopes; + std::vector Scopes; // Namespace scopes we should search in. }; /// Records the last unresolved name seen by Sema. diff --git a/clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp b/clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp index 71aa148d6b62..7cf0e277a5d4 100644 --- a/clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp +++ b/clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp @@ -797,6 +797,27 @@ namespace c { "Add include \"x.h\" for symbol a::X"))))); } +TEST(IncludeFixerTest, NoCrashOnTemplateInstantiations) { + Annotations Test(R"cpp( + template struct Templ { + template + typename U::type operator=(const U &); + }; + + struct A { + Templ s; + A() { [[a]]; } // this caused crashes if we compute scopes lazily. + }; + )cpp"); + + auto TU = TestTU::withCode(Test.code()); + auto Index = buildIndexWithSymbol({}); + TU.ExternalIndex = Index.get(); + + EXPECT_THAT(TU.build().getDiagnostics(), + ElementsAre(Diag(Test.range(), "use of undeclared identifier 'a'"))); +} + TEST(DiagsInHeaders, DiagInsideHeader) { Annotations Main(R"cpp( #include [["a.h"]] From 0d584eff89ce4b7aa2920cb2ff8eb26d1c26a756 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Wed, 7 Aug 2019 08:34:28 +0000 Subject: [PATCH 082/289] Merging r367837: ------------------------------------------------------------------------ r367837 | mstorsjo | 2019-08-05 13:57:06 +0200 (Mon, 05 Aug 2019) | 10 lines [MinGW] Add an lld specific option for requesting to delay load libraries With GNU tools, delayload is handled completely differently. (One creates a specific delayload import library using dlltool and then links against it instead of the normal import library.) Instead of requiring using -Xlink=-delayload:lib.dll, we can provide an lld specific option for this. Differential Revision: https://reviews.llvm.org/D65728 ------------------------------------------------------------------------ llvm-svn: 368134 --- lld/MinGW/Driver.cpp | 2 ++ lld/MinGW/Options.td | 2 ++ lld/test/MinGW/driver.test | 4 ++++ 3 files changed, 8 insertions(+) diff --git a/lld/MinGW/Driver.cpp b/lld/MinGW/Driver.cpp index 24e18aacb3c1..be1b757e45b5 100644 --- a/lld/MinGW/Driver.cpp +++ b/lld/MinGW/Driver.cpp @@ -303,6 +303,8 @@ bool mingw::link(ArrayRef argsArr, raw_ostream &diag) { add("-include:" + StringRef(a->getValue())); for (auto *a : args.filtered(OPT_undefined)) add("-includeoptional:" + StringRef(a->getValue())); + for (auto *a : args.filtered(OPT_delayload)) + add("-delayload:" + StringRef(a->getValue())); std::vector searchPaths; for (auto *a : args.filtered(OPT_L)) { diff --git a/lld/MinGW/Options.td b/lld/MinGW/Options.td index 44de98dfc90b..86400433d041 100644 --- a/lld/MinGW/Options.td +++ b/lld/MinGW/Options.td @@ -80,6 +80,8 @@ def require_defined_eq: J<"require-defined=">, Alias; def _HASH_HASH_HASH : Flag<["-"], "###">, HelpText<"Print (but do not run) the commands to run for this compilation">; def appcontainer: F<"appcontainer">, HelpText<"Set the appcontainer flag in the executable">; +def delayload: S<"delayload">, HelpText<"DLL to load only on demand">; +def delayload_eq: J<"delayload=">, Alias; def mllvm: S<"mllvm">; def pdb: S<"pdb">, HelpText<"Output PDB debug info file, chosen implicitly if the argument is empty">; def pdb_eq: J<"pdb=">, Alias; diff --git a/lld/test/MinGW/driver.test b/lld/test/MinGW/driver.test index cdd802e93f4d..b8bc2ddea8a3 100644 --- a/lld/test/MinGW/driver.test +++ b/lld/test/MinGW/driver.test @@ -200,3 +200,7 @@ APPCONTAINER: -appcontainer # RUN: ld.lld -m i386pep --help 2>&1 | FileCheck -check-prefix=HELP %s # HELP: USAGE: # HELP: --enable-auto-import + +RUN: ld.lld -### -m i386pep foo.o -delayload user32.dll --delayload shell32.dll | FileCheck -check-prefix DELAYLOAD %s +RUN: ld.lld -### -m i386pep foo.o -delayload=user32.dll --delayload=shell32.dll | FileCheck -check-prefix DELAYLOAD %s +DELAYLOAD: -delayload:user32.dll -delayload:shell32.dll From 1cda5aef2c7a5d7185f062b367b0623d554f0462 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Wed, 7 Aug 2019 08:51:54 +0000 Subject: [PATCH 083/289] Merging r368078: ------------------------------------------------------------------------ r368078 | quantum | 2019-08-06 22:09:04 +0200 (Tue, 06 Aug 2019) | 18 lines [WebAssembly] Fix null pointer in createInitTLSFunction Summary: `createSyntheticSymbols`, which creates `WasmSym::InitTLS`, is only called when `!config->relocatable`, but this condition is not checked when calling `createInitTLSFunction`. This diff checks `!config->relocatable` before calling `createInitTLSFunction`. Fixes https://github.com/emscripten-core/emscripten/issues/9155. Reviewers: tlively, aheejin, kripken, sbc100 Subscribers: dschuff, jgravelle-google, sunfish, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D65785 ------------------------------------------------------------------------ llvm-svn: 368137 --- lld/test/wasm/relocatable.ll | 360 ++++++++++++++++++----------------- lld/wasm/Writer.cpp | 2 +- 2 files changed, 186 insertions(+), 176 deletions(-) diff --git a/lld/test/wasm/relocatable.ll b/lld/test/wasm/relocatable.ll index 67f8ac0d8bec..097adca48456 100644 --- a/lld/test/wasm/relocatable.ll +++ b/lld/test/wasm/relocatable.ll @@ -1,7 +1,12 @@ ; RUN: llc -filetype=obj %p/Inputs/hello.ll -o %t.hello.o ; RUN: llc -filetype=obj %s -o %t.o ; RUN: wasm-ld -r -o %t.wasm %t.hello.o %t.o -; RUN: obj2yaml %t.wasm | FileCheck %s +; RUN: obj2yaml %t.wasm | FileCheck %s --check-prefixes CHECK,NORMAL + +; RUN: llc -filetype=obj %p/Inputs/hello.ll -o %t.hello.bm.o -mattr=+bulk-memory +; RUN: llc -filetype=obj %s -o %t.bm.o -mattr=+bulk-memory +; RUN: wasm-ld -r -o %t.mt.wasm %t.hello.bm.o %t.bm.o --shared-memory --max-memory=131072 +; RUN: obj2yaml %t.mt.wasm | FileCheck %s --check-prefixes CHECK,SHARED target triple = "wasm32-unknown-unknown" @@ -70,13 +75,18 @@ entry: ; CHECK-NEXT: Maximum: 0x00000004 ; CHECK-NEXT: - Type: MEMORY ; CHECK-NEXT: Memories: -; CHECK-NEXT: - Initial: 0x00000001 +; NORMAL-NEXT: - Initial: 0x00000001 +; SHARED-NEXT: - Flags: [ HAS_MAX, IS_SHARED ] +; SHARED-NEXT: Initial: 0x00000001 +; SHARED-NEXT: Maximum: 0x00000002 ; CHECK-NEXT: - Type: ELEM ; CHECK-NEXT: Segments: ; CHECK-NEXT: - Offset: ; CHECK-NEXT: Opcode: I32_CONST ; CHECK-NEXT: Value: 1 ; CHECK-NEXT: Functions: [ 4, 1, 2 ] +; SHARED-NEXT: - Type: DATACOUNT +; SHARED-NEXT: Count: 6 ; CHECK-NEXT: - Type: CODE ; CHECK-NEXT: Relocations: ; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_SLEB @@ -104,176 +114,176 @@ entry: ; CHECK-NEXT: - Index: 5 ; CHECK-NEXT: Locals: ; CHECK-NEXT: Body: 419C808080000B -; CHECK-NEXT: - Type: DATA -; CHECK-NEXT: Relocations: -; CHECK-NEXT: - Type: R_WASM_TABLE_INDEX_I32 -; CHECK-NEXT: Index: 3 -; CHECK-NEXT: Offset: 0x00000012 -; CHECK-NEXT: - Type: R_WASM_TABLE_INDEX_I32 -; CHECK-NEXT: Index: 4 -; CHECK-NEXT: Offset: 0x0000001B -; CHECK-NEXT: - Type: R_WASM_TABLE_INDEX_I32 -; CHECK-NEXT: Index: 5 -; CHECK-NEXT: Offset: 0x00000024 -; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_I32 -; CHECK-NEXT: Index: 12 -; CHECK-NEXT: Offset: 0x0000002D -; CHECK-NEXT: Segments: -; CHECK-NEXT: - SectionOffset: 6 -; CHECK-NEXT: InitFlags: 0 -; CHECK-NEXT: Offset: -; CHECK-NEXT: Opcode: I32_CONST -; CHECK-NEXT: Value: 0 -; CHECK-NEXT: Content: 68656C6C6F0A00 -; CHECK-NEXT: - SectionOffset: 18 -; CHECK-NEXT: InitFlags: 0 -; CHECK-NEXT: Offset: -; CHECK-NEXT: Opcode: I32_CONST -; CHECK-NEXT: Value: 8 -; CHECK-NEXT: Content: '01000000' -; CHECK-NEXT: - SectionOffset: 27 -; CHECK-NEXT: InitFlags: 0 -; CHECK-NEXT: Offset: -; CHECK-NEXT: Opcode: I32_CONST -; CHECK-NEXT: Value: 12 -; CHECK-NEXT: Content: '02000000' -; CHECK-NEXT: - SectionOffset: 36 -; CHECK-NEXT: InitFlags: 0 -; CHECK-NEXT: Offset: -; CHECK-NEXT: Opcode: I32_CONST -; CHECK-NEXT: Value: 16 -; CHECK-NEXT: Content: '03000000' -; CHECK-NEXT: - SectionOffset: 45 -; CHECK-NEXT: InitFlags: 0 -; CHECK-NEXT: Offset: -; CHECK-NEXT: Opcode: I32_CONST -; CHECK-NEXT: Value: 24 -; CHECK-NEXT: Content: '00000000' -; CHECK-NEXT: - SectionOffset: 54 -; CHECK-NEXT: InitFlags: 0 -; CHECK-NEXT: Offset: -; CHECK-NEXT: Opcode: I32_CONST -; CHECK-NEXT: Value: 28 -; CHECK-NEXT: Content: '616263' -; CHECK-NEXT: - Type: CUSTOM -; CHECK-NEXT: Name: linking -; CHECK-NEXT: Version: 2 -; CHECK-NEXT: SymbolTable: -; CHECK-NEXT: - Index: 0 -; CHECK-NEXT: Kind: FUNCTION -; CHECK-NEXT: Name: hello -; CHECK-NEXT: Flags: [ VISIBILITY_HIDDEN ] -; CHECK-NEXT: Function: 3 -; CHECK-NEXT: - Index: 1 -; CHECK-NEXT: Kind: DATA -; CHECK-NEXT: Name: hello_str -; CHECK-NEXT: Flags: [ ] -; CHECK-NEXT: Segment: 0 -; CHECK-NEXT: Size: 7 -; CHECK-NEXT: - Index: 2 -; CHECK-NEXT: Kind: FUNCTION -; CHECK-NEXT: Name: puts -; CHECK-NEXT: Flags: [ UNDEFINED ] -; CHECK-NEXT: Function: 0 -; CHECK-NEXT: - Index: 3 -; CHECK-NEXT: Kind: FUNCTION -; CHECK-NEXT: Name: my_func -; CHECK-NEXT: Flags: [ VISIBILITY_HIDDEN ] -; CHECK-NEXT: Function: 4 -; CHECK-NEXT: - Index: 4 -; CHECK-NEXT: Kind: FUNCTION -; CHECK-NEXT: Name: foo_import -; CHECK-NEXT: Flags: [ UNDEFINED ] -; CHECK-NEXT: Function: 1 -; CHECK-NEXT: - Index: 5 -; CHECK-NEXT: Kind: FUNCTION -; CHECK-NEXT: Name: bar_import -; CHECK-NEXT: Flags: [ BINDING_WEAK, UNDEFINED ] -; CHECK-NEXT: Function: 2 -; CHECK-NEXT: - Index: 6 -; CHECK-NEXT: Kind: FUNCTION -; CHECK-NEXT: Name: func_comdat -; CHECK-NEXT: Flags: [ BINDING_WEAK ] -; CHECK-NEXT: Function: 5 -; CHECK-NEXT: - Index: 7 -; CHECK-NEXT: Kind: DATA -; CHECK-NEXT: Name: data_comdat -; CHECK-NEXT: Flags: [ BINDING_WEAK ] -; CHECK-NEXT: Segment: 5 -; CHECK-NEXT: Size: 3 -; CHECK-NEXT: - Index: 8 -; CHECK-NEXT: Kind: DATA -; CHECK-NEXT: Name: func_addr1 -; CHECK-NEXT: Flags: [ VISIBILITY_HIDDEN ] -; CHECK-NEXT: Segment: 1 -; CHECK-NEXT: Size: 4 -; CHECK-NEXT: - Index: 9 -; CHECK-NEXT: Kind: DATA -; CHECK-NEXT: Name: func_addr2 -; CHECK-NEXT: Flags: [ VISIBILITY_HIDDEN ] -; CHECK-NEXT: Segment: 2 -; CHECK-NEXT: Size: 4 -; CHECK-NEXT: - Index: 10 -; CHECK-NEXT: Kind: DATA -; CHECK-NEXT: Name: func_addr3 -; CHECK-NEXT: Flags: [ VISIBILITY_HIDDEN ] -; CHECK-NEXT: Segment: 3 -; CHECK-NEXT: Size: 4 -; CHECK-NEXT: - Index: 11 -; CHECK-NEXT: Kind: DATA -; CHECK-NEXT: Name: data_addr1 -; CHECK-NEXT: Flags: [ VISIBILITY_HIDDEN ] -; CHECK-NEXT: Segment: 4 -; CHECK-NEXT: Size: 4 -; CHECK-NEXT: - Index: 12 -; CHECK-NEXT: Kind: DATA -; CHECK-NEXT: Name: data_import -; CHECK-NEXT: Flags: [ UNDEFINED ] -; CHECK-NEXT: SegmentInfo: -; CHECK-NEXT: - Index: 0 -; CHECK-NEXT: Name: .rodata.hello_str -; CHECK-NEXT: Alignment: 0 -; CHECK-NEXT: Flags: [ ] -; CHECK-NEXT: - Index: 1 -; CHECK-NEXT: Name: .data.func_addr1 -; CHECK-NEXT: Alignment: 2 -; CHECK-NEXT: Flags: [ ] -; CHECK-NEXT: - Index: 2 -; CHECK-NEXT: Name: .data.func_addr2 -; CHECK-NEXT: Alignment: 2 -; CHECK-NEXT: Flags: [ ] -; CHECK-NEXT: - Index: 3 -; CHECK-NEXT: Name: .data.func_addr3 -; CHECK-NEXT: Alignment: 2 -; CHECK-NEXT: Flags: [ ] -; CHECK-NEXT: - Index: 4 -; CHECK-NEXT: Name: .data.data_addr1 -; CHECK-NEXT: Alignment: 3 -; CHECK-NEXT: Flags: [ ] -; CHECK-NEXT: - Index: 5 -; CHECK-NEXT: Name: .rodata.data_comdat -; CHECK-NEXT: Alignment: 0 -; CHECK-NEXT: Flags: [ ] -; CHECK-NEXT: Comdats: -; CHECK-NEXT: - Name: func_comdat -; CHECK-NEXT: Entries: -; CHECK-NEXT: - Kind: FUNCTION -; CHECK-NEXT: Index: 5 -; CHECK-NEXT: - Kind: DATA -; CHECK-NEXT: Index: 5 -; CHECK-NEXT: - Type: CUSTOM -; CHECK-NEXT: Name: name -; CHECK-NEXT: FunctionNames: -; CHECK-NEXT: - Index: 0 -; CHECK-NEXT: Name: puts -; CHECK-NEXT: - Index: 1 -; CHECK-NEXT: Name: foo_import -; CHECK-NEXT: - Index: 2 -; CHECK-NEXT: Name: bar_import -; CHECK-NEXT: - Index: 3 -; CHECK-NEXT: Name: hello -; CHECK-NEXT: - Index: 4 -; CHECK-NEXT: Name: my_func -; CHECK-NEXT: - Index: 5 -; CHECK-NEXT: Name: func_comdat -; CHECK-NEXT: ... +; NORMAL-NEXT: - Type: DATA +; NORMAL-NEXT: Relocations: +; NORMAL-NEXT: - Type: R_WASM_TABLE_INDEX_I32 +; NORMAL-NEXT: Index: 3 +; NORMAL-NEXT: Offset: 0x00000012 +; NORMAL-NEXT: - Type: R_WASM_TABLE_INDEX_I32 +; NORMAL-NEXT: Index: 4 +; NORMAL-NEXT: Offset: 0x0000001B +; NORMAL-NEXT: - Type: R_WASM_TABLE_INDEX_I32 +; NORMAL-NEXT: Index: 5 +; NORMAL-NEXT: Offset: 0x00000024 +; NORMAL-NEXT: - Type: R_WASM_MEMORY_ADDR_I32 +; NORMAL-NEXT: Index: 12 +; NORMAL-NEXT: Offset: 0x0000002D +; NORMAL-NEXT: Segments: +; NORMAL-NEXT: - SectionOffset: 6 +; NORMAL-NEXT: InitFlags: 0 +; NORMAL-NEXT: Offset: +; NORMAL-NEXT: Opcode: I32_CONST +; NORMAL-NEXT: Value: 0 +; NORMAL-NEXT: Content: 68656C6C6F0A00 +; NORMAL-NEXT: - SectionOffset: 18 +; NORMAL-NEXT: InitFlags: 0 +; NORMAL-NEXT: Offset: +; NORMAL-NEXT: Opcode: I32_CONST +; NORMAL-NEXT: Value: 8 +; NORMAL-NEXT: Content: '01000000' +; NORMAL-NEXT: - SectionOffset: 27 +; NORMAL-NEXT: InitFlags: 0 +; NORMAL-NEXT: Offset: +; NORMAL-NEXT: Opcode: I32_CONST +; NORMAL-NEXT: Value: 12 +; NORMAL-NEXT: Content: '02000000' +; NORMAL-NEXT: - SectionOffset: 36 +; NORMAL-NEXT: InitFlags: 0 +; NORMAL-NEXT: Offset: +; NORMAL-NEXT: Opcode: I32_CONST +; NORMAL-NEXT: Value: 16 +; NORMAL-NEXT: Content: '03000000' +; NORMAL-NEXT: - SectionOffset: 45 +; NORMAL-NEXT: InitFlags: 0 +; NORMAL-NEXT: Offset: +; NORMAL-NEXT: Opcode: I32_CONST +; NORMAL-NEXT: Value: 24 +; NORMAL-NEXT: Content: '00000000' +; NORMAL-NEXT: - SectionOffset: 54 +; NORMAL-NEXT: InitFlags: 0 +; NORMAL-NEXT: Offset: +; NORMAL-NEXT: Opcode: I32_CONST +; NORMAL-NEXT: Value: 28 +; NORMAL-NEXT: Content: '616263' +; NORMAL-NEXT: - Type: CUSTOM +; NORMAL-NEXT: Name: linking +; NORMAL-NEXT: Version: 2 +; NORMAL-NEXT: SymbolTable: +; NORMAL-NEXT: - Index: 0 +; NORMAL-NEXT: Kind: FUNCTION +; NORMAL-NEXT: Name: hello +; NORMAL-NEXT: Flags: [ VISIBILITY_HIDDEN ] +; NORMAL-NEXT: Function: 3 +; NORMAL-NEXT: - Index: 1 +; NORMAL-NEXT: Kind: DATA +; NORMAL-NEXT: Name: hello_str +; NORMAL-NEXT: Flags: [ ] +; NORMAL-NEXT: Segment: 0 +; NORMAL-NEXT: Size: 7 +; NORMAL-NEXT: - Index: 2 +; NORMAL-NEXT: Kind: FUNCTION +; NORMAL-NEXT: Name: puts +; NORMAL-NEXT: Flags: [ UNDEFINED ] +; NORMAL-NEXT: Function: 0 +; NORMAL-NEXT: - Index: 3 +; NORMAL-NEXT: Kind: FUNCTION +; NORMAL-NEXT: Name: my_func +; NORMAL-NEXT: Flags: [ VISIBILITY_HIDDEN ] +; NORMAL-NEXT: Function: 4 +; NORMAL-NEXT: - Index: 4 +; NORMAL-NEXT: Kind: FUNCTION +; NORMAL-NEXT: Name: foo_import +; NORMAL-NEXT: Flags: [ UNDEFINED ] +; NORMAL-NEXT: Function: 1 +; NORMAL-NEXT: - Index: 5 +; NORMAL-NEXT: Kind: FUNCTION +; NORMAL-NEXT: Name: bar_import +; NORMAL-NEXT: Flags: [ BINDING_WEAK, UNDEFINED ] +; NORMAL-NEXT: Function: 2 +; NORMAL-NEXT: - Index: 6 +; NORMAL-NEXT: Kind: FUNCTION +; NORMAL-NEXT: Name: func_comdat +; NORMAL-NEXT: Flags: [ BINDING_WEAK ] +; NORMAL-NEXT: Function: 5 +; NORMAL-NEXT: - Index: 7 +; NORMAL-NEXT: Kind: DATA +; NORMAL-NEXT: Name: data_comdat +; NORMAL-NEXT: Flags: [ BINDING_WEAK ] +; NORMAL-NEXT: Segment: 5 +; NORMAL-NEXT: Size: 3 +; NORMAL-NEXT: - Index: 8 +; NORMAL-NEXT: Kind: DATA +; NORMAL-NEXT: Name: func_addr1 +; NORMAL-NEXT: Flags: [ VISIBILITY_HIDDEN ] +; NORMAL-NEXT: Segment: 1 +; NORMAL-NEXT: Size: 4 +; NORMAL-NEXT: - Index: 9 +; NORMAL-NEXT: Kind: DATA +; NORMAL-NEXT: Name: func_addr2 +; NORMAL-NEXT: Flags: [ VISIBILITY_HIDDEN ] +; NORMAL-NEXT: Segment: 2 +; NORMAL-NEXT: Size: 4 +; NORMAL-NEXT: - Index: 10 +; NORMAL-NEXT: Kind: DATA +; NORMAL-NEXT: Name: func_addr3 +; NORMAL-NEXT: Flags: [ VISIBILITY_HIDDEN ] +; NORMAL-NEXT: Segment: 3 +; NORMAL-NEXT: Size: 4 +; NORMAL-NEXT: - Index: 11 +; NORMAL-NEXT: Kind: DATA +; NORMAL-NEXT: Name: data_addr1 +; NORMAL-NEXT: Flags: [ VISIBILITY_HIDDEN ] +; NORMAL-NEXT: Segment: 4 +; NORMAL-NEXT: Size: 4 +; NORMAL-NEXT: - Index: 12 +; NORMAL-NEXT: Kind: DATA +; NORMAL-NEXT: Name: data_import +; NORMAL-NEXT: Flags: [ UNDEFINED ] +; NORMAL-NEXT: SegmentInfo: +; NORMAL-NEXT: - Index: 0 +; NORMAL-NEXT: Name: .rodata.hello_str +; NORMAL-NEXT: Alignment: 0 +; NORMAL-NEXT: Flags: [ ] +; NORMAL-NEXT: - Index: 1 +; NORMAL-NEXT: Name: .data.func_addr1 +; NORMAL-NEXT: Alignment: 2 +; NORMAL-NEXT: Flags: [ ] +; NORMAL-NEXT: - Index: 2 +; NORMAL-NEXT: Name: .data.func_addr2 +; NORMAL-NEXT: Alignment: 2 +; NORMAL-NEXT: Flags: [ ] +; NORMAL-NEXT: - Index: 3 +; NORMAL-NEXT: Name: .data.func_addr3 +; NORMAL-NEXT: Alignment: 2 +; NORMAL-NEXT: Flags: [ ] +; NORMAL-NEXT: - Index: 4 +; NORMAL-NEXT: Name: .data.data_addr1 +; NORMAL-NEXT: Alignment: 3 +; NORMAL-NEXT: Flags: [ ] +; NORMAL-NEXT: - Index: 5 +; NORMAL-NEXT: Name: .rodata.data_comdat +; NORMAL-NEXT: Alignment: 0 +; NORMAL-NEXT: Flags: [ ] +; NORMAL-NEXT: Comdats: +; NORMAL-NEXT: - Name: func_comdat +; NORMAL-NEXT: Entries: +; NORMAL-NEXT: - Kind: FUNCTION +; NORMAL-NEXT: Index: 5 +; NORMAL-NEXT: - Kind: DATA +; NORMAL-NEXT: Index: 5 +; NORMAL-NEXT: - Type: CUSTOM +; NORMAL-NEXT: Name: name +; NORMAL-NEXT: FunctionNames: +; NORMAL-NEXT: - Index: 0 +; NORMAL-NEXT: Name: puts +; NORMAL-NEXT: - Index: 1 +; NORMAL-NEXT: Name: foo_import +; NORMAL-NEXT: - Index: 2 +; NORMAL-NEXT: Name: bar_import +; NORMAL-NEXT: - Index: 3 +; NORMAL-NEXT: Name: hello +; NORMAL-NEXT: - Index: 4 +; NORMAL-NEXT: Name: my_func +; NORMAL-NEXT: - Index: 5 +; NORMAL-NEXT: Name: func_comdat +; NORMAL-NEXT:... diff --git a/lld/wasm/Writer.cpp b/lld/wasm/Writer.cpp index 68e001ccc800..6338b6e5fa2a 100644 --- a/lld/wasm/Writer.cpp +++ b/lld/wasm/Writer.cpp @@ -898,7 +898,7 @@ void Writer::run() { createCallCtorsFunction(); } - if (config->sharedMemory && !config->shared) + if (!config->relocatable && config->sharedMemory && !config->shared) createInitTLSFunction(); if (errorCount()) From 79d4fef4977d93d950f11369b8bbb5fc94861017 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Thu, 8 Aug 2019 08:41:49 +0000 Subject: [PATCH 084/289] Merging r366513: ------------------------------------------------------------------------ r366513 | lanza | 2019-07-19 01:40:23 +0200 (Fri, 19 Jul 2019) | 9 lines [cmake] Update NATIVE build variables to account for standalone changes Summary: LLDB_PATH_TO_{CLANG,LLVM}_BUILD were removed and replaced with {LLVM,Clang}_DIR. Adjust the NATIVE build to account for this. Subscribers: mgorny Differential Revision: https://reviews.llvm.org/D64959 ------------------------------------------------------------------------ llvm-svn: 368268 --- lldb/CMakeLists.txt | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/lldb/CMakeLists.txt b/lldb/CMakeLists.txt index 609aa0bd2a60..5d52f6450657 100644 --- a/lldb/CMakeLists.txt +++ b/lldb/CMakeLists.txt @@ -42,15 +42,14 @@ endif () if(CMAKE_CROSSCOMPILING AND LLDB_BUILT_STANDALONE) set(LLVM_USE_HOST_TOOLS ON) include(CrossCompile) - if (NOT LLDB_PATH_TO_NATIVE_LLVM_BUILD OR - NOT LLDB_PATH_TO_NATIVE_CLANG_BUILD) + if (NOT NATIVE_LLVM_DIR OR NOT NATIVE_Clang_DIR) message(FATAL_ERROR - "Crosscompiling standalone requires the variables LLDB_PATH_TO_NATIVE_{CLANG,LLVM}_BUILD + "Crosscompiling standalone requires the variables NATIVE_{CLANG,LLVM}_DIR for building the native lldb-tblgen used during the build process.") endif() llvm_create_cross_target(lldb NATIVE "" Release - -DLLDB_PATH_TO_LLVM_BUILD=${LLDB_PATH_TO_NATIVE_LLVM_BUILD} - -DLLDB_PATH_TO_CLANG_BUILD=${LLDB_PATH_TO_NATIVE_CLANG_BUILD}) + -DLLVM_DIR=${NATIVE_LLVM_DIR} + -DClang_DIR=${NATIVE_Clang_DIR}) endif() add_subdirectory(utils/TableGen) From 343874d13569b57a276b27300c1bce85908be16b Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Thu, 8 Aug 2019 08:52:26 +0000 Subject: [PATCH 085/289] ReleaseNotes: LLVM_ENABLE_Z3_SOLVER (PR42921) llvm-svn: 368269 --- llvm/docs/ReleaseNotes.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst index 67da442abbd5..7fa6c713317f 100644 --- a/llvm/docs/ReleaseNotes.rst +++ b/llvm/docs/ReleaseNotes.rst @@ -52,6 +52,10 @@ Non-comprehensive list of changes in this release * **llvm-objcopy/llvm-strip** got support for COFF object files/executables, supporting the most common copying/stripping options. +* The CMake parameter ``CLANG_ANALYZER_ENABLE_Z3_SOLVER`` has been replaced by + ``LLVM_ENABLE_Z3_SOLVER``. + + .. NOTE If you would like to document a larger change, then you can add a subsection about it right here. You can copy the following boilerplate From 94e7307d120bbb90b6fb1b8e87c0ca134afb6fc1 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Thu, 8 Aug 2019 08:57:23 +0000 Subject: [PATCH 086/289] Merging r368041: ------------------------------------------------------------------------ r368041 | psmith | 2019-08-06 16:13:38 +0200 (Tue, 06 Aug 2019) | 16 lines [ELF][ARM] Fix /DISCARD/ of section with .ARM.exidx section The combineEhSections runs, by design, before processSectionCommands so that input exception sections like .ARM.exidx and .eh_frame are not assigned to OutputSections. Unfortunately if /DISCARD/ removes InputSections that have associated .ARM.exidx sections without discarding the .ARM.exidx synthetic section then we will end up crashing when trying to sort the InputSections in ascending address order. We fix this by filtering out the sections that have been discarded prior to processing the InputSections in finalizeContents(). fixes pr42890 Differential Revision: https://reviews.llvm.org/D65759 ------------------------------------------------------------------------ llvm-svn: 368270 --- lld/ELF/SyntheticSections.cpp | 14 ++++++++- lld/test/ELF/arm-exidx-partial-discard.s | 37 ++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 lld/test/ELF/arm-exidx-partial-discard.s diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index f6d0f190d84d..35b9b8928c9f 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -3177,11 +3177,23 @@ static bool isDuplicateArmExidxSec(InputSection *prev, InputSection *cur) { // The .ARM.exidx table must be sorted in ascending order of the address of the // functions the table describes. Optionally duplicate adjacent table entries -// can be removed. At the end of the function the ExecutableSections must be +// can be removed. At the end of the function the executableSections must be // sorted in ascending order of address, Sentinel is set to the InputSection // with the highest address and any InputSections that have mergeable // .ARM.exidx table entries are removed from it. void ARMExidxSyntheticSection::finalizeContents() { + if (script->hasSectionsCommand) { + // The executableSections and exidxSections that we use to derive the + // final contents of this SyntheticSection are populated before the + // linker script assigns InputSections to OutputSections. The linker script + // SECTIONS command may have a /DISCARD/ entry that removes executable + // InputSections and their dependent .ARM.exidx section that we recorded + // earlier. + auto isDiscarded = [](const InputSection *isec) { return !isec->isLive(); }; + llvm::erase_if(executableSections, isDiscarded); + llvm::erase_if(exidxSections, isDiscarded); + } + // Sort the executable sections that may or may not have associated // .ARM.exidx sections by order of ascending address. This requires the // relative positions of InputSections to be known. diff --git a/lld/test/ELF/arm-exidx-partial-discard.s b/lld/test/ELF/arm-exidx-partial-discard.s new file mode 100644 index 000000000000..770a811c1b83 --- /dev/null +++ b/lld/test/ELF/arm-exidx-partial-discard.s @@ -0,0 +1,37 @@ +// REQUIRES: arm +// RUN: llvm-mc -filetype=obj -triple arm-gnu-linux-eabi -mcpu cortex-a7 -arm-add-build-attributes %s -o %t.o +// RUN: echo "SECTIONS { . = 0x10000; .text : { *(.text) } /DISCARD/ : { *(.exit.text) } }" > %t.script +// RUN: ld.lld -T %t.script %t.o -o %t.elf +// RUN: llvm-readobj -x .ARM.exidx --sections %t.elf | FileCheck %s + +// CHECK-NOT: .exit.text +/// Expect 2 entries both CANTUNWIND as the .ARM.exidx.exit.text +// should have been removed. +// CHECK: Hex dump of section '.ARM.exidx': +// CHECK-NEXT: 0x00010000 10000000 01000000 10000000 01000000 + +/// The /DISCARD/ is evaluated after sections have been assigned to the +/// .ARM.exidx synthetic section. We must account for the /DISCARD/ + .section .exit.text, "ax", %progbits + .globl foo + .type foo, %function +foo: + .fnstart + bx lr + .save {r7, lr} + .setfp r7, sp, #0 + .fnend + + .text + .globl _start + .type _start, %function +_start: + .fnstart + bx lr + .cantunwind + .fnend + + .section .text.__aeabi_unwind_cpp_pr0, "ax", %progbits + .global __aeabi_unwind_cpp_pr0 +__aeabi_unwind_cpp_pr0: + bx lr From 280dccc54dc48fa1b7c4aeab2d6eb223fe292405 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Fri, 9 Aug 2019 08:21:53 +0000 Subject: [PATCH 087/289] Merging r368058: ------------------------------------------------------------------------ r368058 | sureyeaah | 2019-08-06 19:01:12 +0200 (Tue, 06 Aug 2019) | 11 lines Fixed toHalfOpenFileRange assertion fail Summary: - Added new function that gets Expansion range with both ends in the same file. - Fixes the crash at https://github.com/clangd/clangd/issues/113 Subscribers: ilya-biryukov, jkorous, arphaman, kadircet, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D65754 ------------------------------------------------------------------------ llvm-svn: 368407 --- clang-tools-extra/clangd/SourceCode.cpp | 63 +++++++++++++++---- .../clangd/unittests/SourceCodeTests.cpp | 10 ++- 2 files changed, 61 insertions(+), 12 deletions(-) diff --git a/clang-tools-extra/clangd/SourceCode.cpp b/clang-tools-extra/clangd/SourceCode.cpp index fb1183aef511..9996f0ba6749 100644 --- a/clang-tools-extra/clangd/SourceCode.cpp +++ b/clang-tools-extra/clangd/SourceCode.cpp @@ -296,14 +296,52 @@ static SourceRange unionTokenRange(SourceRange R1, SourceRange R2, E1 < E2 ? R2.getEnd() : R1.getEnd()); } -// Returns the tokenFileRange for a given Location as a Token Range +// Check if two locations have the same file id. +static bool inSameFile(SourceLocation Loc1, SourceLocation Loc2, + const SourceManager &SM) { + return SM.getFileID(Loc1) == SM.getFileID(Loc2); +} + +// Find an expansion range (not necessarily immediate) the ends of which are in +// the same file id. +static SourceRange +getExpansionTokenRangeInSameFile(SourceLocation Loc, const SourceManager &SM, + const LangOptions &LangOpts) { + SourceRange ExpansionRange = + toTokenRange(SM.getImmediateExpansionRange(Loc), SM, LangOpts); + // Fast path for most common cases. + if (inSameFile(ExpansionRange.getBegin(), ExpansionRange.getEnd(), SM)) + return ExpansionRange; + // Record the stack of expansion locations for the beginning, keyed by FileID. + llvm::DenseMap BeginExpansions; + for (SourceLocation Begin = ExpansionRange.getBegin(); Begin.isValid(); + Begin = Begin.isFileID() + ? SourceLocation() + : SM.getImmediateExpansionRange(Begin).getBegin()) { + BeginExpansions[SM.getFileID(Begin)] = Begin; + } + // Move up the stack of expansion locations for the end until we find the + // location in BeginExpansions with that has the same file id. + for (SourceLocation End = ExpansionRange.getEnd(); End.isValid(); + End = End.isFileID() ? SourceLocation() + : toTokenRange(SM.getImmediateExpansionRange(End), + SM, LangOpts) + .getEnd()) { + auto It = BeginExpansions.find(SM.getFileID(End)); + if (It != BeginExpansions.end()) + return {It->second, End}; + } + llvm_unreachable( + "We should able to find a common ancestor in the expansion tree."); +} +// Returns the file range for a given Location as a Token Range // This is quite similar to getFileLoc in SourceManager as both use // getImmediateExpansionRange and getImmediateSpellingLoc (for macro IDs). // However: // - We want to maintain the full range information as we move from one file to // the next. getFileLoc only uses the BeginLoc of getImmediateExpansionRange. -// - We want to split '>>' tokens as the lexer parses the '>>' in template -// instantiations as a '>>' instead of a '>'. +// - We want to split '>>' tokens as the lexer parses the '>>' in nested +// template instantiations as a '>>' instead of two '>'s. // There is also getExpansionRange but it simply calls // getImmediateExpansionRange on the begin and ends separately which is wrong. static SourceRange getTokenFileRange(SourceLocation Loc, @@ -311,16 +349,19 @@ static SourceRange getTokenFileRange(SourceLocation Loc, const LangOptions &LangOpts) { SourceRange FileRange = Loc; while (!FileRange.getBegin().isFileID()) { - assert(!FileRange.getEnd().isFileID() && - "Both Begin and End should be MacroIDs."); if (SM.isMacroArgExpansion(FileRange.getBegin())) { - FileRange.setBegin(SM.getImmediateSpellingLoc(FileRange.getBegin())); - FileRange.setEnd(SM.getImmediateSpellingLoc(FileRange.getEnd())); + FileRange = unionTokenRange( + SM.getImmediateSpellingLoc(FileRange.getBegin()), + SM.getImmediateSpellingLoc(FileRange.getEnd()), SM, LangOpts); + assert(inSameFile(FileRange.getBegin(), FileRange.getEnd(), SM)); } else { - SourceRange ExpansionRangeForBegin = toTokenRange( - SM.getImmediateExpansionRange(FileRange.getBegin()), SM, LangOpts); - SourceRange ExpansionRangeForEnd = toTokenRange( - SM.getImmediateExpansionRange(FileRange.getEnd()), SM, LangOpts); + SourceRange ExpansionRangeForBegin = + getExpansionTokenRangeInSameFile(FileRange.getBegin(), SM, LangOpts); + SourceRange ExpansionRangeForEnd = + getExpansionTokenRangeInSameFile(FileRange.getEnd(), SM, LangOpts); + assert(inSameFile(ExpansionRangeForBegin.getBegin(), + ExpansionRangeForEnd.getBegin(), SM) && + "Both Expansion ranges should be in same file."); FileRange = unionTokenRange(ExpansionRangeForBegin, ExpansionRangeForEnd, SM, LangOpts); } diff --git a/clang-tools-extra/clangd/unittests/SourceCodeTests.cpp b/clang-tools-extra/clangd/unittests/SourceCodeTests.cpp index 29eda85bc458..1b2f4266bc2b 100644 --- a/clang-tools-extra/clangd/unittests/SourceCodeTests.cpp +++ b/clang-tools-extra/clangd/unittests/SourceCodeTests.cpp @@ -430,15 +430,22 @@ TEST(SourceCodeTests, HalfOpenFileRange) { #define FOO(X, Y) int Y = ++X #define BAR(X) X + 1 #define ECHO(X) X + + #define BUZZ BAZZ(ADD) + #define BAZZ(m) m(1) + #define ADD(a) int f = a + 1; template class P {}; - void f() { + + int main() { $a[[P>>>> a]]; $b[[int b = 1]]; $c[[FOO(b, c)]]; $d[[FOO(BAR(BAR(b)), d)]]; // FIXME: We might want to select everything inside the outer ECHO. ECHO(ECHO($e[[int) ECHO(e]])); + // Shouldn't crash. + $f[[BUZZ]]; } )cpp"); @@ -465,6 +472,7 @@ TEST(SourceCodeTests, HalfOpenFileRange) { CheckRange("c"); CheckRange("d"); CheckRange("e"); + CheckRange("f"); } } // namespace From 4ed16edfa02151fec8d5928cb8fb768c7826657d Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Fri, 9 Aug 2019 08:35:17 +0000 Subject: [PATCH 088/289] [docs][mips] 9.0 Release notes By Simon Atanasyan! Differential revision: https://reviews.llvm.org/D65830 llvm-svn: 368411 --- llvm/docs/ReleaseNotes.rst | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst index 7fa6c713317f..f33af9ac3e68 100644 --- a/llvm/docs/ReleaseNotes.rst +++ b/llvm/docs/ReleaseNotes.rst @@ -115,7 +115,19 @@ Changes to the ARM Backend Changes to the MIPS Target -------------------------- - During this release ... +* Support for ``.cplocal`` assembler directive. + +* Support for ``sge``, ``sgeu``, ``sgt``, ``sgtu`` pseudo instructions. + +* Support for ``o`` inline asm constraint. + +* Improved support of GlobalISel instruction selection framework. + This feature is still in experimental state for MIPS targets though. + +* Various code-gen improvements, related to improved and fixed instruction + selection and encoding and floating-point registers allocation. + +* Complete P5600 scheduling model. Changes to the PowerPC Target From 97fe26c4e172dad07e70f067495092c71b00f148 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Fri, 9 Aug 2019 08:37:40 +0000 Subject: [PATCH 089/289] [docs][mips] 9.0 Release notes By Simon Atanasyan! Differential revision: https://reviews.llvm.org/D65830 llvm-svn: 368412 --- lld/docs/ReleaseNotes.rst | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/lld/docs/ReleaseNotes.rst b/lld/docs/ReleaseNotes.rst index bccef8165f82..2d358bf8f246 100644 --- a/lld/docs/ReleaseNotes.rst +++ b/lld/docs/ReleaseNotes.rst @@ -28,6 +28,15 @@ ELF Improvements ``$ ld.lld --call-shared`` now prints ``unknown argument '--call-shared', did you mean '--call_shared'``. +* lld now supports replacing ``JAL`` with ``JALX`` instructions in case + of MIPS - microMIPS cross-mode jumps. + +* lld now creates LA25 thunks for MIPS R6 code. + +* Put MIPS-specific .reginfo, .MIPS.options, and .MIPS.abiflags sections + into corresponding PT_MIPS_REGINFO, PT_MIPS_OPTIONS, and PT_MIPS_ABIFLAGS + segments. + * ... COFF Improvements From 817e3eae7545690f9e80178d0ba4be9e6772a740 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Fri, 9 Aug 2019 08:53:00 +0000 Subject: [PATCH 090/289] Merging r368315: ------------------------------------------------------------------------ r368315 | tstellar | 2019-08-08 19:23:33 +0200 (Thu, 08 Aug 2019) | 21 lines lit: Use a License classifier that pypi will accept Summary: 'OSI Approved :: Apache-2.0 with LLVM exception' is not a valid classifier. 'OSI Approved :: Apache Software License' is the closest fit for the new license, so we've decided to use this one. The classifiers seem to only be used for searching on the pypi website, so this does not actually change the license of the code. We still pass 'Apache-2.0 with LLVM exception' as the license to setup(), and this appears alongside the classifier on the pypi webpage for lit. Reviewers: chandlerc, ddunbar, joerg Reviewed By: joerg Subscribers: delcypher, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D65762 ------------------------------------------------------------------------ llvm-svn: 368414 --- llvm/utils/lit/setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/utils/lit/setup.py b/llvm/utils/lit/setup.py index 10b75e7fe6ee..9d26b2ed71c7 100644 --- a/llvm/utils/lit/setup.py +++ b/llvm/utils/lit/setup.py @@ -60,7 +60,7 @@ 'Development Status :: 3 - Alpha', 'Environment :: Console', 'Intended Audience :: Developers', - 'License :: OSI Approved :: Apache-2.0 with LLVM exception', + 'License :: OSI Approved :: Apache Software License', 'Natural Language :: English', 'Operating System :: OS Independent', 'Programming Language :: Python', From 702cccb1769c7903b06a8f206a09815bac77de27 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Fri, 9 Aug 2019 09:39:44 +0000 Subject: [PATCH 091/289] Merging r367403: ------------------------------------------------------------------------ r367403 | lenary | 2019-07-31 11:45:55 +0200 (Wed, 31 Jul 2019) | 20 lines [RISCV] Support 'f' Inline Assembly Constraint Summary: This adds the 'f' inline assembly constraint, as supported by GCC. An 'f'-constrained operand is passed in a floating point register. Exactly which kind of floating-point register (32-bit or 64-bit) is decided based on the operand type and the available standard extensions (-f and -d, respectively). This patch adds support in both the clang frontend, and LLVM itself. Reviewers: asb, lewis-revill Reviewed By: asb Subscribers: hiraditya, rbar, johnrusso, simoncook, apazos, sabuasal, niosHD, kito-cheng, shiva0217, jrtc27, MaskRay, zzheng, edward-jones, rogfer01, MartinMosbeck, brucehoult, the_o, rkruppe, PkmX, jocewei, psnobl, benna, Jim, s.egerton, cfe-commits, llvm-commits Tags: #clang, #llvm Differential Revision: https://reviews.llvm.org/D65500 ------------------------------------------------------------------------ llvm-svn: 368419 --- llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 21 ++++++++++ llvm/lib/Target/RISCV/RISCVISelLowering.h | 1 + .../RISCV/inline-asm-d-constraint-f.ll | 40 +++++++++++++++++++ .../RISCV/inline-asm-f-constraint-f.ll | 34 ++++++++++++++++ llvm/test/CodeGen/RISCV/inline-asm-invalid.ll | 8 ++++ 5 files changed, 104 insertions(+) create mode 100644 llvm/test/CodeGen/RISCV/inline-asm-d-constraint-f.ll create mode 100644 llvm/test/CodeGen/RISCV/inline-asm-f-constraint-f.ll diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index ce7b85911ab6..b2dbff385305 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -2397,6 +2397,21 @@ const char *RISCVTargetLowering::getTargetNodeName(unsigned Opcode) const { return nullptr; } +/// getConstraintType - Given a constraint letter, return the type of +/// constraint it is for this target. +RISCVTargetLowering::ConstraintType +RISCVTargetLowering::getConstraintType(StringRef Constraint) const { + if (Constraint.size() == 1) { + switch (Constraint[0]) { + default: + break; + case 'f': + return C_RegisterClass; + } + } + return TargetLowering::getConstraintType(Constraint); +} + std::pair RISCVTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, @@ -2407,6 +2422,12 @@ RISCVTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, switch (Constraint[0]) { case 'r': return std::make_pair(0U, &RISCV::GPRRegClass); + case 'f': + if (Subtarget.hasStdExtF() && VT == MVT::f32) + return std::make_pair(0U, &RISCV::FPR32RegClass); + if (Subtarget.hasStdExtD() && VT == MVT::f64) + return std::make_pair(0U, &RISCV::FPR64RegClass); + break; default: break; } diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.h b/llvm/lib/Target/RISCV/RISCVISelLowering.h index 17db03bbb69e..f28c4753c1d9 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.h +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.h @@ -92,6 +92,7 @@ class RISCVTargetLowering : public TargetLowering { // This method returns the name of a target specific DAG node. const char *getTargetNodeName(unsigned Opcode) const override; + ConstraintType getConstraintType(StringRef Constraint) const override; std::pair getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const override; diff --git a/llvm/test/CodeGen/RISCV/inline-asm-d-constraint-f.ll b/llvm/test/CodeGen/RISCV/inline-asm-d-constraint-f.ll new file mode 100644 index 000000000000..251c06343805 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/inline-asm-d-constraint-f.ll @@ -0,0 +1,40 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=riscv32 -mattr=+d -verify-machineinstrs < %s \ +; RUN: | FileCheck -check-prefix=RV32F %s +; RUN: llc -mtriple=riscv64 -mattr=+d -verify-machineinstrs < %s \ +; RUN: | FileCheck -check-prefix=RV64F %s + +@gd = external global double + +define double @constraint_f_double(double %a) nounwind { +; RV32F-LABEL: constraint_f_double: +; RV32F: # %bb.0: +; RV32F-NEXT: addi sp, sp, -16 +; RV32F-NEXT: sw a0, 8(sp) +; RV32F-NEXT: sw a1, 12(sp) +; RV32F-NEXT: fld ft0, 8(sp) +; RV32F-NEXT: lui a0, %hi(gd) +; RV32F-NEXT: fld ft1, %lo(gd)(a0) +; RV32F-NEXT: #APP +; RV32F-NEXT: fadd.d ft0, ft0, ft1 +; RV32F-NEXT: #NO_APP +; RV32F-NEXT: fsd ft0, 8(sp) +; RV32F-NEXT: lw a0, 8(sp) +; RV32F-NEXT: lw a1, 12(sp) +; RV32F-NEXT: addi sp, sp, 16 +; RV32F-NEXT: ret +; +; RV64F-LABEL: constraint_f_double: +; RV64F: # %bb.0: +; RV64F-NEXT: fmv.d.x ft0, a0 +; RV64F-NEXT: lui a0, %hi(gd) +; RV64F-NEXT: fld ft1, %lo(gd)(a0) +; RV64F-NEXT: #APP +; RV64F-NEXT: fadd.d ft0, ft0, ft1 +; RV64F-NEXT: #NO_APP +; RV64F-NEXT: fmv.x.d a0, ft0 +; RV64F-NEXT: ret + %1 = load double, double* @gd + %2 = tail call double asm "fadd.d $0, $1, $2", "=f,f,f"(double %a, double %1) + ret double %2 +} diff --git a/llvm/test/CodeGen/RISCV/inline-asm-f-constraint-f.ll b/llvm/test/CodeGen/RISCV/inline-asm-f-constraint-f.ll new file mode 100644 index 000000000000..e342789ca7cf --- /dev/null +++ b/llvm/test/CodeGen/RISCV/inline-asm-f-constraint-f.ll @@ -0,0 +1,34 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=riscv32 -mattr=+f -verify-machineinstrs < %s \ +; RUN: | FileCheck -check-prefix=RV32F %s +; RUN: llc -mtriple=riscv64 -mattr=+f -verify-machineinstrs < %s \ +; RUN: | FileCheck -check-prefix=RV64F %s + +@gf = external global float + +define float @constraint_f_float(float %a) nounwind { +; RV32F-LABEL: constraint_f_float: +; RV32F: # %bb.0: +; RV32F-NEXT: fmv.w.x ft0, a0 +; RV32F-NEXT: lui a0, %hi(gf) +; RV32F-NEXT: flw ft1, %lo(gf)(a0) +; RV32F-NEXT: #APP +; RV32F-NEXT: fadd.s ft0, ft0, ft1 +; RV32F-NEXT: #NO_APP +; RV32F-NEXT: fmv.x.w a0, ft0 +; RV32F-NEXT: ret +; +; RV64F-LABEL: constraint_f_float: +; RV64F: # %bb.0: +; RV64F-NEXT: fmv.w.x ft0, a0 +; RV64F-NEXT: lui a0, %hi(gf) +; RV64F-NEXT: flw ft1, %lo(gf)(a0) +; RV64F-NEXT: #APP +; RV64F-NEXT: fadd.s ft0, ft0, ft1 +; RV64F-NEXT: #NO_APP +; RV64F-NEXT: fmv.x.w a0, ft0 +; RV64F-NEXT: ret + %1 = load float, float* @gf + %2 = tail call float asm "fadd.s $0, $1, $2", "=f,f,f"(float %a, float %1) + ret float %2 +} diff --git a/llvm/test/CodeGen/RISCV/inline-asm-invalid.ll b/llvm/test/CodeGen/RISCV/inline-asm-invalid.ll index ee9c04322a52..06b0f2c2bfea 100644 --- a/llvm/test/CodeGen/RISCV/inline-asm-invalid.ll +++ b/llvm/test/CodeGen/RISCV/inline-asm-invalid.ll @@ -22,3 +22,11 @@ define void @constraint_K() { tail call void asm sideeffect "csrwi mstatus, $0", "K"(i32 -1) ret void } + +define void @constraint_f() nounwind { +; CHECK: error: couldn't allocate input reg for constraint 'f' + tail call void asm "fadd.s fa0, fa0, $0", "f"(float 0.0) +; CHECK: error: couldn't allocate input reg for constraint 'f' + tail call void asm "fadd.d fa0, fa0, $0", "f"(double 0.0) + ret void +} From 172e22201f1db6ec1a77863f11ce6f192b993207 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Fri, 9 Aug 2019 09:40:09 +0000 Subject: [PATCH 092/289] Merging r367403: ------------------------------------------------------------------------ r367403 | lenary | 2019-07-31 11:45:55 +0200 (Wed, 31 Jul 2019) | 20 lines [RISCV] Support 'f' Inline Assembly Constraint Summary: This adds the 'f' inline assembly constraint, as supported by GCC. An 'f'-constrained operand is passed in a floating point register. Exactly which kind of floating-point register (32-bit or 64-bit) is decided based on the operand type and the available standard extensions (-f and -d, respectively). This patch adds support in both the clang frontend, and LLVM itself. Reviewers: asb, lewis-revill Reviewed By: asb Subscribers: hiraditya, rbar, johnrusso, simoncook, apazos, sabuasal, niosHD, kito-cheng, shiva0217, jrtc27, MaskRay, zzheng, edward-jones, rogfer01, MartinMosbeck, brucehoult, the_o, rkruppe, PkmX, jocewei, psnobl, benna, Jim, s.egerton, cfe-commits, llvm-commits Tags: #clang, #llvm Differential Revision: https://reviews.llvm.org/D65500 ------------------------------------------------------------------------ llvm-svn: 368420 --- clang/lib/Basic/Targets/RISCV.cpp | 4 ++++ clang/test/CodeGen/riscv-inline-asm.c | 12 ++++++++++++ 2 files changed, 16 insertions(+) diff --git a/clang/lib/Basic/Targets/RISCV.cpp b/clang/lib/Basic/Targets/RISCV.cpp index 58272d14abd1..939ac46d671b 100644 --- a/clang/lib/Basic/Targets/RISCV.cpp +++ b/clang/lib/Basic/Targets/RISCV.cpp @@ -56,6 +56,10 @@ bool RISCVTargetInfo::validateAsmConstraint( // A 5-bit unsigned immediate for CSR access instructions. Info.setRequiresImmediate(0, 31); return true; + case 'f': + // A floating-point register. + Info.setAllowsRegister(); + return true; } } diff --git a/clang/test/CodeGen/riscv-inline-asm.c b/clang/test/CodeGen/riscv-inline-asm.c index 2d23b7e35e2b..f79527337bdf 100644 --- a/clang/test/CodeGen/riscv-inline-asm.c +++ b/clang/test/CodeGen/riscv-inline-asm.c @@ -26,3 +26,15 @@ void test_K() { // CHECK: call void asm sideeffect "", "K"(i32 0) asm volatile ("" :: "K"(0)); } + +float f; +double d; +void test_f() { +// CHECK-LABEL: define void @test_f() +// CHECK: [[FLT_ARG:%[a-zA-Z_0-9]+]] = load float, float* @f +// CHECK: call void asm sideeffect "", "f"(float [[FLT_ARG]]) + asm volatile ("" :: "f"(f)); +// CHECK: [[FLT_ARG:%[a-zA-Z_0-9]+]] = load double, double* @d +// CHECK: call void asm sideeffect "", "f"(double [[FLT_ARG]]) + asm volatile ("" :: "f"(d)); +} From ffea3e37369707a7e67b8cfd7068137a72b80949 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Fri, 9 Aug 2019 09:45:06 +0000 Subject: [PATCH 093/289] Merging r367750: ------------------------------------------------------------------------ r367750 | void | 2019-08-03 07:52:47 +0200 (Sat, 03 Aug 2019) | 15 lines Emit diagnostic if an inline asm constraint requires an immediate Summary: An inline asm call can result in an immediate after inlining. Therefore emit a diagnostic here if constraint requires an immediate but one isn't supplied. Reviewers: joerg, mgorny, efriedma, rsmith Reviewed By: joerg Subscribers: asb, rbar, johnrusso, simoncook, apazos, sabuasal, niosHD, zzheng, edward-jones, rogfer01, MartinMosbeck, brucehoult, the_o, PkmX, jocewei, s.egerton, MaskRay, jyknight, dylanmckay, javed.absar, fedor.sergeev, jrtc27, Jim, krytarowski, eraman, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D60942 ------------------------------------------------------------------------ llvm-svn: 368421 --- llvm/include/llvm/CodeGen/TargetLowering.h | 1 + .../SelectionDAG/SelectionDAGBuilder.cpp | 35 +++++++++++++++---- .../CodeGen/SelectionDAG/TargetLowering.cpp | 18 ++++++---- .../Target/AArch64/AArch64ISelLowering.cpp | 12 +++++-- llvm/lib/Target/ARM/ARMISelLowering.cpp | 11 +++--- llvm/lib/Target/AVR/AVRISelLowering.cpp | 6 ++-- llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 4 +++ llvm/lib/Target/Sparc/SparcISelLowering.cpp | 2 +- .../Target/SystemZ/SystemZISelLowering.cpp | 2 +- llvm/lib/Target/X86/X86ISelLowering.cpp | 5 +-- .../AArch64/arm64-inline-asm-error-I.ll | 2 +- .../AArch64/arm64-inline-asm-error-J.ll | 2 +- .../AArch64/arm64-inline-asm-error-K.ll | 2 +- .../AArch64/arm64-inline-asm-error-L.ll | 2 +- .../AArch64/arm64-inline-asm-error-M.ll | 2 +- .../AArch64/arm64-inline-asm-error-N.ll | 2 +- llvm/test/CodeGen/RISCV/inline-asm-invalid.ll | 10 +++--- .../X86/inline-asm-bad-constraint-n.ll | 2 +- .../CodeGen/X86/inline-asm-e-constraint.ll | 17 +++++++++ .../X86/inline-asm-imm-out-of-range.ll | 7 ++++ .../CodeGen/X86/inline-asm-n-constraint.ll | 13 +++++++ 21 files changed, 117 insertions(+), 40 deletions(-) create mode 100644 llvm/test/CodeGen/X86/inline-asm-e-constraint.ll create mode 100644 llvm/test/CodeGen/X86/inline-asm-imm-out-of-range.ll create mode 100644 llvm/test/CodeGen/X86/inline-asm-n-constraint.ll diff --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h index d5cca60bb1b2..ca7548cd8d6f 100644 --- a/llvm/include/llvm/CodeGen/TargetLowering.h +++ b/llvm/include/llvm/CodeGen/TargetLowering.h @@ -3665,6 +3665,7 @@ class TargetLowering : public TargetLoweringBase { C_Register, // Constraint represents specific register(s). C_RegisterClass, // Constraint represents any of register(s) in class. C_Memory, // Memory constraint. + C_Immediate, // Requires an immediate. C_Other, // Something else. C_Unknown // Unsupported constraint. }; diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index e818dd27c05e..3c02c36a7d26 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -8021,6 +8021,14 @@ void SelectionDAGBuilder::visitInlineAsm(ImmutableCallSite CS) { // Compute the constraint code and ConstraintType to use. TLI.ComputeConstraintToUse(T, SDValue()); + if (T.ConstraintType == TargetLowering::C_Immediate && + OpInfo.CallOperand && !isa(OpInfo.CallOperand)) + // We've delayed emitting a diagnostic like the "n" constraint because + // inlining could cause an integer showing up. + return emitInlineAsmError( + CS, "constraint '" + Twine(T.ConstraintCode) + "' expects an " + "integer constant expression"); + ExtraInfo.update(T); } @@ -8105,7 +8113,8 @@ void SelectionDAGBuilder::visitInlineAsm(ImmutableCallSite CS) { switch (OpInfo.Type) { case InlineAsm::isOutput: if (OpInfo.ConstraintType == TargetLowering::C_Memory || - (OpInfo.ConstraintType == TargetLowering::C_Other && + ((OpInfo.ConstraintType == TargetLowering::C_Immediate || + OpInfo.ConstraintType == TargetLowering::C_Other) && OpInfo.isIndirect)) { unsigned ConstraintID = TLI.getInlineAsmMemConstraint(OpInfo.ConstraintCode); @@ -8119,13 +8128,14 @@ void SelectionDAGBuilder::visitInlineAsm(ImmutableCallSite CS) { MVT::i32)); AsmNodeOperands.push_back(OpInfo.CallOperand); break; - } else if ((OpInfo.ConstraintType == TargetLowering::C_Other && + } else if (((OpInfo.ConstraintType == TargetLowering::C_Immediate || + OpInfo.ConstraintType == TargetLowering::C_Other) && !OpInfo.isIndirect) || OpInfo.ConstraintType == TargetLowering::C_Register || OpInfo.ConstraintType == TargetLowering::C_RegisterClass) { // Otherwise, this outputs to a register (directly for C_Register / - // C_RegisterClass, and a target-defined fashion for C_Other). Find a - // register that we can use. + // C_RegisterClass, and a target-defined fashion for + // C_Immediate/C_Other). Find a register that we can use. if (OpInfo.AssignedRegs.Regs.empty()) { emitInlineAsmError( CS, "couldn't allocate output register for constraint '" + @@ -8205,15 +8215,24 @@ void SelectionDAGBuilder::visitInlineAsm(ImmutableCallSite CS) { } // Treat indirect 'X' constraint as memory. - if (OpInfo.ConstraintType == TargetLowering::C_Other && + if ((OpInfo.ConstraintType == TargetLowering::C_Immediate || + OpInfo.ConstraintType == TargetLowering::C_Other) && OpInfo.isIndirect) OpInfo.ConstraintType = TargetLowering::C_Memory; - if (OpInfo.ConstraintType == TargetLowering::C_Other) { + if (OpInfo.ConstraintType == TargetLowering::C_Immediate || + OpInfo.ConstraintType == TargetLowering::C_Other) { std::vector Ops; TLI.LowerAsmOperandForConstraint(InOperandVal, OpInfo.ConstraintCode, Ops, DAG); if (Ops.empty()) { + if (OpInfo.ConstraintType == TargetLowering::C_Immediate) + if (isa(InOperandVal)) { + emitInlineAsmError(CS, "value out of range for constraint '" + + Twine(OpInfo.ConstraintCode) + "'"); + return; + } + emitInlineAsmError(CS, "invalid operand for inline asm constraint '" + Twine(OpInfo.ConstraintCode) + "'"); return; @@ -8250,7 +8269,8 @@ void SelectionDAGBuilder::visitInlineAsm(ImmutableCallSite CS) { } assert((OpInfo.ConstraintType == TargetLowering::C_RegisterClass || - OpInfo.ConstraintType == TargetLowering::C_Register) && + OpInfo.ConstraintType == TargetLowering::C_Register || + OpInfo.ConstraintType == TargetLowering::C_Immediate) && "Unknown constraint type!"); // TODO: Support this. @@ -8356,6 +8376,7 @@ void SelectionDAGBuilder::visitInlineAsm(ImmutableCallSite CS) { Val = OpInfo.AssignedRegs.getCopyFromRegs( DAG, FuncInfo, getCurSDLoc(), Chain, &Flag, CS.getInstruction()); break; + case TargetLowering::C_Immediate: case TargetLowering::C_Other: Val = TLI.LowerAsmOutputForConstraint(Chain, Flag, getCurSDLoc(), OpInfo, DAG); diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp index b260cd91d468..2d90dcba12b6 100644 --- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -3567,15 +3567,17 @@ TargetLowering::getConstraintType(StringRef Constraint) const { if (S == 1) { switch (Constraint[0]) { default: break; - case 'r': return C_RegisterClass; + case 'r': + return C_RegisterClass; case 'm': // memory case 'o': // offsetable case 'V': // not offsetable return C_Memory; - case 'i': // Simple Integer or Relocatable Constant case 'n': // Simple Integer case 'E': // Floating Point Constant case 'F': // Floating Point Constant + return C_Immediate; + case 'i': // Simple Integer or Relocatable Constant case 's': // Relocatable Constant case 'p': // Address. case 'X': // Allow ANY value. @@ -3950,6 +3952,7 @@ TargetLowering::ParseConstraints(const DataLayout &DL, /// Return an integer indicating how general CT is. static unsigned getConstraintGenerality(TargetLowering::ConstraintType CT) { switch (CT) { + case TargetLowering::C_Immediate: case TargetLowering::C_Other: case TargetLowering::C_Unknown: return 0; @@ -4069,11 +4072,12 @@ static void ChooseConstraint(TargetLowering::AsmOperandInfo &OpInfo, TargetLowering::ConstraintType CType = TLI.getConstraintType(OpInfo.Codes[i]); - // If this is an 'other' constraint, see if the operand is valid for it. - // For example, on X86 we might have an 'rI' constraint. If the operand - // is an integer in the range [0..31] we want to use I (saving a load - // of a register), otherwise we must use 'r'. - if (CType == TargetLowering::C_Other && Op.getNode()) { + // If this is an 'other' or 'immediate' constraint, see if the operand is + // valid for it. For example, on X86 we might have an 'rI' constraint. If + // the operand is an integer in the range [0..31] we want to use I (saving a + // load of a register), otherwise we must use 'r'. + if ((CType == TargetLowering::C_Other || + CType == TargetLowering::C_Immediate) && Op.getNode()) { assert(OpInfo.Codes[i].size() == 1 && "Unhandled multi-letter 'other' constraint"); std::vector ResultOps; diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp index 816db6f919bf..6c250aea39f0 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -5665,8 +5665,6 @@ AArch64TargetLowering::getConstraintType(StringRef Constraint) const { switch (Constraint[0]) { default: break; - case 'z': - return C_Other; case 'x': case 'w': return C_RegisterClass; @@ -5674,6 +5672,16 @@ AArch64TargetLowering::getConstraintType(StringRef Constraint) const { // currently handle addresses it is the same as 'r'. case 'Q': return C_Memory; + case 'I': + case 'J': + case 'K': + case 'L': + case 'M': + case 'N': + case 'Y': + case 'Z': + return C_Immediate; + case 'z': case 'S': // A symbolic address return C_Other; } diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp index 18bb9bf3eccc..d390c9e237e6 100644 --- a/llvm/lib/Target/ARM/ARMISelLowering.cpp +++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp @@ -14369,7 +14369,8 @@ const char *ARMTargetLowering::LowerXConstraint(EVT ConstraintVT) const { /// constraint it is for this target. ARMTargetLowering::ConstraintType ARMTargetLowering::getConstraintType(StringRef Constraint) const { - if (Constraint.size() == 1) { + unsigned S = Constraint.size(); + if (S == 1) { switch (Constraint[0]) { default: break; case 'l': return C_RegisterClass; @@ -14377,12 +14378,12 @@ ARMTargetLowering::getConstraintType(StringRef Constraint) const { case 'h': return C_RegisterClass; case 'x': return C_RegisterClass; case 't': return C_RegisterClass; - case 'j': return C_Other; // Constant for movw. - // An address with a single base register. Due to the way we - // currently handle addresses it is the same as an 'r' memory constraint. + case 'j': return C_Immediate; // Constant for movw. + // An address with a single base register. Due to the way we + // currently handle addresses it is the same as an 'r' memory constraint. case 'Q': return C_Memory; } - } else if (Constraint.size() == 2) { + } else if (S == 2) { switch (Constraint[0]) { default: break; case 'T': return C_RegisterClass; diff --git a/llvm/lib/Target/AVR/AVRISelLowering.cpp b/llvm/lib/Target/AVR/AVRISelLowering.cpp index b6ba5f22fafb..f159beee9730 100644 --- a/llvm/lib/Target/AVR/AVRISelLowering.cpp +++ b/llvm/lib/Target/AVR/AVRISelLowering.cpp @@ -1689,6 +1689,8 @@ AVRTargetLowering::getConstraintType(StringRef Constraint) const { if (Constraint.size() == 1) { // See http://www.nongnu.org/avr-libc/user-manual/inline_asm.html switch (Constraint[0]) { + default: + break; case 'a': // Simple upper registers case 'b': // Base pointer registers pairs case 'd': // Upper register @@ -1715,9 +1717,7 @@ AVRTargetLowering::getConstraintType(StringRef Constraint) const { case 'O': // Integer constant (Range: 8, 16, 24) case 'P': // Integer constant (Range: 1) case 'R': // Integer constant (Range: -6 to 5)x - return C_Other; - default: - break; + return C_Immediate; } } diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index b2dbff385305..cdad4d461f10 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -2407,6 +2407,10 @@ RISCVTargetLowering::getConstraintType(StringRef Constraint) const { break; case 'f': return C_RegisterClass; + case 'I': + case 'J': + case 'K': + return C_Immediate; } } return TargetLowering::getConstraintType(Constraint); diff --git a/llvm/lib/Target/Sparc/SparcISelLowering.cpp b/llvm/lib/Target/Sparc/SparcISelLowering.cpp index a6d440fa8aa2..804f7ba74edf 100644 --- a/llvm/lib/Target/Sparc/SparcISelLowering.cpp +++ b/llvm/lib/Target/Sparc/SparcISelLowering.cpp @@ -3183,7 +3183,7 @@ SparcTargetLowering::getConstraintType(StringRef Constraint) const { case 'e': return C_RegisterClass; case 'I': // SIMM13 - return C_Other; + return C_Immediate; } } diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp index 78820f511ab4..e7b7a5b0cd53 100644 --- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp +++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp @@ -956,7 +956,7 @@ SystemZTargetLowering::getConstraintType(StringRef Constraint) const { case 'K': // Signed 16-bit constant case 'L': // Signed 20-bit displacement (on all targets we support) case 'M': // 0x7fffffff - return C_Other; + return C_Immediate; default: break; diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index a03ce7988580..598fa9240f55 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -44656,10 +44656,11 @@ X86TargetLowering::getConstraintType(StringRef Constraint) const { case 'I': case 'J': case 'K': - case 'L': - case 'M': case 'N': case 'G': + case 'L': + case 'M': + return C_Immediate; case 'C': case 'e': case 'Z': diff --git a/llvm/test/CodeGen/AArch64/arm64-inline-asm-error-I.ll b/llvm/test/CodeGen/AArch64/arm64-inline-asm-error-I.ll index 7dc9f7260037..7784c9b24426 100644 --- a/llvm/test/CodeGen/AArch64/arm64-inline-asm-error-I.ll +++ b/llvm/test/CodeGen/AArch64/arm64-inline-asm-error-I.ll @@ -2,7 +2,7 @@ ; RUN: FileCheck --check-prefix=CHECK-ERRORS < %t %s ; Check for at least one invalid constant. -; CHECK-ERRORS: error: invalid operand for inline asm constraint 'I' +; CHECK-ERRORS: error: value out of range for constraint 'I' define i32 @constraint_I(i32 %i, i32 %j) nounwind ssp { entry: diff --git a/llvm/test/CodeGen/AArch64/arm64-inline-asm-error-J.ll b/llvm/test/CodeGen/AArch64/arm64-inline-asm-error-J.ll index 592875b0cb0c..c90178513d27 100644 --- a/llvm/test/CodeGen/AArch64/arm64-inline-asm-error-J.ll +++ b/llvm/test/CodeGen/AArch64/arm64-inline-asm-error-J.ll @@ -2,7 +2,7 @@ ; RUN: FileCheck --check-prefix=CHECK-ERRORS < %t %s ; Check for at least one invalid constant. -; CHECK-ERRORS: error: invalid operand for inline asm constraint 'J' +; CHECK-ERRORS: error: value out of range for constraint 'J' define i32 @constraint_J(i32 %i, i32 %j) nounwind ssp { entry: diff --git a/llvm/test/CodeGen/AArch64/arm64-inline-asm-error-K.ll b/llvm/test/CodeGen/AArch64/arm64-inline-asm-error-K.ll index 893e8d29e65d..e5baf85e9542 100644 --- a/llvm/test/CodeGen/AArch64/arm64-inline-asm-error-K.ll +++ b/llvm/test/CodeGen/AArch64/arm64-inline-asm-error-K.ll @@ -2,7 +2,7 @@ ; RUN: FileCheck --check-prefix=CHECK-ERRORS < %t %s ; Check for at least one invalid constant. -; CHECK-ERRORS: error: invalid operand for inline asm constraint 'K' +; CHECK-ERRORS: error: value out of range for constraint 'K' define i32 @constraint_K(i32 %i, i32 %j) nounwind { entry: diff --git a/llvm/test/CodeGen/AArch64/arm64-inline-asm-error-L.ll b/llvm/test/CodeGen/AArch64/arm64-inline-asm-error-L.ll index b2fb822aa299..cdba05627556 100644 --- a/llvm/test/CodeGen/AArch64/arm64-inline-asm-error-L.ll +++ b/llvm/test/CodeGen/AArch64/arm64-inline-asm-error-L.ll @@ -2,7 +2,7 @@ ; RUN: FileCheck --check-prefix=CHECK-ERRORS < %t %s ; Check for at least one invalid constant. -; CHECK-ERRORS: error: invalid operand for inline asm constraint 'L' +; CHECK-ERRORS: error: value out of range for constraint 'L' define i32 @constraint_L(i32 %i, i32 %j) nounwind { entry: diff --git a/llvm/test/CodeGen/AArch64/arm64-inline-asm-error-M.ll b/llvm/test/CodeGen/AArch64/arm64-inline-asm-error-M.ll index aaee933fd6dc..c7a786b26bbe 100644 --- a/llvm/test/CodeGen/AArch64/arm64-inline-asm-error-M.ll +++ b/llvm/test/CodeGen/AArch64/arm64-inline-asm-error-M.ll @@ -2,7 +2,7 @@ ; RUN: FileCheck --check-prefix=CHECK-ERRORS < %t %s ; Check for at least one invalid constant. -; CHECK-ERRORS: error: invalid operand for inline asm constraint 'M' +; CHECK-ERRORS: error: value out of range for constraint 'M' define i32 @constraint_M(i32 %i, i32 %j) nounwind { entry: diff --git a/llvm/test/CodeGen/AArch64/arm64-inline-asm-error-N.ll b/llvm/test/CodeGen/AArch64/arm64-inline-asm-error-N.ll index d1d2e03548e2..38b0ab8fa296 100644 --- a/llvm/test/CodeGen/AArch64/arm64-inline-asm-error-N.ll +++ b/llvm/test/CodeGen/AArch64/arm64-inline-asm-error-N.ll @@ -2,7 +2,7 @@ ; RUN: FileCheck --check-prefix=CHECK-ERRORS < %t %s ; Check for at least one invalid constant. -; CHECK-ERRORS: error: invalid operand for inline asm constraint 'N' +; CHECK-ERRORS: error: value out of range for constraint 'N' define i32 @constraint_N(i32 %i, i32 %j) nounwind { entry: diff --git a/llvm/test/CodeGen/RISCV/inline-asm-invalid.ll b/llvm/test/CodeGen/RISCV/inline-asm-invalid.ll index 06b0f2c2bfea..20ac5ef11111 100644 --- a/llvm/test/CodeGen/RISCV/inline-asm-invalid.ll +++ b/llvm/test/CodeGen/RISCV/inline-asm-invalid.ll @@ -2,23 +2,23 @@ ; RUN: not llc -mtriple=riscv64 < %s 2>&1 | FileCheck %s define void @constraint_I() { -; CHECK: error: invalid operand for inline asm constraint 'I' +; CHECK: error: value out of range for constraint 'I' tail call void asm sideeffect "addi a0, a0, $0", "I"(i32 2048) -; CHECK: error: invalid operand for inline asm constraint 'I' +; CHECK: error: value out of range for constraint 'I' tail call void asm sideeffect "addi a0, a0, $0", "I"(i32 -2049) ret void } define void @constraint_J() { -; CHECK: error: invalid operand for inline asm constraint 'J' +; CHECK: error: value out of range for constraint 'J' tail call void asm sideeffect "addi a0, a0, $0", "J"(i32 1) ret void } define void @constraint_K() { -; CHECK: error: invalid operand for inline asm constraint 'K' +; CHECK: error: value out of range for constraint 'K' tail call void asm sideeffect "csrwi mstatus, $0", "K"(i32 32) -; CHECK: error: invalid operand for inline asm constraint 'K' +; CHECK: error: value out of range for constraint 'K' tail call void asm sideeffect "csrwi mstatus, $0", "K"(i32 -1) ret void } diff --git a/llvm/test/CodeGen/X86/inline-asm-bad-constraint-n.ll b/llvm/test/CodeGen/X86/inline-asm-bad-constraint-n.ll index 967477d076d3..a3099ab36795 100644 --- a/llvm/test/CodeGen/X86/inline-asm-bad-constraint-n.ll +++ b/llvm/test/CodeGen/X86/inline-asm-bad-constraint-n.ll @@ -2,7 +2,7 @@ @x = global i32 0, align 4 -;CHECK: error: invalid operand for inline asm constraint 'n' +; CHECK: error: constraint 'n' expects an integer constant expression define void @foo() { %a = getelementptr i32, i32* @x, i32 1 call void asm sideeffect "foo $0", "n"(i32* %a) nounwind diff --git a/llvm/test/CodeGen/X86/inline-asm-e-constraint.ll b/llvm/test/CodeGen/X86/inline-asm-e-constraint.ll new file mode 100644 index 000000000000..fd10ba424081 --- /dev/null +++ b/llvm/test/CodeGen/X86/inline-asm-e-constraint.ll @@ -0,0 +1,17 @@ +; RUN: not llc -mtriple=x86_64-unknown-unknown -no-integrated-as < %s 2>&1 | FileCheck %s + +%struct.s = type { i32, i32 } + +@pr40890.s = internal global %struct.s zeroinitializer, align 4 + +; CHECK: error: invalid operand for inline asm constraint 'e' +; CHECK: error: invalid operand for inline asm constraint 'e' + +define void @pr40890() { +entry: + ; This pointer cannot be used as an integer constant expression. + tail call void asm sideeffect "\0A#define GLOBAL_A abcd$0\0A", "e,~{dirflag},~{fpsr},~{flags}"(i32* getelementptr inbounds (%struct.s, %struct.s* @pr40890.s, i64 0, i32 0)) + ; Floating-point is also not okay. + tail call void asm sideeffect "\0A#define PI abcd$0\0A", "e,~{dirflag},~{fpsr},~{flags}"(float 0x40091EB860000000) + ret void +} diff --git a/llvm/test/CodeGen/X86/inline-asm-imm-out-of-range.ll b/llvm/test/CodeGen/X86/inline-asm-imm-out-of-range.ll new file mode 100644 index 000000000000..9c5177d02a16 --- /dev/null +++ b/llvm/test/CodeGen/X86/inline-asm-imm-out-of-range.ll @@ -0,0 +1,7 @@ +; RUN: not llc -mtriple=i686-- -no-integrated-as < %s 2>&1 | FileCheck %s + +; CHECK: error: value out of range for constraint 'I' +define void @foo() { + call void asm sideeffect "foo $0", "I"(i32 42) + ret void +} diff --git a/llvm/test/CodeGen/X86/inline-asm-n-constraint.ll b/llvm/test/CodeGen/X86/inline-asm-n-constraint.ll new file mode 100644 index 000000000000..669e464f1f6f --- /dev/null +++ b/llvm/test/CodeGen/X86/inline-asm-n-constraint.ll @@ -0,0 +1,13 @@ +; RUN: llc -mtriple=x86_64-unknown-unknown -no-integrated-as < %s 2>&1 | FileCheck %s + +@x = global i32 0, align 4 + +define void @foo() { +; CHECK-LABEL: foo: + call void asm sideeffect "foo $0", "n"(i32 42) nounwind +; CHECK: #APP +; CHECK-NEXT: foo $42 +; CHECK-NEXT: #NO_APP + ret void +; CHECK-NEXT: retq +} From 87e914c5113d7b6f49324ff7c87ea260798b7f8e Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Fri, 9 Aug 2019 09:48:02 +0000 Subject: [PATCH 094/289] Merging r368104 and r368202: ------------------------------------------------------------------------ r368104 | void | 2019-08-07 00:41:22 +0200 (Wed, 07 Aug 2019) | 13 lines Delay diagnosing asm constraints that require immediates until after inlining Summary: An inline asm call may result in an immediate input value after inlining. Therefore, don't emit a diagnostic here if the input isn't an immediate. Reviewers: joerg, eli.friedman, rsmith Subscribers: asb, rbar, johnrusso, simoncook, apazos, sabuasal, niosHD, jrtc27, zzheng, edward-jones, rogfer01, MartinMosbeck, brucehoult, the_o, PkmX, jocewei, s.egerton, krytarowski, mgorny, riccibruno, eraman, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D60943 ------------------------------------------------------------------------ ------------------------------------------------------------------------ r368202 | void | 2019-08-07 21:36:48 +0200 (Wed, 07 Aug 2019) | 2 lines Add target requirements for those bots which don't handle x86. ------------------------------------------------------------------------ llvm-svn: 368422 --- clang/lib/CodeGen/CGStmt.cpp | 8 ++---- clang/lib/Sema/SemaStmtAsm.cpp | 32 +++++++++------------ clang/test/CodeGen/pr41027.c | 20 +++++++++++++ clang/test/Sema/inline-asm-validate-riscv.c | 3 -- clang/test/Sema/inline-asm-validate-x86.c | 25 ---------------- clang/test/Sema/pr41027.c | 10 ------- 6 files changed, 36 insertions(+), 62 deletions(-) create mode 100644 clang/test/CodeGen/pr41027.c delete mode 100644 clang/test/Sema/pr41027.c diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index dd0dea5b94a0..40ab79509f98 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -1846,11 +1846,9 @@ llvm::Value* CodeGenFunction::EmitAsmInput( InputExpr->EvaluateAsRValue(EVResult, getContext(), true); llvm::APSInt IntResult; - if (!EVResult.Val.toIntegralConstant(IntResult, InputExpr->getType(), - getContext())) - llvm_unreachable("Invalid immediate constant!"); - - return llvm::ConstantInt::get(getLLVMContext(), IntResult); + if (EVResult.Val.toIntegralConstant(IntResult, InputExpr->getType(), + getContext())) + return llvm::ConstantInt::get(getLLVMContext(), IntResult); } Expr::EvalResult Result; diff --git a/clang/lib/Sema/SemaStmtAsm.cpp b/clang/lib/Sema/SemaStmtAsm.cpp index b123a739a7ab..9b051e02d127 100644 --- a/clang/lib/Sema/SemaStmtAsm.cpp +++ b/clang/lib/Sema/SemaStmtAsm.cpp @@ -383,25 +383,19 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, } else if (Info.requiresImmediateConstant() && !Info.allowsRegister()) { if (!InputExpr->isValueDependent()) { Expr::EvalResult EVResult; - if (!InputExpr->EvaluateAsRValue(EVResult, Context, true)) - return StmtError( - Diag(InputExpr->getBeginLoc(), diag::err_asm_immediate_expected) - << Info.getConstraintStr() << InputExpr->getSourceRange()); - - // For compatibility with GCC, we also allow pointers that would be - // integral constant expressions if they were cast to int. - llvm::APSInt IntResult; - if (!EVResult.Val.toIntegralConstant(IntResult, InputExpr->getType(), - Context)) - return StmtError( - Diag(InputExpr->getBeginLoc(), diag::err_asm_immediate_expected) - << Info.getConstraintStr() << InputExpr->getSourceRange()); - - if (!Info.isValidAsmImmediate(IntResult)) - return StmtError(Diag(InputExpr->getBeginLoc(), - diag::err_invalid_asm_value_for_constraint) - << IntResult.toString(10) << Info.getConstraintStr() - << InputExpr->getSourceRange()); + if (InputExpr->EvaluateAsRValue(EVResult, Context, true)) { + // For compatibility with GCC, we also allow pointers that would be + // integral constant expressions if they were cast to int. + llvm::APSInt IntResult; + if (EVResult.Val.toIntegralConstant(IntResult, InputExpr->getType(), + Context)) + if (!Info.isValidAsmImmediate(IntResult)) + return StmtError(Diag(InputExpr->getBeginLoc(), + diag::err_invalid_asm_value_for_constraint) + << IntResult.toString(10) + << Info.getConstraintStr() + << InputExpr->getSourceRange()); + } } } else { diff --git a/clang/test/CodeGen/pr41027.c b/clang/test/CodeGen/pr41027.c new file mode 100644 index 000000000000..c16e232931c0 --- /dev/null +++ b/clang/test/CodeGen/pr41027.c @@ -0,0 +1,20 @@ +// REQUIRES: x86-registered-target +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -S -O2 -o - %s | FileCheck %s + +// CHECK-LABEL: f: +// CHECK: movl $1, %eax +// CHECK-NEXT: #APP +// CHECK-NEXT: outl %eax, $1 +// CHECK-NEXT: #NO_APP + +static inline void pr41027(unsigned a, unsigned b) { + if (__builtin_constant_p(a)) { + __asm__ volatile("outl %0,%w1" : : "a"(b), "n"(a)); + } else { + __asm__ volatile("outl %0,%w1" : : "a"(b), "d"(a)); + } +} + +void f(unsigned port) { + pr41027(1, 1); +} diff --git a/clang/test/Sema/inline-asm-validate-riscv.c b/clang/test/Sema/inline-asm-validate-riscv.c index cba08c865287..744f73e23cf2 100644 --- a/clang/test/Sema/inline-asm-validate-riscv.c +++ b/clang/test/Sema/inline-asm-validate-riscv.c @@ -4,7 +4,6 @@ void I(int i) { static const int BelowMin = -2049; static const int AboveMax = 2048; - asm volatile ("" :: "I"(i)); // expected-error{{constraint 'I' expects an integer constant expression}} asm volatile ("" :: "I"(BelowMin)); // expected-error{{value '-2049' out of range for constraint 'I'}} asm volatile ("" :: "I"(AboveMax)); // expected-error{{value '2048' out of range for constraint 'I'}} } @@ -12,7 +11,6 @@ void I(int i) { void J(int j) { static const int BelowMin = -1; static const int AboveMax = 1; - asm volatile ("" :: "J"(j)); // expected-error{{constraint 'J' expects an integer constant expression}} asm volatile ("" :: "J"(BelowMin)); // expected-error{{value '-1' out of range for constraint 'J'}} asm volatile ("" :: "J"(AboveMax)); // expected-error{{value '1' out of range for constraint 'J'}} } @@ -20,7 +18,6 @@ void J(int j) { void K(int k) { static const int BelowMin = -1; static const int AboveMax = 32; - asm volatile ("" :: "K"(k)); // expected-error{{constraint 'K' expects an integer constant expression}} asm volatile ("" :: "K"(BelowMin)); // expected-error{{value '-1' out of range for constraint 'K'}} asm volatile ("" :: "K"(AboveMax)); // expected-error{{value '32' out of range for constraint 'K'}} } diff --git a/clang/test/Sema/inline-asm-validate-x86.c b/clang/test/Sema/inline-asm-validate-x86.c index c6fa2e1b4fa8..87b60a095530 100644 --- a/clang/test/Sema/inline-asm-validate-x86.c +++ b/clang/test/Sema/inline-asm-validate-x86.c @@ -4,9 +4,6 @@ void I(int i, int j) { static const int BelowMin = -1; static const int AboveMax = 32; - __asm__("xorl %0,%2" - : "=r"(i) - : "0"(i), "I"(j)); // expected-error{{constraint 'I' expects an integer constant expression}} __asm__("xorl %0,%2" : "=r"(i) : "0"(i), "I"(BelowMin)); // expected-error{{value '-1' out of range for constraint 'I'}} @@ -21,9 +18,6 @@ void I(int i, int j) { void J(int i, int j) { static const int BelowMin = -1; static const int AboveMax = 64; - __asm__("xorl %0,%2" - : "=r"(i) - : "0"(i), "J"(j)); // expected-error{{constraint 'J' expects an integer constant expression}} __asm__("xorl %0,%2" : "=r"(i) : "0"(i), "J"(BelowMin)); // expected-error{{value '-1' out of range for constraint 'J'}} @@ -38,9 +32,6 @@ void J(int i, int j) { void K(int i, int j) { static const int BelowMin = -129; static const int AboveMax = 128; - __asm__("xorl %0,%2" - : "=r"(i) - : "0"(i), "K"(j)); // expected-error{{constraint 'K' expects an integer constant expression}} __asm__("xorl %0,%2" : "=r"(i) : "0"(i), "K"(BelowMin)); // expected-error{{value '-129' out of range for constraint 'K'}} @@ -60,9 +51,6 @@ void L(int i, int j) { static const int Valid1 = 0xff; static const int Valid2 = 0xffff; static const int Valid3 = 0xffffffff; - __asm__("xorl %0,%2" - : "=r"(i) - : "0"(i), "L"(j)); // expected-error{{constraint 'L' expects an integer constant expression}} __asm__("xorl %0,%2" : "=r"(i) : "0"(i), "L"(Invalid1)); // expected-error{{value '1' out of range for constraint 'L'}} @@ -89,9 +77,6 @@ void L(int i, int j) { void M(int i, int j) { static const int BelowMin = -1; static const int AboveMax = 4; - __asm__("xorl %0,%2" - : "=r"(i) - : "0"(i), "M"(j)); // expected-error{{constraint 'M' expects an integer constant expression}} __asm__("xorl %0,%2" : "=r"(i) : "0"(i), "M"(BelowMin)); // expected-error{{value '-1' out of range for constraint 'M'}} @@ -106,9 +91,6 @@ void M(int i, int j) { void N(int i, int j) { static const int BelowMin = -1; static const int AboveMax = 256; - __asm__("xorl %0,%2" - : "=r"(i) - : "0"(i), "N"(j)); // expected-error{{constraint 'N' expects an integer constant expression}} __asm__("xorl %0,%2" : "=r"(i) : "0"(i), "N"(BelowMin)); // expected-error{{value '-1' out of range for constraint 'N'}} @@ -123,9 +105,6 @@ void N(int i, int j) { void O(int i, int j) { static const int BelowMin = -1; static const int AboveMax = 128; - __asm__("xorl %0,%2" - : "=r"(i) - : "0"(i), "O"(j)); // expected-error{{constraint 'O' expects an integer constant expression}} __asm__("xorl %0,%2" : "=r"(i) : "0"(i), "O"(BelowMin)); // expected-error{{value '-1' out of range for constraint 'O'}} @@ -146,10 +125,6 @@ void pr40890(void) { __asm__ __volatile__("\n#define S_A abcd%0\n" : : "n"(&((struct s*)0)->a)); // This offset-from-null pointer can be used as an integer constant expression. __asm__ __volatile__("\n#define S_B abcd%0\n" : : "n"(&((struct s*)0)->b)); - // This pointer cannot be used as an integer constant expression. - __asm__ __volatile__("\n#define GLOBAL_A abcd%0\n" : : "n"(&s.a)); // expected-error{{constraint 'n' expects an integer constant expression}} - // Floating-point is also not okay. - __asm__ __volatile__("\n#define PI abcd%0\n" : : "n"(3.14f)); // expected-error{{constraint 'n' expects an integer constant expression}} #ifdef AMD64 // This arbitrary pointer is fine. __asm__ __volatile__("\n#define BEEF abcd%0\n" : : "n"((int*)0xdeadbeeeeeef)); diff --git a/clang/test/Sema/pr41027.c b/clang/test/Sema/pr41027.c deleted file mode 100644 index 94ace6463810..000000000000 --- a/clang/test/Sema/pr41027.c +++ /dev/null @@ -1,10 +0,0 @@ -// RUN: %clang_cc1 -triple x86_64 -fsyntax-only %s -// XFAIL: * - -inline void pr41027(unsigned a, unsigned b) { - if (__builtin_constant_p(a)) { - __asm__ volatile("outl %0,%w1" : : "a"(b), "n"(a)); - } else { - __asm__ volatile("outl %0,%w1" : : "a"(b), "d"(a)); - } -} From ffa29fd9c0891bd9afc184a4c6759feec32f21f1 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Fri, 9 Aug 2019 09:56:27 +0000 Subject: [PATCH 095/289] Merging r368324: ------------------------------------------------------------------------ r368324 | ctopper | 2019-08-08 20:11:17 +0200 (Thu, 08 Aug 2019) | 7 lines [X86] Make CMPXCHG16B feature imply CMPXCHG8B feature. This fixes znver1 so that it properly enables CMPXHG8B. We can probably remove explicit CMPXCHG8B from CPUs that also have CMPXCHG16B, but keeping this simple to allow cherry pick to 9.0. Fixes PR42935. ------------------------------------------------------------------------ llvm-svn: 368423 --- llvm/lib/Target/X86/X86.td | 3 ++- llvm/test/CodeGen/X86/cmpxchg8b.ll | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/llvm/lib/Target/X86/X86.td b/llvm/lib/Target/X86/X86.td index 3112f00c91f2..e20315da55a5 100644 --- a/llvm/lib/Target/X86/X86.td +++ b/llvm/lib/Target/X86/X86.td @@ -95,7 +95,8 @@ def Feature3DNowA : SubtargetFeature<"3dnowa", "X863DNowLevel", "ThreeDNowA", def Feature64Bit : SubtargetFeature<"64bit", "HasX86_64", "true", "Support 64-bit instructions">; def FeatureCMPXCHG16B : SubtargetFeature<"cx16", "HasCmpxchg16b", "true", - "64-bit with cmpxchg16b">; + "64-bit with cmpxchg16b", + [FeatureCMPXCHG8B]>; def FeatureSlowSHLD : SubtargetFeature<"slow-shld", "IsSHLDSlow", "true", "SHLD instruction is slow">; def FeatureSlowPMULLD : SubtargetFeature<"slow-pmulld", "IsPMULLDSlow", "true", diff --git a/llvm/test/CodeGen/X86/cmpxchg8b.ll b/llvm/test/CodeGen/X86/cmpxchg8b.ll index 8eb3dda6b6eb..caf40c541e28 100644 --- a/llvm/test/CodeGen/X86/cmpxchg8b.ll +++ b/llvm/test/CodeGen/X86/cmpxchg8b.ll @@ -2,6 +2,7 @@ ; RUN: llc < %s -mtriple=i686-unknown- -mcpu=core2 | FileCheck %s --check-prefixes=CHECK,X86 ; RUN: llc < %s -mtriple=x86_64-unknown- -mcpu=core2 | FileCheck %s --check-prefixes=CHECK,X64 ; RUN: llc < %s -mtriple=i686-unknown- -mcpu=i486 | FileCheck %s --check-prefixes=I486 +; RUN: llc < %s -mtriple=i686-unknown- -mcpu=znver1 | FileCheck %s --check-prefixes=CHECK,X86 ; Basic 64-bit cmpxchg define void @t1(i64* nocapture %p) nounwind ssp { From 542fb41b31e369c3123fa6aee19b82c7ce86fb77 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Fri, 9 Aug 2019 10:15:41 +0000 Subject: [PATCH 096/289] Merge r368103 '[TSAN] Fix tsan on FreeBSD after D54889' llvm-svn: 368426 --- compiler-rt/lib/tsan/rtl/tsan_rtl.cc | 1 + compiler-rt/test/tsan/ignored-interceptors-mmap.cc | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler-rt/lib/tsan/rtl/tsan_rtl.cc b/compiler-rt/lib/tsan/rtl/tsan_rtl.cc index 8a2704ff0631..897679128ac3 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_rtl.cc +++ b/compiler-rt/lib/tsan/rtl/tsan_rtl.cc @@ -149,6 +149,7 @@ static void BackgroundThread(void *arg) { // We don't use ScopedIgnoreInterceptors, because we want ignores to be // enabled even when the thread function exits (e.g. during pthread thread // shutdown code). + cur_thread_init(); cur_thread()->ignore_interceptors++; const u64 kMs2Ns = 1000 * 1000; diff --git a/compiler-rt/test/tsan/ignored-interceptors-mmap.cc b/compiler-rt/test/tsan/ignored-interceptors-mmap.cc index bb43250a659d..bcfafa409914 100644 --- a/compiler-rt/test/tsan/ignored-interceptors-mmap.cc +++ b/compiler-rt/test/tsan/ignored-interceptors-mmap.cc @@ -1,7 +1,7 @@ // RUN: %clangxx_tsan -O0 %s -o %t // RUN: not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-RACE // RUN: %run %t ignore 2>&1 | FileCheck %s --check-prefix=CHECK-IGNORE -// XFAIL: freebsd,netbsd +// XFAIL: netbsd #include #include From a23c9071322605f7186bd4c5d2f96a819b60c9ef Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Fri, 9 Aug 2019 10:19:34 +0000 Subject: [PATCH 097/289] Merging r367802: ------------------------------------------------------------------------ r367802 | baloghadamsoftware | 2019-08-05 08:45:41 +0200 (Mon, 05 Aug 2019) | 6 lines [Analyzer] Iterator Checkers - Fix for Crash on Iterator Differences Iterators differences were mistakenly handled as random decrements which causes an assertion. This patch fixes this. ------------------------------------------------------------------------ llvm-svn: 368427 --- .../lib/StaticAnalyzer/Checkers/IteratorChecker.cpp | 12 ++++++++---- .../Analysis/Inputs/system-header-simulator-cxx.h | 3 +++ .../Analysis/diagnostics/explicit-suppression.cpp | 2 +- clang/test/Analysis/iterator-range.cpp | 5 +++++ 4 files changed, 17 insertions(+), 5 deletions(-) diff --git a/clang/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp index 6f1060b5f26d..600458a743ea 100644 --- a/clang/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/IteratorChecker.cpp @@ -406,13 +406,15 @@ void IteratorChecker::checkPreCall(const CallEvent &Call, } else if (isRandomIncrOrDecrOperator(Func->getOverloadedOperator())) { if (const auto *InstCall = dyn_cast(&Call)) { // Check for out-of-range incrementions and decrementions - if (Call.getNumArgs() >= 1) { + if (Call.getNumArgs() >= 1 && + Call.getArgExpr(0)->getType()->isIntegralOrEnumerationType()) { verifyRandomIncrOrDecr(C, Func->getOverloadedOperator(), InstCall->getCXXThisVal(), Call.getArgSVal(0)); } } else { - if (Call.getNumArgs() >= 2) { + if (Call.getNumArgs() >= 2 && + Call.getArgExpr(1)->getType()->isIntegralOrEnumerationType()) { verifyRandomIncrOrDecr(C, Func->getOverloadedOperator(), Call.getArgSVal(0), Call.getArgSVal(1)); } @@ -590,14 +592,16 @@ void IteratorChecker::checkPostCall(const CallEvent &Call, return; } else if (isRandomIncrOrDecrOperator(Func->getOverloadedOperator())) { if (const auto *InstCall = dyn_cast(&Call)) { - if (Call.getNumArgs() >= 1) { + if (Call.getNumArgs() >= 1 && + Call.getArgExpr(0)->getType()->isIntegralOrEnumerationType()) { handleRandomIncrOrDecr(C, Func->getOverloadedOperator(), Call.getReturnValue(), InstCall->getCXXThisVal(), Call.getArgSVal(0)); return; } } else { - if (Call.getNumArgs() >= 2) { + if (Call.getNumArgs() >= 2 && + Call.getArgExpr(1)->getType()->isIntegralOrEnumerationType()) { handleRandomIncrOrDecr(C, Func->getOverloadedOperator(), Call.getReturnValue(), Call.getArgSVal(0), Call.getArgSVal(1)); diff --git a/clang/test/Analysis/Inputs/system-header-simulator-cxx.h b/clang/test/Analysis/Inputs/system-header-simulator-cxx.h index 5b37e96f6027..30b25b85944b 100644 --- a/clang/test/Analysis/Inputs/system-header-simulator-cxx.h +++ b/clang/test/Analysis/Inputs/system-header-simulator-cxx.h @@ -70,6 +70,9 @@ template struct __vector_iterator { return ptr -= n; } + template + difference_type operator-(const __vector_iterator &rhs); + Ref operator*() const { return *ptr; } Ptr operator->() const { return *ptr; } diff --git a/clang/test/Analysis/diagnostics/explicit-suppression.cpp b/clang/test/Analysis/diagnostics/explicit-suppression.cpp index 2bb969059ffb..6bc01479b815 100644 --- a/clang/test/Analysis/diagnostics/explicit-suppression.cpp +++ b/clang/test/Analysis/diagnostics/explicit-suppression.cpp @@ -19,6 +19,6 @@ class C { void testCopyNull(C *I, C *E) { std::copy(I, E, (C *)0); #ifndef SUPPRESSED - // expected-warning@../Inputs/system-header-simulator-cxx.h:677 {{Called C++ object pointer is null}} + // expected-warning@../Inputs/system-header-simulator-cxx.h:680 {{Called C++ object pointer is null}} #endif } diff --git a/clang/test/Analysis/iterator-range.cpp b/clang/test/Analysis/iterator-range.cpp index 6fc8939c8e84..bc7e08263ae2 100644 --- a/clang/test/Analysis/iterator-range.cpp +++ b/clang/test/Analysis/iterator-range.cpp @@ -236,3 +236,8 @@ void good_derived(simple_container c) { *i0; // no-warning } } + +void iter_diff(std::vector &V) { + auto i0 = V.begin(), i1 = V.end(); + ptrdiff_t len = i1 - i0; // no-crash +} From 47a55832c348102824c9b084a95b5e72981b2990 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Mon, 12 Aug 2019 13:40:27 +0000 Subject: [PATCH 098/289] Merging r368498: ------------------------------------------------------------------------ r368498 | sammccall | 2019-08-10 01:03:32 +0200 (Sat, 10 Aug 2019) | 25 lines clangd: use -j for background index pool Summary: clangd supports a -j option to limit the amount of threads to use for parsing TUs. However, when using -background-index (the default in later versions of clangd), the parallelism used by clangd defaults to the hardware_parallelisn, i.e. number of physical cores. On shared hardware environments, with large projects, this can significantly affect performance with no way to tune it down. This change makes the -j parameter apply equally to parsing and background index. It's not perfect, because the total number of threads is 2x the -j value, which may still be unexpected. But at least this change allows users to prevent clangd using all CPU cores. Reviewers: kadircet, sammccall Reviewed By: sammccall Subscribers: javed.absar, jfb, sammccall, ilya-biryukov, MaskRay, jkorous, arphaman, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D66031 ------------------------------------------------------------------------ llvm-svn: 368569 --- clang-tools-extra/clangd/ClangdServer.cpp | 8 +++++--- clang-tools-extra/clangd/TUScheduler.cpp | 9 +++++---- clang-tools-extra/clangd/tool/ClangdMain.cpp | 6 ++++-- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/clang-tools-extra/clangd/ClangdServer.cpp b/clang-tools-extra/clangd/ClangdServer.cpp index 7e77e18725a6..8cb72696f863 100644 --- a/clang-tools-extra/clangd/ClangdServer.cpp +++ b/clang-tools-extra/clangd/ClangdServer.cpp @@ -38,9 +38,11 @@ #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" +#include #include #include #include +#include namespace clang { namespace clangd { @@ -101,8 +103,7 @@ ClangdServer::ClangdServer(const GlobalCompilationDatabase &CDB, : nullptr), GetClangTidyOptions(Opts.GetClangTidyOptions), SuggestMissingIncludes(Opts.SuggestMissingIncludes), - TweakFilter(Opts.TweakFilter), - WorkspaceRoot(Opts.WorkspaceRoot), + TweakFilter(Opts.TweakFilter), WorkspaceRoot(Opts.WorkspaceRoot), // Pass a callback into `WorkScheduler` to extract symbols from a newly // parsed file and rebuild the file index synchronously each time an AST // is parsed. @@ -128,7 +129,8 @@ ClangdServer::ClangdServer(const GlobalCompilationDatabase &CDB, BackgroundIdx = llvm::make_unique( Context::current().clone(), FSProvider, CDB, BackgroundIndexStorage::createDiskBackedStorageFactory( - [&CDB](llvm::StringRef File) { return CDB.getProjectInfo(File); })); + [&CDB](llvm::StringRef File) { return CDB.getProjectInfo(File); }), + std::max(Opts.AsyncThreadsCount, 1u)); AddIndex(BackgroundIdx.get()); } if (DynamicIdx) diff --git a/clang-tools-extra/clangd/TUScheduler.cpp b/clang-tools-extra/clangd/TUScheduler.cpp index a77d226902c9..573c83140755 100644 --- a/clang-tools-extra/clangd/TUScheduler.cpp +++ b/clang-tools-extra/clangd/TUScheduler.cpp @@ -54,6 +54,7 @@ #include "llvm/ADT/ScopeExit.h" #include "llvm/Support/Errc.h" #include "llvm/Support/Path.h" +#include "llvm/Support/Threading.h" #include #include #include @@ -799,10 +800,10 @@ std::string renderTUAction(const TUAction &Action) { } // namespace unsigned getDefaultAsyncThreadsCount() { - unsigned HardwareConcurrency = std::thread::hardware_concurrency(); - // C++ standard says that hardware_concurrency() - // may return 0, fallback to 1 worker thread in - // that case. + unsigned HardwareConcurrency = llvm::heavyweight_hardware_concurrency(); + // heavyweight_hardware_concurrency may fall back to hardware_concurrency. + // C++ standard says that hardware_concurrency() may return 0; fallback to 1 + // worker thread in that case. if (HardwareConcurrency == 0) return 1; return HardwareConcurrency; diff --git a/clang-tools-extra/clangd/tool/ClangdMain.cpp b/clang-tools-extra/clangd/tool/ClangdMain.cpp index 840f3d6453f2..c047a9531e6a 100644 --- a/clang-tools-extra/clangd/tool/ClangdMain.cpp +++ b/clang-tools-extra/clangd/tool/ClangdMain.cpp @@ -267,7 +267,8 @@ list TweakList{ opt WorkerThreadsCount{ "j", cat(Misc), - desc("Number of async workers used by clangd"), + desc("Number of async workers used by clangd. Background index also " + "uses this many workers."), init(getDefaultAsyncThreadsCount()), }; @@ -308,7 +309,8 @@ opt PCHStorage{ opt Sync{ "sync", cat(Misc), - desc("Parse on main thread. If set, -j is ignored"), + desc("Handle client requests on main thread. Background index still uses " + "its own thread."), init(false), Hidden, }; From 4b59015880aa4db564f6aaa9c11cade58adb9f4e Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Mon, 12 Aug 2019 13:49:27 +0000 Subject: [PATCH 099/289] Merging r368230: ------------------------------------------------------------------------ r368230 | akhuang | 2019-08-08 00:49:40 +0200 (Thu, 08 Aug 2019) | 2 lines Recommit "[MS] Emit S_HEAPALLOCSITE debug info in Selection DAG" with a fix to clear the SDNode map when SelectionDAG is cleared. ------------------------------------------------------------------------ llvm-svn: 368571 --- llvm/include/llvm/CodeGen/SelectionDAG.h | 28 ++- .../SelectionDAG/ScheduleDAGSDNodes.cpp | 10 + .../lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 1 + llvm/lib/Target/X86/X86ISelLowering.cpp | 5 + llvm/test/CodeGen/X86/label-heapallocsite.ll | 173 ++++++++++-------- 5 files changed, 137 insertions(+), 80 deletions(-) diff --git a/llvm/include/llvm/CodeGen/SelectionDAG.h b/llvm/include/llvm/CodeGen/SelectionDAG.h index 12a970847021..45a598c898c8 100644 --- a/llvm/include/llvm/CodeGen/SelectionDAG.h +++ b/llvm/include/llvm/CodeGen/SelectionDAG.h @@ -269,7 +269,13 @@ class SelectionDAG { using CallSiteInfo = MachineFunction::CallSiteInfo; using CallSiteInfoImpl = MachineFunction::CallSiteInfoImpl; - DenseMap SDCallSiteInfo; + + struct CallSiteDbgInfo { + CallSiteInfo CSInfo; + MDNode *HeapAllocSite = nullptr; + }; + + DenseMap SDCallSiteDbgInfo; uint16_t NextPersistentId = 0; @@ -1664,16 +1670,28 @@ class SelectionDAG { } void addCallSiteInfo(const SDNode *CallNode, CallSiteInfoImpl &&CallInfo) { - SDCallSiteInfo[CallNode] = std::move(CallInfo); + SDCallSiteDbgInfo[CallNode].CSInfo = std::move(CallInfo); } CallSiteInfo getSDCallSiteInfo(const SDNode *CallNode) { - auto I = SDCallSiteInfo.find(CallNode); - if (I != SDCallSiteInfo.end()) - return std::move(I->second); + auto I = SDCallSiteDbgInfo.find(CallNode); + if (I != SDCallSiteDbgInfo.end()) + return std::move(I->second).CSInfo; return CallSiteInfo(); } + void addHeapAllocSite(const SDNode *Node, MDNode *MD) { + SDCallSiteDbgInfo[Node].HeapAllocSite = MD; + } + + /// Return the HeapAllocSite type associated with the SDNode, if it exists. + MDNode *getHeapAllocSite(const SDNode *Node) { + auto It = SDCallSiteDbgInfo.find(Node); + if (It == SDCallSiteDbgInfo.end()) + return nullptr; + return It->second.HeapAllocSite; + } + private: void InsertNode(SDNode *N); bool RemoveNodeFromCSEMaps(SDNode *N); diff --git a/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp b/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp index 568c6191e512..e09f2e760f55 100644 --- a/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/ScheduleDAGSDNodes.cpp @@ -909,6 +909,12 @@ EmitSchedule(MachineBasicBlock::iterator &InsertPos) { // Remember the source order of the inserted instruction. if (HasDbg) ProcessSourceNode(N, DAG, Emitter, VRBaseMap, Orders, Seen, NewInsn); + + if (MDNode *MD = DAG->getHeapAllocSite(N)) { + if (NewInsn && NewInsn->isCall()) + MF.addCodeViewHeapAllocSite(NewInsn, MD); + } + GluedNodes.pop_back(); } auto NewInsn = @@ -917,6 +923,10 @@ EmitSchedule(MachineBasicBlock::iterator &InsertPos) { if (HasDbg) ProcessSourceNode(SU->getNode(), DAG, Emitter, VRBaseMap, Orders, Seen, NewInsn); + if (MDNode *MD = DAG->getHeapAllocSite(SU->getNode())) { + if (NewInsn && NewInsn->isCall()) + MF.addCodeViewHeapAllocSite(NewInsn, MD); + } } // Insert all the dbg_values which have not already been inserted in source diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index 5852e693fa9f..6b0245dfd380 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -1084,6 +1084,7 @@ void SelectionDAG::clear() { ExternalSymbols.clear(); TargetExternalSymbols.clear(); MCSymbols.clear(); + SDCallSiteDbgInfo.clear(); std::fill(CondCodeNodes.begin(), CondCodeNodes.end(), static_cast(nullptr)); std::fill(ValueTypeNodes.begin(), ValueTypeNodes.end(), diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index 598fa9240f55..ff1e4ed85a41 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -4069,6 +4069,11 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, InFlag = Chain.getValue(1); DAG.addCallSiteInfo(Chain.getNode(), std::move(CSInfo)); + // Save heapallocsite metadata. + if (CLI.CS) + if (MDNode *HeapAlloc = CLI.CS->getMetadata("heapallocsite")) + DAG.addHeapAllocSite(Chain.getNode(), HeapAlloc); + // Create the CALLSEQ_END node. unsigned NumBytesForCalleeToPop; if (X86::isCalleePop(CallConv, Is64Bit, isVarArg, diff --git a/llvm/test/CodeGen/X86/label-heapallocsite.ll b/llvm/test/CodeGen/X86/label-heapallocsite.ll index f693695580ed..deb74c2ea237 100644 --- a/llvm/test/CodeGen/X86/label-heapallocsite.ll +++ b/llvm/test/CodeGen/X86/label-heapallocsite.ll @@ -1,80 +1,96 @@ -; RUN: llc -O0 < %s | FileCheck %s -; FIXME: Add test for llc with optimizations once it is implemented. +; RUN: llc < %s | FileCheck --check-prefixes=DAG,CHECK %s +; RUN: llc -O0 < %s | FileCheck --check-prefixes=FAST,CHECK %s ; Source to regenerate: -; $ clang --target=x86_64-windows-msvc -S heapallocsite.cpp -g -gcodeview -o t.ll \ -; -emit-llvm -O0 -Xclang -disable-llvm-passes -fms-extensions +; $ clang -cc1 -triple x86_64-windows-msvc t.cpp -debug-info-kind=limited \ +; -gcodeview -O2 -fms-extensions -emit-llvm -o t.ll ; -; struct Foo { +; extern "C" struct Foo { ; __declspec(allocator) virtual void *alloc(); ; }; -; ; extern "C" __declspec(allocator) Foo *alloc_foo(); -; -; extern "C" void use_alloc(void*); -; extern "C" void call_virtual(Foo *p) { -; use_alloc(p->alloc()); +; extern "C" void use_result(void *); +; extern "C" Foo *call_tail() { +; return alloc_foo(); ; } -; -; extern "C" void call_multiple() { -; use_alloc(alloc_foo()); -; use_alloc(alloc_foo()); +; extern "C" int call_virtual(Foo *p) { +; use_result(p->alloc()); +; return 0; +; } +; extern "C" int call_multiple() { +; use_result(alloc_foo()); +; use_result(alloc_foo()); +; return 0; ; } +; ModuleID = 't.cpp' +source_filename = "t.cpp" target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-windows-msvc" %struct.Foo = type { i32 (...)** } -; Function Attrs: noinline optnone uwtable -define dso_local void @call_virtual(%struct.Foo* %p) #0 !dbg !8 { +; Function Attrs: nounwind +define dso_local %struct.Foo* @call_tail() local_unnamed_addr #0 !dbg !7 { entry: - %p.addr = alloca %struct.Foo*, align 8 - store %struct.Foo* %p, %struct.Foo** %p.addr, align 8 - call void @llvm.dbg.declare(metadata %struct.Foo** %p.addr, metadata !13, metadata !DIExpression()), !dbg !14 - %0 = load %struct.Foo*, %struct.Foo** %p.addr, align 8, !dbg !15 - %1 = bitcast %struct.Foo* %0 to i8* (%struct.Foo*)***, !dbg !15 - %vtable = load i8* (%struct.Foo*)**, i8* (%struct.Foo*)*** %1, align 8, !dbg !15 - %vfn = getelementptr inbounds i8* (%struct.Foo*)*, i8* (%struct.Foo*)** %vtable, i64 0, !dbg !15 - %2 = load i8* (%struct.Foo*)*, i8* (%struct.Foo*)** %vfn, align 8, !dbg !15 - %call = call i8* %2(%struct.Foo* %0), !dbg !15, !heapallocsite !2 - call void @use_alloc(i8* %call), !dbg !15 - ret void, !dbg !16 + %call = tail call %struct.Foo* @alloc_foo() #3, !dbg !13, !heapallocsite !12 + ret %struct.Foo* %call, !dbg !13 } -; Function Attrs: nounwind readnone speculatable -declare void @llvm.dbg.declare(metadata, metadata, metadata) #1 +declare dso_local %struct.Foo* @alloc_foo() local_unnamed_addr #1 + +; Function Attrs: nounwind +define dso_local i32 @call_virtual(%struct.Foo* %p) local_unnamed_addr #0 !dbg !14 { +entry: + call void @llvm.dbg.value(metadata %struct.Foo* %p, metadata !19, metadata !DIExpression()), !dbg !20 + %0 = bitcast %struct.Foo* %p to i8* (%struct.Foo*)***, !dbg !21 + %vtable = load i8* (%struct.Foo*)**, i8* (%struct.Foo*)*** %0, align 8, !dbg !21, !tbaa !22 + %1 = load i8* (%struct.Foo*)*, i8* (%struct.Foo*)** %vtable, align 8, !dbg !21 + %call = tail call i8* %1(%struct.Foo* %p) #3, !dbg !21, !heapallocsite !2 + tail call void @use_result(i8* %call) #3, !dbg !21 + ret i32 0, !dbg !25 +} -declare dso_local void @use_alloc(i8*) #2 +declare dso_local void @use_result(i8*) local_unnamed_addr #1 -; Function Attrs: noinline optnone uwtable -define dso_local void @call_multiple() #0 !dbg !17 { +; Function Attrs: nounwind +define dso_local i32 @call_multiple() local_unnamed_addr #0 !dbg !26 { entry: - %call = call %struct.Foo* @alloc_foo(), !dbg !20, !heapallocsite !12 - %0 = bitcast %struct.Foo* %call to i8*, !dbg !20 - call void @use_alloc(i8* %0), !dbg !20 - %call1 = call %struct.Foo* @alloc_foo(), !dbg !21, !heapallocsite !12 - %1 = bitcast %struct.Foo* %call1 to i8*, !dbg !21 - call void @use_alloc(i8* %1), !dbg !21 - ret void, !dbg !22 + %call = tail call %struct.Foo* @alloc_foo() #3, !dbg !29, !heapallocsite !12 + %0 = bitcast %struct.Foo* %call to i8*, !dbg !29 + tail call void @use_result(i8* %0) #3, !dbg !29 + %call1 = tail call %struct.Foo* @alloc_foo() #3, !dbg !30, !heapallocsite !12 + %1 = bitcast %struct.Foo* %call1 to i8*, !dbg !30 + tail call void @use_result(i8* %1) #3, !dbg !30 + ret i32 0, !dbg !31 } -declare dso_local %struct.Foo* @alloc_foo() #2 +; Function Attrs: nounwind readnone speculatable willreturn +declare void @llvm.dbg.value(metadata, metadata, metadata) #2 -; CHECK-LABEL: call_virtual: # @call_virtual + +; Don't emit metadata for tail calls. +; CHECK-LABEL: call_tail: # @call_tail +; CHECK-NOT: .Lheapallocsite +; CHECK: jmp alloc_foo + +; CHECK-LABEL: call_virtual: # @call_virtual ; CHECK: .Lheapallocsite0: -; CHECK: callq *(%rax) +; CHECK: callq *{{.*}}%rax{{.*}} ; CHECK: .Lheapallocsite1: -; CHECK: retq -; CHECK-LABEL: call_multiple: # @call_multiple -; CHECK: .Lheapallocsite4: +; CHECK-LABEL: call_multiple: # @call_multiple +; FastISel emits instructions in a different order. +; DAG: .Lheapallocsite2: +; FAST: .Lheapallocsite4: ; CHECK: callq alloc_foo -; CHECK: .Lheapallocsite5: -; CHECK: .Lheapallocsite2: +; DAG: .Lheapallocsite3: +; FAST: .Lheapallocsite5: +; DAG: .Lheapallocsite4: +; FAST: .Lheapallocsite2: ; CHECK: callq alloc_foo -; CHECK: .Lheapallocsite3: -; CHECK: retq +; DAG: .Lheapallocsite5: +; FAST: .Lheapallocsite3: ; CHECK-LABEL: .short 4423 # Record kind: S_GPROC32_ID ; CHECK: .short 4446 # Record kind: S_HEAPALLOCSITE @@ -82,48 +98,55 @@ declare dso_local %struct.Foo* @alloc_foo() #2 ; CHECK-NEXT: .secidx .Lheapallocsite0 ; CHECK-NEXT: .short .Lheapallocsite1-.Lheapallocsite0 ; CHECK-NEXT: .long 3 -; CHECK-NEXT: .p2align 2 -; CHECK-LABEL: .short 4431 # Record kind: S_PROC_ID_END - -; CHECK-LABEL: .short 4423 # Record kind: S_GPROC32_ID ; CHECK: .short 4446 # Record kind: S_HEAPALLOCSITE ; CHECK-NEXT: .secrel32 .Lheapallocsite2 ; CHECK-NEXT: .secidx .Lheapallocsite2 ; CHECK-NEXT: .short .Lheapallocsite3-.Lheapallocsite2 ; CHECK-NEXT: .long 4096 -; CHECK-NEXT: .p2align 2 - ; CHECK: .short 4446 # Record kind: S_HEAPALLOCSITE ; CHECK-NEXT: .secrel32 .Lheapallocsite4 ; CHECK-NEXT: .secidx .Lheapallocsite4 ; CHECK-NEXT: .short .Lheapallocsite5-.Lheapallocsite4 ; CHECK-NEXT: .long 4096 -; CHECK-NEXT: .p2align 2 -; CHECK-LABEL: .short 4431 # Record kind: S_PROC_ID_END + +attributes #0 = { nounwind "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="none" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-features"="+cx8,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #1 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "frame-pointer"="none" "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-features"="+cx8,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #2 = { nounwind readnone speculatable willreturn } +attributes #3 = { nounwind } !llvm.dbg.cu = !{!0} -!llvm.module.flags = !{!3, !4, !5, !6} -!llvm.ident = !{!7} +!llvm.module.flags = !{!3, !4, !5} +!llvm.ident = !{!6} -!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 9.0.0 (https://github.com/llvm/llvm-project.git 9c8073f44f786fbf47335e53f20abe64429e8e47)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None)!1 = !DIFile(filename: "filename", directory: "directory", checksumkind: CSK_MD5, checksum: "096443b661a0af36da9006330c08f97e") +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 10.0.0 (https://github.com/llvm/llvm-project.git fa686ea7650235c6dff988cc8cba49e130b3d5f8)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None) +!1 = !DIFile(filename: "", directory: "/usr/local/google/home/akhuang/testing/heapallocsite", checksumkind: CSK_MD5, checksum: "e0a04508b4229fc4aee0baa364e25987") !2 = !{} !3 = !{i32 2, !"CodeView", i32 1} !4 = !{i32 2, !"Debug Info Version", i32 3} !5 = !{i32 1, !"wchar_size", i32 2} -!6 = !{i32 7, !"PIC Level", i32 2} -!7 = !{!"clang version 9.0.0 (https://github.com/llvm/llvm-project.git 9c8073f44f786fbf47335e53f20abe64429e8e47)"} -!8 = distinct !DISubprogram(name: "call_virtual", scope: !1, file: !1, line: 8, type: !9, scopeLine: 8, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2) +!6 = !{!"clang version 10.0.0 (https://github.com/llvm/llvm-project.git fa686ea7650235c6dff988cc8cba49e130b3d5f8)"} +!7 = distinct !DISubprogram(name: "call_tail", scope: !8, file: !8, line: 6, type: !9, scopeLine: 6, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !2) +!8 = !DIFile(filename: "t.cpp", directory: "/usr/local/google/home/akhuang/testing/heapallocsite", checksumkind: CSK_MD5, checksum: "e0a04508b4229fc4aee0baa364e25987") !9 = !DISubroutineType(types: !10) -!10 = !{null, !11} +!10 = !{!11} !11 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !12, size: 64) -!12 = !DICompositeType(tag: DW_TAG_structure_type, name: "Foo", file: !1, line: 1, flags: DIFlagFwdDecl, identifier: ".?AUFoo@@") -!13 = !DILocalVariable(name: "p", arg: 1, scope: !8, file: !1, line: 8, type: !11) -!14 = !DILocation(line: 8, scope: !8) -!15 = !DILocation(line: 9, scope: !8) -!16 = !DILocation(line: 10, scope: !8) -!17 = distinct !DISubprogram(name: "call_multiple", scope: !1, file: !1, line: 12, type: !18, scopeLine: 12, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2) -!18 = !DISubroutineType(types: !19) -!19 = !{null} -!20 = !DILocation(line: 13, scope: !17) -!21 = !DILocation(line: 14, scope: !17) -!22 = !DILocation(line: 15, scope: !17) +!12 = !DICompositeType(tag: DW_TAG_structure_type, name: "Foo", file: !8, line: 1, flags: DIFlagFwdDecl, identifier: ".?AUFoo@@") +!13 = !DILocation(line: 7, scope: !7) +!14 = distinct !DISubprogram(name: "call_virtual", scope: !8, file: !8, line: 9, type: !15, scopeLine: 9, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !18) +!15 = !DISubroutineType(types: !16) +!16 = !{!17, !11} +!17 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!18 = !{!19} +!19 = !DILocalVariable(name: "p", arg: 1, scope: !14, file: !8, line: 9, type: !11) +!20 = !DILocation(line: 0, scope: !14) +!21 = !DILocation(line: 10, scope: !14) +!22 = !{!23, !23, i64 0} +!23 = !{!"vtable pointer", !24, i64 0} +!24 = !{!"Simple C++ TBAA"} +!25 = !DILocation(line: 11, scope: !14) +!26 = distinct !DISubprogram(name: "call_multiple", scope: !8, file: !8, line: 13, type: !27, scopeLine: 13, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !2) +!27 = !DISubroutineType(types: !28) +!28 = !{!17} +!29 = !DILocation(line: 14, scope: !26) +!30 = !DILocation(line: 15, scope: !26) +!31 = !DILocation(line: 16, scope: !26) From b13c264ccaf8891c3f784afef8f48f609c9f5ce5 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Tue, 13 Aug 2019 11:35:16 +0000 Subject: [PATCH 100/289] Merging r366541: ------------------------------------------------------------------------ r366541 | hokein | 2019-07-19 10:33:39 +0200 (Fri, 19 Jul 2019) | 11 lines [clangd] cleanup: unify the implemenation of checking a location is inside main file. Summary: We have variant implementations in the codebase, this patch unifies them. Reviewers: ilya-biryukov, kadircet Subscribers: MaskRay, jkorous, arphaman, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D64915 ------------------------------------------------------------------------ llvm-svn: 368669 --- clang-tools-extra/clangd/ClangdUnit.cpp | 5 ++-- clang-tools-extra/clangd/Diagnostics.cpp | 6 +--- clang-tools-extra/clangd/Headers.cpp | 2 +- clang-tools-extra/clangd/IncludeFixer.cpp | 2 +- clang-tools-extra/clangd/Quality.cpp | 7 ++--- clang-tools-extra/clangd/SourceCode.cpp | 4 +++ clang-tools-extra/clangd/SourceCode.h | 8 +++++ clang-tools-extra/clangd/XRefs.cpp | 2 +- .../clangd/index/SymbolCollector.cpp | 3 +- clang-tools-extra/clangd/refactor/Rename.cpp | 3 +- .../clangd/unittests/SourceCodeTests.cpp | 30 +++++++++++++++++++ .../clangd/unittests/SymbolCollectorTests.cpp | 3 +- 12 files changed, 54 insertions(+), 21 deletions(-) diff --git a/clang-tools-extra/clangd/ClangdUnit.cpp b/clang-tools-extra/clangd/ClangdUnit.cpp index b337d851d0f7..3e9db706cfad 100644 --- a/clang-tools-extra/clangd/ClangdUnit.cpp +++ b/clang-tools-extra/clangd/ClangdUnit.cpp @@ -68,7 +68,7 @@ class DeclTrackingASTConsumer : public ASTConsumer { bool HandleTopLevelDecl(DeclGroupRef DG) override { for (Decl *D : DG) { auto &SM = D->getASTContext().getSourceManager(); - if (!SM.isWrittenInMainFile(SM.getExpansionLoc(D->getLocation()))) + if (!isInsideMainFile(D->getLocation(), SM)) continue; // ObjCMethodDecl are not actually top-level decls. @@ -355,8 +355,7 @@ ParsedAST::build(std::unique_ptr CI, // those might take us into a preamble file as well. bool IsInsideMainFile = Info.hasSourceManager() && - Info.getSourceManager().isWrittenInMainFile( - Info.getSourceManager().getFileLoc(Info.getLocation())); + isInsideMainFile(Info.getLocation(), Info.getSourceManager()); if (IsInsideMainFile && tidy::ShouldSuppressDiagnostic( DiagLevel, Info, *CTContext, /* CheckMacroExpansion = */ false)) { diff --git a/clang-tools-extra/clangd/Diagnostics.cpp b/clang-tools-extra/clangd/Diagnostics.cpp index 88bd6fdcad11..53192711a5df 100644 --- a/clang-tools-extra/clangd/Diagnostics.cpp +++ b/clang-tools-extra/clangd/Diagnostics.cpp @@ -140,15 +140,11 @@ void adjustDiagFromHeader(Diag &D, const clang::Diagnostic &Info, D.Message = llvm::Twine("in included file: ", D.Message).str(); } -bool isInsideMainFile(const SourceLocation Loc, const SourceManager &M) { - return Loc.isValid() && M.isWrittenInMainFile(M.getFileLoc(Loc)); -} - bool isInsideMainFile(const clang::Diagnostic &D) { if (!D.hasSourceManager()) return false; - return isInsideMainFile(D.getLocation(), D.getSourceManager()); + return clangd::isInsideMainFile(D.getLocation(), D.getSourceManager()); } bool isNote(DiagnosticsEngine::Level L) { diff --git a/clang-tools-extra/clangd/Headers.cpp b/clang-tools-extra/clangd/Headers.cpp index 877301ee2d92..7caaebaa6f30 100644 --- a/clang-tools-extra/clangd/Headers.cpp +++ b/clang-tools-extra/clangd/Headers.cpp @@ -35,7 +35,7 @@ class RecordHeaders : public PPCallbacks { llvm::StringRef /*RelativePath*/, const Module * /*Imported*/, SrcMgr::CharacteristicKind FileKind) override { - if (SM.isWrittenInMainFile(HashLoc)) { + if (isInsideMainFile(HashLoc, SM)) { Out->MainFileIncludes.emplace_back(); auto &Inc = Out->MainFileIncludes.back(); Inc.R = halfOpenToRange(SM, FilenameRange); diff --git a/clang-tools-extra/clangd/IncludeFixer.cpp b/clang-tools-extra/clangd/IncludeFixer.cpp index eb525f40e257..081dad83583b 100644 --- a/clang-tools-extra/clangd/IncludeFixer.cpp +++ b/clang-tools-extra/clangd/IncludeFixer.cpp @@ -338,7 +338,7 @@ class IncludeFixer::UnresolvedNameRecorder : public ExternalSemaSource { assert(SemaPtr && "Sema must have been set."); if (SemaPtr->isSFINAEContext()) return TypoCorrection(); - if (!SemaPtr->SourceMgr.isWrittenInMainFile(Typo.getLoc())) + if (!isInsideMainFile(Typo.getLoc(), SemaPtr->SourceMgr)) return clang::TypoCorrection(); auto Extracted = extractUnresolvedNameCheaply( diff --git a/clang-tools-extra/clangd/Quality.cpp b/clang-tools-extra/clangd/Quality.cpp index 6ab05293274f..bd25256904cd 100644 --- a/clang-tools-extra/clangd/Quality.cpp +++ b/clang-tools-extra/clangd/Quality.cpp @@ -9,6 +9,7 @@ #include "Quality.h" #include "AST.h" #include "FileDistance.h" +#include "SourceCode.h" #include "URI.h" #include "index/Symbol.h" #include "clang/AST/ASTContext.h" @@ -42,8 +43,7 @@ static bool isReserved(llvm::StringRef Name) { static bool hasDeclInMainFile(const Decl &D) { auto &SourceMgr = D.getASTContext().getSourceManager(); for (auto *Redecl : D.redecls()) { - auto Loc = SourceMgr.getSpellingLoc(Redecl->getLocation()); - if (SourceMgr.isWrittenInMainFile(Loc)) + if (isInsideMainFile(Redecl->getLocation(), SourceMgr)) return true; } return false; @@ -53,8 +53,7 @@ static bool hasUsingDeclInMainFile(const CodeCompletionResult &R) { const auto &Context = R.Declaration->getASTContext(); const auto &SourceMgr = Context.getSourceManager(); if (R.ShadowDecl) { - const auto Loc = SourceMgr.getExpansionLoc(R.ShadowDecl->getLocation()); - if (SourceMgr.isWrittenInMainFile(Loc)) + if (isInsideMainFile(R.ShadowDecl->getLocation(), SourceMgr)) return true; } return false; diff --git a/clang-tools-extra/clangd/SourceCode.cpp b/clang-tools-extra/clangd/SourceCode.cpp index 9996f0ba6749..5370a8d88479 100644 --- a/clang-tools-extra/clangd/SourceCode.cpp +++ b/clang-tools-extra/clangd/SourceCode.cpp @@ -369,6 +369,10 @@ static SourceRange getTokenFileRange(SourceLocation Loc, return FileRange; } +bool isInsideMainFile(SourceLocation Loc, const SourceManager &SM) { + return Loc.isValid() && SM.isWrittenInMainFile(SM.getExpansionLoc(Loc)); +} + llvm::Optional toHalfOpenFileRange(const SourceManager &SM, const LangOptions &LangOpts, SourceRange R) { diff --git a/clang-tools-extra/clangd/SourceCode.h b/clang-tools-extra/clangd/SourceCode.h index 8e58e66f4db8..4bbf3cf49fcd 100644 --- a/clang-tools-extra/clangd/SourceCode.h +++ b/clang-tools-extra/clangd/SourceCode.h @@ -75,6 +75,14 @@ llvm::Optional getTokenRange(const SourceManager &SM, llvm::Expected sourceLocationInMainFile(const SourceManager &SM, Position P); +/// Returns true iff \p Loc is inside the main file. This function handles +/// file & macro locations. For macro locations, returns iff the macro is being +/// expanded inside the main file. +/// +/// The function is usually used to check whether a declaration is inside the +/// the main file. +bool isInsideMainFile(SourceLocation Loc, const SourceManager &SM); + /// Turns a token range into a half-open range and checks its correctness. /// The resulting range will have only valid source location on both sides, both /// of which are file locations. diff --git a/clang-tools-extra/clangd/XRefs.cpp b/clang-tools-extra/clangd/XRefs.cpp index 77c975870c01..6d4f6f1fb292 100644 --- a/clang-tools-extra/clangd/XRefs.cpp +++ b/clang-tools-extra/clangd/XRefs.cpp @@ -406,7 +406,7 @@ class ReferenceFinder : public index::IndexDataConsumer { assert(D->isCanonicalDecl() && "expect D to be a canonical declaration"); const SourceManager &SM = AST.getSourceManager(); Loc = SM.getFileLoc(Loc); - if (SM.isWrittenInMainFile(Loc) && CanonicalTargets.count(D)) + if (isInsideMainFile(Loc, SM) && CanonicalTargets.count(D)) References.push_back({D, Loc, Roles}); return true; } diff --git a/clang-tools-extra/clangd/index/SymbolCollector.cpp b/clang-tools-extra/clangd/index/SymbolCollector.cpp index 8b2d40b3d389..cca8b004ca36 100644 --- a/clang-tools-extra/clangd/index/SymbolCollector.cpp +++ b/clang-tools-extra/clangd/index/SymbolCollector.cpp @@ -185,8 +185,7 @@ getTokenLocation(SourceLocation TokLoc, const SourceManager &SM, bool isPreferredDeclaration(const NamedDecl &ND, index::SymbolRoleSet Roles) { const auto &SM = ND.getASTContext().getSourceManager(); return (Roles & static_cast(index::SymbolRole::Definition)) && - isa(&ND) && - !SM.isWrittenInMainFile(SM.getExpansionLoc(ND.getLocation())); + isa(&ND) && !isInsideMainFile(ND.getLocation(), SM); } RefKind toRefKind(index::SymbolRoleSet Roles) { diff --git a/clang-tools-extra/clangd/refactor/Rename.cpp b/clang-tools-extra/clangd/refactor/Rename.cpp index d54fae519140..b66eac4ee8da 100644 --- a/clang-tools-extra/clangd/refactor/Rename.cpp +++ b/clang-tools-extra/clangd/refactor/Rename.cpp @@ -104,8 +104,7 @@ llvm::Optional renamableWithinFile(const Decl &RenameDecl, auto &ASTCtx = RenameDecl.getASTContext(); const auto &SM = ASTCtx.getSourceManager(); bool MainFileIsHeader = ASTCtx.getLangOpts().IsHeaderFile; - bool DeclaredInMainFile = - SM.isWrittenInMainFile(SM.getExpansionLoc(RenameDecl.getLocation())); + bool DeclaredInMainFile = isInsideMainFile(RenameDecl.getBeginLoc(), SM); // If the symbol is declared in the main file (which is not a header), we // rename it. diff --git a/clang-tools-extra/clangd/unittests/SourceCodeTests.cpp b/clang-tools-extra/clangd/unittests/SourceCodeTests.cpp index 1b2f4266bc2b..47d1f802cb7d 100644 --- a/clang-tools-extra/clangd/unittests/SourceCodeTests.cpp +++ b/clang-tools-extra/clangd/unittests/SourceCodeTests.cpp @@ -422,6 +422,36 @@ TEST(SourceCodeTests, GetMacros) { EXPECT_THAT(*Result, MacroName("MACRO")); } +TEST(SourceCodeTests, IsInsideMainFile){ + TestTU TU; + TU.HeaderCode = R"cpp( + #define DEFINE_CLASS(X) class X {}; + #define DEFINE_YY DEFINE_CLASS(YY) + + class Header1 {}; + DEFINE_CLASS(Header2) + class Header {}; + )cpp"; + TU.Code = R"cpp( + class Main1 {}; + DEFINE_CLASS(Main2) + DEFINE_YY + class Main {}; + )cpp"; + TU.ExtraArgs.push_back("-DHeader=Header3"); + TU.ExtraArgs.push_back("-DMain=Main3"); + auto AST = TU.build(); + const auto& SM = AST.getSourceManager(); + auto DeclLoc = [&AST](llvm::StringRef Name) { + return findDecl(AST, Name).getLocation(); + }; + for (const auto *HeaderDecl : {"Header1", "Header2", "Header3"}) + EXPECT_FALSE(isInsideMainFile(DeclLoc(HeaderDecl), SM)); + + for (const auto *MainDecl : {"Main1", "Main2", "Main3", "YY"}) + EXPECT_TRUE(isInsideMainFile(DeclLoc(MainDecl), SM)); +} + // Test for functions toHalfOpenFileRange and getHalfOpenFileRange TEST(SourceCodeTests, HalfOpenFileRange) { // Each marked range should be the file range of the decl with the same name diff --git a/clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp b/clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp index 8c88fe5169d8..8caa1c5aa732 100644 --- a/clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp +++ b/clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp @@ -124,8 +124,7 @@ class ShouldCollectSymbolTest : public ::testing::Test { const NamedDecl &ND = Qualified ? findDecl(*AST, Name) : findUnqualifiedDecl(*AST, Name); const SourceManager &SM = AST->getSourceManager(); - bool MainFile = - SM.isWrittenInMainFile(SM.getExpansionLoc(ND.getBeginLoc())); + bool MainFile = isInsideMainFile(ND.getBeginLoc(), SM); return SymbolCollector::shouldCollectSymbol( ND, AST->getASTContext(), SymbolCollector::Options(), MainFile); } From 2c69b1377cb6327b601045451adc59cbf852ef7e Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Tue, 13 Aug 2019 11:42:12 +0000 Subject: [PATCH 101/289] Merging r368581: ------------------------------------------------------------------------ r368581 | ibiryukov | 2019-08-12 16:35:30 +0200 (Mon, 12 Aug 2019) | 18 lines [clangd] Separate chunks with a space when rendering markdown Summary: This results in better rendering of resulting markdown. Especially noticeable in coc.nvim that does not have a visible horizontal spaces around inline code blocks. More details and a screenshot from coc.nvim can be found in https://github.com/clangd/clangd/issues/95. Reviewers: sammccall Reviewed By: sammccall Subscribers: MaskRay, jkorous, arphaman, kadircet, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D66086 ------------------------------------------------------------------------ llvm-svn: 368670 --- clang-tools-extra/clangd/FormattedString.cpp | 11 ++++-- .../clangd/unittests/FormattedStringTests.cpp | 38 ++++++++++++++++++- 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/clang-tools-extra/clangd/FormattedString.cpp b/clang-tools-extra/clangd/FormattedString.cpp index 102612af03a1..27fd37b9ae62 100644 --- a/clang-tools-extra/clangd/FormattedString.cpp +++ b/clang-tools-extra/clangd/FormattedString.cpp @@ -112,15 +112,20 @@ void FormattedString::appendInlineCode(std::string Code) { std::string FormattedString::renderAsMarkdown() const { std::string R; + auto EnsureWhitespace = [&R]() { + // Adds a space for nicer rendering. + if (!R.empty() && !isWhitespace(R.back())) + R += " "; + }; for (const auto &C : Chunks) { switch (C.Kind) { case ChunkKind::PlainText: + if (!C.Contents.empty() && !isWhitespace(C.Contents.front())) + EnsureWhitespace(); R += renderText(C.Contents); continue; case ChunkKind::InlineCodeBlock: - // Make sure we don't glue two backticks together. - if (llvm::StringRef(R).endswith("`")) - R += " "; + EnsureWhitespace(); R += renderInlineBlock(C.Contents); continue; case ChunkKind::CodeBlock: diff --git a/clang-tools-extra/clangd/unittests/FormattedStringTests.cpp b/clang-tools-extra/clangd/unittests/FormattedStringTests.cpp index da19f890dadb..e8077563df1a 100644 --- a/clang-tools-extra/clangd/unittests/FormattedStringTests.cpp +++ b/clang-tools-extra/clangd/unittests/FormattedStringTests.cpp @@ -72,7 +72,7 @@ after)md"; S.appendText("baz"); EXPECT_EQ(S.renderAsPlainText(), "foo bar baz"); - EXPECT_EQ(S.renderAsMarkdown(), "foo`bar`baz"); + EXPECT_EQ(S.renderAsMarkdown(), "foo `bar` baz"); } TEST(FormattedString, Escaping) { @@ -158,6 +158,42 @@ TEST(FormattedString, Escaping) { "`````\n"); } +TEST(FormattedString, MarkdownWhitespace) { + // Whitespace should be added as separators between blocks. + FormattedString S; + S.appendText("foo"); + S.appendText("bar"); + EXPECT_EQ(S.renderAsMarkdown(), "foo bar"); + + S = FormattedString(); + S.appendInlineCode("foo"); + S.appendInlineCode("bar"); + EXPECT_EQ(S.renderAsMarkdown(), "`foo` `bar`"); + + // However, we don't want to add any extra whitespace. + S = FormattedString(); + S.appendText("foo "); + S.appendInlineCode("bar"); + EXPECT_EQ(S.renderAsMarkdown(), "foo `bar`"); + + S = FormattedString(); + S.appendText("foo\n"); + S.appendInlineCode("bar"); + EXPECT_EQ(S.renderAsMarkdown(), "foo\n`bar`"); + + S = FormattedString(); + S.appendInlineCode("foo"); + S.appendText(" bar"); + EXPECT_EQ(S.renderAsMarkdown(), "`foo` bar"); + + S = FormattedString(); + S.appendText("foo"); + S.appendCodeBlock("bar"); + S.appendText("baz"); + EXPECT_EQ(S.renderAsMarkdown(), "foo\n```cpp\nbar\n```\nbaz"); +} + + } // namespace } // namespace clangd } // namespace clang From 97e6d088e9466dd79a2ae8c22e7e47f98cdf347a Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Tue, 13 Aug 2019 11:56:03 +0000 Subject: [PATCH 102/289] Merging r368517, r368518, r368519, and r368554: ------------------------------------------------------------------------ r368517 | lebedevri | 2019-08-10 21:28:12 +0200 (Sat, 10 Aug 2019) | 1 line [NFC][InstCombine] Tests for shift amount reassociation in bittest with shift of const ------------------------------------------------------------------------ ------------------------------------------------------------------------ r368518 | lebedevri | 2019-08-10 21:28:44 +0200 (Sat, 10 Aug 2019) | 5 lines [InstCombine] Shift amount reassociation in bittest: drop pointless one-use restriction That one-use restriction is not needed for correctness - we have already ensured that one of the shifts will go away, so we know we won't increase the instruction count. So there is no need for that restriction. ------------------------------------------------------------------------ ------------------------------------------------------------------------ r368519 | lebedevri | 2019-08-10 21:28:54 +0200 (Sat, 10 Aug 2019) | 5 lines [InstCombine] Shift amount reassociation in bittest: relax one-use check when shifting constant If one of the values being shifted is a constant, since the new shift amount is known-constant, the new shift will end up being constant-folded so, we don't need that one-use restriction then. ------------------------------------------------------------------------ ------------------------------------------------------------------------ r368554 | lebedevri | 2019-08-12 13:28:02 +0200 (Mon, 12 Aug 2019) | 6 lines [InstCombine] foldShiftIntoShiftInAnotherHandOfAndInICmp(): avoid constantexpr pitfail (PR42962) Instead of matching value and then blindly casting to BinaryOperator just to get the opcode, just match instruction and do no cast. Fixes https://bugs.llvm.org/show_bug.cgi?id=42962 ------------------------------------------------------------------------ llvm-svn: 368673 --- .../InstCombine/InstCombineCompares.cpp | 25 +++-- .../shift-amount-reassociation-in-bittest.ll | 99 ++++++++++++++++--- 2 files changed, 100 insertions(+), 24 deletions(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index 3a4283ae5406..147af8bc37c9 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -3288,26 +3288,35 @@ foldShiftIntoShiftInAnotherHandOfAndInICmp(ICmpInst &I, const SimplifyQuery SQ, // Look for an 'and' of two (opposite) logical shifts. // Pick the single-use shift as XShift. - Value *XShift, *YShift; + Instruction *XShift, *YShift; if (!match(I.getOperand(0), - m_c_And(m_OneUse(m_CombineAnd(m_AnyLogicalShift, m_Value(XShift))), - m_CombineAnd(m_AnyLogicalShift, m_Value(YShift))))) + m_c_And(m_CombineAnd(m_AnyLogicalShift, m_Instruction(XShift)), + m_CombineAnd(m_AnyLogicalShift, m_Instruction(YShift))))) return nullptr; - // If YShift is a single-use 'lshr', swap the shifts around. - if (match(YShift, m_OneUse(m_AnyLShr))) + // If YShift is a 'lshr', swap the shifts around. + if (match(YShift, m_AnyLShr)) std::swap(XShift, YShift); // The shifts must be in opposite directions. - Instruction::BinaryOps XShiftOpcode = - cast(XShift)->getOpcode(); - if (XShiftOpcode == cast(YShift)->getOpcode()) + auto XShiftOpcode = XShift->getOpcode(); + if (XShiftOpcode == YShift->getOpcode()) return nullptr; // Do not care about same-direction shifts here. Value *X, *XShAmt, *Y, *YShAmt; match(XShift, m_BinOp(m_Value(X), m_Value(XShAmt))); match(YShift, m_BinOp(m_Value(Y), m_Value(YShAmt))); + // If one of the values being shifted is a constant, then we will end with + // and+icmp, and shift instr will be constant-folded. If they are not, + // however, we will need to ensure that we won't increase instruction count. + if (!isa(X) && !isa(Y)) { + // At least one of the hands of the 'and' should be one-use shift. + if (!match(I.getOperand(0), + m_c_And(m_OneUse(m_AnyLogicalShift), m_Value()))) + return nullptr; + } + // Can we fold (XShAmt+YShAmt) ? Value *NewShAmt = SimplifyBinOp(Instruction::BinaryOps::Add, XShAmt, YShAmt, SQ.getWithInstruction(&I)); diff --git a/llvm/test/Transforms/InstCombine/shift-amount-reassociation-in-bittest.ll b/llvm/test/Transforms/InstCombine/shift-amount-reassociation-in-bittest.ll index c0bce48b3bed..9a2cfa5977a2 100644 --- a/llvm/test/Transforms/InstCombine/shift-amount-reassociation-in-bittest.ll +++ b/llvm/test/Transforms/InstCombine/shift-amount-reassociation-in-bittest.ll @@ -279,8 +279,8 @@ define i1 @t18_const_oneuse0(i32 %x, i32 %y) { ; CHECK-LABEL: @t18_const_oneuse0( ; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[X:%.*]], 1 ; CHECK-NEXT: call void @use32(i32 [[T0]]) -; CHECK-NEXT: [[TMP1:%.*]] = shl i32 [[Y:%.*]], 2 -; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[X]] +; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X]], 2 +; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[Y:%.*]] ; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0 ; CHECK-NEXT: ret i1 [[TMP3]] ; @@ -521,15 +521,70 @@ define i1 @t31_var_oneuse6(i32 %x, i32 %y, i32 %shamt0, i32 %shamt1) { ret i1 %t3 } +; Shift-of-const + +; Ok, non-truncated shift is of constant; +define i1 @t32_shift_of_const_oneuse0(i32 %x, i32 %y, i32 %len) { +; CHECK-LABEL: @t32_shift_of_const_oneuse0( +; CHECK-NEXT: [[T0:%.*]] = sub i32 32, [[LEN:%.*]] +; CHECK-NEXT: call void @use32(i32 [[T0]]) +; CHECK-NEXT: [[T1:%.*]] = lshr i32 -52543054, [[T0]] +; CHECK-NEXT: call void @use32(i32 [[T1]]) +; CHECK-NEXT: [[T2:%.*]] = add i32 [[LEN]], -1 +; CHECK-NEXT: call void @use32(i32 [[T2]]) +; CHECK-NEXT: [[T3:%.*]] = shl i32 [[Y:%.*]], [[T2]] +; CHECK-NEXT: call void @use32(i32 [[T3]]) +; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[Y]], 1 +; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i32 [[TMP1]], 0 +; CHECK-NEXT: ret i1 [[TMP2]] +; + %t0 = sub i32 32, %len + call void @use32(i32 %t0) + %t1 = lshr i32 4242424242, %t0 ; shift-of-constant + call void @use32(i32 %t1) + %t2 = add i32 %len, -1 + call void @use32(i32 %t2) + %t3 = shl i32 %y, %t2 + call void @use32(i32 %t3) + %t4 = and i32 %t1, %t3 ; no extra uses + %t5 = icmp ne i32 %t4, 0 + ret i1 %t5 +} +; Ok, truncated shift is of constant; +define i1 @t33_shift_of_const_oneuse1(i32 %x, i32 %y, i32 %len) { +; CHECK-LABEL: @t33_shift_of_const_oneuse1( +; CHECK-NEXT: [[T0:%.*]] = sub i32 32, [[LEN:%.*]] +; CHECK-NEXT: call void @use32(i32 [[T0]]) +; CHECK-NEXT: [[T1:%.*]] = lshr i32 [[X:%.*]], [[T0]] +; CHECK-NEXT: call void @use32(i32 [[T1]]) +; CHECK-NEXT: [[T2:%.*]] = add i32 [[LEN]], -1 +; CHECK-NEXT: call void @use32(i32 [[T2]]) +; CHECK-NEXT: [[T3:%.*]] = shl i32 -52543054, [[T2]] +; CHECK-NEXT: call void @use32(i32 [[T3]]) +; CHECK-NEXT: ret i1 false +; + %t0 = sub i32 32, %len + call void @use32(i32 %t0) + %t1 = lshr i32 %x, %t0 ; shift-of-constant + call void @use32(i32 %t1) + %t2 = add i32 %len, -1 + call void @use32(i32 %t2) + %t3 = shl i32 4242424242, %t2 + call void @use32(i32 %t3) + %t4 = and i32 %t1, %t3 ; no extra uses + %t5 = icmp ne i32 %t4, 0 + ret i1 %t5 +} + ; Commutativity with extra uses -define i1 @t32_commutativity0_oneuse0(i32 %x) { -; CHECK-LABEL: @t32_commutativity0_oneuse0( +define i1 @t34_commutativity0_oneuse0(i32 %x) { +; CHECK-LABEL: @t34_commutativity0_oneuse0( ; CHECK-NEXT: [[Y:%.*]] = call i32 @gen32() ; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[X:%.*]], 1 ; CHECK-NEXT: call void @use32(i32 [[T0]]) -; CHECK-NEXT: [[TMP1:%.*]] = shl i32 [[Y]], 2 -; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[X]] +; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X]], 2 +; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[Y]] ; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0 ; CHECK-NEXT: ret i1 [[TMP3]] ; @@ -541,8 +596,8 @@ define i1 @t32_commutativity0_oneuse0(i32 %x) { %t3 = icmp ne i32 %t2, 0 ret i1 %t3 } -define i1 @t33_commutativity0_oneuse1(i32 %x) { -; CHECK-LABEL: @t33_commutativity0_oneuse1( +define i1 @t35_commutativity0_oneuse1(i32 %x) { +; CHECK-LABEL: @t35_commutativity0_oneuse1( ; CHECK-NEXT: [[Y:%.*]] = call i32 @gen32() ; CHECK-NEXT: [[T1:%.*]] = shl i32 [[Y]], 1 ; CHECK-NEXT: call void @use32(i32 [[T1]]) @@ -560,13 +615,13 @@ define i1 @t33_commutativity0_oneuse1(i32 %x) { ret i1 %t3 } -define i1 @t34_commutativity1_oneuse0(i32 %y) { -; CHECK-LABEL: @t34_commutativity1_oneuse0( +define i1 @t36_commutativity1_oneuse0(i32 %y) { +; CHECK-LABEL: @t36_commutativity1_oneuse0( ; CHECK-NEXT: [[X:%.*]] = call i32 @gen32() ; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[X]], 1 ; CHECK-NEXT: call void @use32(i32 [[T0]]) -; CHECK-NEXT: [[TMP1:%.*]] = shl i32 [[Y:%.*]], 2 -; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[X]] +; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X]], 2 +; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[Y:%.*]] ; CHECK-NEXT: [[TMP3:%.*]] = icmp ne i32 [[TMP2]], 0 ; CHECK-NEXT: ret i1 [[TMP3]] ; @@ -578,8 +633,8 @@ define i1 @t34_commutativity1_oneuse0(i32 %y) { %t3 = icmp ne i32 %t2, 0 ret i1 %t3 } -define i1 @t35_commutativity1_oneuse1(i32 %y) { -; CHECK-LABEL: @t35_commutativity1_oneuse1( +define i1 @t37_commutativity1_oneuse1(i32 %y) { +; CHECK-LABEL: @t37_commutativity1_oneuse1( ; CHECK-NEXT: [[X:%.*]] = call i32 @gen32() ; CHECK-NEXT: [[T1:%.*]] = shl i32 [[Y:%.*]], 1 ; CHECK-NEXT: call void @use32(i32 [[T1]]) @@ -598,8 +653,8 @@ define i1 @t35_commutativity1_oneuse1(i32 %y) { } ; Negative tests -define <2 x i1> @n36_overshift(<2 x i32> %x, <2 x i32> %y) { -; CHECK-LABEL: @n36_overshift( +define <2 x i1> @n38_overshift(<2 x i32> %x, <2 x i32> %y) { +; CHECK-LABEL: @n38_overshift( ; CHECK-NEXT: [[T0:%.*]] = lshr <2 x i32> [[X:%.*]], ; CHECK-NEXT: [[T1:%.*]] = shl <2 x i32> [[Y:%.*]], ; CHECK-NEXT: [[T2:%.*]] = and <2 x i32> [[T1]], [[T0]] @@ -612,3 +667,15 @@ define <2 x i1> @n36_overshift(<2 x i32> %x, <2 x i32> %y) { %t3 = icmp ne <2 x i32> %t2, ret <2 x i1> %t3 } + +; As usual, don't crash given constantexpr's :/ +@f.a = internal global i16 0 +define i1 @constantexpr() { +entry: + %0 = load i16, i16* @f.a + %shr = ashr i16 %0, 1 + %shr1 = ashr i16 %shr, zext (i1 icmp ne (i16 ptrtoint (i16* @f.a to i16), i16 1) to i16) + %and = and i16 %shr1, 1 + %tobool = icmp ne i16 %and, 0 + ret i1 %tobool +} From 3f910512f5b67577c6cfc1346981c1f1957dd5b1 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Tue, 13 Aug 2019 12:00:39 +0000 Subject: [PATCH 103/289] Merging r368572: ------------------------------------------------------------------------ r368572 | lenary | 2019-08-12 15:51:00 +0200 (Mon, 12 Aug 2019) | 18 lines [RISCV] Fix ICE in isDesirableToCommuteWithShift Summary: Ana Pazos reported a bug where we were not checking that an APInt would fit into 64-bits before calling `getSExtValue()`. This caused asserts when compiling large constants, such as i128s, as happens when compiling compiler-rt. This patch adds a testcase and makes the callback less error-prone. Reviewers: apazos, asb, luismarques Reviewed By: luismarques Subscribers: hiraditya, rbar, johnrusso, simoncook, sabuasal, niosHD, kito-cheng, shiva0217, jrtc27, MaskRay, zzheng, edward-jones, rogfer01, MartinMosbeck, brucehoult, the_o, rkruppe, PkmX, jocewei, psnobl, benna, Jim, s.egerton, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D66081 ------------------------------------------------------------------------ llvm-svn: 368674 --- llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 6 ++-- llvm/test/CodeGen/RISCV/add-before-shl.ll | 40 +++++++++++++++++++++ 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index cdad4d461f10..e695f79f5cf4 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -1007,12 +1007,14 @@ bool RISCVTargetLowering::isDesirableToCommuteWithShift( // We can materialise `c1 << c2` into an add immediate, so it's "free", // and the combine should happen, to potentially allow further combines // later. - if (isLegalAddImmediate(ShiftedC1Int.getSExtValue())) + if (ShiftedC1Int.getMinSignedBits() <= 64 && + isLegalAddImmediate(ShiftedC1Int.getSExtValue())) return true; // We can materialise `c1` in an add immediate, so it's "free", and the // combine should be prevented. - if (isLegalAddImmediate(C1Int.getSExtValue())) + if (C1Int.getMinSignedBits() <= 64 && + isLegalAddImmediate(C1Int.getSExtValue())) return false; // Neither constant will fit into an immediate, so find materialisation diff --git a/llvm/test/CodeGen/RISCV/add-before-shl.ll b/llvm/test/CodeGen/RISCV/add-before-shl.ll index 05bcc191b6cb..3279de3ea99b 100644 --- a/llvm/test/CodeGen/RISCV/add-before-shl.ll +++ b/llvm/test/CodeGen/RISCV/add-before-shl.ll @@ -91,3 +91,43 @@ define signext i24 @add_non_machine_type(i24 signext %a) nounwind { %2 = shl i24 %1, 12 ret i24 %2 } + +define i128 @add_wide_operand(i128 %a) nounwind { +; RV32I-LABEL: add_wide_operand: +; RV32I: # %bb.0: +; RV32I-NEXT: lw a2, 0(a1) +; RV32I-NEXT: srli a3, a2, 29 +; RV32I-NEXT: lw a4, 4(a1) +; RV32I-NEXT: slli a5, a4, 3 +; RV32I-NEXT: or a6, a5, a3 +; RV32I-NEXT: srli a4, a4, 29 +; RV32I-NEXT: lw a5, 8(a1) +; RV32I-NEXT: slli a3, a5, 3 +; RV32I-NEXT: or a3, a3, a4 +; RV32I-NEXT: slli a2, a2, 3 +; RV32I-NEXT: sw a2, 0(a0) +; RV32I-NEXT: sw a3, 8(a0) +; RV32I-NEXT: sw a6, 4(a0) +; RV32I-NEXT: srli a2, a5, 29 +; RV32I-NEXT: lw a1, 12(a1) +; RV32I-NEXT: slli a1, a1, 3 +; RV32I-NEXT: or a1, a1, a2 +; RV32I-NEXT: lui a2, 128 +; RV32I-NEXT: add a1, a1, a2 +; RV32I-NEXT: sw a1, 12(a0) +; RV32I-NEXT: ret +; +; RV64I-LABEL: add_wide_operand: +; RV64I: # %bb.0: +; RV64I-NEXT: slli a1, a1, 3 +; RV64I-NEXT: srli a2, a0, 61 +; RV64I-NEXT: or a1, a1, a2 +; RV64I-NEXT: addi a2, zero, 1 +; RV64I-NEXT: slli a2, a2, 51 +; RV64I-NEXT: add a1, a1, a2 +; RV64I-NEXT: slli a0, a0, 3 +; RV64I-NEXT: ret + %1 = add i128 %a, 5192296858534827628530496329220096 + %2 = shl i128 %1, 3 + ret i128 %2 +} From 8bb0d04858db3df82edae1d2f685e0b7048bb62b Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Tue, 13 Aug 2019 12:07:33 +0000 Subject: [PATCH 104/289] Merging r368477: ------------------------------------------------------------------------ r368477 | void | 2019-08-09 22:16:31 +0200 (Fri, 09 Aug 2019) | 22 lines [MC] Don't recreate a label if it's already used Summary: This patch keeps track of MCSymbols created for blocks that were referenced in inline asm. It prevents creating a new symbol which doesn't refer to the block. Inline asm may have a reference to a label. The asm parser however doesn't recognize it as a label and tries to create a new symbol. The result being that instead of the original symbol (e.g. ".Ltmp0") the parser replaces it in the inline asm with the new one (e.g. ".Ltmp00") without updating it in the symbol table. So the machine basic block retains the "old" symbol (".Ltmp0"), but the inline asm uses the new one (".Ltmp00"). Reviewers: nickdesaulniers, craig.topper Subscribers: nathanchance, javed.absar, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D65304 ------------------------------------------------------------------------ llvm-svn: 368676 --- llvm/include/llvm/MC/MCContext.h | 13 ++++ .../AsmPrinter/AsmPrinterInlineAsm.cpp | 1 + llvm/lib/MC/MCContext.cpp | 6 ++ llvm/lib/MC/MCParser/AsmParser.cpp | 4 +- llvm/test/CodeGen/AArch64/callbr-asm-label.ll | 63 +++++++++++++++++++ .../test/CodeGen/X86/callbr-asm-label-addr.ll | 30 +++++++++ llvm/test/CodeGen/X86/callbr-asm.ll | 16 ++--- 7 files changed, 124 insertions(+), 9 deletions(-) create mode 100644 llvm/test/CodeGen/AArch64/callbr-asm-label.ll create mode 100644 llvm/test/CodeGen/X86/callbr-asm-label-addr.ll diff --git a/llvm/include/llvm/MC/MCContext.h b/llvm/include/llvm/MC/MCContext.h index 5c2124cc0d15..c40cd7c2c257 100644 --- a/llvm/include/llvm/MC/MCContext.h +++ b/llvm/include/llvm/MC/MCContext.h @@ -112,6 +112,9 @@ namespace llvm { /// number of section symbols with the same name). StringMap UsedNames; + /// Keeps track of labels that are used in inline assembly. + SymbolTable InlineAsmUsedLabelNames; + /// The next ID to dole out to an unnamed assembler temporary symbol with /// a given prefix. StringMap NextID; @@ -377,6 +380,16 @@ namespace llvm { /// APIs. const SymbolTable &getSymbols() const { return Symbols; } + /// isInlineAsmLabel - Return true if the name is a label referenced in + /// inline assembly. + MCSymbol *getInlineAsmLabel(StringRef Name) const { + return InlineAsmUsedLabelNames.lookup(Name); + } + + /// registerInlineAsmLabel - Records that the name is a label referenced in + /// inline assembly. + void registerInlineAsmLabel(MCSymbol *Sym); + /// @} /// \name Section Management diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp index 7721e996aca5..5e49fec9c053 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp @@ -432,6 +432,7 @@ static void EmitGCCInlineAsmStr(const char *AsmStr, const MachineInstr *MI, const BlockAddress *BA = MI->getOperand(OpNo).getBlockAddress(); MCSymbol *Sym = AP->GetBlockAddressSymbol(BA); Sym->print(OS, AP->MAI); + MMI->getContext().registerInlineAsmLabel(Sym); } else if (MI->getOperand(OpNo).isMBB()) { const MCSymbol *Sym = MI->getOperand(OpNo).getMBB()->getSymbol(); Sym->print(OS, AP->MAI); diff --git a/llvm/lib/MC/MCContext.cpp b/llvm/lib/MC/MCContext.cpp index 0dc2e2d37caf..6f9efec36361 100644 --- a/llvm/lib/MC/MCContext.cpp +++ b/llvm/lib/MC/MCContext.cpp @@ -61,6 +61,7 @@ MCContext::MCContext(const MCAsmInfo *mai, const MCRegisterInfo *mri, bool DoAutoReset) : SrcMgr(mgr), InlineSrcMgr(nullptr), MAI(mai), MRI(mri), MOFI(mofi), Symbols(Allocator), UsedNames(Allocator), + InlineAsmUsedLabelNames(Allocator), CurrentDwarfLoc(0, 0, 0, DWARF2_FLAG_IS_STMT, 0, 0), AutoReset(DoAutoReset) { SecureLogFile = AsSecureLogFileName; @@ -90,6 +91,7 @@ void MCContext::reset() { XCOFFAllocator.DestroyAll(); MCSubtargetAllocator.DestroyAll(); + InlineAsmUsedLabelNames.clear(); UsedNames.clear(); Symbols.clear(); Allocator.Reset(); @@ -272,6 +274,10 @@ void MCContext::setSymbolValue(MCStreamer &Streamer, Streamer.EmitAssignment(Symbol, MCConstantExpr::create(Val, *this)); } +void MCContext::registerInlineAsmLabel(MCSymbol *Sym) { + InlineAsmUsedLabelNames[Sym->getName()] = Sym; +} + //===----------------------------------------------------------------------===// // Section Management //===----------------------------------------------------------------------===// diff --git a/llvm/lib/MC/MCParser/AsmParser.cpp b/llvm/lib/MC/MCParser/AsmParser.cpp index 084f6a7a2e14..c2cbca2177be 100644 --- a/llvm/lib/MC/MCParser/AsmParser.cpp +++ b/llvm/lib/MC/MCParser/AsmParser.cpp @@ -1142,7 +1142,9 @@ bool AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) { } } - MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName); + MCSymbol *Sym = getContext().getInlineAsmLabel(SymbolName); + if (!Sym) + Sym = getContext().getOrCreateSymbol(SymbolName); // If this is an absolute variable reference, substitute it now to preserve // semantics in the face of reassignment. diff --git a/llvm/test/CodeGen/AArch64/callbr-asm-label.ll b/llvm/test/CodeGen/AArch64/callbr-asm-label.ll new file mode 100644 index 000000000000..583587da71a9 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/callbr-asm-label.ll @@ -0,0 +1,63 @@ +; RUN: llc < %s -mtriple=aarch64-linux-gnu | FileCheck %s + +@X = common local_unnamed_addr global i32 0, align 4 + +define i32 @test1() { +; CHECK-LABEL: test1: +; CHECK: .word b +; CHECK-NEXT: .word .Ltmp0 +; CHECK-LABEL: .Ltmp0: +; CHECK-LABEL: .LBB0_1: // %l_yes +; CHECK-LABEL: .LBB0_2: // %cleanup +entry: + callbr void asm sideeffect "1:\0A\09.word b, ${0:l}\0A\09", "X"(i8* blockaddress(@test1, %l_yes)) + to label %cleanup [label %l_yes] + +l_yes: + br label %cleanup + +cleanup: + %retval.0 = phi i32 [ 1, %l_yes ], [ 0, %entry ] + ret i32 %retval.0 +} + +define void @test2() { +; CHECK-LABEL: test2: +entry: + %0 = load i32, i32* @X, align 4 + %and = and i32 %0, 1 + %tobool = icmp eq i32 %and, 0 + br i1 %tobool, label %if.end10, label %if.then + +if.then: +; CHECK: .word b +; CHECK-NEXT: .word .Ltmp2 +; CHECK-LABEL: .Ltmp2: +; CHECK-NEXT: .LBB1_3: // %if.end6 + callbr void asm sideeffect "1:\0A\09.word b, ${0:l}\0A\09", "X"(i8* blockaddress(@test2, %if.end6)) + to label %if.then4 [label %if.end6] + +if.then4: + %call5 = tail call i32 bitcast (i32 (...)* @g to i32 ()*)() + br label %if.end6 + +if.end6: + %.pre = load i32, i32* @X, align 4 + %.pre13 = and i32 %.pre, 1 + %phitmp = icmp eq i32 %.pre13, 0 + br i1 %phitmp, label %if.end10, label %if.then9 + +if.then9: +; CHECK-LABEL: .Ltmp4: +; CHECK-NEXT: .LBB1_5: // %l_yes + callbr void asm sideeffect "", "X"(i8* blockaddress(@test2, %l_yes)) + to label %if.end10 [label %l_yes] + +if.end10: + br label %l_yes + +l_yes: + ret void +} + +declare i32 @g(...) diff --git a/llvm/test/CodeGen/X86/callbr-asm-label-addr.ll b/llvm/test/CodeGen/X86/callbr-asm-label-addr.ll new file mode 100644 index 000000000000..dc0e83634658 --- /dev/null +++ b/llvm/test/CodeGen/X86/callbr-asm-label-addr.ll @@ -0,0 +1,30 @@ +; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu | FileCheck %s + +define i32 @test1(i32 %x) { +; CHECK-LABEL: test1: +; CHECK: .quad .Ltmp0 +; CHECK-NEXT: .quad .Ltmp1 +; CHECK-LABEL: .Ltmp1: +; CHECK-LABEL: .LBB0_1: # %bar +; CHECK-NEXT: callq foo +; CHECK-LABEL: .Ltmp0: +; CHECK-NEXT: # %bb.2: # %baz +entry: + callbr void asm sideeffect ".quad ${0:l}\0A\09.quad ${1:l}", "i,X,~{dirflag},~{fpsr},~{flags}"(i8* blockaddress(@test1, %baz), i8* blockaddress(@test1, %bar)) + to label %asm.fallthrough [label %bar] + +asm.fallthrough: + br label %bar + +bar: + %call = tail call i32 @foo(i32 %x) + br label %baz + +baz: + %call1 = tail call i32 @mux(i32 %call) + ret i32 %call1 +} + +declare i32 @foo(i32) + +declare i32 @mux(i32) diff --git a/llvm/test/CodeGen/X86/callbr-asm.ll b/llvm/test/CodeGen/X86/callbr-asm.ll index 48a80ae167ba..ed3c314ed424 100644 --- a/llvm/test/CodeGen/X86/callbr-asm.ll +++ b/llvm/test/CodeGen/X86/callbr-asm.ll @@ -12,7 +12,7 @@ define i32 @test1(i32 %a) { ; CHECK-NEXT: addl $4, %eax ; CHECK-NEXT: #APP ; CHECK-NEXT: xorl %eax, %eax -; CHECK-NEXT: jmp .Ltmp00 +; CHECK-NEXT: jmp .Ltmp0 ; CHECK-NEXT: #NO_APP ; CHECK-NEXT: .LBB0_1: # %normal ; CHECK-NEXT: xorl %eax, %eax @@ -87,17 +87,17 @@ define dso_local i32 @test3(i32 %a) { ; CHECK-NEXT: # Parent Loop BB2_3 Depth=3 ; CHECK-NEXT: # => This Inner Loop Header: Depth=4 ; CHECK-NEXT: #APP -; CHECK-NEXT: jmp .Ltmp10 -; CHECK-NEXT: jmp .Ltmp20 -; CHECK-NEXT: jmp .Ltmp30 +; CHECK-NEXT: jmp .Ltmp1 +; CHECK-NEXT: jmp .Ltmp2 +; CHECK-NEXT: jmp .Ltmp3 ; CHECK-NEXT: #NO_APP ; CHECK-NEXT: .LBB2_5: # %normal0 ; CHECK-NEXT: # in Loop: Header=BB2_4 Depth=4 ; CHECK-NEXT: #APP -; CHECK-NEXT: jmp .Ltmp10 -; CHECK-NEXT: jmp .Ltmp20 -; CHECK-NEXT: jmp .Ltmp30 -; CHECK-NEXT: jmp .Ltmp40 +; CHECK-NEXT: jmp .Ltmp1 +; CHECK-NEXT: jmp .Ltmp2 +; CHECK-NEXT: jmp .Ltmp3 +; CHECK-NEXT: jmp .Ltmp4 ; CHECK-NEXT: #NO_APP ; CHECK-NEXT: .LBB2_6: # %normal1 ; CHECK-NEXT: movl {{[0-9]+}}(%esp), %eax From a705aadb6c0afcd176318087fcde44f104a5a29f Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Tue, 13 Aug 2019 12:08:26 +0000 Subject: [PATCH 105/289] Merging r368478: ------------------------------------------------------------------------ r368478 | void | 2019-08-09 22:18:30 +0200 (Fri, 09 Aug 2019) | 16 lines [CodeGen] Require a name for a block addr target Summary: A block address may be used in inline assembly. In which case it requires a name so that the asm parser has something to parse. Creating a name for every block address is a large hammer, but is necessary because at the point when a temp symbol is created we don't necessarily know if it's used in inline asm. This ensures that it exists regardless. Reviewers: nickdesaulniers, craig.topper Subscribers: nathanchance, javed.absar, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D65352 ------------------------------------------------------------------------ llvm-svn: 368678 --- llvm/lib/CodeGen/MachineModuleInfo.cpp | 2 +- .../CodeGen/AArch64/callbr-asm-obj-file.ll | 102 ++++++++++++++++++ llvm/test/CodeGen/X86/callbr-asm-obj-file.ll | 19 ++++ 3 files changed, 122 insertions(+), 1 deletion(-) create mode 100644 llvm/test/CodeGen/AArch64/callbr-asm-obj-file.ll create mode 100644 llvm/test/CodeGen/X86/callbr-asm-obj-file.ll diff --git a/llvm/lib/CodeGen/MachineModuleInfo.cpp b/llvm/lib/CodeGen/MachineModuleInfo.cpp index aadcd7319799..2e720018262c 100644 --- a/llvm/lib/CodeGen/MachineModuleInfo.cpp +++ b/llvm/lib/CodeGen/MachineModuleInfo.cpp @@ -121,7 +121,7 @@ ArrayRef MMIAddrLabelMap::getAddrLabelSymbolToEmit(BasicBlock *BB) { BBCallbacks.back().setMap(this); Entry.Index = BBCallbacks.size() - 1; Entry.Fn = BB->getParent(); - Entry.Symbols.push_back(Context.createTempSymbol()); + Entry.Symbols.push_back(Context.createTempSymbol(!BB->hasAddressTaken())); return Entry.Symbols; } diff --git a/llvm/test/CodeGen/AArch64/callbr-asm-obj-file.ll b/llvm/test/CodeGen/AArch64/callbr-asm-obj-file.ll new file mode 100644 index 000000000000..579158568b6f --- /dev/null +++ b/llvm/test/CodeGen/AArch64/callbr-asm-obj-file.ll @@ -0,0 +1,102 @@ +; RUN: llc < %s -mtriple=aarch64-unknown-linux-gnu -filetype=obj -o - \ +; RUN: | llvm-objdump -triple aarch64-unknown-linux-gnu -d - \ +; RUN: | FileCheck %s + +%struct.c = type { i1 (...)* } + +@l = common hidden local_unnamed_addr global i32 0, align 4 + +; CHECK-LABEL: 0000000000000000 test1: +; CHECK-LABEL: 0000000000000018 $d.1: +; CHECK-LABEL: 0000000000000020 $x.2: +; CHECK-NEXT: b #16 <$x.4+0x4> +; CHECK-LABEL: 000000000000002c $x.4: +; CHECK-NEXT: b #4 <$x.4+0x4> +; CHECK-NEXT: mov w0, wzr +; CHECK-NEXT: ldr x30, [sp], #16 +; CHECK-NEXT: ret +define hidden i32 @test1() { + %1 = tail call i32 bitcast (i32 (...)* @g to i32 ()*)() + %2 = icmp eq i32 %1, 0 + br i1 %2, label %3, label %5 + +3: ; preds = %0 + callbr void asm sideeffect "1: nop\0A\09.quad a\0A\09b ${1:l}\0A\09.quad ${0:c}", "i,X"(i32* null, i8* blockaddress(@test1, %7)) + to label %4 [label %7] + +4: ; preds = %3 + br label %7 + +5: ; preds = %0 + %6 = tail call i32 bitcast (i32 (...)* @i to i32 ()*)() + br label %7 + +7: ; preds = %3, %4, %5 + %8 = phi i32 [ %6, %5 ], [ 0, %4 ], [ 0, %3 ] + ret i32 %8 +} + +declare dso_local i32 @g(...) local_unnamed_addr + +declare dso_local i32 @i(...) local_unnamed_addr + +; CHECK-LABEL: 000000000000003c test2: +; CHECK: bl #0 +; CHECK-LABEL: 0000000000000064 $d.5: +; CHECK-LABEL: 000000000000006c $x.6: +; CHECK-NEXT: b #-24 +define hidden i32 @test2() local_unnamed_addr { + %1 = load i32, i32* @l, align 4 + %2 = icmp eq i32 %1, 0 + br i1 %2, label %10, label %3 + +3: ; preds = %0 + %4 = tail call i32 bitcast (i32 (...)* @g to i32 ()*)() + %5 = icmp eq i32 %4, 0 + br i1 %5, label %6, label %7 + +6: ; preds = %3 + callbr void asm sideeffect "1: nop\0A\09.quad b\0A\09b ${1:l}\0A\09.quad ${0:c}", "i,X"(i32* null, i8* blockaddress(@test2, %7)) + to label %10 [label %9] + +7: ; preds = %3 + %8 = tail call i32 bitcast (i32 (...)* @i to i32 ()*)() + br label %10 + +9: ; preds = %6 + br label %10 + +10: ; preds = %7, %0, %6, %9 + ret i32 undef +} + +; CHECK-LABEL: 0000000000000084 test3: +; CHECK-LABEL: 00000000000000a8 $d.9: +; CHECK-LABEL: 00000000000000b0 $x.10: +; CHECK-NEXT: b #20 <$x.12+0x8> +; CHECK-LABEL: 00000000000000bc $x.12: +; CHECK-NEXT: b #4 <$x.12+0x4> +; CHECK-NEXT: mov w0, wzr +; CHECK-NEXT: ldr x30, [sp], #16 +; CHECK-NEXT: ret +define internal i1 @test3() { + %1 = tail call i32 bitcast (i32 (...)* @g to i32 ()*)() + %2 = icmp eq i32 %1, 0 + br i1 %2, label %3, label %5 + +3: ; preds = %0 + callbr void asm sideeffect "1: nop\0A\09.quad c\0A\09b ${1:l}\0A\09.quad ${0:c}", "i,X"(i32* null, i8* blockaddress(@test3, %8)) + to label %4 [label %8] + +4: ; preds = %3 + br label %8 + +5: ; preds = %0 + %6 = tail call i32 bitcast (i32 (...)* @i to i32 ()*)() + %7 = icmp ne i32 %6, 0 + br label %8 + +8: ; preds = %3, %4, %5 + %9 = phi i1 [ %7, %5 ], [ false, %4 ], [ false, %3 ] + ret i1 %9 +} diff --git a/llvm/test/CodeGen/X86/callbr-asm-obj-file.ll b/llvm/test/CodeGen/X86/callbr-asm-obj-file.ll new file mode 100644 index 000000000000..d526045f93c0 --- /dev/null +++ b/llvm/test/CodeGen/X86/callbr-asm-obj-file.ll @@ -0,0 +1,19 @@ +; RUN: llc < %s -mtriple=x86_64-linux-gnu -filetype=obj -o - \ +; RUN: | llvm-objdump -triple x86_64-linux-gnu -d - \ +; RUN: | FileCheck %s + +; CHECK: 0000000000000000 test1: +; CHECK-NEXT: 0: 74 00 je 0 +; CHECK-NEXT: 2: c3 retq + +define void @test1() { +entry: + callbr void asm sideeffect "je ${0:l}", "X,~{dirflag},~{fpsr},~{flags}"(i8* blockaddress(@test1, %a.b.normal.jump)) + to label %asm.fallthrough [label %a.b.normal.jump] + +asm.fallthrough: + ret void + +a.b.normal.jump: + ret void +} From ff20769ba578566e290479044ae479b8049f9d17 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Tue, 13 Aug 2019 12:21:30 +0000 Subject: [PATCH 106/289] Merging r368516: ------------------------------------------------------------------------ r368516 | dim | 2019-08-10 21:07:38 +0200 (Sat, 10 Aug 2019) | 25 lines Add support for FreeBSD's LD_32_LIBRARY_PATH Summary: Because the dynamic linker for 32-bit executables on 64-bit FreeBSD uses the environment variable `LD_32_LIBRARY_PATH` instead of `LD_LIBRARY_PATH` to find needed dynamic libraries, running the 32-bit parts of the dynamic ASan tests will fail with errors similar to: ``` ld-elf32.so.1: Shared object "libclang_rt.asan-i386.so" not found, required by "Asan-i386-inline-Dynamic-Test" ``` This adds support for setting up `LD_32_LIBRARY_PATH` for the unit and regression tests. It will likely also require a minor change to the `TestingConfig` class in `llvm/utils/lit/lit`. Reviewers: emaste, kcc, rnk, arichardson Reviewed By: arichardson Subscribers: kubamracek, krytarowski, fedor.sergeev, delcypher, #sanitizers, llvm-commits Tags: #llvm, #sanitizers Differential Revision: https://reviews.llvm.org/D65772 ------------------------------------------------------------------------ llvm-svn: 368680 --- compiler-rt/test/asan/Unit/lit.site.cfg.py.in | 6 ++++++ compiler-rt/test/asan/lit.cfg.py | 8 +++++++- compiler-rt/test/xray/Unit/lit.site.cfg.py.in | 8 ++++++++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/compiler-rt/test/asan/Unit/lit.site.cfg.py.in b/compiler-rt/test/asan/Unit/lit.site.cfg.py.in index 1c59a6bad233..d1fd640e7385 100644 --- a/compiler-rt/test/asan/Unit/lit.site.cfg.py.in +++ b/compiler-rt/test/asan/Unit/lit.site.cfg.py.in @@ -1,6 +1,7 @@ @LIT_SITE_CFG_IN_HEADER@ import os +import platform # Load common config for all compiler-rt unit tests. lit_config.load_config(config, "@COMPILER_RT_BINARY_DIR@/unittests/lit.common.unit.configured") @@ -10,6 +11,11 @@ def push_ld_library_path(config, new_path): (new_path, config.environment.get('LD_LIBRARY_PATH', ''))) config.environment['LD_LIBRARY_PATH'] = new_ld_library_path + if platform.system() == 'FreeBSD': + new_ld_32_library_path = os.path.pathsep.join( + (new_path, config.environment.get('LD_32_LIBRARY_PATH', ''))) + config.environment['LD_32_LIBRARY_PATH'] = new_ld_32_library_path + # Setup config name. config.name = 'AddressSanitizer-Unit' diff --git a/compiler-rt/test/asan/lit.cfg.py b/compiler-rt/test/asan/lit.cfg.py index e94a65304c45..0e21011340ef 100644 --- a/compiler-rt/test/asan/lit.cfg.py +++ b/compiler-rt/test/asan/lit.cfg.py @@ -36,6 +36,12 @@ def push_dynamic_library_lookup_path(config, new_path): (new_path, config.environment.get(dynamic_library_lookup_var, ''))) config.environment[dynamic_library_lookup_var] = new_ld_library_path + if platform.system() == 'FreeBSD': + dynamic_library_lookup_var = 'LD_32_LIBRARY_PATH' + new_ld_32_library_path = os.path.pathsep.join( + (new_path, config.environment.get(dynamic_library_lookup_var, ''))) + config.environment[dynamic_library_lookup_var] = new_ld_32_library_path + # Setup config name. config.name = 'AddressSanitizer' + config.name_suffix @@ -111,7 +117,7 @@ def build_invocation(compile_flags): config.substitutions.append( ("%clang_asan ", build_invocation(clang_asan_cflags)) ) config.substitutions.append( ("%clangxx_asan ", build_invocation(clang_asan_cxxflags)) ) if config.asan_dynamic: - if config.host_os in ['Linux', 'NetBSD', 'SunOS']: + if config.host_os in ['Linux', 'FreeBSD', 'NetBSD', 'SunOS']: shared_libasan_path = os.path.join(config.compiler_rt_libdir, "libclang_rt.asan{}.so".format(config.target_suffix)) elif config.host_os == 'Darwin': shared_libasan_path = os.path.join(config.compiler_rt_libdir, 'libclang_rt.asan_{}_dynamic.dylib'.format(config.apple_platform)) diff --git a/compiler-rt/test/xray/Unit/lit.site.cfg.py.in b/compiler-rt/test/xray/Unit/lit.site.cfg.py.in index 54fcc1cbd23c..54709ac70ce4 100644 --- a/compiler-rt/test/xray/Unit/lit.site.cfg.py.in +++ b/compiler-rt/test/xray/Unit/lit.site.cfg.py.in @@ -1,6 +1,7 @@ @LIT_SITE_CFG_IN_HEADER@ import os +import platform # Load common config for all compiler-rt unit tests. lit_config.load_config(config, "@COMPILER_RT_BINARY_DIR@/unittests/lit.common.unit.configured") @@ -22,3 +23,10 @@ if 'LD_LIBRARY_PATH' in os.environ: config.environment['LD_LIBRARY_PATH'] = libdirs else: config.environment['LD_LIBRARY_PATH'] = config.llvm_lib_dir + +if platform.system() == 'FreeBSD': + if 'LD_32_LIBRARY_PATH' in os.environ: + libdirs = os.path.pathsep.join((config.llvm_lib_dir, os.environ['LD_32_LIBRARY_PATH'])) + config.environment['LD_32_LIBRARY_PATH'] = libdirs + else: + config.environment['LD_32_LIBRARY_PATH'] = config.llvm_lib_dir From fcfd891f22aa593a659b866f8d834ded64285b03 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Tue, 13 Aug 2019 12:37:46 +0000 Subject: [PATCH 107/289] Merging r367303: ------------------------------------------------------------------------ r367303 | kadircet | 2019-07-30 12:26:51 +0200 (Tue, 30 Jul 2019) | 15 lines [clangd] Ignore diags from builtin files Summary: This fixes a case where we show diagnostics on arbitrary lines, in an internal codebase. Open for ideas on unittesting this. Reviewers: ilya-biryukov Subscribers: MaskRay, jkorous, arphaman, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D64863 ------------------------------------------------------------------------ llvm-svn: 368682 --- clang-tools-extra/clangd/Diagnostics.cpp | 36 +++++++++++-------- clang-tools-extra/clangd/Diagnostics.h | 2 ++ .../clangd/unittests/DiagnosticsTests.cpp | 14 +++++++- 3 files changed, 37 insertions(+), 15 deletions(-) diff --git a/clang-tools-extra/clangd/Diagnostics.cpp b/clang-tools-extra/clangd/Diagnostics.cpp index 53192711a5df..919182d5f70c 100644 --- a/clang-tools-extra/clangd/Diagnostics.cpp +++ b/clang-tools-extra/clangd/Diagnostics.cpp @@ -20,6 +20,7 @@ #include "clang/Lex/Lexer.h" #include "clang/Lex/Token.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/Capacity.h" @@ -107,8 +108,13 @@ Range diagnosticRange(const clang::Diagnostic &D, const LangOptions &L) { return halfOpenToRange(M, R); } -void adjustDiagFromHeader(Diag &D, const clang::Diagnostic &Info, +// Returns whether the \p D is modified. +bool adjustDiagFromHeader(Diag &D, const clang::Diagnostic &Info, const LangOptions &LangOpts) { + // We only report diagnostics with at least error severity from headers. + if (D.Severity < DiagnosticsEngine::Level::Error) + return false; + const SourceLocation &DiagLoc = Info.getLocation(); const SourceManager &SM = Info.getSourceManager(); SourceLocation IncludeInMainFile; @@ -119,13 +125,14 @@ void adjustDiagFromHeader(Diag &D, const clang::Diagnostic &Info, IncludeLocation = GetIncludeLoc(IncludeLocation)) IncludeInMainFile = IncludeLocation; if (IncludeInMainFile.isInvalid()) - return; + return false; // Update diag to point at include inside main file. D.File = SM.getFileEntryForID(SM.getMainFileID())->getName().str(); D.Range.start = sourceLocToPosition(SM, IncludeInMainFile); D.Range.end = sourceLocToPosition( SM, Lexer::getLocForEndOfToken(IncludeInMainFile, 0, SM, LangOpts)); + D.InsideMainFile = true; // Add a note that will point to real diagnostic. const auto *FE = SM.getFileEntryForID(SM.getFileID(DiagLoc)); @@ -138,6 +145,7 @@ void adjustDiagFromHeader(Diag &D, const clang::Diagnostic &Info, // Update message to mention original file. D.Message = llvm::Twine("in included file: ", D.Message).str(); + return true; } bool isInsideMainFile(const clang::Diagnostic &D) { @@ -465,6 +473,7 @@ void StoreDiags::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, } bool InsideMainFile = isInsideMainFile(Info); + SourceManager &SM = Info.getSourceManager(); auto FillDiagBase = [&](DiagBase &D) { D.Range = diagnosticRange(Info, *LangOpts); @@ -472,8 +481,7 @@ void StoreDiags::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, Info.FormatDiagnostic(Message); D.Message = Message.str(); D.InsideMainFile = InsideMainFile; - D.File = Info.getSourceManager().getFilename(Info.getLocation()); - auto &SM = Info.getSourceManager(); + D.File = SM.getFilename(Info.getLocation()); D.AbsFile = getCanonicalPath( SM.getFileEntryForID(SM.getFileID(Info.getLocation())), SM); D.Severity = DiagLevel; @@ -496,10 +504,9 @@ void StoreDiags::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, if (FixIt.RemoveRange.getBegin().isMacroID() || FixIt.RemoveRange.getEnd().isMacroID()) return false; - if (!isInsideMainFile(FixIt.RemoveRange.getBegin(), - Info.getSourceManager())) + if (!isInsideMainFile(FixIt.RemoveRange.getBegin(), SM)) return false; - Edits.push_back(toTextEdit(FixIt, Info.getSourceManager(), *LangOpts)); + Edits.push_back(toTextEdit(FixIt, SM, *LangOpts)); } llvm::SmallString<64> Message; @@ -507,8 +514,8 @@ void StoreDiags::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, if (SyntheticMessage && Info.getNumFixItHints() == 1) { const auto &FixIt = Info.getFixItHint(0); bool Invalid = false; - llvm::StringRef Remove = Lexer::getSourceText( - FixIt.RemoveRange, Info.getSourceManager(), *LangOpts, &Invalid); + llvm::StringRef Remove = + Lexer::getSourceText(FixIt.RemoveRange, SM, *LangOpts, &Invalid); llvm::StringRef Insert = FixIt.CodeToInsert; if (!Invalid) { llvm::raw_svector_ostream M(Message); @@ -553,7 +560,9 @@ void StoreDiags::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, LastDiag = Diag(); LastDiag->ID = Info.getID(); FillDiagBase(*LastDiag); - adjustDiagFromHeader(*LastDiag, Info, *LangOpts); + LastDiagWasAdjusted = false; + if (!InsideMainFile) + LastDiagWasAdjusted = adjustDiagFromHeader(*LastDiag, Info, *LangOpts); if (!Info.getFixItHints().empty()) AddFix(true /* try to invent a message instead of repeating the diag */); @@ -595,10 +604,9 @@ void StoreDiags::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, void StoreDiags::flushLastDiag() { if (!LastDiag) return; - // Only keeps diagnostics inside main file or the first one coming from a - // header. - if (mentionsMainFile(*LastDiag) || - (LastDiag->Severity >= DiagnosticsEngine::Level::Error && + if (mentionsMainFile(*LastDiag) && + (!LastDiagWasAdjusted || + // Only report the first diagnostic coming from each particular header. IncludeLinesWithErrors.insert(LastDiag->Range.start.line).second)) { Output.push_back(std::move(*LastDiag)); } else { diff --git a/clang-tools-extra/clangd/Diagnostics.h b/clang-tools-extra/clangd/Diagnostics.h index b6cfe895504c..6d848ce2a3c0 100644 --- a/clang-tools-extra/clangd/Diagnostics.h +++ b/clang-tools-extra/clangd/Diagnostics.h @@ -145,6 +145,8 @@ class StoreDiags : public DiagnosticConsumer { std::vector Output; llvm::Optional LangOpts; llvm::Optional LastDiag; + /// Set iff adjustDiagFromHeader resulted in changes to LastDiag. + bool LastDiagWasAdjusted = false; llvm::DenseSet IncludeLinesWithErrors; bool LastPrimaryDiagnosticWasSuppressed = false; }; diff --git a/clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp b/clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp index 7cf0e277a5d4..c80dafeef68c 100644 --- a/clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp +++ b/clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp @@ -928,7 +928,6 @@ TEST(DiagsInHeaders, OnlyErrorOrFatal) { int x = 5/0;)cpp"); TestTU TU = TestTU::withCode(Main.code()); TU.AdditionalFiles = {{"a.h", Header.code()}}; - auto diags = TU.build().getDiagnostics(); EXPECT_THAT(TU.build().getDiagnostics(), UnorderedElementsAre(AllOf( Diag(Main.range(), "in included file: C++ requires " @@ -936,6 +935,19 @@ TEST(DiagsInHeaders, OnlyErrorOrFatal) { WithNote(Diag(Header.range(), "error occurred here"))))); } +TEST(IgnoreDiags, FromNonWrittenSources) { + Annotations Main(R"cpp( + #include [["a.h"]] + void foo() {})cpp"); + Annotations Header(R"cpp( + int x = 5/0; + int b = [[FOO]];)cpp"); + TestTU TU = TestTU::withCode(Main.code()); + TU.AdditionalFiles = {{"a.h", Header.code()}}; + TU.ExtraArgs = {"-DFOO=NOOO"}; + EXPECT_THAT(TU.build().getDiagnostics(), UnorderedElementsAre()); +} + } // namespace } // namespace clangd From f44fc8869c1609ab5235a00ec748175dd0f1cf18 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Tue, 13 Aug 2019 12:39:23 +0000 Subject: [PATCH 108/289] Merging r368549: ------------------------------------------------------------------------ r368549 | hokein | 2019-08-12 11:35:04 +0200 (Mon, 12 Aug 2019) | 11 lines [clangd] Drop diags from non-written #include. Summary: This would fix that we show weird diagnostics on random lines of the main file. Reviewers: ilya-biryukov Subscribers: MaskRay, jkorous, arphaman, kadircet, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D66074 ------------------------------------------------------------------------ llvm-svn: 368683 --- clang-tools-extra/clangd/Diagnostics.cpp | 8 ++++++-- clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp | 9 +++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/clang-tools-extra/clangd/Diagnostics.cpp b/clang-tools-extra/clangd/Diagnostics.cpp index 919182d5f70c..7f1ab06db9d1 100644 --- a/clang-tools-extra/clangd/Diagnostics.cpp +++ b/clang-tools-extra/clangd/Diagnostics.cpp @@ -122,8 +122,12 @@ bool adjustDiagFromHeader(Diag &D, const clang::Diagnostic &Info, return SM.getIncludeLoc(SM.getFileID(SLoc)); }; for (auto IncludeLocation = GetIncludeLoc(DiagLoc); IncludeLocation.isValid(); - IncludeLocation = GetIncludeLoc(IncludeLocation)) - IncludeInMainFile = IncludeLocation; + IncludeLocation = GetIncludeLoc(IncludeLocation)) { + if (clangd::isInsideMainFile(IncludeLocation, SM)) { + IncludeInMainFile = IncludeLocation; + break; + } + } if (IncludeInMainFile.isInvalid()) return false; diff --git a/clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp b/clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp index c80dafeef68c..2089c89e0664 100644 --- a/clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp +++ b/clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp @@ -948,6 +948,15 @@ TEST(IgnoreDiags, FromNonWrittenSources) { EXPECT_THAT(TU.build().getDiagnostics(), UnorderedElementsAre()); } +TEST(IgnoreDiags, FromNonWrittenInclude) { + TestTU TU = TestTU::withCode(""); + TU.ExtraArgs.push_back("--include=a.h"); + TU.AdditionalFiles = {{"a.h", "void main();"}}; + // The diagnostic "main must return int" is from the header, we don't attempt + // to render it in the main file as there is no written location there. + EXPECT_THAT(TU.build().getDiagnostics(), UnorderedElementsAre()); +} + } // namespace } // namespace clangd From 9bea39db27e4f8b3be69f65991bd12c79e433ccc Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Wed, 14 Aug 2019 12:53:30 +0000 Subject: [PATCH 109/289] Merging r368561: ------------------------------------------------------------------------ r368561 | svenvh | 2019-08-12 14:44:26 +0200 (Mon, 12 Aug 2019) | 9 lines [OpenCL] Ignore parentheses for sampler initialization The sampler handling logic in SemaInit.cpp would inadvertently treat parentheses around sampler arguments as an implicit cast, leading to an unreachable "can't implicitly cast lvalue to rvalue with this cast kind". Fix by ignoring parentheses once we are in the sampler initializer case. Differential Revision: https://reviews.llvm.org/D66080 ------------------------------------------------------------------------ llvm-svn: 368843 --- clang/lib/Sema/SemaInit.cpp | 2 +- clang/test/SemaOpenCL/sampler_t.cl | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 85af4bc492ce..60f34775c6b2 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -8116,7 +8116,7 @@ ExprResult InitializationSequence::Perform(Sema &S, // argument passing. assert(Step->Type->isSamplerT() && "Sampler initialization on non-sampler type."); - Expr *Init = CurInit.get(); + Expr *Init = CurInit.get()->IgnoreParens(); QualType SourceType = Init->getType(); // Case 1 if (Entity.isParameterKind()) { diff --git a/clang/test/SemaOpenCL/sampler_t.cl b/clang/test/SemaOpenCL/sampler_t.cl index 28e7a0ad27ec..fe9d997c8960 100644 --- a/clang/test/SemaOpenCL/sampler_t.cl +++ b/clang/test/SemaOpenCL/sampler_t.cl @@ -10,6 +10,9 @@ #define CLK_FILTER_NEAREST 0x10 #define CLK_FILTER_LINEAR 0x20 +typedef float float4 __attribute__((ext_vector_type(4))); +float4 read_imagef(read_only image1d_t, sampler_t, float); + constant sampler_t glb_smp = CLK_ADDRESS_CLAMP_TO_EDGE | CLK_NORMALIZED_COORDS_TRUE | CLK_FILTER_LINEAR; constant sampler_t glb_smp2; // expected-error{{variable in constant address space must be initialized}} global sampler_t glb_smp3 = CLK_ADDRESS_CLAMP_TO_EDGE | CLK_NORMALIZED_COORDS_TRUE | CLK_FILTER_NEAREST; // expected-error{{sampler type cannot be used with the __local and __global address space qualifiers}} expected-error {{global sampler requires a const or constant address space qualifier}} @@ -74,3 +77,7 @@ void bar() { foo(smp1+1); //expected-error{{invalid operands to binary expression ('sampler_t' and 'int')}} } +void smp_args(read_only image1d_t image) { + // Test that parentheses around sampler arguments are ignored. + float4 res = read_imagef(image, (glb_smp10), 0.0f); +} From 69e3c1a27b3dc647c7f6943e43b632ea2d817f56 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Wed, 14 Aug 2019 12:56:18 +0000 Subject: [PATCH 110/289] Merging r368552: ------------------------------------------------------------------------ r368552 | stulova | 2019-08-12 12:44:07 +0200 (Mon, 12 Aug 2019) | 12 lines [OpenCL] Fix lang mode predefined macros for C++ mode. In C++ mode we should only avoid adding __OPENCL_C_VERSION__, all other predefined macros about the language mode are still valid. This change also fixes the language version check in the headers accordingly. Differential Revision: https://reviews.llvm.org/D65941 ------------------------------------------------------------------------ llvm-svn: 368844 --- clang/lib/Frontend/InitPreprocessor.cpp | 18 +- clang/lib/Headers/opencl-c-base.h | 17 +- clang/lib/Headers/opencl-c.h | 210 ++++++++++++------------ 3 files changed, 119 insertions(+), 126 deletions(-) diff --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp index 3906e2ae1b98..6feb7bcbd4b7 100644 --- a/clang/lib/Frontend/InitPreprocessor.cpp +++ b/clang/lib/Frontend/InitPreprocessor.cpp @@ -437,17 +437,17 @@ static void InitializeStandardPredefinedMacros(const TargetInfo &TI, default: llvm_unreachable("Unsupported OpenCL version"); } - Builder.defineMacro("CL_VERSION_1_0", "100"); - Builder.defineMacro("CL_VERSION_1_1", "110"); - Builder.defineMacro("CL_VERSION_1_2", "120"); - Builder.defineMacro("CL_VERSION_2_0", "200"); + } + Builder.defineMacro("CL_VERSION_1_0", "100"); + Builder.defineMacro("CL_VERSION_1_1", "110"); + Builder.defineMacro("CL_VERSION_1_2", "120"); + Builder.defineMacro("CL_VERSION_2_0", "200"); - if (TI.isLittleEndian()) - Builder.defineMacro("__ENDIAN_LITTLE__"); + if (TI.isLittleEndian()) + Builder.defineMacro("__ENDIAN_LITTLE__"); - if (LangOpts.FastRelaxedMath) - Builder.defineMacro("__FAST_RELAXED_MATH__"); - } + if (LangOpts.FastRelaxedMath) + Builder.defineMacro("__FAST_RELAXED_MATH__"); } // Not "standard" per se, but available even with the -undef flag. if (LangOpts.AsmPreprocessor) diff --git a/clang/lib/Headers/opencl-c-base.h b/clang/lib/Headers/opencl-c-base.h index a82954ddd326..9a23333a33e6 100644 --- a/clang/lib/Headers/opencl-c-base.h +++ b/clang/lib/Headers/opencl-c-base.h @@ -126,7 +126,7 @@ typedef double double8 __attribute__((ext_vector_type(8))); typedef double double16 __attribute__((ext_vector_type(16))); #endif -#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) #define NULL ((void*)0) #endif @@ -276,7 +276,7 @@ typedef uint cl_mem_fence_flags; */ #define CLK_GLOBAL_MEM_FENCE 0x02 -#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) typedef enum memory_scope { memory_scope_work_item = __OPENCL_MEMORY_SCOPE_WORK_ITEM, @@ -288,9 +288,6 @@ typedef enum memory_scope { #endif } memory_scope; -#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0 - -#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0 /** * Queue a memory fence to ensure correct ordering of memory * operations between work-items of a work-group to @@ -313,7 +310,7 @@ typedef enum memory_order memory_order_seq_cst = __ATOMIC_SEQ_CST } memory_order; -#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#endif // defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) // OpenCL v1.1 s6.11.3, v1.2 s6.12.14, v2.0 s6.13.14 - Image Read and Write Functions @@ -389,14 +386,10 @@ typedef enum memory_order #endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0 // OpenCL v2.0 s6.13.16 - Pipe Functions -#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) #define CLK_NULL_RESERVE_ID (__builtin_astype(((void*)(__SIZE_MAX__)), reserve_id_t)) -#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0 - // OpenCL v2.0 s6.13.17 - Enqueue Kernels -#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0 - #define CL_COMPLETE 0x0 #define CL_RUNNING 0x1 #define CL_SUBMITTED 0x2 @@ -435,7 +428,7 @@ typedef struct { size_t localWorkSize[MAX_WORK_DIM]; } ndrange_t; -#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#endif // defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) #ifdef cl_intel_device_side_avc_motion_estimation #pragma OPENCL EXTENSION cl_intel_device_side_avc_motion_estimation : begin diff --git a/clang/lib/Headers/opencl-c.h b/clang/lib/Headers/opencl-c.h index 4207c53ccedb..8741bccec9ad 100644 --- a/clang/lib/Headers/opencl-c.h +++ b/clang/lib/Headers/opencl-c.h @@ -11,11 +11,11 @@ #include "opencl-c-base.h" -#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) #ifndef cl_khr_depth_images #define cl_khr_depth_images #endif //cl_khr_depth_images -#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) #if __OPENCL_C_VERSION__ < CL_VERSION_2_0 #ifdef cl_khr_3d_image_writes @@ -23,10 +23,10 @@ #endif //cl_khr_3d_image_writes #endif //__OPENCL_C_VERSION__ < CL_VERSION_2_0 -#if __OPENCL_C_VERSION__ >= CL_VERSION_1_2 +#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_1_2) #pragma OPENCL EXTENSION cl_intel_planar_yuv : begin #pragma OPENCL EXTENSION cl_intel_planar_yuv : end -#endif // __OPENCL_C_VERSION__ >= CL_VERSION_1_2 +#endif // defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_1_2) #define __ovld __attribute__((overloadable)) #define __conv __attribute__((convergent)) @@ -6517,11 +6517,11 @@ size_t __ovld __cnfn get_group_id(uint dimindx); */ size_t __ovld __cnfn get_global_offset(uint dimindx); -#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) size_t __ovld get_enqueued_local_size(uint dimindx); size_t __ovld get_global_linear_id(void); size_t __ovld get_local_linear_id(void); -#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) // OpenCL v1.1 s6.11.2, v1.2 s6.12.2, v2.0 s6.13.2 - Math functions @@ -7352,7 +7352,7 @@ half16 __ovld __cnfn fmod(half16 x, half16 y); * Returns fmin(x - floor (x), 0x1.fffffep-1f ). * floor(x) is returned in iptr. */ -#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) float __ovld fract(float x, float *iptr); float2 __ovld fract(float2 x, float2 *iptr); float3 __ovld fract(float3 x, float3 *iptr); @@ -7434,7 +7434,7 @@ half4 __ovld fract(half4 x, __private half4 *iptr); half8 __ovld fract(half8 x, __private half8 *iptr); half16 __ovld fract(half16 x, __private half16 *iptr); #endif //cl_khr_fp16 -#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) /** * Extract mantissa and exponent from x. For each @@ -7442,7 +7442,7 @@ half16 __ovld fract(half16 x, __private half16 *iptr); * magnitude in the interval [1/2, 1) or 0. Each * component of x equals mantissa returned * 2^exp. */ -#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) float __ovld frexp(float x, int *exp); float2 __ovld frexp(float2 x, int2 *exp); float3 __ovld frexp(float3 x, int3 *exp); @@ -7524,7 +7524,7 @@ half4 __ovld frexp(half4 x, __private int4 *exp); half8 __ovld frexp(half8 x, __private int8 *exp); half16 __ovld frexp(half16 x, __private int16 *exp); #endif //cl_khr_fp16 -#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) /** * Compute the value of the square root of x^2 + y^2 @@ -7649,7 +7649,7 @@ half8 __ovld __cnfn lgamma(half8 x); half16 __ovld __cnfn lgamma(half16 x); #endif //cl_khr_fp16 -#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) float __ovld lgamma_r(float x, int *signp); float2 __ovld lgamma_r(float2 x, int2 *signp); float3 __ovld lgamma_r(float3 x, int3 *signp); @@ -7731,7 +7731,7 @@ half4 __ovld lgamma_r(half4 x, __private int4 *signp); half8 __ovld lgamma_r(half8 x, __private int8 *signp); half16 __ovld lgamma_r(half16 x, __private int16 *signp); #endif //cl_khr_fp16 -#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) /** * Compute natural logarithm. @@ -7955,7 +7955,7 @@ half16 __ovld __cnfn minmag(half16 x, half16 y); * the argument. It stores the integral part in the object * pointed to by iptr. */ -#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) float __ovld modf(float x, float *iptr); float2 __ovld modf(float2 x, float2 *iptr); float3 __ovld modf(float3 x, float3 *iptr); @@ -8037,7 +8037,7 @@ half4 __ovld modf(half4 x, __private half4 *iptr); half8 __ovld modf(half8 x, __private half8 *iptr); half16 __ovld modf(half16 x, __private half16 *iptr); #endif //cl_khr_fp16 -#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) /** * Returns a quiet NaN. The nancode may be placed @@ -8215,7 +8215,7 @@ half16 __ovld __cnfn remainder(half16 x, half16 y); * sign as x/y. It stores this signed value in the object * pointed to by quo. */ -#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) 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); @@ -8298,7 +8298,7 @@ half4 __ovld remquo(half4 x, half4 y, __private int4 *quo); half8 __ovld remquo(half8 x, half8 y, __private int8 *quo); half16 __ovld remquo(half16 x, half16 y, __private int16 *quo); #endif //cl_khr_fp16 -#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) /** * Round to integral value (using round to nearest * even rounding mode) in floating-point format. @@ -8439,7 +8439,7 @@ half16 __ovld __cnfn sin(half16); * is the return value and computed cosine is returned * in cosval. */ -#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) float __ovld sincos(float x, float *cosval); float2 __ovld sincos(float2 x, float2 *cosval); float3 __ovld sincos(float3 x, float3 *cosval); @@ -8521,7 +8521,7 @@ half4 __ovld sincos(half4 x, __private half4 *cosval); half8 __ovld sincos(half8 x, __private half8 *cosval); half16 __ovld sincos(half16 x, __private half16 *cosval); #endif //cl_khr_fp16 -#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) /** * Compute hyperbolic sine. @@ -9446,7 +9446,7 @@ ulong16 __ovld __cnfn clz(ulong16 x); * returns the size in bits of the type of x or * component type of x, if x is a vector. */ -#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#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); @@ -9495,7 +9495,7 @@ long8 __ovld ctz(long8 x); ulong8 __ovld ctz(ulong8 x); long16 __ovld ctz(long16 x); ulong16 __ovld ctz(ulong16 x); -#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) /** * Returns mul_hi(a, b) + c. @@ -11340,7 +11340,7 @@ half8 __ovld vload8(size_t offset, const __constant half *p); half16 __ovld vload16(size_t offset, const __constant half *p); #endif //cl_khr_fp16 -#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) 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); @@ -11578,9 +11578,9 @@ half4 __ovld vload4(size_t offset, const __private half *p); half8 __ovld vload8(size_t offset, const __private half *p); half16 __ovld vload16(size_t offset, const __private half *p); #endif //cl_khr_fp16 -#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) -#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) 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); @@ -11814,7 +11814,7 @@ void __ovld vstore4(half4 data, size_t offset, __private half *p); void __ovld vstore8(half8 data, size_t offset, __private half *p); void __ovld vstore16(half16 data, size_t offset, __private half *p); #endif //cl_khr_fp16 -#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) /** * Read sizeof (half) bytes of data from address @@ -11825,13 +11825,13 @@ void __ovld vstore16(half16 data, size_t offset, __private half *p); * must be 16-bit aligned. */ float __ovld vload_half(size_t offset, const __constant half *p); -#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) 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 //__OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) /** * Read sizeof (halfn) bytes of data from address @@ -11846,7 +11846,7 @@ float3 __ovld vload_half3(size_t offset, const __constant half *p); float4 __ovld vload_half4(size_t offset, const __constant half *p); float8 __ovld vload_half8(size_t offset, const __constant half *p); float16 __ovld vload_half16(size_t offset, const __constant half *p); -#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) 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); @@ -11868,7 +11868,7 @@ float3 __ovld vload_half3(size_t offset, const __private half *p); float4 __ovld vload_half4(size_t offset, const __private half *p); float8 __ovld vload_half8(size_t offset, const __private half *p); float16 __ovld vload_half16(size_t offset, const __private half *p); -#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) /** * The float value given by data is first @@ -11881,7 +11881,7 @@ float16 __ovld vload_half16(size_t offset, const __private half *p); * The default current rounding mode is round to * nearest even. */ -#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) 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); @@ -11927,7 +11927,7 @@ void __ovld vstore_half_rtz(double data, size_t offset, __private half *p); void __ovld vstore_half_rtp(double data, size_t offset, __private half *p); void __ovld vstore_half_rtn(double data, size_t offset, __private half *p); #endif //cl_khr_fp64 -#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) /** * The floatn value given by data is converted to @@ -11940,7 +11940,7 @@ void __ovld vstore_half_rtn(double data, size_t offset, __private half *p); * The default current rounding mode is round to * nearest even. */ -#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) 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); @@ -12146,7 +12146,7 @@ void __ovld vstore_half4_rtn(double4 data, size_t offset, __private half *p); void __ovld vstore_half8_rtn(double8 data, size_t offset, __private half *p); void __ovld vstore_half16_rtn(double16 data, size_t offset, __private half *p); #endif //cl_khr_fp64 -#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) /** * For n = 1, 2, 4, 8 and 16 read sizeof (halfn) @@ -12167,7 +12167,7 @@ float3 __ovld vloada_half3(size_t offset, const __constant half *p); float4 __ovld vloada_half4(size_t offset, const __constant half *p); float8 __ovld vloada_half8(size_t offset, const __constant half *p); float16 __ovld vloada_half16(size_t offset, const __constant half *p); -#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) 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); @@ -12193,7 +12193,7 @@ float3 __ovld vloada_half3(size_t offset, const __private half *p); float4 __ovld vloada_half4(size_t offset, const __private half *p); float8 __ovld vloada_half8(size_t offset, const __private half *p); float16 __ovld vloada_half16(size_t offset, const __private half *p); -#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) /** * The floatn value given by data is converted to @@ -12211,7 +12211,7 @@ float16 __ovld vloada_half16(size_t offset, const __private half *p); * mode. The default current rounding mode is * round to nearest even. */ -#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) 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); @@ -12496,7 +12496,7 @@ void __ovld vstorea_half4_rtn(double4 data,size_t offset, __private half *p); void __ovld vstorea_half8_rtn(double8 data,size_t offset, __private half *p); void __ovld vstorea_half16_rtn(double16 data,size_t offset, __private half *p); #endif //cl_khr_fp64 -#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) // OpenCL v1.1 s6.11.8, v1.2 s6.12.8, v2.0 s6.13.8 - Synchronization Functions @@ -12532,10 +12532,10 @@ void __ovld vstorea_half16_rtn(double16 data,size_t offset, __private half *p); void __ovld __conv barrier(cl_mem_fence_flags flags); -#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) void __ovld __conv work_group_barrier(cl_mem_fence_flags flags, memory_scope scope); void __ovld __conv work_group_barrier(cl_mem_fence_flags flags); -#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) // OpenCL v1.1 s6.11.9, v1.2 s6.12.9 - Explicit Memory Fence Functions @@ -12580,7 +12580,7 @@ void __ovld write_mem_fence(cl_mem_fence_flags flags); // OpenCL v2.0 s6.13.9 - Address Space Qualifier Functions -#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) cl_mem_fence_flags __ovld get_fence(const void *ptr); cl_mem_fence_flags __ovld get_fence(void *ptr); @@ -12591,7 +12591,7 @@ cl_mem_fence_flags __ovld get_fence(void *ptr); * where gentype is builtin type or user defined type. */ -#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) // 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 @@ -13371,7 +13371,7 @@ unsigned long __ovld atom_xor(volatile __local unsigned long *p, unsigned long v // OpenCL v2.0 s6.13.11 - Atomics Functions -#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) // double atomics support requires extensions cl_khr_int64_base_atomics and cl_khr_int64_extended_atomics #if defined(cl_khr_int64_base_atomics) && defined(cl_khr_int64_extended_atomics) @@ -13692,7 +13692,7 @@ 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 //__OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#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 @@ -14186,7 +14186,7 @@ half16 __ovld __cnfn shuffle2(half8 x, half8 y, ushort16 mask); half16 __ovld __cnfn shuffle2(half16 x, half16 y, ushort16 mask); #endif //cl_khr_fp16 -#if __OPENCL_C_VERSION__ >= CL_VERSION_1_2 +#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))); @@ -14307,7 +14307,7 @@ int4 __purefn __ovld read_imagei(read_only image3d_t image, sampler_t sampler, f uint4 __purefn __ovld read_imageui(read_only image3d_t image, sampler_t sampler, int4 coord); uint4 __purefn __ovld read_imageui(read_only image3d_t image, sampler_t sampler, float4 coord); -#if __OPENCL_C_VERSION__ >= CL_VERSION_1_2 +#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_1_2) float4 __purefn __ovld read_imagef(read_only image2d_array_t image_array, sampler_t sampler, int4 coord); float4 __purefn __ovld read_imagef(read_only image2d_array_t image_array, sampler_t sampler, float4 coord); @@ -14315,7 +14315,7 @@ int4 __purefn __ovld read_imagei(read_only image2d_array_t image_array, sampler_ int4 __purefn __ovld read_imagei(read_only image2d_array_t image_array, sampler_t sampler, float4 coord); uint4 __purefn __ovld read_imageui(read_only image2d_array_t image_array, sampler_t sampler, int4 coord); uint4 __purefn __ovld read_imageui(read_only image2d_array_t image_array, sampler_t sampler, float4 coord); -#endif // __OPENCL_C_VERSION__ >= CL_VERSION_1_2 +#endif // defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_1_2) float4 __purefn __ovld read_imagef(read_only image1d_t image, sampler_t sampler, int coord); float4 __purefn __ovld read_imagef(read_only image1d_t image, sampler_t sampler, float coord); @@ -14325,7 +14325,7 @@ int4 __purefn __ovld read_imagei(read_only image1d_t image, sampler_t sampler, f uint4 __purefn __ovld read_imageui(read_only image1d_t image, sampler_t sampler, int coord); uint4 __purefn __ovld read_imageui(read_only image1d_t image, sampler_t sampler, float coord); -#if __OPENCL_C_VERSION__ >= CL_VERSION_1_2 +#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_1_2) float4 __purefn __ovld read_imagef(read_only image1d_array_t image_array, sampler_t sampler, int2 coord); float4 __purefn __ovld read_imagef(read_only image1d_array_t image_array, sampler_t sampler, float2 coord); @@ -14333,7 +14333,7 @@ int4 __purefn __ovld read_imagei(read_only image1d_array_t image_array, sampler_ int4 __purefn __ovld read_imagei(read_only image1d_array_t image_array, sampler_t sampler, float2 coord); uint4 __purefn __ovld read_imageui(read_only image1d_array_t image_array, sampler_t sampler, int2 coord); uint4 __purefn __ovld read_imageui(read_only image1d_array_t image_array, sampler_t sampler, float2 coord); -#endif // __OPENCL_C_VERSION__ >= CL_VERSION_1_2 +#endif // defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_1_2) #ifdef cl_khr_depth_images float __purefn __ovld read_imagef(read_only image2d_depth_t image, sampler_t sampler, float2 coord); @@ -14358,7 +14358,7 @@ float __purefn __ovld read_imagef(read_only image2d_array_msaa_depth_t image, in #endif //cl_khr_gl_msaa_sharing // OpenCL Extension v2.0 s9.18 - Mipmaps -#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) #ifdef cl_khr_mipmap_image float4 __purefn __ovld read_imagef(read_only image1d_t image, sampler_t sampler, float coord, float lod); @@ -14410,9 +14410,9 @@ int4 __purefn __ovld read_imagei(read_only image3d_t image, sampler_t sampler, f uint4 __purefn __ovld read_imageui(read_only image3d_t image, sampler_t sampler, float4 coord, float4 gradientX, float4 gradientY); #endif //cl_khr_mipmap_image -#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) -#if __OPENCL_C_VERSION__ >= CL_VERSION_1_2 +#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_1_2) /** * Sampler-less Image Access @@ -14447,7 +14447,7 @@ float4 __purefn __ovld read_imagef(read_only image3d_t image, int4 coord); int4 __purefn __ovld read_imagei(read_only image3d_t image, int4 coord); uint4 __purefn __ovld read_imageui(read_only image3d_t image, int4 coord); -#endif // __OPENCL_C_VERSION__ >= CL_VERSION_1_2 +#endif // defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_1_2) // Image read functions returning half4 type #ifdef cl_khr_fp16 @@ -14457,7 +14457,7 @@ half4 __purefn __ovld read_imageh(read_only image2d_t image, sampler_t sampler, half4 __purefn __ovld read_imageh(read_only image2d_t image, sampler_t sampler, float2 coord); half4 __purefn __ovld read_imageh(read_only image3d_t image, sampler_t sampler, int4 coord); half4 __purefn __ovld read_imageh(read_only image3d_t image, sampler_t sampler, float4 coord); -#if __OPENCL_C_VERSION__ >= CL_VERSION_1_2 +#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_1_2) half4 __purefn __ovld read_imageh(read_only image1d_array_t image, sampler_t sampler, int2 coord); half4 __purefn __ovld read_imageh(read_only image1d_array_t image, sampler_t sampler, float2 coord); half4 __purefn __ovld read_imageh(read_only image2d_array_t image, sampler_t sampler, int4 coord); @@ -14471,11 +14471,11 @@ half4 __purefn __ovld read_imageh(read_only image3d_t image, int4 coord); half4 __purefn __ovld read_imageh(read_only image1d_array_t image, int2 coord); half4 __purefn __ovld read_imageh(read_only image2d_array_t image, int4 coord); half4 __purefn __ovld read_imageh(read_only image1d_buffer_t image, int coord); -#endif // __OPENCL_C_VERSION__ >= CL_VERSION_1_2 +#endif // defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_1_2) #endif //cl_khr_fp16 // Image read functions for read_write images -#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) float4 __purefn __ovld read_imagef(read_write image1d_t image, int coord); int4 __purefn __ovld read_imagei(read_write image1d_t image, int coord); uint4 __purefn __ovld read_imageui(read_write image1d_t image, int coord); @@ -14518,7 +14518,7 @@ float __purefn __ovld read_imagef(read_write image2d_msaa_depth_t image, int2 co float __purefn __ovld read_imagef(read_write image2d_array_msaa_depth_t image, int4 coord, int sample); #endif //cl_khr_gl_msaa_sharing -#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) #ifdef cl_khr_mipmap_image float4 __purefn __ovld read_imagef(read_write image1d_t image, sampler_t sampler, float coord, float lod); int4 __purefn __ovld read_imagei(read_write image1d_t image, sampler_t sampler, float coord, float lod); @@ -14569,7 +14569,7 @@ int4 __purefn __ovld read_imagei(read_write image3d_t image, sampler_t sampler, uint4 __purefn __ovld read_imageui(read_write image3d_t image, sampler_t sampler, float4 coord, float4 gradientX, float4 gradientY); #endif //cl_khr_mipmap_image -#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) // Image read functions returning half4 type #ifdef cl_khr_fp16 @@ -14580,7 +14580,7 @@ half4 __purefn __ovld read_imageh(read_write image1d_array_t image, int2 coord); half4 __purefn __ovld read_imageh(read_write image2d_array_t image, int4 coord); half4 __purefn __ovld read_imageh(read_write image1d_buffer_t image, int coord); #endif //cl_khr_fp16 -#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) /** * Write color value to location specified by coordinate @@ -14681,7 +14681,7 @@ void __ovld write_imagef(write_only image2d_array_depth_t image, int4 coord, flo #endif //cl_khr_depth_images // OpenCL Extension v2.0 s9.18 - Mipmaps -#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) #ifdef cl_khr_mipmap_image void __ovld write_imagef(write_only image1d_t image, int coord, int lod, float4 color); void __ovld write_imagei(write_only image1d_t image, int coord, int lod, int4 color); @@ -14708,7 +14708,7 @@ void __ovld write_imagei(write_only image3d_t image, int4 coord, int lod, int4 c void __ovld write_imageui(write_only image3d_t image, int4 coord, int lod, uint4 color); #endif #endif //cl_khr_mipmap_image -#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) // Image write functions for half4 type #ifdef cl_khr_fp16 @@ -14723,7 +14723,7 @@ void __ovld write_imageh(write_only image1d_buffer_t image, int coord, half4 col #endif //cl_khr_fp16 // Image write functions for read_write images -#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) void __ovld write_imagef(read_write image2d_t image, int2 coord, float4 color); void __ovld write_imagei(read_write image2d_t image, int2 coord, int4 color); void __ovld write_imageui(read_write image2d_t image, int2 coord, uint4 color); @@ -14755,7 +14755,7 @@ void __ovld write_imagef(read_write image2d_depth_t image, int2 coord, float col void __ovld write_imagef(read_write image2d_array_depth_t image, int4 coord, float color); #endif //cl_khr_depth_images -#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) #ifdef cl_khr_mipmap_image void __ovld write_imagef(read_write image1d_t image, int coord, int lod, float4 color); void __ovld write_imagei(read_write image1d_t image, int coord, int lod, int4 color); @@ -14782,7 +14782,7 @@ void __ovld write_imagei(read_write image3d_t image, int4 coord, int lod, int4 c void __ovld write_imageui(read_write image3d_t image, int4 coord, int lod, uint4 color); #endif #endif //cl_khr_mipmap_image -#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) // Image write functions for half4 type #ifdef cl_khr_fp16 @@ -14795,7 +14795,7 @@ void __ovld write_imageh(read_write image1d_array_t image, int2 coord, half4 col void __ovld write_imageh(read_write image2d_array_t image, int4 coord, half4 color); void __ovld write_imageh(read_write image1d_buffer_t image, int coord, half4 color); #endif //cl_khr_fp16 -#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) // Note: In OpenCL v1.0/1.1/1.2, image argument of image query builtin functions does not have // access qualifier, which by default assume read_only access qualifier. Image query builtin @@ -14843,7 +14843,7 @@ int __ovld __cnfn get_image_width(write_only image2d_array_msaa_t image); int __ovld __cnfn get_image_width(write_only image2d_array_msaa_depth_t image); #endif //cl_khr_gl_msaa_sharing -#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) int __ovld __cnfn get_image_width(read_write image1d_t image); int __ovld __cnfn get_image_width(read_write image1d_buffer_t image); int __ovld __cnfn get_image_width(read_write image2d_t image); @@ -14860,7 +14860,7 @@ int __ovld __cnfn get_image_width(read_write image2d_msaa_depth_t image); int __ovld __cnfn get_image_width(read_write image2d_array_msaa_t image); int __ovld __cnfn get_image_width(read_write image2d_array_msaa_depth_t image); #endif //cl_khr_gl_msaa_sharing -#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) /** * Return the image height in pixels. @@ -14895,7 +14895,7 @@ int __ovld __cnfn get_image_height(write_only image2d_array_msaa_t image); int __ovld __cnfn get_image_height(write_only image2d_array_msaa_depth_t image); #endif //cl_khr_gl_msaa_sharing -#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) int __ovld __cnfn get_image_height(read_write image2d_t image); int __ovld __cnfn get_image_height(read_write image3d_t image); int __ovld __cnfn get_image_height(read_write image2d_array_t image); @@ -14909,7 +14909,7 @@ int __ovld __cnfn get_image_height(read_write image2d_msaa_depth_t image); int __ovld __cnfn get_image_height(read_write image2d_array_msaa_t image); int __ovld __cnfn get_image_height(read_write image2d_array_msaa_depth_t image); #endif //cl_khr_gl_msaa_sharing -#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) /** * Return the image depth in pixels. @@ -14920,12 +14920,12 @@ int __ovld __cnfn get_image_depth(read_only image3d_t image); int __ovld __cnfn get_image_depth(write_only image3d_t image); #endif -#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) int __ovld __cnfn get_image_depth(read_write image3d_t image); -#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) // OpenCL Extension v2.0 s9.18 - Mipmaps -#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) #ifdef cl_khr_mipmap_image /** * Return the image miplevels. @@ -14961,7 +14961,7 @@ int __ovld get_image_num_mip_levels(read_write image2d_array_depth_t image); int __ovld get_image_num_mip_levels(read_write image2d_depth_t image); #endif //cl_khr_mipmap_image -#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) /** * Return the channel data type. Valid values are: @@ -15018,7 +15018,7 @@ int __ovld __cnfn get_image_channel_data_type(write_only image2d_array_msaa_t im int __ovld __cnfn get_image_channel_data_type(write_only image2d_array_msaa_depth_t image); #endif //cl_khr_gl_msaa_sharing -#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) int __ovld __cnfn get_image_channel_data_type(read_write image1d_t image); int __ovld __cnfn get_image_channel_data_type(read_write image1d_buffer_t image); int __ovld __cnfn get_image_channel_data_type(read_write image2d_t image); @@ -15035,7 +15035,7 @@ int __ovld __cnfn get_image_channel_data_type(read_write image2d_msaa_depth_t im int __ovld __cnfn get_image_channel_data_type(read_write image2d_array_msaa_t image); int __ovld __cnfn get_image_channel_data_type(read_write image2d_array_msaa_depth_t image); #endif //cl_khr_gl_msaa_sharing -#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) /** * Return the image channel order. Valid values are: @@ -15090,7 +15090,7 @@ int __ovld __cnfn get_image_channel_order(write_only image2d_array_msaa_t image) int __ovld __cnfn get_image_channel_order(write_only image2d_array_msaa_depth_t image); #endif //cl_khr_gl_msaa_sharing -#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) int __ovld __cnfn get_image_channel_order(read_write image1d_t image); int __ovld __cnfn get_image_channel_order(read_write image1d_buffer_t image); int __ovld __cnfn get_image_channel_order(read_write image2d_t image); @@ -15107,7 +15107,7 @@ int __ovld __cnfn get_image_channel_order(read_write image2d_msaa_depth_t image) int __ovld __cnfn get_image_channel_order(read_write image2d_array_msaa_t image); int __ovld __cnfn get_image_channel_order(read_write image2d_array_msaa_depth_t image); #endif //cl_khr_gl_msaa_sharing -#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) /** * Return the 2D image width and height as an int2 @@ -15140,7 +15140,7 @@ int2 __ovld __cnfn get_image_dim(write_only image2d_array_msaa_t image); int2 __ovld __cnfn get_image_dim(write_only image2d_array_msaa_depth_t image); #endif //cl_khr_gl_msaa_sharing -#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) int2 __ovld __cnfn get_image_dim(read_write image2d_t image); int2 __ovld __cnfn get_image_dim(read_write image2d_array_t image); #ifdef cl_khr_depth_images @@ -15153,7 +15153,7 @@ int2 __ovld __cnfn get_image_dim(read_write image2d_msaa_depth_t image); int2 __ovld __cnfn get_image_dim(read_write image2d_array_msaa_t image); int2 __ovld __cnfn get_image_dim(read_write image2d_array_msaa_depth_t image); #endif //cl_khr_gl_msaa_sharing -#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) /** * Return the 3D image width, height, and depth as an @@ -15165,9 +15165,9 @@ int4 __ovld __cnfn get_image_dim(read_only image3d_t image); #ifdef cl_khr_3d_image_writes int4 __ovld __cnfn get_image_dim(write_only image3d_t image); #endif -#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) int4 __ovld __cnfn get_image_dim(read_write image3d_t image); -#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) /** * Return the image array size. @@ -15193,7 +15193,7 @@ size_t __ovld __cnfn get_image_array_size(write_only image2d_array_msaa_t image_ size_t __ovld __cnfn get_image_array_size(write_only image2d_array_msaa_depth_t image_array); #endif //cl_khr_gl_msaa_sharing -#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) size_t __ovld __cnfn get_image_array_size(read_write image1d_array_t image_array); size_t __ovld __cnfn get_image_array_size(read_write image2d_array_t image_array); #ifdef cl_khr_depth_images @@ -15203,7 +15203,7 @@ size_t __ovld __cnfn get_image_array_size(read_write image2d_array_depth_t image size_t __ovld __cnfn get_image_array_size(read_write image2d_array_msaa_t image_array); size_t __ovld __cnfn get_image_array_size(read_write image2d_array_msaa_depth_t image_array); #endif //cl_khr_gl_msaa_sharing -#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) /** * Return the number of samples associated with image @@ -15219,17 +15219,17 @@ int __ovld get_image_num_samples(write_only image2d_msaa_depth_t image); int __ovld get_image_num_samples(write_only image2d_array_msaa_t image); int __ovld get_image_num_samples(write_only image2d_array_msaa_depth_t image); -#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) int __ovld get_image_num_samples(read_write image2d_msaa_t image); int __ovld get_image_num_samples(read_write image2d_msaa_depth_t image); int __ovld get_image_num_samples(read_write image2d_array_msaa_t image); int __ovld get_image_num_samples(read_write image2d_array_msaa_depth_t image); -#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) #endif // OpenCL v2.0 s6.13.15 - Work-group Functions -#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) int __ovld __conv work_group_all(int predicate); int __ovld __conv work_group_any(int predicate); @@ -15327,16 +15327,16 @@ double __ovld __conv work_group_scan_inclusive_min(double x); double __ovld __conv work_group_scan_inclusive_max(double x); #endif //cl_khr_fp64 -#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) // OpenCL v2.0 s6.13.16 - Pipe Functions -#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) bool __ovld is_valid_reserve_id(reserve_id_t reserve_id); -#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) // OpenCL v2.0 s6.13.17 - Enqueue Kernels -#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) ndrange_t __ovld ndrange_1D(size_t); ndrange_t __ovld ndrange_1D(size_t, size_t); @@ -15365,7 +15365,7 @@ bool __ovld is_valid_event (clk_event_t event); void __ovld capture_event_profiling_info(clk_event_t, clk_profiling_info, __global void* value); queue_t __ovld get_default_queue(void); -#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) // OpenCL Extension v2.0 s9.17 - Sub-groups @@ -15374,16 +15374,16 @@ queue_t __ovld get_default_queue(void); uint __ovld get_sub_group_size(void); uint __ovld get_max_sub_group_size(void); uint __ovld get_num_sub_groups(void); -#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) uint __ovld get_enqueued_num_sub_groups(void); -#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) uint __ovld get_sub_group_id(void); uint __ovld get_sub_group_local_id(void); void __ovld __conv sub_group_barrier(cl_mem_fence_flags flags); -#if __OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) void __ovld __conv sub_group_barrier(cl_mem_fence_flags flags, memory_scope scope); -#endif //__OPENCL_C_VERSION__ >= CL_VERSION_2_0 +#endif //defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) int __ovld __conv sub_group_all(int predicate); int __ovld __conv sub_group_any(int predicate); @@ -15573,12 +15573,12 @@ uint2 __ovld __conv intel_sub_group_block_read2( read_only image2d_t image, in uint4 __ovld __conv intel_sub_group_block_read4( read_only image2d_t image, int2 coord ); uint8 __ovld __conv intel_sub_group_block_read8( read_only image2d_t image, int2 coord ); -#if (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) +#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) uint __ovld __conv intel_sub_group_block_read(read_write image2d_t image, int2 coord); uint2 __ovld __conv intel_sub_group_block_read2(read_write image2d_t image, int2 coord); uint4 __ovld __conv intel_sub_group_block_read4(read_write image2d_t image, int2 coord); uint8 __ovld __conv intel_sub_group_block_read8(read_write image2d_t image, int2 coord); -#endif // (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) +#endif // defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) uint __ovld __conv intel_sub_group_block_read( const __global uint* p ); uint2 __ovld __conv intel_sub_group_block_read2( const __global uint* p ); @@ -15590,12 +15590,12 @@ void __ovld __conv intel_sub_group_block_write2(write_only image2d_t image, i void __ovld __conv intel_sub_group_block_write4(write_only image2d_t image, int2 coord, uint4 data); void __ovld __conv intel_sub_group_block_write8(write_only image2d_t image, int2 coord, uint8 data); -#if (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) +#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) void __ovld __conv intel_sub_group_block_write(read_write image2d_t image, int2 coord, uint data); void __ovld __conv intel_sub_group_block_write2(read_write image2d_t image, int2 coord, uint2 data); void __ovld __conv intel_sub_group_block_write4(read_write image2d_t image, int2 coord, uint4 data); void __ovld __conv intel_sub_group_block_write8(read_write image2d_t image, int2 coord, uint8 data); -#endif // (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) +#endif // defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) void __ovld __conv intel_sub_group_block_write( __global uint* p, uint data ); void __ovld __conv intel_sub_group_block_write2( __global uint* p, uint2 data ); @@ -15713,12 +15713,12 @@ uint2 __ovld __conv intel_sub_group_block_read_ui2( read_only image2d_t ima uint4 __ovld __conv intel_sub_group_block_read_ui4( read_only image2d_t image, int2 byte_coord ); uint8 __ovld __conv intel_sub_group_block_read_ui8( read_only image2d_t image, int2 byte_coord ); -#if (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) +#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) uint __ovld __conv intel_sub_group_block_read_ui( read_write image2d_t image, int2 byte_coord ); uint2 __ovld __conv intel_sub_group_block_read_ui2( read_write image2d_t image, int2 byte_coord ); uint4 __ovld __conv intel_sub_group_block_read_ui4( read_write image2d_t image, int2 byte_coord ); uint8 __ovld __conv intel_sub_group_block_read_ui8( read_write image2d_t image, int2 byte_coord ); -#endif // (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) +#endif // defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) uint __ovld __conv intel_sub_group_block_read_ui( const __global uint* p ); uint2 __ovld __conv intel_sub_group_block_read_ui2( const __global uint* p ); @@ -15730,12 +15730,12 @@ void __ovld __conv intel_sub_group_block_write_ui2( read_only image2d_t im void __ovld __conv intel_sub_group_block_write_ui4( read_only image2d_t image, int2 byte_coord, uint4 data ); void __ovld __conv intel_sub_group_block_write_ui8( read_only image2d_t image, int2 byte_coord, uint8 data ); -#if (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) +#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) void __ovld __conv intel_sub_group_block_write_ui( read_write image2d_t image, int2 byte_coord, uint data ); void __ovld __conv intel_sub_group_block_write_ui2( read_write image2d_t image, int2 byte_coord, uint2 data ); void __ovld __conv intel_sub_group_block_write_ui4( read_write image2d_t image, int2 byte_coord, uint4 data ); void __ovld __conv intel_sub_group_block_write_ui8( read_write image2d_t image, int2 byte_coord, uint8 data ); -#endif // (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) +#endif // defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) void __ovld __conv intel_sub_group_block_write_ui( __global uint* p, uint data ); void __ovld __conv intel_sub_group_block_write_ui2( __global uint* p, uint2 data ); @@ -15747,12 +15747,12 @@ ushort2 __ovld __conv intel_sub_group_block_read_us2( read_only image2d_t im ushort4 __ovld __conv intel_sub_group_block_read_us4( read_only image2d_t image, int2 coord ); ushort8 __ovld __conv intel_sub_group_block_read_us8( read_only image2d_t image, int2 coord ); -#if (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) +#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) ushort __ovld __conv intel_sub_group_block_read_us(read_write image2d_t image, int2 coord); ushort2 __ovld __conv intel_sub_group_block_read_us2(read_write image2d_t image, int2 coord); ushort4 __ovld __conv intel_sub_group_block_read_us4(read_write image2d_t image, int2 coord); ushort8 __ovld __conv intel_sub_group_block_read_us8(read_write image2d_t image, int2 coord); -#endif // (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) +#endif // defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) ushort __ovld __conv intel_sub_group_block_read_us( const __global ushort* p ); ushort2 __ovld __conv intel_sub_group_block_read_us2( const __global ushort* p ); @@ -15764,12 +15764,12 @@ void __ovld __conv intel_sub_group_block_write_us2(write_only image2d_t i void __ovld __conv intel_sub_group_block_write_us4(write_only image2d_t image, int2 coord, ushort4 data); void __ovld __conv intel_sub_group_block_write_us8(write_only image2d_t image, int2 coord, ushort8 data); -#if (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) +#if defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) void __ovld __conv intel_sub_group_block_write_us(read_write image2d_t image, int2 coord, ushort data); void __ovld __conv intel_sub_group_block_write_us2(read_write image2d_t image, int2 coord, ushort2 data); void __ovld __conv intel_sub_group_block_write_us4(read_write image2d_t image, int2 coord, ushort4 data); void __ovld __conv intel_sub_group_block_write_us8(read_write image2d_t image, int2 coord, ushort8 data); -#endif // (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) +#endif // defined(__OPENCL_CPP_VERSION__) || (__OPENCL_C_VERSION__ >= CL_VERSION_2_0) void __ovld __conv intel_sub_group_block_write_us( __global ushort* p, ushort data ); void __ovld __conv intel_sub_group_block_write_us2( __global ushort* p, ushort2 data ); From 82330f1c510c4486c57c9df9069005317bc9af39 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Wed, 14 Aug 2019 12:59:17 +0000 Subject: [PATCH 111/289] Merging r368300: ------------------------------------------------------------------------ r368300 | lenary | 2019-08-08 16:40:54 +0200 (Thu, 08 Aug 2019) | 18 lines [RISCV] Minimal stack realignment support Summary: Currently the RISC-V backend does not realign the stack. This can be an issue even for the RV32I/RV64I ABIs (where the stack is 16-byte aligned), though is rare. It will be much more comment with RV32E (though the alignment requirements for common data types remain under-documented...). This patch adds minimal support for stack realignment. It should cope with large realignments. It will error out if the stack needs realignment and variable sized objects are present. It feels like a lot of the code like getFrameIndexReference and determineFrameLayout could be refactored somehow, as right now it feels fiddly and brittle. We also seem to allocate a lot more memory than GCC does for equivalent C code. Reviewers: asb Reviewed By: asb Subscribers: wwei, jrtc27, s.egerton, MaskRay, Jim, lenary, hiraditya, rbar, johnrusso, simoncook, apazos, sabuasal, niosHD, kito-cheng, shiva0217, zzheng, edward-jones, rogfer01, MartinMosbeck, brucehoult, the_o, rkruppe, PkmX, jocewei, psnobl, benna, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D62007 ------------------------------------------------------------------------ llvm-svn: 368846 --- llvm/lib/Target/RISCV/RISCVFrameLowering.cpp | 48 +- .../RISCV/stack-realignment-unsupported.ll | 13 + llvm/test/CodeGen/RISCV/stack-realignment.ll | 627 ++++++++++++++++++ 3 files changed, 686 insertions(+), 2 deletions(-) create mode 100644 llvm/test/CodeGen/RISCV/stack-realignment-unsupported.ll create mode 100644 llvm/test/CodeGen/RISCV/stack-realignment.ll diff --git a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp index 32c3b9684d2c..bbaa16c08634 100644 --- a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp @@ -40,8 +40,16 @@ void RISCVFrameLowering::determineFrameLayout(MachineFunction &MF) const { uint64_t FrameSize = MFI.getStackSize(); // Get the alignment. - uint64_t StackAlign = RI->needsStackRealignment(MF) ? MFI.getMaxAlignment() - : getStackAlignment(); + unsigned StackAlign = getStackAlignment(); + if (RI->needsStackRealignment(MF)) { + unsigned MaxStackAlign = std::max(StackAlign, MFI.getMaxAlignment()); + FrameSize += (MaxStackAlign - StackAlign); + StackAlign = MaxStackAlign; + } + + // Set Max Call Frame Size + uint64_t MaxCallSize = alignTo(MFI.getMaxCallFrameSize(), StackAlign); + MFI.setMaxCallFrameSize(MaxCallSize); // Make sure the frame is aligned. FrameSize = alignTo(FrameSize, StackAlign); @@ -101,6 +109,12 @@ void RISCVFrameLowering::emitPrologue(MachineFunction &MF, const RISCVInstrInfo *TII = STI.getInstrInfo(); MachineBasicBlock::iterator MBBI = MBB.begin(); + if (RI->needsStackRealignment(MF) && MFI.hasVarSizedObjects()) { + report_fatal_error( + "RISC-V backend can't currently handle functions that need stack " + "realignment and have variable sized objects"); + } + unsigned FPReg = getFPReg(STI); unsigned SPReg = getSPReg(STI); @@ -158,6 +172,29 @@ void RISCVFrameLowering::emitPrologue(MachineFunction &MF, nullptr, RI->getDwarfRegNum(FPReg, true), 0)); BuildMI(MBB, MBBI, DL, TII->get(TargetOpcode::CFI_INSTRUCTION)) .addCFIIndex(CFIIndex); + + // Realign Stack + const RISCVRegisterInfo *RI = STI.getRegisterInfo(); + if (RI->needsStackRealignment(MF)) { + unsigned MaxAlignment = MFI.getMaxAlignment(); + + const RISCVInstrInfo *TII = STI.getInstrInfo(); + if (isInt<12>(-(int)MaxAlignment)) { + BuildMI(MBB, MBBI, DL, TII->get(RISCV::ANDI), SPReg) + .addReg(SPReg) + .addImm(-(int)MaxAlignment); + } else { + unsigned ShiftAmount = countTrailingZeros(MaxAlignment); + unsigned VR = + MF.getRegInfo().createVirtualRegister(&RISCV::GPRRegClass); + BuildMI(MBB, MBBI, DL, TII->get(RISCV::SRLI), VR) + .addReg(SPReg) + .addImm(ShiftAmount); + BuildMI(MBB, MBBI, DL, TII->get(RISCV::SLLI), SPReg) + .addReg(VR) + .addImm(ShiftAmount); + } + } } } @@ -257,6 +294,13 @@ int RISCVFrameLowering::getFrameIndexReference(const MachineFunction &MF, if (FI >= MinCSFI && FI <= MaxCSFI) { FrameReg = RISCV::X2; Offset += MF.getFrameInfo().getStackSize(); + } else if (RI->needsStackRealignment(MF)) { + assert(!MFI.hasVarSizedObjects() && + "Unexpected combination of stack realignment and varsized objects"); + // If the stack was realigned, the frame pointer is set in order to allow + // SP to be restored, but we still access stack objects using SP. + FrameReg = RISCV::X2; + Offset += MF.getFrameInfo().getStackSize(); } else { FrameReg = RI->getFrameRegister(MF); if (hasFP(MF)) diff --git a/llvm/test/CodeGen/RISCV/stack-realignment-unsupported.ll b/llvm/test/CodeGen/RISCV/stack-realignment-unsupported.ll new file mode 100644 index 000000000000..f2f11b073cfb --- /dev/null +++ b/llvm/test/CodeGen/RISCV/stack-realignment-unsupported.ll @@ -0,0 +1,13 @@ +; RUN: not llc -mtriple=riscv32 < %s 2>&1 | FileCheck %s +; RUN: not llc -mtriple=riscv64 < %s 2>&1 | FileCheck %s + +; CHECK: LLVM ERROR: RISC-V backend can't currently handle functions that need stack realignment and have variable sized objects + +declare void @callee(i8*, i32*) + +define void @caller(i32 %n) nounwind { + %1 = alloca i8, i32 %n + %2 = alloca i32, align 64 + call void @callee(i8* %1, i32 *%2) + ret void +} diff --git a/llvm/test/CodeGen/RISCV/stack-realignment.ll b/llvm/test/CodeGen/RISCV/stack-realignment.ll new file mode 100644 index 000000000000..252a099d0986 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/stack-realignment.ll @@ -0,0 +1,627 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=riscv32 -verify-machineinstrs < %s \ +; RUN: | FileCheck %s -check-prefix=RV32I +; RUN: llc -mtriple=riscv64 -verify-machineinstrs < %s \ +; RUN: | FileCheck %s -check-prefix=RV64I + +declare void @callee(i8*) + +define void @caller32() nounwind { +; RV32I-LABEL: caller32: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -64 +; RV32I-NEXT: sw ra, 60(sp) +; RV32I-NEXT: sw s0, 56(sp) +; RV32I-NEXT: addi s0, sp, 64 +; RV32I-NEXT: andi sp, sp, -32 +; RV32I-NEXT: addi a0, sp, 32 +; RV32I-NEXT: call callee +; RV32I-NEXT: addi sp, s0, -64 +; RV32I-NEXT: lw s0, 56(sp) +; RV32I-NEXT: lw ra, 60(sp) +; RV32I-NEXT: addi sp, sp, 64 +; RV32I-NEXT: ret +; +; RV64I-LABEL: caller32: +; RV64I: # %bb.0: +; RV64I-NEXT: addi sp, sp, -64 +; RV64I-NEXT: sd ra, 56(sp) +; RV64I-NEXT: sd s0, 48(sp) +; RV64I-NEXT: addi s0, sp, 64 +; RV64I-NEXT: andi sp, sp, -32 +; RV64I-NEXT: addi a0, sp, 32 +; RV64I-NEXT: call callee +; RV64I-NEXT: addi sp, s0, -64 +; RV64I-NEXT: ld s0, 48(sp) +; RV64I-NEXT: ld ra, 56(sp) +; RV64I-NEXT: addi sp, sp, 64 +; RV64I-NEXT: ret + %1 = alloca i8, align 32 + call void @callee(i8* %1) + ret void +} + +define void @caller_no_realign32() nounwind "no-realign-stack" { +; RV32I-LABEL: caller_no_realign32: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: mv a0, sp +; RV32I-NEXT: call callee +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret +; +; RV64I-LABEL: caller_no_realign32: +; RV64I: # %bb.0: +; RV64I-NEXT: addi sp, sp, -16 +; RV64I-NEXT: sd ra, 8(sp) +; RV64I-NEXT: mv a0, sp +; RV64I-NEXT: call callee +; RV64I-NEXT: ld ra, 8(sp) +; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: ret + %1 = alloca i8, align 32 + call void @callee(i8* %1) + ret void +} + +define void @caller64() nounwind { +; RV32I-LABEL: caller64: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -128 +; RV32I-NEXT: sw ra, 124(sp) +; RV32I-NEXT: sw s0, 120(sp) +; RV32I-NEXT: addi s0, sp, 128 +; RV32I-NEXT: andi sp, sp, -64 +; RV32I-NEXT: addi a0, sp, 64 +; RV32I-NEXT: call callee +; RV32I-NEXT: addi sp, s0, -128 +; RV32I-NEXT: lw s0, 120(sp) +; RV32I-NEXT: lw ra, 124(sp) +; RV32I-NEXT: addi sp, sp, 128 +; RV32I-NEXT: ret +; +; RV64I-LABEL: caller64: +; RV64I: # %bb.0: +; RV64I-NEXT: addi sp, sp, -128 +; RV64I-NEXT: sd ra, 120(sp) +; RV64I-NEXT: sd s0, 112(sp) +; RV64I-NEXT: addi s0, sp, 128 +; RV64I-NEXT: andi sp, sp, -64 +; RV64I-NEXT: addi a0, sp, 64 +; RV64I-NEXT: call callee +; RV64I-NEXT: addi sp, s0, -128 +; RV64I-NEXT: ld s0, 112(sp) +; RV64I-NEXT: ld ra, 120(sp) +; RV64I-NEXT: addi sp, sp, 128 +; RV64I-NEXT: ret + %1 = alloca i8, align 64 + call void @callee(i8* %1) + ret void +} + +define void @caller_no_realign64() nounwind "no-realign-stack" { +; RV32I-LABEL: caller_no_realign64: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: mv a0, sp +; RV32I-NEXT: call callee +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret +; +; RV64I-LABEL: caller_no_realign64: +; RV64I: # %bb.0: +; RV64I-NEXT: addi sp, sp, -16 +; RV64I-NEXT: sd ra, 8(sp) +; RV64I-NEXT: mv a0, sp +; RV64I-NEXT: call callee +; RV64I-NEXT: ld ra, 8(sp) +; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: ret + %1 = alloca i8, align 64 + call void @callee(i8* %1) + ret void +} + +define void @caller128() nounwind { +; RV32I-LABEL: caller128: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -256 +; RV32I-NEXT: sw ra, 252(sp) +; RV32I-NEXT: sw s0, 248(sp) +; RV32I-NEXT: addi s0, sp, 256 +; RV32I-NEXT: andi sp, sp, -128 +; RV32I-NEXT: addi a0, sp, 128 +; RV32I-NEXT: call callee +; RV32I-NEXT: addi sp, s0, -256 +; RV32I-NEXT: lw s0, 248(sp) +; RV32I-NEXT: lw ra, 252(sp) +; RV32I-NEXT: addi sp, sp, 256 +; RV32I-NEXT: ret +; +; RV64I-LABEL: caller128: +; RV64I: # %bb.0: +; RV64I-NEXT: addi sp, sp, -256 +; RV64I-NEXT: sd ra, 248(sp) +; RV64I-NEXT: sd s0, 240(sp) +; RV64I-NEXT: addi s0, sp, 256 +; RV64I-NEXT: andi sp, sp, -128 +; RV64I-NEXT: addi a0, sp, 128 +; RV64I-NEXT: call callee +; RV64I-NEXT: addi sp, s0, -256 +; RV64I-NEXT: ld s0, 240(sp) +; RV64I-NEXT: ld ra, 248(sp) +; RV64I-NEXT: addi sp, sp, 256 +; RV64I-NEXT: ret + %1 = alloca i8, align 128 + call void @callee(i8* %1) + ret void +} + +define void @caller_no_realign128() nounwind "no-realign-stack" { +; RV32I-LABEL: caller_no_realign128: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: mv a0, sp +; RV32I-NEXT: call callee +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret +; +; RV64I-LABEL: caller_no_realign128: +; RV64I: # %bb.0: +; RV64I-NEXT: addi sp, sp, -16 +; RV64I-NEXT: sd ra, 8(sp) +; RV64I-NEXT: mv a0, sp +; RV64I-NEXT: call callee +; RV64I-NEXT: ld ra, 8(sp) +; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: ret + %1 = alloca i8, align 128 + call void @callee(i8* %1) + ret void +} + +define void @caller256() nounwind { +; RV32I-LABEL: caller256: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -512 +; RV32I-NEXT: sw ra, 508(sp) +; RV32I-NEXT: sw s0, 504(sp) +; RV32I-NEXT: addi s0, sp, 512 +; RV32I-NEXT: andi sp, sp, -256 +; RV32I-NEXT: addi a0, sp, 256 +; RV32I-NEXT: call callee +; RV32I-NEXT: addi sp, s0, -512 +; RV32I-NEXT: lw s0, 504(sp) +; RV32I-NEXT: lw ra, 508(sp) +; RV32I-NEXT: addi sp, sp, 512 +; RV32I-NEXT: ret +; +; RV64I-LABEL: caller256: +; RV64I: # %bb.0: +; RV64I-NEXT: addi sp, sp, -512 +; RV64I-NEXT: sd ra, 504(sp) +; RV64I-NEXT: sd s0, 496(sp) +; RV64I-NEXT: addi s0, sp, 512 +; RV64I-NEXT: andi sp, sp, -256 +; RV64I-NEXT: addi a0, sp, 256 +; RV64I-NEXT: call callee +; RV64I-NEXT: addi sp, s0, -512 +; RV64I-NEXT: ld s0, 496(sp) +; RV64I-NEXT: ld ra, 504(sp) +; RV64I-NEXT: addi sp, sp, 512 +; RV64I-NEXT: ret + %1 = alloca i8, align 256 + call void @callee(i8* %1) + ret void +} + +define void @caller_no_realign256() nounwind "no-realign-stack" { +; RV32I-LABEL: caller_no_realign256: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: mv a0, sp +; RV32I-NEXT: call callee +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret +; +; RV64I-LABEL: caller_no_realign256: +; RV64I: # %bb.0: +; RV64I-NEXT: addi sp, sp, -16 +; RV64I-NEXT: sd ra, 8(sp) +; RV64I-NEXT: mv a0, sp +; RV64I-NEXT: call callee +; RV64I-NEXT: ld ra, 8(sp) +; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: ret + %1 = alloca i8, align 256 + call void @callee(i8* %1) + ret void +} + +define void @caller512() nounwind { +; RV32I-LABEL: caller512: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -1536 +; RV32I-NEXT: sw ra, 1532(sp) +; RV32I-NEXT: sw s0, 1528(sp) +; RV32I-NEXT: addi s0, sp, 1536 +; RV32I-NEXT: andi sp, sp, -512 +; RV32I-NEXT: addi a0, sp, 1024 +; RV32I-NEXT: call callee +; RV32I-NEXT: addi sp, s0, -1536 +; RV32I-NEXT: lw s0, 1528(sp) +; RV32I-NEXT: lw ra, 1532(sp) +; RV32I-NEXT: addi sp, sp, 1536 +; RV32I-NEXT: ret +; +; RV64I-LABEL: caller512: +; RV64I: # %bb.0: +; RV64I-NEXT: addi sp, sp, -1536 +; RV64I-NEXT: sd ra, 1528(sp) +; RV64I-NEXT: sd s0, 1520(sp) +; RV64I-NEXT: addi s0, sp, 1536 +; RV64I-NEXT: andi sp, sp, -512 +; RV64I-NEXT: addi a0, sp, 1024 +; RV64I-NEXT: call callee +; RV64I-NEXT: addi sp, s0, -1536 +; RV64I-NEXT: ld s0, 1520(sp) +; RV64I-NEXT: ld ra, 1528(sp) +; RV64I-NEXT: addi sp, sp, 1536 +; RV64I-NEXT: ret + %1 = alloca i8, align 512 + call void @callee(i8* %1) + ret void +} + +define void @caller_no_realign512() nounwind "no-realign-stack" { +; RV32I-LABEL: caller_no_realign512: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: mv a0, sp +; RV32I-NEXT: call callee +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret +; +; RV64I-LABEL: caller_no_realign512: +; RV64I: # %bb.0: +; RV64I-NEXT: addi sp, sp, -16 +; RV64I-NEXT: sd ra, 8(sp) +; RV64I-NEXT: mv a0, sp +; RV64I-NEXT: call callee +; RV64I-NEXT: ld ra, 8(sp) +; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: ret + %1 = alloca i8, align 512 + call void @callee(i8* %1) + ret void +} + +define void @caller1024() nounwind { +; RV32I-LABEL: caller1024: +; RV32I: # %bb.0: +; RV32I-NEXT: lui a0, 1 +; RV32I-NEXT: addi a0, a0, -1024 +; RV32I-NEXT: sub sp, sp, a0 +; RV32I-NEXT: lui a0, 1 +; RV32I-NEXT: addi a0, a0, -1028 +; RV32I-NEXT: add a0, sp, a0 +; RV32I-NEXT: sw ra, 0(a0) +; RV32I-NEXT: lui a0, 1 +; RV32I-NEXT: addi a0, a0, -1032 +; RV32I-NEXT: add a0, sp, a0 +; RV32I-NEXT: sw s0, 0(a0) +; RV32I-NEXT: lui a0, 1 +; RV32I-NEXT: addi a0, a0, -1024 +; RV32I-NEXT: add s0, sp, a0 +; RV32I-NEXT: andi sp, sp, -1024 +; RV32I-NEXT: lui a0, 1 +; RV32I-NEXT: addi a0, a0, -2048 +; RV32I-NEXT: add a0, sp, a0 +; RV32I-NEXT: mv a0, a0 +; RV32I-NEXT: call callee +; RV32I-NEXT: lui a0, 1 +; RV32I-NEXT: addi a0, a0, -1024 +; RV32I-NEXT: sub sp, s0, a0 +; RV32I-NEXT: lui a0, 1 +; RV32I-NEXT: addi a0, a0, -1032 +; RV32I-NEXT: add a0, sp, a0 +; RV32I-NEXT: lw s0, 0(a0) +; RV32I-NEXT: lui a0, 1 +; RV32I-NEXT: addi a0, a0, -1028 +; RV32I-NEXT: add a0, sp, a0 +; RV32I-NEXT: lw ra, 0(a0) +; RV32I-NEXT: lui a0, 1 +; RV32I-NEXT: addi a0, a0, -1024 +; RV32I-NEXT: add sp, sp, a0 +; RV32I-NEXT: ret +; +; RV64I-LABEL: caller1024: +; RV64I: # %bb.0: +; RV64I-NEXT: lui a0, 1 +; RV64I-NEXT: addi a0, a0, -1024 +; RV64I-NEXT: sub sp, sp, a0 +; RV64I-NEXT: lui a0, 1 +; RV64I-NEXT: addi a0, a0, -1032 +; RV64I-NEXT: add a0, sp, a0 +; RV64I-NEXT: sd ra, 0(a0) +; RV64I-NEXT: lui a0, 1 +; RV64I-NEXT: addi a0, a0, -1040 +; RV64I-NEXT: add a0, sp, a0 +; RV64I-NEXT: sd s0, 0(a0) +; RV64I-NEXT: lui a0, 1 +; RV64I-NEXT: addi a0, a0, -1024 +; RV64I-NEXT: add s0, sp, a0 +; RV64I-NEXT: andi sp, sp, -1024 +; RV64I-NEXT: lui a0, 1 +; RV64I-NEXT: addi a0, a0, -2048 +; RV64I-NEXT: add a0, sp, a0 +; RV64I-NEXT: mv a0, a0 +; RV64I-NEXT: call callee +; RV64I-NEXT: lui a0, 1 +; RV64I-NEXT: addi a0, a0, -1024 +; RV64I-NEXT: sub sp, s0, a0 +; RV64I-NEXT: lui a0, 1 +; RV64I-NEXT: addi a0, a0, -1040 +; RV64I-NEXT: add a0, sp, a0 +; RV64I-NEXT: ld s0, 0(a0) +; RV64I-NEXT: lui a0, 1 +; RV64I-NEXT: addi a0, a0, -1032 +; RV64I-NEXT: add a0, sp, a0 +; RV64I-NEXT: ld ra, 0(a0) +; RV64I-NEXT: lui a0, 1 +; RV64I-NEXT: addi a0, a0, -1024 +; RV64I-NEXT: add sp, sp, a0 +; RV64I-NEXT: ret + %1 = alloca i8, align 1024 + call void @callee(i8* %1) + ret void +} + +define void @caller_no_realign1024() nounwind "no-realign-stack" { +; RV32I-LABEL: caller_no_realign1024: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: mv a0, sp +; RV32I-NEXT: call callee +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret +; +; RV64I-LABEL: caller_no_realign1024: +; RV64I: # %bb.0: +; RV64I-NEXT: addi sp, sp, -16 +; RV64I-NEXT: sd ra, 8(sp) +; RV64I-NEXT: mv a0, sp +; RV64I-NEXT: call callee +; RV64I-NEXT: ld ra, 8(sp) +; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: ret + %1 = alloca i8, align 1024 + call void @callee(i8* %1) + ret void +} + +define void @caller2048() nounwind { +; RV32I-LABEL: caller2048: +; RV32I: # %bb.0: +; RV32I-NEXT: lui a0, 2 +; RV32I-NEXT: addi a0, a0, -2048 +; RV32I-NEXT: sub sp, sp, a0 +; RV32I-NEXT: lui a0, 1 +; RV32I-NEXT: addi a0, a0, 2044 +; RV32I-NEXT: add a0, sp, a0 +; RV32I-NEXT: sw ra, 0(a0) +; RV32I-NEXT: lui a0, 1 +; RV32I-NEXT: addi a0, a0, 2040 +; RV32I-NEXT: add a0, sp, a0 +; RV32I-NEXT: sw s0, 0(a0) +; RV32I-NEXT: lui a0, 2 +; RV32I-NEXT: addi a0, a0, -2048 +; RV32I-NEXT: add s0, sp, a0 +; RV32I-NEXT: andi sp, sp, -2048 +; RV32I-NEXT: lui a0, 1 +; RV32I-NEXT: mv a0, a0 +; RV32I-NEXT: add a0, sp, a0 +; RV32I-NEXT: mv a0, a0 +; RV32I-NEXT: call callee +; RV32I-NEXT: lui a0, 2 +; RV32I-NEXT: addi a0, a0, -2048 +; RV32I-NEXT: sub sp, s0, a0 +; RV32I-NEXT: lui a0, 1 +; RV32I-NEXT: addi a0, a0, 2040 +; RV32I-NEXT: add a0, sp, a0 +; RV32I-NEXT: lw s0, 0(a0) +; RV32I-NEXT: lui a0, 1 +; RV32I-NEXT: addi a0, a0, 2044 +; RV32I-NEXT: add a0, sp, a0 +; RV32I-NEXT: lw ra, 0(a0) +; RV32I-NEXT: lui a0, 2 +; RV32I-NEXT: addi a0, a0, -2048 +; RV32I-NEXT: add sp, sp, a0 +; RV32I-NEXT: ret +; +; RV64I-LABEL: caller2048: +; RV64I: # %bb.0: +; RV64I-NEXT: lui a0, 2 +; RV64I-NEXT: addi a0, a0, -2048 +; RV64I-NEXT: sub sp, sp, a0 +; RV64I-NEXT: lui a0, 1 +; RV64I-NEXT: addi a0, a0, 2040 +; RV64I-NEXT: add a0, sp, a0 +; RV64I-NEXT: sd ra, 0(a0) +; RV64I-NEXT: lui a0, 1 +; RV64I-NEXT: addi a0, a0, 2032 +; RV64I-NEXT: add a0, sp, a0 +; RV64I-NEXT: sd s0, 0(a0) +; RV64I-NEXT: lui a0, 2 +; RV64I-NEXT: addi a0, a0, -2048 +; RV64I-NEXT: add s0, sp, a0 +; RV64I-NEXT: andi sp, sp, -2048 +; RV64I-NEXT: lui a0, 1 +; RV64I-NEXT: mv a0, a0 +; RV64I-NEXT: add a0, sp, a0 +; RV64I-NEXT: mv a0, a0 +; RV64I-NEXT: call callee +; RV64I-NEXT: lui a0, 2 +; RV64I-NEXT: addi a0, a0, -2048 +; RV64I-NEXT: sub sp, s0, a0 +; RV64I-NEXT: lui a0, 1 +; RV64I-NEXT: addi a0, a0, 2032 +; RV64I-NEXT: add a0, sp, a0 +; RV64I-NEXT: ld s0, 0(a0) +; RV64I-NEXT: lui a0, 1 +; RV64I-NEXT: addi a0, a0, 2040 +; RV64I-NEXT: add a0, sp, a0 +; RV64I-NEXT: ld ra, 0(a0) +; RV64I-NEXT: lui a0, 2 +; RV64I-NEXT: addi a0, a0, -2048 +; RV64I-NEXT: add sp, sp, a0 +; RV64I-NEXT: ret + %1 = alloca i8, align 2048 + call void @callee(i8* %1) + ret void +} + +define void @caller_no_realign2048() nounwind "no-realign-stack" { +; RV32I-LABEL: caller_no_realign2048: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: mv a0, sp +; RV32I-NEXT: call callee +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret +; +; RV64I-LABEL: caller_no_realign2048: +; RV64I: # %bb.0: +; RV64I-NEXT: addi sp, sp, -16 +; RV64I-NEXT: sd ra, 8(sp) +; RV64I-NEXT: mv a0, sp +; RV64I-NEXT: call callee +; RV64I-NEXT: ld ra, 8(sp) +; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: ret + %1 = alloca i8, align 2048 + call void @callee(i8* %1) + ret void +} + +define void @caller4096() nounwind { +; RV32I-LABEL: caller4096: +; RV32I: # %bb.0: +; RV32I-NEXT: lui a0, 3 +; RV32I-NEXT: mv a0, a0 +; RV32I-NEXT: sub sp, sp, a0 +; RV32I-NEXT: lui a0, 3 +; RV32I-NEXT: addi a0, a0, -4 +; RV32I-NEXT: add a0, sp, a0 +; RV32I-NEXT: sw ra, 0(a0) +; RV32I-NEXT: lui a0, 3 +; RV32I-NEXT: addi a0, a0, -8 +; RV32I-NEXT: add a0, sp, a0 +; RV32I-NEXT: sw s0, 0(a0) +; RV32I-NEXT: lui a0, 3 +; RV32I-NEXT: mv a0, a0 +; RV32I-NEXT: add s0, sp, a0 +; RV32I-NEXT: srli a0, sp, 12 +; RV32I-NEXT: slli sp, a0, 12 +; RV32I-NEXT: lui a0, 2 +; RV32I-NEXT: mv a0, a0 +; RV32I-NEXT: add a0, sp, a0 +; RV32I-NEXT: mv a0, a0 +; RV32I-NEXT: call callee +; RV32I-NEXT: lui a0, 3 +; RV32I-NEXT: mv a0, a0 +; RV32I-NEXT: sub sp, s0, a0 +; RV32I-NEXT: lui a0, 3 +; RV32I-NEXT: addi a0, a0, -8 +; RV32I-NEXT: add a0, sp, a0 +; RV32I-NEXT: lw s0, 0(a0) +; RV32I-NEXT: lui a0, 3 +; RV32I-NEXT: addi a0, a0, -4 +; RV32I-NEXT: add a0, sp, a0 +; RV32I-NEXT: lw ra, 0(a0) +; RV32I-NEXT: lui a0, 3 +; RV32I-NEXT: mv a0, a0 +; RV32I-NEXT: add sp, sp, a0 +; RV32I-NEXT: ret +; +; RV64I-LABEL: caller4096: +; RV64I: # %bb.0: +; RV64I-NEXT: lui a0, 3 +; RV64I-NEXT: mv a0, a0 +; RV64I-NEXT: sub sp, sp, a0 +; RV64I-NEXT: lui a0, 3 +; RV64I-NEXT: addi a0, a0, -8 +; RV64I-NEXT: add a0, sp, a0 +; RV64I-NEXT: sd ra, 0(a0) +; RV64I-NEXT: lui a0, 3 +; RV64I-NEXT: addi a0, a0, -16 +; RV64I-NEXT: add a0, sp, a0 +; RV64I-NEXT: sd s0, 0(a0) +; RV64I-NEXT: lui a0, 3 +; RV64I-NEXT: mv a0, a0 +; RV64I-NEXT: add s0, sp, a0 +; RV64I-NEXT: srli a0, sp, 12 +; RV64I-NEXT: slli sp, a0, 12 +; RV64I-NEXT: lui a0, 2 +; RV64I-NEXT: mv a0, a0 +; RV64I-NEXT: add a0, sp, a0 +; RV64I-NEXT: mv a0, a0 +; RV64I-NEXT: call callee +; RV64I-NEXT: lui a0, 3 +; RV64I-NEXT: mv a0, a0 +; RV64I-NEXT: sub sp, s0, a0 +; RV64I-NEXT: lui a0, 3 +; RV64I-NEXT: addi a0, a0, -16 +; RV64I-NEXT: add a0, sp, a0 +; RV64I-NEXT: ld s0, 0(a0) +; RV64I-NEXT: lui a0, 3 +; RV64I-NEXT: addi a0, a0, -8 +; RV64I-NEXT: add a0, sp, a0 +; RV64I-NEXT: ld ra, 0(a0) +; RV64I-NEXT: lui a0, 3 +; RV64I-NEXT: mv a0, a0 +; RV64I-NEXT: add sp, sp, a0 +; RV64I-NEXT: ret + %1 = alloca i8, align 4096 + call void @callee(i8* %1) + ret void +} + +define void @caller_no_realign4096() nounwind "no-realign-stack" { +; RV32I-LABEL: caller_no_realign4096: +; RV32I: # %bb.0: +; RV32I-NEXT: addi sp, sp, -16 +; RV32I-NEXT: sw ra, 12(sp) +; RV32I-NEXT: mv a0, sp +; RV32I-NEXT: call callee +; RV32I-NEXT: lw ra, 12(sp) +; RV32I-NEXT: addi sp, sp, 16 +; RV32I-NEXT: ret +; +; RV64I-LABEL: caller_no_realign4096: +; RV64I: # %bb.0: +; RV64I-NEXT: addi sp, sp, -16 +; RV64I-NEXT: sd ra, 8(sp) +; RV64I-NEXT: mv a0, sp +; RV64I-NEXT: call callee +; RV64I-NEXT: ld ra, 8(sp) +; RV64I-NEXT: addi sp, sp, 16 +; RV64I-NEXT: ret + %1 = alloca i8, align 4096 + call void @callee(i8* %1) + ret void +} From 2a3980935ded793415704f905fb625a005b8b970 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Wed, 14 Aug 2019 13:14:17 +0000 Subject: [PATCH 112/289] Merging r367084: ------------------------------------------------------------------------ r367084 | kongyi | 2019-07-26 07:17:14 +0200 (Fri, 26 Jul 2019) | 6 lines Fix macOS build after r358716 COPYFILE_CLONE is only defined on newer macOS versions, using it without check breaks build on systems running legacy OS and toolchain. Differential Revision: https://reviews.llvm.org/D65317 ------------------------------------------------------------------------ llvm-svn: 368848 --- llvm/lib/Support/Unix/Path.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/lib/Support/Unix/Path.inc b/llvm/lib/Support/Unix/Path.inc index e80880c6b3cb..27c8a1bc9b74 100644 --- a/llvm/lib/Support/Unix/Path.inc +++ b/llvm/lib/Support/Unix/Path.inc @@ -1200,7 +1200,7 @@ namespace fs { /// implementation. std::error_code copy_file(const Twine &From, const Twine &To) { uint32_t Flag = COPYFILE_DATA; -#if __has_builtin(__builtin_available) +#if __has_builtin(__builtin_available) && defined(COPYFILE_CLONE) if (__builtin_available(macos 10.12, *)) { bool IsSymlink; if (std::error_code Error = is_symlink_file(From, IsSymlink)) From 201b879fd7fe3ab7652ee614b80e44ed946af235 Mon Sep 17 00:00:00 2001 From: Chris Bieneman Date: Wed, 14 Aug 2019 18:11:11 +0000 Subject: [PATCH 113/289] Merging release note update in r368874 llvm-svn: 368894 --- clang/docs/ReleaseNotes.rst | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 425fbfcb445b..8e06798b7139 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -192,7 +192,15 @@ release of Clang. Users of the build system should adjust accordingly. install-clang-headers target now installs clang's API headers (corresponding to its libraries), which is consistent with the install-llvm-headers target. -- ... +- In 9.0.0 and later Clang added a new target, clang-cpp, which generates a + shared library comprised of all the clang component libraries and exporting + the clang C++ APIs. Additionally the build system gained the new + "CLANG_LINK_CLANG_DYLIB" option, which defaults Off, and when set to On, will + force clang (and clang-based tools) to link the clang-cpp library instead of + statically linking clang's components. This option will reduce the size of + binary distributions at the expense of compiler performance. + +- ... AST Matchers ------------ From 450f5f3986cedc8519fdf6b312e022755be425b4 Mon Sep 17 00:00:00 2001 From: Chris Bieneman Date: Thu, 15 Aug 2019 16:54:13 +0000 Subject: [PATCH 114/289] Correcting clang-cpp release not to spcify supported targets. llvm-svn: 369017 --- clang/docs/ReleaseNotes.rst | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 8e06798b7139..018bc2a3716a 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -192,13 +192,13 @@ release of Clang. Users of the build system should adjust accordingly. install-clang-headers target now installs clang's API headers (corresponding to its libraries), which is consistent with the install-llvm-headers target. -- In 9.0.0 and later Clang added a new target, clang-cpp, which generates a - shared library comprised of all the clang component libraries and exporting - the clang C++ APIs. Additionally the build system gained the new - "CLANG_LINK_CLANG_DYLIB" option, which defaults Off, and when set to On, will - force clang (and clang-based tools) to link the clang-cpp library instead of - statically linking clang's components. This option will reduce the size of - binary distributions at the expense of compiler performance. +- In 9.0.0 and later Clang added a new target on Linux/Unix systems, clang-cpp, + which generates a shared library comprised of all the clang component + libraries and exporting the clang C++ APIs. Additionally the build system + gained the new "CLANG_LINK_CLANG_DYLIB" option, which defaults Off, and when + set to On, will force clang (and clang-based tools) to link the clang-cpp + library instead of statically linking clang's components. This option will + reduce the size of binary distributions at the expense of compiler performance. - ... From 8cb652b05c2e084c9813e6833efe9825b6e49eb7 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Fri, 16 Aug 2019 07:18:49 +0000 Subject: [PATCH 115/289] Merging r368873: ------------------------------------------------------------------------ r368873 | void | 2019-08-14 18:44:07 +0200 (Wed, 14 Aug 2019) | 15 lines Ignore indirect branches from callbr. Summary: We can't speculate around indirect branches: indirectbr and invoke. The callbr instruction needs to be included here. Reviewers: nickdesaulniers, manojgupta, chandlerc Reviewed By: chandlerc Subscribers: llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D66200 ------------------------------------------------------------------------ llvm-svn: 369085 --- .../Transforms/Scalar/SpeculateAroundPHIs.cpp | 6 ++- .../Transforms/SpeculateAroundPHIs/pr42991.ll | 44 +++++++++++++++++++ 2 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 llvm/test/Transforms/SpeculateAroundPHIs/pr42991.ll diff --git a/llvm/lib/Transforms/Scalar/SpeculateAroundPHIs.cpp b/llvm/lib/Transforms/Scalar/SpeculateAroundPHIs.cpp index c13fb3e04516..e6db11f47ead 100644 --- a/llvm/lib/Transforms/Scalar/SpeculateAroundPHIs.cpp +++ b/llvm/lib/Transforms/Scalar/SpeculateAroundPHIs.cpp @@ -777,8 +777,10 @@ static bool tryToSpeculatePHIs(SmallVectorImpl &PNs, // speculation if the predecessor is an invoke. This doesn't seem // fundamental and we should probably be splitting critical edges // differently. - if (isa(PredBB->getTerminator()) || - isa(PredBB->getTerminator())) { + const auto *TermInst = PredBB->getTerminator(); + if (isa(TermInst) || + isa(TermInst) || + isa(TermInst)) { LLVM_DEBUG(dbgs() << " Invalid: predecessor terminator: " << PredBB->getName() << "\n"); return false; diff --git a/llvm/test/Transforms/SpeculateAroundPHIs/pr42991.ll b/llvm/test/Transforms/SpeculateAroundPHIs/pr42991.ll new file mode 100644 index 000000000000..4aef689f53de --- /dev/null +++ b/llvm/test/Transforms/SpeculateAroundPHIs/pr42991.ll @@ -0,0 +1,44 @@ +; RUN: opt -S -passes=spec-phis %s + +; This testcase crashes during the speculate around PHIs pass. The pass however +; results in no changes. + +define i32 @test1() { +entry: + callbr void asm sideeffect "", "X,X,~{dirflag},~{fpsr},~{flags}"(i8* blockaddress(@test1, %return), i8* blockaddress(@test1, %f)) + to label %asm.fallthrough [label %return, label %f] + +asm.fallthrough: + br label %return + +f: + br label %return + +return: + %retval.0 = phi i32 [ 0, %f ], [ 1, %asm.fallthrough ], [ 1, %entry ] + ret i32 %retval.0 +} + +define void @test2() { +entry: + br label %tailrecurse + +tailrecurse: + %call = tail call i32 @test3() + %tobool1 = icmp eq i32 %call, 0 + callbr void asm sideeffect "", "X,X,~{dirflag},~{fpsr},~{flags}"(i8* blockaddress(@test2, %test1.exit), i8* blockaddress(@test2, %f.i)) + to label %if.end6 [label %test1.exit, label %f.i] + +f.i: + br label %test1.exit + +test1.exit: + %retval.0.i = phi i1 [ false, %f.i ], [ true, %tailrecurse ] + %brmerge = or i1 %tobool1, %retval.0.i + br i1 %brmerge, label %if.end6, label %tailrecurse + +if.end6: + ret void +} + +declare i32 @test3() From b77d4716f4b211d15f874c779598ee26460eb091 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Fri, 16 Aug 2019 07:44:53 +0000 Subject: [PATCH 116/289] Merging r367019: ------------------------------------------------------------------------ r367019 | chill | 2019-07-25 15:56:04 +0200 (Thu, 25 Jul 2019) | 10 lines [AArch64][SVE] Allow explicit size specifier for predicate operand ... for the vector forms of `{SQ,UQ,}{INC,DEC}P` instructions. Also continue supporting the exsting behaviour of not requiring an explicit size specifier. The preferred disasembly is *with* the specifier. This is implemented by redefining intruction forms to require vector predicates with explicit size and adding aliases, which allow a predicate with no size. Differential Revision: https://reviews.llvm.org/D65145 ------------------------------------------------------------------------ llvm-svn: 369086 --- llvm/lib/Target/AArch64/SVEInstrFormats.td | 23 +++++++++++------- llvm/test/MC/AArch64/SVE/decp.s | 26 ++++++++++++++++---- llvm/test/MC/AArch64/SVE/incp.s | 28 ++++++++++++++++++---- llvm/test/MC/AArch64/SVE/sqdecp.s | 28 ++++++++++++++++++---- llvm/test/MC/AArch64/SVE/sqincp.s | 28 ++++++++++++++++++---- llvm/test/MC/AArch64/SVE/uqdecp.s | 28 ++++++++++++++++++---- llvm/test/MC/AArch64/SVE/uqincp.s | 28 ++++++++++++++++++---- 7 files changed, 152 insertions(+), 37 deletions(-) diff --git a/llvm/lib/Target/AArch64/SVEInstrFormats.td b/llvm/lib/Target/AArch64/SVEInstrFormats.td index 3f698f5762b6..dfd6c576e99b 100644 --- a/llvm/lib/Target/AArch64/SVEInstrFormats.td +++ b/llvm/lib/Target/AArch64/SVEInstrFormats.td @@ -403,12 +403,12 @@ multiclass sve_int_count_r_x64 opc, string asm> { } class sve_int_count_v sz8_64, bits<5> opc, string asm, - ZPRRegOp zprty> -: I<(outs zprty:$Zdn), (ins zprty:$_Zdn, PPRAny:$Pg), - asm, "\t$Zdn, $Pg", + ZPRRegOp zprty, PPRRegOp pprty> +: I<(outs zprty:$Zdn), (ins zprty:$_Zdn, pprty:$Pm), + asm, "\t$Zdn, $Pm", "", []>, Sched<[]> { - bits<4> Pg; + bits<4> Pm; bits<5> Zdn; let Inst{31-24} = 0b00100101; let Inst{23-22} = sz8_64; @@ -416,7 +416,7 @@ class sve_int_count_v sz8_64, bits<5> opc, string asm, let Inst{18-16} = opc{4-2}; let Inst{15-11} = 0b10000; let Inst{10-9} = opc{1-0}; - let Inst{8-5} = Pg; + let Inst{8-5} = Pm; let Inst{4-0} = Zdn; let Constraints = "$Zdn = $_Zdn"; @@ -425,9 +425,16 @@ class sve_int_count_v sz8_64, bits<5> opc, string asm, } multiclass sve_int_count_v opc, string asm> { - def _H : sve_int_count_v<0b01, opc, asm, ZPR16>; - def _S : sve_int_count_v<0b10, opc, asm, ZPR32>; - def _D : sve_int_count_v<0b11, opc, asm, ZPR64>; + def _H : sve_int_count_v<0b01, opc, asm, ZPR16, PPR16>; + def _S : sve_int_count_v<0b10, opc, asm, ZPR32, PPR32>; + def _D : sve_int_count_v<0b11, opc, asm, ZPR64, PPR64>; + + def : InstAlias(NAME # "_H") ZPR16:$Zdn, PPRAny:$Pm), 0>; + def : InstAlias(NAME # "_S") ZPR32:$Zdn, PPRAny:$Pm), 0>; + def : InstAlias(NAME # "_D") ZPR64:$Zdn, PPRAny:$Pm), 0>; } class sve_int_pcount_pred sz8_64, bits<4> opc, string asm, diff --git a/llvm/test/MC/AArch64/SVE/decp.s b/llvm/test/MC/AArch64/SVE/decp.s index 8bbe726a422d..6cf73033e69e 100644 --- a/llvm/test/MC/AArch64/SVE/decp.s +++ b/llvm/test/MC/AArch64/SVE/decp.s @@ -56,19 +56,37 @@ decp xzr, p15.d // CHECK-UNKNOWN: ff 89 ed 25 decp z31.h, p15 -// CHECK-INST: decp z31.h, p15 +// CHECK-INST: decp z31.h, p15.h +// CHECK-ENCODING: [0xff,0x81,0x6d,0x25] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: ff 81 6d 25 + +decp z31.h, p15.h +// CHECK-INST: decp z31.h, p15.h // CHECK-ENCODING: [0xff,0x81,0x6d,0x25] // CHECK-ERROR: instruction requires: sve // CHECK-UNKNOWN: ff 81 6d 25 decp z31.s, p15 -// CHECK-INST: decp z31.s, p15 +// CHECK-INST: decp z31.s, p15.s +// CHECK-ENCODING: [0xff,0x81,0xad,0x25] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: ff 81 ad 25 + +decp z31.s, p15.s +// CHECK-INST: decp z31.s, p15.s // CHECK-ENCODING: [0xff,0x81,0xad,0x25] // CHECK-ERROR: instruction requires: sve // CHECK-UNKNOWN: ff 81 ad 25 decp z31.d, p15 -// CHECK-INST: decp z31.d, p15 +// CHECK-INST: decp z31.d, p15.d +// CHECK-ENCODING: [0xff,0x81,0xed,0x25] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: ff 81 ed 25 + +decp z31.d, p15.d +// CHECK-INST: decp z31.d, p15.d // CHECK-ENCODING: [0xff,0x81,0xed,0x25] // CHECK-ERROR: instruction requires: sve // CHECK-UNKNOWN: ff 81 ed 25 @@ -83,7 +101,7 @@ movprfx z31, z6 // CHECK-ERROR: instruction requires: sve // CHECK-UNKNOWN: df bc 20 04 -decp z31.d, p15 +decp z31.d, p15.d // CHECK-INST: decp z31.d, p15 // CHECK-ENCODING: [0xff,0x81,0xed,0x25] // CHECK-ERROR: instruction requires: sve diff --git a/llvm/test/MC/AArch64/SVE/incp.s b/llvm/test/MC/AArch64/SVE/incp.s index 6bc2c5160925..b180fcc698d2 100644 --- a/llvm/test/MC/AArch64/SVE/incp.s +++ b/llvm/test/MC/AArch64/SVE/incp.s @@ -56,19 +56,37 @@ incp xzr, p15.d // CHECK-UNKNOWN: ff 89 ec 25 incp z31.h, p15 -// CHECK-INST: incp z31.h, p15 +// CHECK-INST: incp z31.h, p15.h +// CHECK-ENCODING: [0xff,0x81,0x6c,0x25] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: ff 81 6c 25 + +incp z31.h, p15.h +// CHECK-INST: incp z31.h, p15.h // CHECK-ENCODING: [0xff,0x81,0x6c,0x25] // CHECK-ERROR: instruction requires: sve // CHECK-UNKNOWN: ff 81 6c 25 incp z31.s, p15 -// CHECK-INST: incp z31.s, p15 +// CHECK-INST: incp z31.s, p15.s +// CHECK-ENCODING: [0xff,0x81,0xac,0x25] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: ff 81 ac 25 + +incp z31.s, p15.s +// CHECK-INST: incp z31.s, p15.s // CHECK-ENCODING: [0xff,0x81,0xac,0x25] // CHECK-ERROR: instruction requires: sve // CHECK-UNKNOWN: ff 81 ac 25 incp z31.d, p15 -// CHECK-INST: incp z31.d, p15 +// CHECK-INST: incp z31.d, p15.d +// CHECK-ENCODING: [0xff,0x81,0xec,0x25] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: ff 81 ec 25 + +incp z31.d, p15.d +// CHECK-INST: incp z31.d, p15.d // CHECK-ENCODING: [0xff,0x81,0xec,0x25] // CHECK-ERROR: instruction requires: sve // CHECK-UNKNOWN: ff 81 ec 25 @@ -83,8 +101,8 @@ movprfx z31, z6 // CHECK-ERROR: instruction requires: sve // CHECK-UNKNOWN: df bc 20 04 -incp z31.d, p15 -// CHECK-INST: incp z31.d, p15 +incp z31.d, p15.d +// CHECK-INST: incp z31.d, p15.d // CHECK-ENCODING: [0xff,0x81,0xec,0x25] // CHECK-ERROR: instruction requires: sve // CHECK-UNKNOWN: ff 81 ec 25 diff --git a/llvm/test/MC/AArch64/SVE/sqdecp.s b/llvm/test/MC/AArch64/SVE/sqdecp.s index 2a56b182f6bb..7da00beb7b24 100644 --- a/llvm/test/MC/AArch64/SVE/sqdecp.s +++ b/llvm/test/MC/AArch64/SVE/sqdecp.s @@ -56,19 +56,37 @@ sqdecp xzr, p15.d, wzr // CHECK-UNKNOWN: ff 89 ea 25 sqdecp z0.h, p0 -// CHECK-INST: sqdecp z0.h, p0 +// CHECK-INST: sqdecp z0.h, p0.h +// CHECK-ENCODING: [0x00,0x80,0x6a,0x25] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 00 80 6a 25 + +sqdecp z0.h, p0.h +// CHECK-INST: sqdecp z0.h, p0.h // CHECK-ENCODING: [0x00,0x80,0x6a,0x25] // CHECK-ERROR: instruction requires: sve // CHECK-UNKNOWN: 00 80 6a 25 sqdecp z0.s, p0 -// CHECK-INST: sqdecp z0.s, p0 +// CHECK-INST: sqdecp z0.s, p0.s +// CHECK-ENCODING: [0x00,0x80,0xaa,0x25] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 00 80 aa 25 + +sqdecp z0.s, p0.s +// CHECK-INST: sqdecp z0.s, p0.s // CHECK-ENCODING: [0x00,0x80,0xaa,0x25] // CHECK-ERROR: instruction requires: sve // CHECK-UNKNOWN: 00 80 aa 25 sqdecp z0.d, p0 -// CHECK-INST: sqdecp z0.d, p0 +// CHECK-INST: sqdecp z0.d, p0.d +// CHECK-ENCODING: [0x00,0x80,0xea,0x25] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 00 80 ea 25 + +sqdecp z0.d, p0.d +// CHECK-INST: sqdecp z0.d, p0.d // CHECK-ENCODING: [0x00,0x80,0xea,0x25] // CHECK-ERROR: instruction requires: sve // CHECK-UNKNOWN: 00 80 ea 25 @@ -83,8 +101,8 @@ movprfx z0, z7 // CHECK-ERROR: instruction requires: sve // CHECK-UNKNOWN: e0 bc 20 04 -sqdecp z0.d, p0 -// CHECK-INST: sqdecp z0.d, p0 +sqdecp z0.d, p0.d +// CHECK-INST: sqdecp z0.d, p0.d // CHECK-ENCODING: [0x00,0x80,0xea,0x25] // CHECK-ERROR: instruction requires: sve // CHECK-UNKNOWN: 00 80 ea 25 diff --git a/llvm/test/MC/AArch64/SVE/sqincp.s b/llvm/test/MC/AArch64/SVE/sqincp.s index f7d427b0ca6e..e523796a39f1 100644 --- a/llvm/test/MC/AArch64/SVE/sqincp.s +++ b/llvm/test/MC/AArch64/SVE/sqincp.s @@ -56,19 +56,37 @@ sqincp xzr, p15.d, wzr // CHECK-UNKNOWN: ff 89 e8 25 sqincp z0.h, p0 -// CHECK-INST: sqincp z0.h, p0 +// CHECK-INST: sqincp z0.h, p0.h +// CHECK-ENCODING: [0x00,0x80,0x68,0x25] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 00 80 68 25 + +sqincp z0.h, p0.h +// CHECK-INST: sqincp z0.h, p0.h // CHECK-ENCODING: [0x00,0x80,0x68,0x25] // CHECK-ERROR: instruction requires: sve // CHECK-UNKNOWN: 00 80 68 25 sqincp z0.s, p0 -// CHECK-INST: sqincp z0.s, p0 +// CHECK-INST: sqincp z0.s, p0.s +// CHECK-ENCODING: [0x00,0x80,0xa8,0x25] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 00 80 a8 25 + +sqincp z0.s, p0.s +// CHECK-INST: sqincp z0.s, p0.s // CHECK-ENCODING: [0x00,0x80,0xa8,0x25] // CHECK-ERROR: instruction requires: sve // CHECK-UNKNOWN: 00 80 a8 25 sqincp z0.d, p0 -// CHECK-INST: sqincp z0.d, p0 +// CHECK-INST: sqincp z0.d, p0.d +// CHECK-ENCODING: [0x00,0x80,0xe8,0x25] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 00 80 e8 25 + +sqincp z0.d, p0.d +// CHECK-INST: sqincp z0.d, p0.d // CHECK-ENCODING: [0x00,0x80,0xe8,0x25] // CHECK-ERROR: instruction requires: sve // CHECK-UNKNOWN: 00 80 e8 25 @@ -83,8 +101,8 @@ movprfx z0, z7 // CHECK-ERROR: instruction requires: sve // CHECK-UNKNOWN: e0 bc 20 04 -sqincp z0.d, p0 -// CHECK-INST: sqincp z0.d, p0 +sqincp z0.d, p0.d +// CHECK-INST: sqincp z0.d, p0.d // CHECK-ENCODING: [0x00,0x80,0xe8,0x25] // CHECK-ERROR: instruction requires: sve // CHECK-UNKNOWN: 00 80 e8 25 diff --git a/llvm/test/MC/AArch64/SVE/uqdecp.s b/llvm/test/MC/AArch64/SVE/uqdecp.s index 3c07a7da2462..6e4717ba9323 100644 --- a/llvm/test/MC/AArch64/SVE/uqdecp.s +++ b/llvm/test/MC/AArch64/SVE/uqdecp.s @@ -56,19 +56,37 @@ uqdecp wzr, p15.d // CHECK-UNKNOWN: ff 89 eb 25 uqdecp z0.h, p0 -// CHECK-INST: uqdecp z0.h, p0 +// CHECK-INST: uqdecp z0.h, p0.h +// CHECK-ENCODING: [0x00,0x80,0x6b,0x25] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 00 80 6b 25 + +uqdecp z0.h, p0.h +// CHECK-INST: uqdecp z0.h, p0.h // CHECK-ENCODING: [0x00,0x80,0x6b,0x25] // CHECK-ERROR: instruction requires: sve // CHECK-UNKNOWN: 00 80 6b 25 uqdecp z0.s, p0 -// CHECK-INST: uqdecp z0.s, p0 +// CHECK-INST: uqdecp z0.s, p0.s +// CHECK-ENCODING: [0x00,0x80,0xab,0x25] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 00 80 ab 25 + +uqdecp z0.s, p0.s +// CHECK-INST: uqdecp z0.s, p0.s // CHECK-ENCODING: [0x00,0x80,0xab,0x25] // CHECK-ERROR: instruction requires: sve // CHECK-UNKNOWN: 00 80 ab 25 uqdecp z0.d, p0 -// CHECK-INST: uqdecp z0.d, p0 +// CHECK-INST: uqdecp z0.d, p0.d +// CHECK-ENCODING: [0x00,0x80,0xeb,0x25] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 00 80 eb 25 + +uqdecp z0.d, p0.d +// CHECK-INST: uqdecp z0.d, p0.d // CHECK-ENCODING: [0x00,0x80,0xeb,0x25] // CHECK-ERROR: instruction requires: sve // CHECK-UNKNOWN: 00 80 eb 25 @@ -83,8 +101,8 @@ movprfx z0, z7 // CHECK-ERROR: instruction requires: sve // CHECK-UNKNOWN: e0 bc 20 04 -uqdecp z0.d, p0 -// CHECK-INST: uqdecp z0.d, p0 +uqdecp z0.d, p0.d +// CHECK-INST: uqdecp z0.d, p0.d // CHECK-ENCODING: [0x00,0x80,0xeb,0x25] // CHECK-ERROR: instruction requires: sve // CHECK-UNKNOWN: 00 80 eb 25 diff --git a/llvm/test/MC/AArch64/SVE/uqincp.s b/llvm/test/MC/AArch64/SVE/uqincp.s index a4fb8199d994..05cfdea05a30 100644 --- a/llvm/test/MC/AArch64/SVE/uqincp.s +++ b/llvm/test/MC/AArch64/SVE/uqincp.s @@ -56,19 +56,37 @@ uqincp wzr, p15.d // CHECK-UNKNOWN: ff 89 e9 25 uqincp z0.h, p0 -// CHECK-INST: uqincp z0.h, p0 +// CHECK-INST: uqincp z0.h, p0.h +// CHECK-ENCODING: [0x00,0x80,0x69,0x25] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 00 80 69 25 + +uqincp z0.h, p0.h +// CHECK-INST: uqincp z0.h, p0.h // CHECK-ENCODING: [0x00,0x80,0x69,0x25] // CHECK-ERROR: instruction requires: sve // CHECK-UNKNOWN: 00 80 69 25 uqincp z0.s, p0 -// CHECK-INST: uqincp z0.s, p0 +// CHECK-INST: uqincp z0.s, p0.s +// CHECK-ENCODING: [0x00,0x80,0xa9,0x25] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 00 80 a9 25 + +uqincp z0.s, p0.s +// CHECK-INST: uqincp z0.s, p0.s // CHECK-ENCODING: [0x00,0x80,0xa9,0x25] // CHECK-ERROR: instruction requires: sve // CHECK-UNKNOWN: 00 80 a9 25 uqincp z0.d, p0 -// CHECK-INST: uqincp z0.d, p0 +// CHECK-INST: uqincp z0.d, p0.d +// CHECK-ENCODING: [0x00,0x80,0xe9,0x25] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 00 80 e9 25 + +uqincp z0.d, p0.d +// CHECK-INST: uqincp z0.d, p0.d // CHECK-ENCODING: [0x00,0x80,0xe9,0x25] // CHECK-ERROR: instruction requires: sve // CHECK-UNKNOWN: 00 80 e9 25 @@ -83,8 +101,8 @@ movprfx z0, z7 // CHECK-ERROR: instruction requires: sve // CHECK-UNKNOWN: e0 bc 20 04 -uqincp z0.d, p0 -// CHECK-INST: uqincp z0.d, p0 +uqincp z0.d, p0.d +// CHECK-INST: uqincp z0.d, p0.d // CHECK-ENCODING: [0x00,0x80,0xe9,0x25] // CHECK-ERROR: instruction requires: sve // CHECK-UNKNOWN: 00 80 e9 25 From 150ad3120e346ed8dff2bdda458a72e734b1879a Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Fri, 16 Aug 2019 08:11:28 +0000 Subject: [PATCH 117/289] Merging r368940: ------------------------------------------------------------------------ r368940 | rsmith | 2019-08-15 00:57:50 +0200 (Thu, 15 Aug 2019) | 19 lines Fix handling of class member access into a vector type. When handling a member access into a non-class, non-ObjC-object type, we would perform a lookup into the surrounding scope as if for an unqualified lookup. If the member access was followed by a '<' and this lookup (or the typo-correction for it) found a template name, we'd treat the member access as naming that template. Now we treat such accesses as never naming a template if the type of the object expression is of vector type, so that vector component accesses are never misinterpreted as naming something else. This is not entirely correct, since it is in fact valid to name a template from the enclosing scope in this context, when invoking a pseudo-destructor for the vector type via an alias template, but that's very much a corner case, and this change leaves that case only as broken as the corresponding case for Objective-C types is. This incidentally adds support for dr2292, which permits a 'template' keyword at the start of a member access naming a pseudo-destructor. ------------------------------------------------------------------------ llvm-svn: 369087 --- clang/lib/Sema/SemaExprCXX.cpp | 6 +----- clang/lib/Sema/SemaTemplate.cpp | 20 ++++++++++++++++--- clang/test/CXX/drs/dr22xx.cpp | 9 +++++++++ clang/test/CXX/drs/dr4xx.cpp | 4 ++-- .../SemaCXX/cxx2a-adl-only-template-id.cpp | 8 ++++++++ clang/test/SemaCXX/pseudo-destructors.cpp | 4 ++-- clang/test/SemaCXX/vector.cpp | 16 +++++++++++++++ 7 files changed, 55 insertions(+), 12 deletions(-) diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 705e3b9bd7fb..c1c08969c7bd 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -6794,14 +6794,10 @@ ExprResult Sema::ActOnStartCXXMemberReference(Scope *S, Expr *Base, // it's legal for the type to be incomplete if this is a pseudo-destructor // call. We'll do more incomplete-type checks later in the lookup process, // so just skip this check for ObjC types. - if (BaseType->isObjCObjectOrInterfaceType()) { + if (!BaseType->isRecordType()) { ObjectType = ParsedType::make(BaseType); MayBePseudoDestructor = true; return Base; - } else if (!BaseType->isRecordType()) { - ObjectType = nullptr; - MayBePseudoDestructor = true; - return Base; } // The object type must be complete (or dependent), or diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 3212281cc34d..ec4b63a2e508 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -362,13 +362,27 @@ bool Sema::LookupTemplateName(LookupResult &Found, // x->B::f, and we are looking into the type of the object. assert(!SS.isSet() && "ObjectType and scope specifier cannot coexist"); LookupCtx = computeDeclContext(ObjectType); - IsDependent = !LookupCtx; + IsDependent = !LookupCtx && ObjectType->isDependentType(); assert((IsDependent || !ObjectType->isIncompleteType() || ObjectType->castAs()->isBeingDefined()) && "Caller should have completed object type"); - // Template names cannot appear inside an Objective-C class or object type. - if (ObjectType->isObjCObjectOrInterfaceType()) { + // Template names cannot appear inside an Objective-C class or object type + // or a vector type. + // + // FIXME: This is wrong. For example: + // + // template using Vec = T __attribute__((ext_vector_type(4))); + // Vec vi; + // vi.Vec::~Vec(); + // + // ... should be accepted but we will not treat 'Vec' as a template name + // here. The right thing to do would be to check if the name is a valid + // vector component name, and look up a template name if not. And similarly + // for lookups into Objective-C class and object types, where the same + // problem can arise. + if (ObjectType->isObjCObjectOrInterfaceType() || + ObjectType->isVectorType()) { Found.clear(); return false; } diff --git a/clang/test/CXX/drs/dr22xx.cpp b/clang/test/CXX/drs/dr22xx.cpp index 70a26db757c3..8896281e9ca4 100644 --- a/clang/test/CXX/drs/dr22xx.cpp +++ b/clang/test/CXX/drs/dr22xx.cpp @@ -26,3 +26,12 @@ void f() { } } #endif + +namespace dr2292 { // dr2292: 9 +#if __cplusplus >= 201103L + template using id = T; + void test(int *p) { + p->template id::~id(); + } +#endif +} diff --git a/clang/test/CXX/drs/dr4xx.cpp b/clang/test/CXX/drs/dr4xx.cpp index 00393cc2e4c0..8eeb7715cadf 100644 --- a/clang/test/CXX/drs/dr4xx.cpp +++ b/clang/test/CXX/drs/dr4xx.cpp @@ -318,8 +318,8 @@ namespace dr420 { // dr420: yes q->~id(); p->id::~id(); q->id::~id(); - p->template id::~id(); // expected-error {{'template' keyword not permitted here}} expected-error {{base type 'int' is not a struct}} - q->template id::~id(); // expected-error {{'template' keyword not permitted here}} expected-error {{base type 'int' is not a struct}} + p->template id::~id(); // OK since dr2292 + q->template id::~id(); // OK since dr2292 p->A::template id::~id(); q->A::template id::~id(); } diff --git a/clang/test/SemaCXX/cxx2a-adl-only-template-id.cpp b/clang/test/SemaCXX/cxx2a-adl-only-template-id.cpp index 4bd9a22f5f44..28ecbade1b1a 100644 --- a/clang/test/SemaCXX/cxx2a-adl-only-template-id.cpp +++ b/clang/test/SemaCXX/cxx2a-adl-only-template-id.cpp @@ -65,3 +65,11 @@ void xf(g x); // expected-error {{variable has incomplete type 'void'}} exp struct B : g { // expected-error {{expected class name}} B() : g() {} // expected-error {{expected class member or base class name}} }; + +namespace vector_components { + typedef __attribute__((__ext_vector_type__(2))) float vector_float2; + bool foo123(vector_float2 &A, vector_float2 &B) + { + return A.x < B.x && B.y > A.y; + } +} diff --git a/clang/test/SemaCXX/pseudo-destructors.cpp b/clang/test/SemaCXX/pseudo-destructors.cpp index 08938bf34a79..fb2d0afdc3fa 100644 --- a/clang/test/SemaCXX/pseudo-destructors.cpp +++ b/clang/test/SemaCXX/pseudo-destructors.cpp @@ -34,7 +34,7 @@ void f(A* a, Foo *f, int *i, double *d, int ii) { g().~Bar(); // expected-error{{non-scalar}} f->::~Bar(); - f->N::~Wibble(); // FIXME: technically, Wibble isn't a class-name + f->N::~Wibble(); // expected-error{{'N' does not refer to a type}} expected-error{{'Wibble' does not refer to a type}} f->::~Bar(17, 42); // expected-error{{cannot have any arguments}} @@ -79,7 +79,7 @@ namespace PR11339 { template void destroy(T* p) { p->~T(); // ok - p->~oops(); // expected-error{{expected the class name after '~' to name a destructor}} + p->~oops(); // expected-error{{identifier 'oops' in object destruction expression does not name a type}} } template void destroy(int*); // expected-note{{in instantiation of function template specialization}} diff --git a/clang/test/SemaCXX/vector.cpp b/clang/test/SemaCXX/vector.cpp index 40dcd35c1bb6..295e1e173233 100644 --- a/clang/test/SemaCXX/vector.cpp +++ b/clang/test/SemaCXX/vector.cpp @@ -342,3 +342,19 @@ void test_vector_literal(inte4 res) { inte4 b = (inte4)(a, a); //expected-error{{C-style cast from vector 'inte2' (vector of 2 'int' values) to vector 'inte4' (vector of 4 'int' values) of different size}} //expected-warning{{expression result unused}} } +typedef __attribute__((__ext_vector_type__(4))) float vector_float4; +typedef __attribute__((__ext_vector_type__(4))) int vector_int4; + +namespace swizzle_template_confusion { + template struct xyzw {}; + vector_int4 foo123(vector_float4 &A, vector_float4 &B) { + return A.xyzw < B.x && B.y > A.y; // OK, not a template-id + } +} + +namespace swizzle_typo_correction { + template struct xyzv {}; + vector_int4 foo123(vector_float4 &A, vector_float4 &B) { + return A.xyzw < B.x && B.y > A.y; // OK, not a typo for 'xyzv' + } +} From 739ab8a8a701c036eb759d05f936dbb0feaf749c Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Tue, 20 Aug 2019 07:21:14 +0000 Subject: [PATCH 118/289] Revert r365860 for PR42966 (with a tweak to the test case for r365862) > Author: maskray > Date: Thu Jul 11 19:01:51 2019 > New Revision: 365860 > > URL: http://llvm.org/viewvc/llvm-project?rev=365860&view=rev > Log: > [Driver] Refactor interaction between -f(no-)?omit-frame-pointer and -m(no-)?omit-leaf-frame-pointer > > Use a tri-state enum to represent shouldUseFramePointer() and > shouldUseLeafFramePointer(). > > This simplifies the logic and fixes PR9825: > -fno-omit-frame-pointer doesn't imply -mno-omit-leaf-frame-pointer. > > and PR24003: > /Oy- /O2 should not omit leaf frame pointer: this matches MSVC x86-32. > (/Oy- is a no-op on MSVC x86-64.) > > and: > when CC1 option -mdisable-fp-elim if absent, -momit-leaf-frame-pointer > can also be omitted. > > The new behavior matches GCC: > -fomit-frame-pointer wins over -mno-omit-leaf-frame-pointer > -fno-omit-frame-pointer loses out to -momit-leaf-frame-pointer > > The behavior makes lots of sense. We have 4 states: > > - 00) leaf retained, non-leaf retained > - 01) leaf retained, non-leaf omitted (this is invalid) > - 10) leaf omitted, non-leaf retained (what -momit-leaf-frame-pointer was designed for) > - 11) leaf omitted, non-leaf omitted > > "omit" options taking precedence over "no-omit" options is the only way > to make 3 valid states representable with -f(no-)?omit-frame-pointer and > -m(no-)?omit-leaf-pointer. > > Reviewed By: ychen > > Differential Revision: https://reviews.llvm.org/D64294 llvm-svn: 369333 --- clang/lib/Driver/ToolChains/Clang.cpp | 58 +++++++++--------- clang/test/Driver/cl-options.c | 10 +-- clang/test/Driver/clang_f_opts.c | 5 ++ clang/test/Driver/frame-pointer-elim.c | 84 +++++++++----------------- clang/test/Driver/xcore-opts.c | 2 +- 5 files changed, 72 insertions(+), 87 deletions(-) diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index cb861f27aeda..2508178423bf 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -501,8 +501,6 @@ static codegenoptions::DebugInfoKind DebugLevelToInfoKind(const Arg &A) { return codegenoptions::LimitedDebugInfo; } -enum class FramePointerKind { None, NonLeaf, All }; - static bool mustUseNonLeafFramePointerForTarget(const llvm::Triple &Triple) { switch (Triple.getArch()){ default: @@ -517,9 +515,6 @@ static bool mustUseNonLeafFramePointerForTarget(const llvm::Triple &Triple) { static bool useFramePointerForTargetByDefault(const ArgList &Args, const llvm::Triple &Triple) { - if (Args.hasArg(options::OPT_pg)) - return true; - switch (Triple.getArch()) { case llvm::Triple::xcore: case llvm::Triple::wasm32: @@ -579,22 +574,32 @@ static bool useFramePointerForTargetByDefault(const ArgList &Args, return true; } -static FramePointerKind getFramePointerKind(const ArgList &Args, - const llvm::Triple &Triple) { - Arg *A = Args.getLastArg(options::OPT_fomit_frame_pointer, - options::OPT_fno_omit_frame_pointer); - bool OmitFP = A && A->getOption().matches(options::OPT_fomit_frame_pointer); - bool NoOmitFP = - A && A->getOption().matches(options::OPT_fno_omit_frame_pointer); - if (NoOmitFP || mustUseNonLeafFramePointerForTarget(Triple) || - (!OmitFP && useFramePointerForTargetByDefault(Args, Triple))) { - if (Args.hasFlag(options::OPT_momit_leaf_frame_pointer, - options::OPT_mno_omit_leaf_frame_pointer, - Triple.isPS4CPU())) - return FramePointerKind::NonLeaf; - return FramePointerKind::All; - } - return FramePointerKind::None; +static bool shouldUseFramePointer(const ArgList &Args, + const llvm::Triple &Triple) { + if (Arg *A = Args.getLastArg(options::OPT_fno_omit_frame_pointer, + options::OPT_fomit_frame_pointer)) + return A->getOption().matches(options::OPT_fno_omit_frame_pointer) || + mustUseNonLeafFramePointerForTarget(Triple); + + if (Args.hasArg(options::OPT_pg)) + return true; + + return useFramePointerForTargetByDefault(Args, Triple); +} + +static bool shouldUseLeafFramePointer(const ArgList &Args, + const llvm::Triple &Triple) { + if (Arg *A = Args.getLastArg(options::OPT_mno_omit_leaf_frame_pointer, + options::OPT_momit_leaf_frame_pointer)) + return A->getOption().matches(options::OPT_mno_omit_leaf_frame_pointer); + + if (Args.hasArg(options::OPT_pg)) + return true; + + if (Triple.isPS4CPU()) + return false; + + return useFramePointerForTargetByDefault(Args, Triple); } /// Add a CC1 option to specify the debug compilation directory. @@ -3946,12 +3951,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (Args.hasFlag(options::OPT_mrtd, options::OPT_mno_rtd, false)) CmdArgs.push_back("-fdefault-calling-conv=stdcall"); - FramePointerKind FPKeepKind = getFramePointerKind(Args, RawTriple); - if (FPKeepKind != FramePointerKind::None) { + if (shouldUseFramePointer(Args, RawTriple)) CmdArgs.push_back("-mdisable-fp-elim"); - if (FPKeepKind == FramePointerKind::NonLeaf) - CmdArgs.push_back("-momit-leaf-frame-pointer"); - } if (!Args.hasFlag(options::OPT_fzero_initialized_in_bss, options::OPT_fno_zero_initialized_in_bss)) CmdArgs.push_back("-mno-zero-initialized-in-bss"); @@ -4136,6 +4137,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(A->getValue()); } + if (!shouldUseLeafFramePointer(Args, RawTriple)) + CmdArgs.push_back("-momit-leaf-frame-pointer"); + // Explicitly error on some things we know we don't support and can't just // ignore. if (!Args.hasArg(options::OPT_fallow_unsupported)) { @@ -5489,7 +5493,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } if (Arg *A = Args.getLastArg(options::OPT_pg)) - if (FPKeepKind == FramePointerKind::None) + if (!shouldUseFramePointer(Args, Triple)) D.Diag(diag::err_drv_argument_not_allowed_with) << "-fomit-frame-pointer" << A->getAsString(Args); diff --git a/clang/test/Driver/cl-options.c b/clang/test/Driver/cl-options.c index 51a98e535093..04aa08a5576e 100644 --- a/clang/test/Driver/cl-options.c +++ b/clang/test/Driver/cl-options.c @@ -161,28 +161,28 @@ // RUN: %clang_cl /Os --target=i686-pc-windows-msvc -### -- %s 2>&1 | FileCheck -check-prefix=Os %s // RUN: %clang_cl /Os --target=x86_64-pc-windows-msvc -### -- %s 2>&1 | FileCheck -check-prefix=Os %s // Os-NOT: -mdisable-fp-elim -// Os-NOT: -momit-leaf-frame-pointer +// Os: -momit-leaf-frame-pointer // Os: -Os // RUN: %clang_cl /Ot --target=i686-pc-windows-msvc -### -- %s 2>&1 | FileCheck -check-prefix=Ot %s // RUN: %clang_cl /Ot --target=x86_64-pc-windows-msvc -### -- %s 2>&1 | FileCheck -check-prefix=Ot %s // Ot-NOT: -mdisable-fp-elim -// Ot-NOT: -momit-leaf-frame-pointer +// Ot: -momit-leaf-frame-pointer // Ot: -O2 // RUN: %clang_cl /Ox --target=i686-pc-windows-msvc -### -- %s 2>&1 | FileCheck -check-prefix=Ox %s // RUN: %clang_cl /Ox --target=x86_64-pc-windows-msvc -### -- %s 2>&1 | FileCheck -check-prefix=Ox %s // Ox-NOT: -mdisable-fp-elim -// Ox-NOT: -momit-leaf-frame-pointer +// Ox: -momit-leaf-frame-pointer // Ox: -O2 // RUN: %clang_cl --target=i686-pc-win32 /O2sy- -### -- %s 2>&1 | FileCheck -check-prefix=PR24003 %s // PR24003: -mdisable-fp-elim -// PR24003-NOT: -momit-leaf-frame-pointer +// PR24003: -momit-leaf-frame-pointer // PR24003: -Os // RUN: %clang_cl --target=i686-pc-win32 -Werror /Oy- /O2 -### -- %s 2>&1 | FileCheck -check-prefix=Oy_2 %s -// Oy_2-NOT: -momit-leaf-frame-pointer +// Oy_2: -momit-leaf-frame-pointer // Oy_2: -O2 // RUN: %clang_cl --target=aarch64-pc-windows-msvc -Werror /Oy- /O2 -### -- %s 2>&1 | FileCheck -check-prefix=Oy_aarch64 %s diff --git a/clang/test/Driver/clang_f_opts.c b/clang/test/Driver/clang_f_opts.c index 17feaab26ab7..d3d80fdec41a 100644 --- a/clang/test/Driver/clang_f_opts.c +++ b/clang/test/Driver/clang_f_opts.c @@ -548,6 +548,11 @@ // CHECK-NO-NULL-POINTER-CHECKS: "-fno-delete-null-pointer-checks" // CHECK-NULL-POINTER-CHECKS-NOT: "-fno-delete-null-pointer-checks" +// RUN: %clang -### -S -fomit-frame-pointer -pg %s 2>&1 | FileCheck -check-prefix=CHECK-NO-MIX-OMIT-FP-PG %s +// RUN: %clang -### -S -fomit-frame-pointer -fno-omit-frame-pointer -pg %s 2>&1 | FileCheck -check-prefix=CHECK-MIX-NO-OMIT-FP-PG %s +// CHECK-NO-MIX-OMIT-FP-PG: '-fomit-frame-pointer' not allowed with '-pg' +// CHECK-MIX-NO-OMIT-FP-PG-NOT: '-fomit-frame-pointer' not allowed with '-pg' + // RUN: %clang -### -S -target x86_64-unknown-linux -frecord-gcc-switches %s 2>&1 | FileCheck -check-prefix=CHECK-RECORD-GCC-SWITCHES %s // RUN: %clang -### -S -target x86_64-unknown-linux -fno-record-gcc-switches %s 2>&1 | FileCheck -check-prefix=CHECK-NO-RECORD-GCC-SWITCHES %s // RUN: %clang -### -S -target x86_64-unknown-linux -fno-record-gcc-switches -frecord-gcc-switches %s 2>&1 | FileCheck -check-prefix=CHECK-RECORD-GCC-SWITCHES %s diff --git a/clang/test/Driver/frame-pointer-elim.c b/clang/test/Driver/frame-pointer-elim.c index f035860bf039..300953f2e88b 100644 --- a/clang/test/Driver/frame-pointer-elim.c +++ b/clang/test/Driver/frame-pointer-elim.c @@ -1,74 +1,48 @@ -// KEEP-ALL: "-mdisable-fp-elim" -// KEEP-ALL-NOT: "-momit-leaf-frame-pointer" +// For these next two tests when optimized we should omit the leaf frame +// pointer, for unoptimized we should have a leaf frame pointer. +// RUN: %clang -### -target i386-pc-linux-gnu -S -O1 %s 2>&1 | \ +// RUN: FileCheck --check-prefix=LINUX-OPT %s +// LINUX-OPT: "-momit-leaf-frame-pointer" -// KEEP-NON-LEAF: "-mdisable-fp-elim" -// KEEP-NON-LEAF: "-momit-leaf-frame-pointer" - -// KEEP-NONE-NOT: "-mdisable-fp-elim" -// KEEP-NONE-NOT: "-momit-leaf-frame-pointer" - -// On Linux x86, omit frame pointer when optimization is enabled. -// RUN: %clang -### -target i386-linux -S -fomit-frame-pointer %s 2>&1 | \ -// RUN: FileCheck --check-prefix=KEEP-NONE %s -// RUN: %clang -### -target i386-linux -S -O1 %s 2>&1 | \ -// RUN: FileCheck --check-prefix=KEEP-NONE %s - -// -fno-omit-frame-pointer or -pg disables frame pointer omission. -// RUN: %clang -### -target i386-linux -S %s 2>&1 | \ -// RUN: FileCheck --check-prefix=KEEP-ALL %s -// RUN: %clang -### -target i386-linux -S -O1 -fno-omit-frame-pointer %s 2>&1 | \ -// RUN: FileCheck --check-prefix=KEEP-ALL %s -// RUN: %clang -### -target i386-linux -S -O1 -pg %s 2>&1 | \ -// RUN: FileCheck --check-prefix=KEEP-ALL %s - -// -momit-leaf-frame-pointer omits leaf frame pointer. -// -fno-omit-frame-pointer loses out to -momit-leaf-frame-pointer. -// RUN: %clang -### -target i386 -S -momit-leaf-frame-pointer %s 2>&1 | \ -// RUN: FileCheck --check-prefix=KEEP-NON-LEAF %s -// RUN: %clang -### -target i386-linux -S -O1 -fno-omit-frame-pointer -momit-leaf-frame-pointer %s 2>&1 | \ -// RUN: FileCheck --check-prefix=KEEP-NON-LEAF %s -// RUN: %clang -### -target i386-linux -S -O1 -momit-leaf-frame-pointer %s 2>&1 | \ -// RUN: FileCheck --check-prefix=KEEP-NONE %s - -// Explicit or default -fomit-frame-pointer wins over -mno-omit-leaf-frame-pointer. -// RUN: %clang -### -target i386 -S %s -fomit-frame-pointer -mno-omit-leaf-frame-pointer 2>&1 | \ -// RUN: FileCheck --check-prefix=KEEP-NONE %s -// RUN: %clang -### -target i386-linux -S %s -O1 -mno-omit-leaf-frame-pointer 2>&1 | \ -// RUN: FileCheck --check-prefix=KEEP-NONE %s - -// -pg -fomit-frame-pointer => error. -// RUN: %clang -### -S -fomit-frame-pointer -pg %s 2>&1 | FileCheck -check-prefix=CHECK-NO-MIX-OMIT-FP-PG %s -// RUN: %clang -### -S -fomit-frame-pointer -fno-omit-frame-pointer -pg %s 2>&1 | FileCheck -check-prefix=CHECK-MIX-NO-OMIT-FP-PG %s -// CHECK-NO-MIX-OMIT-FP-PG: '-fomit-frame-pointer' not allowed with '-pg' -// CHECK-MIX-NO-OMIT-FP-PG-NOT: '-fomit-frame-pointer' not allowed with '-pg' +// RUN: %clang -### -target i386-pc-linux-gnu -S %s 2>&1 | \ +// RUN: FileCheck --check-prefix=LINUX %s +// LINUX-NOT: "-momit-leaf-frame-pointer" // CloudABI follows the same rules as Linux. // RUN: %clang -### -target x86_64-unknown-cloudabi -S -O1 %s 2>&1 | \ -// RUN: FileCheck --check-prefix=KEEP-NONE %s +// RUN: FileCheck --check-prefix=CLOUDABI-OPT %s +// CLOUDABI-OPT: "-momit-leaf-frame-pointer" // RUN: %clang -### -target x86_64-unknown-cloudabi -S %s 2>&1 | \ -// RUN: FileCheck --check-prefix=KEEP-ALL %s +// RUN: FileCheck --check-prefix=CLOUDABI %s +// CLOUDABI-NOT: "-momit-leaf-frame-pointer" // NetBSD follows the same rules as Linux. // RUN: %clang -### -target x86_64-unknown-netbsd -S -O1 %s 2>&1 | \ -// RUN: FileCheck --check-prefix=KEEP-NONE %s +// RUN: FileCheck --check-prefix=NETBSD-OPT %s +// NETBSD-OPT: "-momit-leaf-frame-pointer" // RUN: %clang -### -target x86_64-unknown-netbsd -S %s 2>&1 | \ -// RUN: FileCheck --check-prefix=KEEP-ALL %s +// RUN: FileCheck --check-prefix=NETBSD %s +// NETBSD-NOT: "-momit-leaf-frame-pointer" // Darwin disables omitting the leaf frame pointer even under optimization // unless the command lines are given. // RUN: %clang -### -target i386-apple-darwin -S %s 2>&1 | \ -// RUN: FileCheck --check-prefix=KEEP-ALL %s +// RUN: FileCheck --check-prefix=DARWIN %s +// DARWIN: "-mdisable-fp-elim" // RUN: %clang -### -target i386-apple-darwin -S -O1 %s 2>&1 | \ -// RUN: FileCheck --check-prefix=KEEP-ALL %s +// RUN: FileCheck --check-prefix=DARWIN-OPT %s +// DARWIN-OPT-NOT: "-momit-leaf-frame-pointer" // RUN: %clang -### -target i386-darwin -S -fomit-frame-pointer %s 2>&1 | \ -// RUN: FileCheck --check-prefix=KEEP-NONE %s +// RUN: FileCheck --check-prefix=OMIT_ALL %s +// OMIT_ALL-NOT: "-mdisable-fp-elim" // RUN: %clang -### -target i386-darwin -S -momit-leaf-frame-pointer %s 2>&1 | \ -// RUN: FileCheck --check-prefix=KEEP-NON-LEAF %s +// RUN: FileCheck --check-prefix=OMIT_LEAF %s +// OMIT_LEAF: "-momit-leaf-frame-pointer" // RUN: %clang -### -target armv7s-apple-ios -fomit-frame-pointer %s 2>&1 | \ // RUN: FileCheck --check-prefix=WARN-OMIT-7S %s @@ -89,15 +63,17 @@ // WARN-OMIT-LEAF-7S: "-momit-leaf-frame-pointer" // On the PS4, we default to omitting the frame pointer on leaf functions +// (OMIT_LEAF check line is above) // RUN: %clang -### -target x86_64-scei-ps4 -S %s 2>&1 | \ -// RUN: FileCheck --check-prefix=KEEP-NON-LEAF %s +// RUN: FileCheck --check-prefix=OMIT_LEAF %s // RUN: %clang -### -target x86_64-scei-ps4 -S -O2 %s 2>&1 | \ -// RUN: FileCheck --check-prefix=KEEP-NON-LEAF %s +// RUN: FileCheck --check-prefix=OMIT_LEAF %s // RUN: %clang -### -target powerpc64 -S %s 2>&1 | \ -// RUN: FileCheck --check-prefix=KEEP-ALL %s +// RUN: FileCheck --check-prefix=KEEP_ALL %s +// KEEP_ALL: "-mdisable-fp-elim" // RUN: %clang -### -target powerpc64 -S -O1 %s 2>&1 | \ -// RUN: FileCheck --check-prefix=KEEP-NONE %s +// RUN: FileCheck --check-prefix=OMIT_ALL %s void f0() {} void f1() { f0(); } diff --git a/clang/test/Driver/xcore-opts.c b/clang/test/Driver/xcore-opts.c index abbc88e10360..9300085724c8 100644 --- a/clang/test/Driver/xcore-opts.c +++ b/clang/test/Driver/xcore-opts.c @@ -4,8 +4,8 @@ // RUN: %clang -target xcore %s -g0 -### -o %t.o 2>&1 | FileCheck -check-prefix CHECK-G0 %s // CHECK: "-nostdsysteminc" +// CHECK: "-momit-leaf-frame-pointer" // CHECK-NOT: "-mdisable-fp-elim" -// CHECK-NOT: "-momit-leaf-frame-pointer" // CHECK: "-fno-signed-char" // CHECK: "-fno-use-cxa-atexit" // CHECK-NOT: "-fcxx-exceptions" From 0a245438c009fb02fd44044592dc7daf3eddebdf Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Tue, 20 Aug 2019 07:26:05 +0000 Subject: [PATCH 119/289] Merging r369011: ------------------------------------------------------------------------ r369011 | bogner | 2019-08-15 17:36:13 +0200 (Thu, 15 Aug 2019) | 4 lines [cmake] install_symlink should obey DESTDIR unconditionally Setting DESTDIR was erroneously buried under a condition here - if it's set it should always be used. ------------------------------------------------------------------------ llvm-svn: 369335 --- llvm/cmake/modules/LLVMInstallSymlink.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/cmake/modules/LLVMInstallSymlink.cmake b/llvm/cmake/modules/LLVMInstallSymlink.cmake index 6f378f20d6ac..09fed8085c23 100644 --- a/llvm/cmake/modules/LLVMInstallSymlink.cmake +++ b/llvm/cmake/modules/LLVMInstallSymlink.cmake @@ -3,9 +3,9 @@ # See PR8397. function(install_symlink name target outdir) + set(DESTDIR $ENV{DESTDIR}) if(CMAKE_HOST_UNIX) set(LINK_OR_COPY create_symlink) - set(DESTDIR $ENV{DESTDIR}) else() set(LINK_OR_COPY copy) endif() From 25ca9e1625eef3880cd275138415a0e326cc4513 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Tue, 20 Aug 2019 07:45:44 +0000 Subject: [PATCH 120/289] Merging r369097: ------------------------------------------------------------------------ r369097 | lewis-revill | 2019-08-16 14:00:56 +0200 (Fri, 16 Aug 2019) | 8 lines [RISCV] Allow parsing of bare symbols with offsets This patch allows symbols followed by an expression for an offset to be parsed as bare symbols. Differential Revision: https://reviews.llvm.org/D57332 ------------------------------------------------------------------------ llvm-svn: 369338 --- .../Target/RISCV/AsmParser/RISCVAsmParser.cpp | 18 +++ llvm/test/MC/RISCV/rvi-pseudos.s | 129 +++++++++--------- 2 files changed, 85 insertions(+), 62 deletions(-) diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp index 0172c6298772..f10f7a2b77d6 100644 --- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp +++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp @@ -1208,6 +1208,24 @@ OperandMatchResultTy RISCVAsmParser::parseBareSymbol(OperandVector &Operands) { Res = V; } else Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext()); + + MCBinaryExpr::Opcode Opcode; + switch (getLexer().getKind()) { + default: + Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64())); + return MatchOperand_Success; + case AsmToken::Plus: + Opcode = MCBinaryExpr::Add; + break; + case AsmToken::Minus: + Opcode = MCBinaryExpr::Sub; + break; + } + + const MCExpr *Expr; + if (getParser().parseExpression(Expr)) + return MatchOperand_ParseFail; + Res = MCBinaryExpr::create(Opcode, Res, Expr, getContext()); Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64())); return MatchOperand_Success; } diff --git a/llvm/test/MC/RISCV/rvi-pseudos.s b/llvm/test/MC/RISCV/rvi-pseudos.s index 7ecdb8fb4ce1..37501a00e3ea 100644 --- a/llvm/test/MC/RISCV/rvi-pseudos.s +++ b/llvm/test/MC/RISCV/rvi-pseudos.s @@ -34,145 +34,150 @@ lla a3, ra lla a4, f1 # CHECK: .Lpcrel_hi5: +# CHECK: auipc a5, %pcrel_hi(a_symbol+2040) +# CHECK: addi a5, a5, %pcrel_lo(.Lpcrel_hi5) +lla a5, a_symbol + (0xFF << 3) + +# CHECK: .Lpcrel_hi6: # CHECK-NOPIC: auipc a0, %pcrel_hi(a_symbol) -# CHECK-NOPIC: addi a0, a0, %pcrel_lo(.Lpcrel_hi5) +# CHECK-NOPIC: addi a0, a0, %pcrel_lo(.Lpcrel_hi6) # CHECK-PIC: auipc a0, %got_pcrel_hi(a_symbol) -# CHECK-PIC-RV32: lw a0, %pcrel_lo(.Lpcrel_hi5)(a0) -# CHECK-PIC-RV64: ld a0, %pcrel_lo(.Lpcrel_hi5)(a0) +# CHECK-PIC-RV32: lw a0, %pcrel_lo(.Lpcrel_hi6)(a0) +# CHECK-PIC-RV64: ld a0, %pcrel_lo(.Lpcrel_hi6)(a0) la a0, a_symbol -# CHECK: .Lpcrel_hi6: +# CHECK: .Lpcrel_hi7: # CHECK-NOPIC: auipc a1, %pcrel_hi(another_symbol) -# CHECK-NOPIC: addi a1, a1, %pcrel_lo(.Lpcrel_hi6) +# CHECK-NOPIC: addi a1, a1, %pcrel_lo(.Lpcrel_hi7) # CHECK-PIC: auipc a1, %got_pcrel_hi(another_symbol) -# CHECK-PIC-RV32: lw a1, %pcrel_lo(.Lpcrel_hi6)(a1) -# CHECK-PIC-RV64: ld a1, %pcrel_lo(.Lpcrel_hi6)(a1) +# CHECK-PIC-RV32: lw a1, %pcrel_lo(.Lpcrel_hi7)(a1) +# CHECK-PIC-RV64: ld a1, %pcrel_lo(.Lpcrel_hi7)(a1) la a1, another_symbol # Check that we can load the address of symbols that are spelled like a register -# CHECK: .Lpcrel_hi7: +# CHECK: .Lpcrel_hi8: # CHECK-NOPIC: auipc a2, %pcrel_hi(zero) -# CHECK-NOPIC: addi a2, a2, %pcrel_lo(.Lpcrel_hi7) +# CHECK-NOPIC: addi a2, a2, %pcrel_lo(.Lpcrel_hi8) # CHECK-PIC: auipc a2, %got_pcrel_hi(zero) -# CHECK-PIC-RV32: lw a2, %pcrel_lo(.Lpcrel_hi7)(a2) -# CHECK-PIC-RV64: ld a2, %pcrel_lo(.Lpcrel_hi7)(a2) +# CHECK-PIC-RV32: lw a2, %pcrel_lo(.Lpcrel_hi8)(a2) +# CHECK-PIC-RV64: ld a2, %pcrel_lo(.Lpcrel_hi8)(a2) la a2, zero -# CHECK: .Lpcrel_hi8: +# CHECK: .Lpcrel_hi9: # CHECK-NOPIC: auipc a3, %pcrel_hi(ra) -# CHECK-NOPIC: addi a3, a3, %pcrel_lo(.Lpcrel_hi8) +# CHECK-NOPIC: addi a3, a3, %pcrel_lo(.Lpcrel_hi9) # CHECK-PIC: auipc a3, %got_pcrel_hi(ra) -# CHECK-PIC-RV32: lw a3, %pcrel_lo(.Lpcrel_hi8)(a3) -# CHECK-PIC-RV64: ld a3, %pcrel_lo(.Lpcrel_hi8)(a3) +# CHECK-PIC-RV32: lw a3, %pcrel_lo(.Lpcrel_hi9)(a3) +# CHECK-PIC-RV64: ld a3, %pcrel_lo(.Lpcrel_hi9)(a3) la a3, ra -# CHECK: .Lpcrel_hi9: +# CHECK: .Lpcrel_hi10: # CHECK-NOPIC: auipc a4, %pcrel_hi(f1) -# CHECK-NOPIC: addi a4, a4, %pcrel_lo(.Lpcrel_hi9) +# CHECK-NOPIC: addi a4, a4, %pcrel_lo(.Lpcrel_hi10) # CHECK-PIC: auipc a4, %got_pcrel_hi(f1) -# CHECK-PIC-RV32: lw a4, %pcrel_lo(.Lpcrel_hi9)(a4) -# CHECK-PIC-RV64: ld a4, %pcrel_lo(.Lpcrel_hi9)(a4) +# CHECK-PIC-RV32: lw a4, %pcrel_lo(.Lpcrel_hi10)(a4) +# CHECK-PIC-RV64: ld a4, %pcrel_lo(.Lpcrel_hi10)(a4) la a4, f1 -# CHECK: .Lpcrel_hi10: +# CHECK: .Lpcrel_hi11: # CHECK: auipc a0, %tls_ie_pcrel_hi(a_symbol) -# CHECK-RV32: lw a0, %pcrel_lo(.Lpcrel_hi10)(a0) -# CHECK-RV64: ld a0, %pcrel_lo(.Lpcrel_hi10)(a0) +# CHECK-RV32: lw a0, %pcrel_lo(.Lpcrel_hi11)(a0) +# CHECK-RV64: ld a0, %pcrel_lo(.Lpcrel_hi11)(a0) la.tls.ie a0, a_symbol -# CHECK: .Lpcrel_hi11: +# CHECK: .Lpcrel_hi12: # CHECK: auipc a1, %tls_ie_pcrel_hi(another_symbol) -# CHECK-RV32: lw a1, %pcrel_lo(.Lpcrel_hi11)(a1) -# CHECK-RV64: ld a1, %pcrel_lo(.Lpcrel_hi11)(a1) +# CHECK-RV32: lw a1, %pcrel_lo(.Lpcrel_hi12)(a1) +# CHECK-RV64: ld a1, %pcrel_lo(.Lpcrel_hi12)(a1) la.tls.ie a1, another_symbol # Check that we can load the address of symbols that are spelled like a register -# CHECK: .Lpcrel_hi12: +# CHECK: .Lpcrel_hi13: # CHECK: auipc a2, %tls_ie_pcrel_hi(zero) -# CHECK-RV32: lw a2, %pcrel_lo(.Lpcrel_hi12)(a2) -# CHECK-RV64: ld a2, %pcrel_lo(.Lpcrel_hi12)(a2) +# CHECK-RV32: lw a2, %pcrel_lo(.Lpcrel_hi13)(a2) +# CHECK-RV64: ld a2, %pcrel_lo(.Lpcrel_hi13)(a2) la.tls.ie a2, zero -# CHECK: .Lpcrel_hi13: +# CHECK: .Lpcrel_hi14: # CHECK: auipc a3, %tls_ie_pcrel_hi(ra) -# CHECK-RV32: lw a3, %pcrel_lo(.Lpcrel_hi13)(a3) -# CHECK-RV64: ld a3, %pcrel_lo(.Lpcrel_hi13)(a3) +# CHECK-RV32: lw a3, %pcrel_lo(.Lpcrel_hi14)(a3) +# CHECK-RV64: ld a3, %pcrel_lo(.Lpcrel_hi14)(a3) la.tls.ie a3, ra -# CHECK: .Lpcrel_hi14: +# CHECK: .Lpcrel_hi15: # CHECK: auipc a4, %tls_ie_pcrel_hi(f1) -# CHECK-RV32: lw a4, %pcrel_lo(.Lpcrel_hi14)(a4) -# CHECK-RV64: ld a4, %pcrel_lo(.Lpcrel_hi14)(a4) +# CHECK-RV32: lw a4, %pcrel_lo(.Lpcrel_hi15)(a4) +# CHECK-RV64: ld a4, %pcrel_lo(.Lpcrel_hi15)(a4) la.tls.ie a4, f1 -# CHECK: .Lpcrel_hi15: +# CHECK: .Lpcrel_hi16: # CHECK: auipc a0, %tls_gd_pcrel_hi(a_symbol) -# CHECK: addi a0, a0, %pcrel_lo(.Lpcrel_hi15) +# CHECK: addi a0, a0, %pcrel_lo(.Lpcrel_hi16) la.tls.gd a0, a_symbol -# CHECK: .Lpcrel_hi16: +# CHECK: .Lpcrel_hi17: # CHECK: auipc a1, %tls_gd_pcrel_hi(another_symbol) -# CHECK: addi a1, a1, %pcrel_lo(.Lpcrel_hi16) +# CHECK: addi a1, a1, %pcrel_lo(.Lpcrel_hi17) la.tls.gd a1, another_symbol # Check that we can load the address of symbols that are spelled like a register -# CHECK: .Lpcrel_hi17: +# CHECK: .Lpcrel_hi18: # CHECK: auipc a2, %tls_gd_pcrel_hi(zero) -# CHECK: addi a2, a2, %pcrel_lo(.Lpcrel_hi17) +# CHECK: addi a2, a2, %pcrel_lo(.Lpcrel_hi18) la.tls.gd a2, zero -# CHECK: .Lpcrel_hi18: +# CHECK: .Lpcrel_hi19: # CHECK: auipc a3, %tls_gd_pcrel_hi(ra) -# CHECK: addi a3, a3, %pcrel_lo(.Lpcrel_hi18) +# CHECK: addi a3, a3, %pcrel_lo(.Lpcrel_hi19) la.tls.gd a3, ra -# CHECK: .Lpcrel_hi19: +# CHECK: .Lpcrel_hi20: # CHECK: auipc a4, %tls_gd_pcrel_hi(f1) -# CHECK: addi a4, a4, %pcrel_lo(.Lpcrel_hi19) +# CHECK: addi a4, a4, %pcrel_lo(.Lpcrel_hi20) la.tls.gd a4, f1 -# CHECK: .Lpcrel_hi20: +# CHECK: .Lpcrel_hi21: # CHECK: auipc a0, %pcrel_hi(a_symbol) -# CHECK: lb a0, %pcrel_lo(.Lpcrel_hi20)(a0) +# CHECK: lb a0, %pcrel_lo(.Lpcrel_hi21)(a0) lb a0, a_symbol -# CHECK: .Lpcrel_hi21: +# CHECK: .Lpcrel_hi22: # CHECK: auipc a1, %pcrel_hi(a_symbol) -# CHECK: lh a1, %pcrel_lo(.Lpcrel_hi21)(a1) +# CHECK: lh a1, %pcrel_lo(.Lpcrel_hi22)(a1) lh a1, a_symbol -# CHECK: .Lpcrel_hi22: +# CHECK: .Lpcrel_hi23: # CHECK: auipc a2, %pcrel_hi(a_symbol) -# CHECK: lhu a2, %pcrel_lo(.Lpcrel_hi22)(a2) +# CHECK: lhu a2, %pcrel_lo(.Lpcrel_hi23)(a2) lhu a2, a_symbol -# CHECK: .Lpcrel_hi23: +# CHECK: .Lpcrel_hi24: # CHECK: auipc a3, %pcrel_hi(a_symbol) -# CHECK: lw a3, %pcrel_lo(.Lpcrel_hi23)(a3) +# CHECK: lw a3, %pcrel_lo(.Lpcrel_hi24)(a3) lw a3, a_symbol -# CHECK: .Lpcrel_hi24: +# CHECK: .Lpcrel_hi25: # CHECK: auipc a4, %pcrel_hi(a_symbol) -# CHECK: sb a3, %pcrel_lo(.Lpcrel_hi24)(a4) +# CHECK: sb a3, %pcrel_lo(.Lpcrel_hi25)(a4) sb a3, a_symbol, a4 -# CHECK: .Lpcrel_hi25: +# CHECK: .Lpcrel_hi26: # CHECK: auipc a4, %pcrel_hi(a_symbol) -# CHECK: sh a3, %pcrel_lo(.Lpcrel_hi25)(a4) +# CHECK: sh a3, %pcrel_lo(.Lpcrel_hi26)(a4) sh a3, a_symbol, a4 -# CHECK: .Lpcrel_hi26: +# CHECK: .Lpcrel_hi27: # CHECK: auipc a4, %pcrel_hi(a_symbol) -# CHECK: sw a3, %pcrel_lo(.Lpcrel_hi26)(a4) +# CHECK: sw a3, %pcrel_lo(.Lpcrel_hi27)(a4) sw a3, a_symbol, a4 # Check that we can load the address of symbols that are spelled like a register -# CHECK: .Lpcrel_hi27: +# CHECK: .Lpcrel_hi28: # CHECK: auipc a2, %pcrel_hi(zero) -# CHECK: lw a2, %pcrel_lo(.Lpcrel_hi27)(a2) +# CHECK: lw a2, %pcrel_lo(.Lpcrel_hi28)(a2) lw a2, zero -# CHECK: .Lpcrel_hi28: +# CHECK: .Lpcrel_hi29: # CHECK: auipc a4, %pcrel_hi(zero) -# CHECK: sw a3, %pcrel_lo(.Lpcrel_hi28)(a4) +# CHECK: sw a3, %pcrel_lo(.Lpcrel_hi29)(a4) sw a3, zero, a4 From 9381f6a8c205288ca14420badc99779988f54d52 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Tue, 20 Aug 2019 07:51:50 +0000 Subject: [PATCH 121/289] Merge r368247 (requested in PR42988) Sync ioctl(2) list with NetBSD 9.99.3 Register 36 new ioctl(2) calls. Enable NVMM for amd64 as the API has been stabilized. llvm-svn: 369339 --- .../sanitizer_interceptors_ioctl_netbsd.inc | 29 +++++++++- .../sanitizer_platform_limits_netbsd.cc | 58 +++++++++++++++++-- .../sanitizer_platform_limits_netbsd.h | 47 ++++++++++++++- 3 files changed, 127 insertions(+), 7 deletions(-) diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_interceptors_ioctl_netbsd.inc b/compiler-rt/lib/sanitizer_common/sanitizer_interceptors_ioctl_netbsd.inc index f29226b3ee3a..1ec73827b8b1 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_interceptors_ioctl_netbsd.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_interceptors_ioctl_netbsd.inc @@ -24,7 +24,7 @@ struct ioctl_desc { const char *name; }; -const unsigned ioctl_table_max = 1200; +const unsigned ioctl_table_max = 1236; static ioctl_desc ioctl_table[ioctl_table_max]; static unsigned ioctl_table_size = 0; @@ -645,7 +645,7 @@ static void ioctl_table_fill() { _(SPKRTUNE, NONE, 0); _(SPKRGETVOL, WRITE, sizeof(unsigned int)); _(SPKRSETVOL, READ, sizeof(unsigned int)); -#if 0 /* WIP */ +#if defined(__x86_64__) /* Entries from file: dev/nvmm/nvmm_ioctl.h */ _(NVMM_IOC_CAPABILITY, WRITE, struct_nvmm_ioc_capability_sz); _(NVMM_IOC_MACHINE_CREATE, READWRITE, struct_nvmm_ioc_machine_create_sz); @@ -661,7 +661,11 @@ static void ioctl_table_fill() { _(NVMM_IOC_GPA_UNMAP, READ, struct_nvmm_ioc_gpa_unmap_sz); _(NVMM_IOC_HVA_MAP, READ, struct_nvmm_ioc_hva_map_sz); _(NVMM_IOC_HVA_UNMAP, READ, struct_nvmm_ioc_hva_unmap_sz); + _(NVMM_IOC_CTL, READ, struct_nvmm_ioc_ctl_sz); #endif + /* Entries from file: dev/spi/spi_io.h */ + _(SPI_IOCTL_CONFIGURE, READ, struct_spi_ioctl_configure_sz); + _(SPI_IOCTL_TRANSFER, READ, struct_spi_ioctl_transfer_sz); /* Entries from file: fs/autofs/autofs_ioctl.h */ _(AUTOFSREQUEST, WRITE, struct_autofs_daemon_request_sz); _(AUTOFSDONE, READ, struct_autofs_daemon_done_sz); @@ -895,6 +899,9 @@ static void ioctl_table_fill() { _(AUDIO_GETBUFINFO, WRITE, struct_audio_info_sz); _(AUDIO_SETCHAN, READ, sizeof(int)); _(AUDIO_GETCHAN, WRITE, sizeof(int)); + _(AUDIO_QUERYFORMAT, READWRITE, struct_audio_format_query_sz); + _(AUDIO_GETFORMAT, WRITE, struct_audio_info_sz); + _(AUDIO_SETFORMAT, READ, struct_audio_info_sz); _(AUDIO_MIXER_READ, READWRITE, struct_mixer_ctrl_sz); _(AUDIO_MIXER_WRITE, READWRITE, struct_mixer_ctrl_sz); _(AUDIO_MIXER_DEVINFO, READWRITE, struct_mixer_devinfo_sz); @@ -985,6 +992,7 @@ static void ioctl_table_fill() { _(DIOCMWEDGES, WRITE, sizeof(int)); _(DIOCGSECTORSIZE, WRITE, sizeof(unsigned int)); _(DIOCGMEDIASIZE, WRITE, sizeof(uptr)); + _(DIOCRMWEDGES, WRITE, sizeof(int)); /* Entries from file: sys/drvctlio.h */ _(DRVDETACHDEV, READ, struct_devdetachargs_sz); _(DRVRESCANBUS, READ, struct_devrescanargs_sz); @@ -1206,6 +1214,8 @@ static void ioctl_table_fill() { _(SIOCGETHERCAP, READWRITE, struct_eccapreq_sz); _(SIOCGIFINDEX, READWRITE, struct_ifreq_sz); _(SIOCSETHERCAP, READ, struct_eccapreq_sz); + _(SIOCSIFDESCR, READ, struct_ifreq_sz); + _(SIOCGIFDESCR, READWRITE, struct_ifreq_sz); _(SIOCGUMBINFO, READWRITE, struct_ifreq_sz); _(SIOCSUMBPARAM, READ, struct_ifreq_sz); _(SIOCGUMBPARAM, READWRITE, struct_ifreq_sz); @@ -1335,6 +1345,21 @@ static void ioctl_table_fill() { _(WDOGIOC_TICKLE, NONE, 0); _(WDOGIOC_GTICKLER, WRITE, sizeof(int)); _(WDOGIOC_GWDOGS, READWRITE, struct_wdog_conf_sz); + /* Entries from file: sys/kcov.h */ + _(KCOV_IOC_SETBUFSIZE, READ, sizeof(u64)); + _(KCOV_IOC_ENABLE, READ, sizeof(int)); + _(KCOV_IOC_DISABLE, NONE, 0); + /* Entries from file: sys/ipmi.h */ + _(IPMICTL_RECEIVE_MSG_TRUNC, READWRITE, struct_ipmi_recv_sz); + _(IPMICTL_RECEIVE_MSG, READWRITE, struct_ipmi_recv_sz); + _(IPMICTL_SEND_COMMAND, READ, struct_ipmi_req_sz); + _(IPMICTL_REGISTER_FOR_CMD, READ, struct_ipmi_cmdspec_sz); + _(IPMICTL_UNREGISTER_FOR_CMD, READ, struct_ipmi_cmdspec_sz); + _(IPMICTL_SET_GETS_EVENTS_CMD, READ, sizeof(int)); + _(IPMICTL_SET_MY_ADDRESS_CMD, READ, sizeof(unsigned int)); + _(IPMICTL_GET_MY_ADDRESS_CMD, WRITE, sizeof(unsigned int)); + _(IPMICTL_SET_MY_LUN_CMD, READ, sizeof(unsigned int)); + _(IPMICTL_GET_MY_LUN_CMD, WRITE, sizeof(unsigned int)); /* Entries from file: soundcard.h */ _(SNDCTL_DSP_RESET, NONE, 0); _(SNDCTL_DSP_SYNC, NONE, 0); diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_netbsd.cc b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_netbsd.cc index b2fb5cb76463..87a55e51c9d0 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_netbsd.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_netbsd.cc @@ -62,6 +62,8 @@ #include #include #include +#include +#include #include #include #include @@ -123,9 +125,6 @@ #include #include #include -#if 0 -#include -#endif #include #include #include @@ -168,6 +167,7 @@ #include #include #include +#include #include #include #include @@ -221,6 +221,10 @@ #include #include #include + +#if defined(__x86_64__) +#include +#endif // clang-format on // Include these after system headers to avoid name clashes and ambiguities. @@ -686,6 +690,26 @@ unsigned struct_usb_config_desc_sz = sizeof(usb_config_desc); unsigned struct_usb_ctl_report_desc_sz = sizeof(usb_ctl_report_desc); unsigned struct_usb_ctl_report_sz = sizeof(usb_ctl_report); unsigned struct_usb_ctl_request_sz = sizeof(usb_ctl_request); +#if defined(__x86_64__) +unsigned struct_nvmm_ioc_capability_sz = sizeof(nvmm_ioc_capability); +unsigned struct_nvmm_ioc_machine_create_sz = sizeof(nvmm_ioc_machine_create); +unsigned struct_nvmm_ioc_machine_destroy_sz = sizeof(nvmm_ioc_machine_destroy); +unsigned struct_nvmm_ioc_machine_configure_sz = + sizeof(nvmm_ioc_machine_configure); +unsigned struct_nvmm_ioc_vcpu_create_sz = sizeof(nvmm_ioc_vcpu_create); +unsigned struct_nvmm_ioc_vcpu_destroy_sz = sizeof(nvmm_ioc_vcpu_destroy); +unsigned struct_nvmm_ioc_vcpu_setstate_sz = sizeof(nvmm_ioc_vcpu_destroy); +unsigned struct_nvmm_ioc_vcpu_getstate_sz = sizeof(nvmm_ioc_vcpu_getstate); +unsigned struct_nvmm_ioc_vcpu_inject_sz = sizeof(nvmm_ioc_vcpu_inject); +unsigned struct_nvmm_ioc_vcpu_run_sz = sizeof(nvmm_ioc_vcpu_run); +unsigned struct_nvmm_ioc_gpa_map_sz = sizeof(nvmm_ioc_gpa_map); +unsigned struct_nvmm_ioc_gpa_unmap_sz = sizeof(nvmm_ioc_gpa_unmap); +unsigned struct_nvmm_ioc_hva_map_sz = sizeof(nvmm_ioc_hva_map); +unsigned struct_nvmm_ioc_hva_unmap_sz = sizeof(nvmm_ioc_hva_unmap); +unsigned struct_nvmm_ioc_ctl_sz = sizeof(nvmm_ioc_ctl); +#endif +unsigned struct_spi_ioctl_configure_sz = sizeof(spi_ioctl_configure); +unsigned struct_spi_ioctl_transfer_sz = sizeof(spi_ioctl_transfer); unsigned struct_autofs_daemon_request_sz = sizeof(autofs_daemon_request); unsigned struct_autofs_daemon_done_sz = sizeof(autofs_daemon_done); unsigned struct_sctp_connectx_addrs_sz = sizeof(sctp_connectx_addrs); @@ -728,6 +752,9 @@ unsigned struct_vnd_user_sz = sizeof(vnd_user); unsigned struct_vt_stat_sz = sizeof(vt_stat); unsigned struct_wdog_conf_sz = sizeof(wdog_conf); unsigned struct_wdog_mode_sz = sizeof(wdog_mode); +unsigned struct_ipmi_recv_sz = sizeof(ipmi_recv); +unsigned struct_ipmi_req_sz = sizeof(ipmi_req); +unsigned struct_ipmi_cmdspec_sz = sizeof(ipmi_cmdspec); unsigned struct_wfq_conf_sz = sizeof(wfq_conf); unsigned struct_wfq_getqid_sz = sizeof(wfq_getqid); unsigned struct_wfq_getstats_sz = sizeof(wfq_getstats); @@ -813,6 +840,7 @@ unsigned struct_iscsi_wait_event_parameters_sz = unsigned struct_isp_stats_sz = sizeof(isp_stats_t); unsigned struct_lsenable_sz = sizeof(struct lsenable); unsigned struct_lsdisable_sz = sizeof(struct lsdisable); +unsigned struct_audio_format_query_sz = sizeof(audio_format_query); unsigned struct_mixer_ctrl_sz = sizeof(struct mixer_ctrl); unsigned struct_mixer_devinfo_sz = sizeof(struct mixer_devinfo); unsigned struct_mpu_command_rec_sz = sizeof(mpu_command_rec); @@ -1423,7 +1451,7 @@ unsigned IOCTL_SPKRTONE = SPKRTONE; unsigned IOCTL_SPKRTUNE = SPKRTUNE; unsigned IOCTL_SPKRGETVOL = SPKRGETVOL; unsigned IOCTL_SPKRSETVOL = SPKRSETVOL; -#if 0 /* interfaces are WIP */ +#if defined(__x86_64__) unsigned IOCTL_NVMM_IOC_CAPABILITY = NVMM_IOC_CAPABILITY; unsigned IOCTL_NVMM_IOC_MACHINE_CREATE = NVMM_IOC_MACHINE_CREATE; unsigned IOCTL_NVMM_IOC_MACHINE_DESTROY = NVMM_IOC_MACHINE_DESTROY; @@ -1438,7 +1466,10 @@ unsigned IOCTL_NVMM_IOC_GPA_MAP = NVMM_IOC_GPA_MAP; unsigned IOCTL_NVMM_IOC_GPA_UNMAP = NVMM_IOC_GPA_UNMAP; unsigned IOCTL_NVMM_IOC_HVA_MAP = NVMM_IOC_HVA_MAP; unsigned IOCTL_NVMM_IOC_HVA_UNMAP = NVMM_IOC_HVA_UNMAP; +unsigned IOCTL_NVMM_IOC_CTL = NVMM_IOC_CTL; #endif +unsigned IOCTL_SPI_IOCTL_CONFIGURE = SPI_IOCTL_CONFIGURE; +unsigned IOCTL_SPI_IOCTL_TRANSFER = SPI_IOCTL_TRANSFER; unsigned IOCTL_AUTOFSREQUEST = AUTOFSREQUEST; unsigned IOCTL_AUTOFSDONE = AUTOFSDONE; unsigned IOCTL_BIOCGBLEN = BIOCGBLEN; @@ -1656,6 +1687,9 @@ unsigned IOCTL_AUDIO_GETPROPS = AUDIO_GETPROPS; unsigned IOCTL_AUDIO_GETBUFINFO = AUDIO_GETBUFINFO; unsigned IOCTL_AUDIO_SETCHAN = AUDIO_SETCHAN; unsigned IOCTL_AUDIO_GETCHAN = AUDIO_GETCHAN; +unsigned IOCTL_AUDIO_QUERYFORMAT = AUDIO_QUERYFORMAT; +unsigned IOCTL_AUDIO_GETFORMAT = AUDIO_GETFORMAT; +unsigned IOCTL_AUDIO_SETFORMAT = AUDIO_SETFORMAT; unsigned IOCTL_AUDIO_MIXER_READ = AUDIO_MIXER_READ; unsigned IOCTL_AUDIO_MIXER_WRITE = AUDIO_MIXER_WRITE; unsigned IOCTL_AUDIO_MIXER_DEVINFO = AUDIO_MIXER_DEVINFO; @@ -1741,6 +1775,7 @@ unsigned IOCTL_DIOCTUR = DIOCTUR; unsigned IOCTL_DIOCMWEDGES = DIOCMWEDGES; unsigned IOCTL_DIOCGSECTORSIZE = DIOCGSECTORSIZE; unsigned IOCTL_DIOCGMEDIASIZE = DIOCGMEDIASIZE; +unsigned IOCTL_DIOCRMWEDGES = DIOCRMWEDGES; unsigned IOCTL_DRVDETACHDEV = DRVDETACHDEV; unsigned IOCTL_DRVRESCANBUS = DRVRESCANBUS; unsigned IOCTL_DRVCTLCOMMAND = DRVCTLCOMMAND; @@ -1945,6 +1980,8 @@ unsigned IOCTL_SIOCSLINKSTR = SIOCSLINKSTR; unsigned IOCTL_SIOCGETHERCAP = SIOCGETHERCAP; unsigned IOCTL_SIOCGIFINDEX = SIOCGIFINDEX; unsigned IOCTL_SIOCSETHERCAP = SIOCSETHERCAP; +unsigned IOCTL_SIOCSIFDESCR = SIOCSIFDESCR; +unsigned IOCTL_SIOCGIFDESCR = SIOCGIFDESCR; unsigned IOCTL_SIOCGUMBINFO = SIOCGUMBINFO; unsigned IOCTL_SIOCSUMBPARAM = SIOCSUMBPARAM; unsigned IOCTL_SIOCGUMBPARAM = SIOCGUMBPARAM; @@ -2069,6 +2106,19 @@ unsigned IOCTL_WDOGIOC_WHICH = WDOGIOC_WHICH; unsigned IOCTL_WDOGIOC_TICKLE = WDOGIOC_TICKLE; unsigned IOCTL_WDOGIOC_GTICKLER = WDOGIOC_GTICKLER; unsigned IOCTL_WDOGIOC_GWDOGS = WDOGIOC_GWDOGS; +unsigned IOCTL_KCOV_IOC_SETBUFSIZE = KCOV_IOC_SETBUFSIZE; +unsigned IOCTL_KCOV_IOC_ENABLE = KCOV_IOC_ENABLE; +unsigned IOCTL_KCOV_IOC_DISABLE = KCOV_IOC_DISABLE; +unsigned IOCTL_IPMICTL_RECEIVE_MSG_TRUNC = IPMICTL_RECEIVE_MSG_TRUNC; +unsigned IOCTL_IPMICTL_RECEIVE_MSG = IPMICTL_RECEIVE_MSG; +unsigned IOCTL_IPMICTL_SEND_COMMAND = IPMICTL_SEND_COMMAND; +unsigned IOCTL_IPMICTL_REGISTER_FOR_CMD = IPMICTL_REGISTER_FOR_CMD; +unsigned IOCTL_IPMICTL_UNREGISTER_FOR_CMD = IPMICTL_UNREGISTER_FOR_CMD; +unsigned IOCTL_IPMICTL_SET_GETS_EVENTS_CMD = IPMICTL_SET_GETS_EVENTS_CMD; +unsigned IOCTL_IPMICTL_SET_MY_ADDRESS_CMD = IPMICTL_SET_MY_ADDRESS_CMD; +unsigned IOCTL_IPMICTL_GET_MY_ADDRESS_CMD = IPMICTL_GET_MY_ADDRESS_CMD; +unsigned IOCTL_IPMICTL_SET_MY_LUN_CMD = IPMICTL_SET_MY_LUN_CMD; +unsigned IOCTL_IPMICTL_GET_MY_LUN_CMD = IPMICTL_GET_MY_LUN_CMD; unsigned IOCTL_SNDCTL_DSP_RESET = SNDCTL_DSP_RESET; unsigned IOCTL_SNDCTL_DSP_SYNC = SNDCTL_DSP_SYNC; unsigned IOCTL_SNDCTL_DSP_SPEED = SNDCTL_DSP_SPEED; diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_netbsd.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_netbsd.h index add9852ec6c3..4fb3b8c0e06f 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_netbsd.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_netbsd.h @@ -849,6 +849,25 @@ extern unsigned struct_usb_config_desc_sz; extern unsigned struct_usb_ctl_report_desc_sz; extern unsigned struct_usb_ctl_report_sz; extern unsigned struct_usb_ctl_request_sz; +#if defined(__x86_64__) +extern unsigned struct_nvmm_ioc_capability_sz; +extern unsigned struct_nvmm_ioc_machine_create_sz; +extern unsigned struct_nvmm_ioc_machine_destroy_sz; +extern unsigned struct_nvmm_ioc_machine_configure_sz; +extern unsigned struct_nvmm_ioc_vcpu_create_sz; +extern unsigned struct_nvmm_ioc_vcpu_destroy_sz; +extern unsigned struct_nvmm_ioc_vcpu_setstate_sz; +extern unsigned struct_nvmm_ioc_vcpu_getstate_sz; +extern unsigned struct_nvmm_ioc_vcpu_inject_sz; +extern unsigned struct_nvmm_ioc_vcpu_run_sz; +extern unsigned struct_nvmm_ioc_gpa_map_sz; +extern unsigned struct_nvmm_ioc_gpa_unmap_sz; +extern unsigned struct_nvmm_ioc_hva_map_sz; +extern unsigned struct_nvmm_ioc_hva_unmap_sz; +extern unsigned struct_nvmm_ioc_ctl_sz; +#endif +extern unsigned struct_spi_ioctl_configure_sz; +extern unsigned struct_spi_ioctl_transfer_sz; extern unsigned struct_autofs_daemon_request_sz; extern unsigned struct_autofs_daemon_done_sz; extern unsigned struct_sctp_connectx_addrs_sz; @@ -891,6 +910,9 @@ extern unsigned struct_vnd_user_sz; extern unsigned struct_vt_stat_sz; extern unsigned struct_wdog_conf_sz; extern unsigned struct_wdog_mode_sz; +extern unsigned struct_ipmi_recv_sz; +extern unsigned struct_ipmi_req_sz; +extern unsigned struct_ipmi_cmdspec_sz; extern unsigned struct_wfq_conf_sz; extern unsigned struct_wfq_getqid_sz; extern unsigned struct_wfq_getstats_sz; @@ -969,6 +991,7 @@ extern unsigned struct_iscsi_wait_event_parameters_sz; extern unsigned struct_isp_stats_sz; extern unsigned struct_lsenable_sz; extern unsigned struct_lsdisable_sz; +extern unsigned struct_audio_format_query_sz; extern unsigned struct_mixer_ctrl_sz; extern unsigned struct_mixer_devinfo_sz; extern unsigned struct_mpu_command_rec_sz; @@ -1575,7 +1598,7 @@ extern unsigned IOCTL_SPKRTONE; extern unsigned IOCTL_SPKRTUNE; extern unsigned IOCTL_SPKRGETVOL; extern unsigned IOCTL_SPKRSETVOL; -#if 0 /* interfaces are WIP */ +#if defined(__x86_64__) extern unsigned IOCTL_NVMM_IOC_CAPABILITY; extern unsigned IOCTL_NVMM_IOC_MACHINE_CREATE; extern unsigned IOCTL_NVMM_IOC_MACHINE_DESTROY; @@ -1590,6 +1613,7 @@ extern unsigned IOCTL_NVMM_IOC_GPA_MAP; extern unsigned IOCTL_NVMM_IOC_GPA_UNMAP; extern unsigned IOCTL_NVMM_IOC_HVA_MAP; extern unsigned IOCTL_NVMM_IOC_HVA_UNMAP; +extern unsigned IOCTL_NVMM_IOC_CTL; #endif extern unsigned IOCTL_AUTOFSREQUEST; extern unsigned IOCTL_AUTOFSDONE; @@ -1808,6 +1832,9 @@ extern unsigned IOCTL_AUDIO_GETPROPS; extern unsigned IOCTL_AUDIO_GETBUFINFO; extern unsigned IOCTL_AUDIO_SETCHAN; extern unsigned IOCTL_AUDIO_GETCHAN; +extern unsigned IOCTL_AUDIO_QUERYFORMAT; +extern unsigned IOCTL_AUDIO_GETFORMAT; +extern unsigned IOCTL_AUDIO_SETFORMAT; extern unsigned IOCTL_AUDIO_MIXER_READ; extern unsigned IOCTL_AUDIO_MIXER_WRITE; extern unsigned IOCTL_AUDIO_MIXER_DEVINFO; @@ -1893,6 +1920,7 @@ extern unsigned IOCTL_DIOCTUR; extern unsigned IOCTL_DIOCMWEDGES; extern unsigned IOCTL_DIOCGSECTORSIZE; extern unsigned IOCTL_DIOCGMEDIASIZE; +extern unsigned IOCTL_DIOCRMWEDGES; extern unsigned IOCTL_DRVDETACHDEV; extern unsigned IOCTL_DRVRESCANBUS; extern unsigned IOCTL_DRVCTLCOMMAND; @@ -1994,6 +2022,8 @@ extern unsigned IOCTL_SEQUENCER_TMR_TEMPO; extern unsigned IOCTL_SEQUENCER_TMR_SOURCE; extern unsigned IOCTL_SEQUENCER_TMR_METRONOME; extern unsigned IOCTL_SEQUENCER_TMR_SELECT; +extern unsigned IOCTL_SPI_IOCTL_CONFIGURE; +extern unsigned IOCTL_SPI_IOCTL_TRANSFER; extern unsigned IOCTL_MTIOCTOP; extern unsigned IOCTL_MTIOCGET; extern unsigned IOCTL_MTIOCIEOT; @@ -2097,6 +2127,8 @@ extern unsigned IOCTL_SIOCSLINKSTR; extern unsigned IOCTL_SIOCGETHERCAP; extern unsigned IOCTL_SIOCGIFINDEX; extern unsigned IOCTL_SIOCSETHERCAP; +extern unsigned IOCTL_SIOCSIFDESCR; +extern unsigned IOCTL_SIOCGIFDESCR; extern unsigned IOCTL_SIOCGUMBINFO; extern unsigned IOCTL_SIOCSUMBPARAM; extern unsigned IOCTL_SIOCGUMBPARAM; @@ -2221,6 +2253,19 @@ extern unsigned IOCTL_WDOGIOC_WHICH; extern unsigned IOCTL_WDOGIOC_TICKLE; extern unsigned IOCTL_WDOGIOC_GTICKLER; extern unsigned IOCTL_WDOGIOC_GWDOGS; +extern unsigned IOCTL_KCOV_IOC_SETBUFSIZE; +extern unsigned IOCTL_KCOV_IOC_ENABLE; +extern unsigned IOCTL_KCOV_IOC_DISABLE; +extern unsigned IOCTL_IPMICTL_RECEIVE_MSG_TRUNC; +extern unsigned IOCTL_IPMICTL_RECEIVE_MSG; +extern unsigned IOCTL_IPMICTL_SEND_COMMAND; +extern unsigned IOCTL_IPMICTL_REGISTER_FOR_CMD; +extern unsigned IOCTL_IPMICTL_UNREGISTER_FOR_CMD; +extern unsigned IOCTL_IPMICTL_SET_GETS_EVENTS_CMD; +extern unsigned IOCTL_IPMICTL_SET_MY_ADDRESS_CMD; +extern unsigned IOCTL_IPMICTL_GET_MY_ADDRESS_CMD; +extern unsigned IOCTL_IPMICTL_SET_MY_LUN_CMD; +extern unsigned IOCTL_IPMICTL_GET_MY_LUN_CMD; extern unsigned IOCTL_SNDCTL_DSP_RESET; extern unsigned IOCTL_SNDCTL_DSP_SYNC; extern unsigned IOCTL_SNDCTL_DSP_SPEED; From f3feb0fdbafeb5cea45f9037d9415381b2cfa137 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Tue, 20 Aug 2019 07:53:07 +0000 Subject: [PATCH 122/289] Merge r368246 for PR42988 Update generate_netbsd_ioctls.awk for NetBSD 9.99.3 Register new ioctl argument types passed in ioctl(2) calls. llvm-svn: 369340 --- compiler-rt/utils/generate_netbsd_ioctls.awk | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/compiler-rt/utils/generate_netbsd_ioctls.awk b/compiler-rt/utils/generate_netbsd_ioctls.awk index 4ae6015f08d9..0986eccf3d71 100755 --- a/compiler-rt/utils/generate_netbsd_ioctls.awk +++ b/compiler-rt/utils/generate_netbsd_ioctls.awk @@ -482,6 +482,8 @@ function get_type(string) return "sizeof(u16)" } else if (string == "u_int32_t" || string == "uint32_t") { return "sizeof(u32)" + } else if (string == "u_int64_t" || string == "uint64_t") { + return "sizeof(u64)" } else if (string ~ /\*$/) { return "sizeof(uptr)" } else if (string == "off_t") { @@ -623,6 +625,10 @@ function get_type(string) return "struct_RF_ProgressInfo_sz" } else if (string == "nvlist_ref_t") { return "struct_nvlist_ref_sz" + } else if (string == "spi_ioctl_transfer_t") { + return "struct_spi_ioctl_transfer_sz" + } else if (string == "spi_ioctl_configure_t") { + return "struct_spi_ioctl_configure_sz" } else { print "Unrecognized entry: " string print "Aborting" From 0c67478875b38f890bce90a0641cf3dcd69b834e Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Tue, 20 Aug 2019 07:58:32 +0000 Subject: [PATCH 123/289] Merge r368219 (PR42988) Restrict the NetBSD ASan TSD fallback to !ASAN_DYNAMIC The fallback to the alternative implementation of TSD with TLS is only needed for the static version of ASan for NetBSD. The same code cannot be reused for the dynamic version of ASan as TLS breaks and TSD code works. llvm-svn: 369341 --- compiler-rt/lib/asan/asan_posix.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler-rt/lib/asan/asan_posix.cc b/compiler-rt/lib/asan/asan_posix.cc index f3fbda07ac5e..cb2dab2ececb 100644 --- a/compiler-rt/lib/asan/asan_posix.cc +++ b/compiler-rt/lib/asan/asan_posix.cc @@ -39,8 +39,8 @@ void AsanOnDeadlySignal(int signo, void *siginfo, void *context) { // ---------------------- TSD ---------------- {{{1 -#if SANITIZER_NETBSD -// Thread Static Data cannot be used in early init on NetBSD. +#if SANITIZER_NETBSD && !ASAN_DYNAMIC +// Thread Static Data cannot be used in early static ASan init on NetBSD. // Reuse the Asan TSD API for compatibility with existing code // with an alternative implementation. From 10f293f38f46855278c5612ecff49ea79f3b3f1f Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Tue, 20 Aug 2019 09:35:16 +0000 Subject: [PATCH 124/289] Merging r369026: ------------------------------------------------------------------------ r369026 | jmorse | 2019-08-15 19:49:46 +0200 (Thu, 15 Aug 2019) | 17 lines [DebugInfo] Avoid crash from dropped fragments in LiveDebugValues This patch avoids a crash caused by DW_OP_LLVM_fragments being dropped from DIExpressions by LiveDebugValues spill-restore code. The appearance of a previously unseen fragment configuration confuses LDV, as documented in PR42773, and reproduced by the test function this patch adds (Crashes on a x86_64 debug build). To avoid this, on spill restore, we now use fragment information from the spilt-location-expression. In addition, when spilling, we now don't spill any DBG_VALUE with a complex expression, as it can't be safely restored and will definitely lead to an incorrect variable location. The discussion of this is in D65368. Differential Revision: https://reviews.llvm.org/D66284 ------------------------------------------------------------------------ llvm-svn: 369354 --- llvm/lib/CodeGen/LiveDebugValues.cpp | 17 ++- .../MIR/X86/live-debug-values-restore.mir | 115 +++++++++++++++++- 2 files changed, 128 insertions(+), 4 deletions(-) diff --git a/llvm/lib/CodeGen/LiveDebugValues.cpp b/llvm/lib/CodeGen/LiveDebugValues.cpp index a669e64692b9..05e994c9eb51 100644 --- a/llvm/lib/CodeGen/LiveDebugValues.cpp +++ b/llvm/lib/CodeGen/LiveDebugValues.cpp @@ -691,9 +691,17 @@ void LiveDebugValues::insertTransferDebugPair( "No register supplied when handling a restore of a debug value"); MachineFunction *MF = MI.getMF(); DIBuilder DIB(*const_cast(MF->getFunction()).getParent()); + + const DIExpression *NewExpr; + if (auto Fragment = DebugInstr->getDebugExpression()->getFragmentInfo()) + NewExpr = *DIExpression::createFragmentExpression(DIB.createExpression(), + Fragment->OffsetInBits, Fragment->SizeInBits); + else + NewExpr = DIB.createExpression(); + NewDebugInstr = BuildMI(*MF, DebugInstr->getDebugLoc(), DebugInstr->getDesc(), false, - NewReg, DebugInstr->getDebugVariable(), DIB.createExpression()); + NewReg, DebugInstr->getDebugVariable(), NewExpr); VarLoc VL(*NewDebugInstr, LS); ProcessVarLoc(VL, NewDebugInstr); LLVM_DEBUG(dbgs() << "Creating DBG_VALUE inst for register restore: "; @@ -848,9 +856,14 @@ void LiveDebugValues::transferSpillOrRestoreInst(MachineInstr &MI, << "\n"); } // Check if the register or spill location is the location of a debug value. + // FIXME: Don't create a spill transfer if there is a complex expression, + // because we currently cannot recover the original expression on restore. for (unsigned ID : OpenRanges.getVarLocs()) { + const MachineInstr *DebugInstr = &VarLocIDs[ID].MI; + if (TKind == TransferKind::TransferSpill && - VarLocIDs[ID].isDescribedByReg() == Reg) { + VarLocIDs[ID].isDescribedByReg() == Reg && + !DebugInstr->getDebugExpression()->isComplex()) { LLVM_DEBUG(dbgs() << "Spilling Register " << printReg(Reg, TRI) << '(' << VarLocIDs[ID].Var.getVar()->getName() << ")\n"); } else if (TKind == TransferKind::TransferRestore && diff --git a/llvm/test/DebugInfo/MIR/X86/live-debug-values-restore.mir b/llvm/test/DebugInfo/MIR/X86/live-debug-values-restore.mir index 2c3feeecdcdc..f43572c7b654 100644 --- a/llvm/test/DebugInfo/MIR/X86/live-debug-values-restore.mir +++ b/llvm/test/DebugInfo/MIR/X86/live-debug-values-restore.mir @@ -14,13 +14,17 @@ # return *(p + 1); # } +# Pick out DILocalVariable numbers for "p" and "q" +# CHECK: ![[PVAR:[0-9]+]] = !DILocalVariable(name: "p", +# CHECK: ![[QVAR:[0-9]+]] = !DILocalVariable(name: "q", + # Ascertain that the spill has been recognized and manifested in a DBG_VALUE. # CHECK: MOV64mr $rsp,{{.*-8.*}}killed{{.*}}$rdi :: (store 8 into %stack.0) -# CHECK-NEXT: DBG_VALUE $rsp,{{.*}}![[MDIX:[0-9]+]],{{.*}}!DIExpression(DW_OP_constu, 8, DW_OP_minus) +# CHECK-NEXT: DBG_VALUE $rsp,{{.*}}![[PVAR]],{{.*}}!DIExpression(DW_OP_constu, 8, DW_OP_minus) # Check for the restore. # CHECK: $rdi = MOV64rm $rsp,{{.*-8.*}}:: (load 8 from %stack.0) -# CHECK-NEXT: DBG_VALUE $rdi,{{.*}}![[MDIX]], !DIExpression() +# CHECK-NEXT: DBG_VALUE $rdi,{{.*}}![[PVAR]], !DIExpression() --- | define dso_local i32 @f(i32* readonly %p) local_unnamed_addr !dbg !7 { @@ -39,6 +43,22 @@ ret i32 %0, !dbg !28 } + define dso_local i32 @g(i32* readonly %p) local_unnamed_addr !dbg !107 { + entry: + call void @llvm.dbg.value(metadata i32* %p, metadata !113, metadata !DIExpression()), !dbg !114 + %tobool = icmp eq i32* %p, null, !dbg !115 + br i1 %tobool, label %if.end, label %if.then, !dbg !117 + + if.then: ; preds = %entry + tail call void asm sideeffect "", "~{rax},~{rbx},~{rcx},~{rdx},~{rsi},~{rdi},~{rbp},~{r8},~{r9},~{r10},~{r11},~{r12},~{r13},~{r14},~{r15},~{dirflag},~{fpsr},~{flags}"(), !dbg !118, !srcloc !120 + br label %if.end, !dbg !121 + + if.end: ; preds = %entry, %if.then + %add.ptr = getelementptr inbounds i32, i32* %p, i64 1, !dbg !122 + %0 = load i32, i32* %add.ptr, align 4, !dbg !123, !tbaa !24 + ret i32 %0, !dbg !128 + } + declare void @llvm.dbg.value(metadata, metadata, metadata) !llvm.dbg.cu = !{!0} @@ -74,6 +94,22 @@ !26 = !{!"omnipotent char", !27, i64 0} !27 = !{!"Simple C/C++ TBAA"} !28 = !DILocation(line: 9, column: 3, scope: !7) + !101 = !DIBasicType(name: "looong int", size: 64, encoding: DW_ATE_signed) + !107 = distinct !DISubprogram(name: "g", scope: !1, file: !1, line: 105, type: !8, scopeLine: 105, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !112) + !112 = !{!113} + !113 = !DILocalVariable(name: "q", arg: 1, scope: !107, file: !1, line: 105, type: !101) + !114 = !DILocation(line: 105, column: 12, scope: !107) + !115 = !DILocation(line: 106, column: 7, scope: !116) + !116 = distinct !DILexicalBlock(scope: !107, file: !1, line: 106, column: 7) + !117 = !DILocation(line: 106, column: 7, scope: !107) + !118 = !DILocation(line: 107, column: 5, scope: !119) + !119 = distinct !DILexicalBlock(scope: !116, file: !1, line: 106, column: 10) + !120 = !{i32 -2147471544} + !121 = !DILocation(line: 108, column: 3, scope: !119) + !122 = !DILocation(line: 109, column: 14, scope: !107) + !123 = !DILocation(line: 109, column: 10, scope: !107) + !128 = !DILocation(line: 109, column: 3, scope: !107) + ... --- @@ -187,3 +223,78 @@ body: | RETQ $eax, debug-location !28 ... +--- +# This second function has been appended as a regression test against a +# crash, caused by expressions being created from spill restores that did +# not preserve fragment information. Test that no empty expressions are +# created at all, and the last block describes both variable fragments. + +# CHECK-LABEL: name: g +# CHECK-NOT: !DIExpression() +# CHECK-LABEL: bb.2.if.end: +# CHECK: DBG_VALUE $rdi, $noreg, ![[QVAR]], !DIExpression(DW_OP_LLVM_fragment, 0, 32) +# CHECK-NEXT: DBG_VALUE $rbx, $noreg, ![[QVAR]], !DIExpression(DW_OP_LLVM_fragment, 32, 32) + +name: g +alignment: 4 +tracksRegLiveness: true +liveins: + - { reg: '$rdi', virtual-reg: '' } +frameInfo: + stackSize: 48 + offsetAdjustment: -48 + maxAlignment: 8 + cvBytesOfCalleeSavedRegisters: 48 + localFrameSize: 0 +fixedStack: + - { id: 0, type: spill-slot, offset: -56, size: 8, alignment: 8, stack-id: default, + callee-saved-register: '$rbx', callee-saved-restored: true, debug-info-variable: '', + debug-info-expression: '', debug-info-location: '' } + - { id: 1, type: spill-slot, offset: -48, size: 8, alignment: 16, stack-id: default, + callee-saved-register: '$r12', callee-saved-restored: true, debug-info-variable: '', + debug-info-expression: '', debug-info-location: '' } + - { id: 2, type: spill-slot, offset: -40, size: 8, alignment: 8, stack-id: default, + callee-saved-register: '$r13', callee-saved-restored: true, debug-info-variable: '', + debug-info-expression: '', debug-info-location: '' } + - { id: 3, type: spill-slot, offset: -32, size: 8, alignment: 16, stack-id: default, + callee-saved-register: '$r14', callee-saved-restored: true, debug-info-variable: '', + debug-info-expression: '', debug-info-location: '' } + - { id: 4, type: spill-slot, offset: -24, size: 8, alignment: 8, stack-id: default, + callee-saved-register: '$r15', callee-saved-restored: true, debug-info-variable: '', + debug-info-expression: '', debug-info-location: '' } + - { id: 5, type: spill-slot, offset: -16, size: 8, alignment: 16, stack-id: default, + callee-saved-register: '$rbp', callee-saved-restored: true, debug-info-variable: '', + debug-info-expression: '', debug-info-location: '' } +stack: + - { id: 0, name: '', type: spill-slot, offset: -64, size: 8, alignment: 8, + stack-id: default, callee-saved-register: '', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } +constants: [] +body: | + bb.0.entry: + successors: %bb.1(0x50000000) + liveins: $rdi, $rbx, $r12, $r13, $r14, $r15, $rbp + + DBG_VALUE $rdi, $noreg, !113, !DIExpression(DW_OP_LLVM_fragment, 0, 32), debug-location !114 + TEST64rr renamable $rdi, renamable $rdi, implicit-def $eflags, debug-location !115 + JMP_1 %bb.1, implicit $eflags, debug-location !117 + + bb.1.if.then: + successors: %bb.2(0x80000000) + liveins: $rdi, $rbp, $r15, $r14, $r13, $r12, $rbx + + MOV64mr $rsp, 1, $noreg, -8, $noreg, killed renamable $rdi :: (store 8 into %stack.0) + renamable $rdi = MOV64rm $rsp, 1, $noreg, -8, $noreg :: (load 8 from %stack.0) + + bb.2.if.end: + liveins: $rdi, $rbx, $r12, $r13, $r14, $r15, $rbp + + DBG_VALUE $rbx, $noreg, !113, !DIExpression(DW_OP_LLVM_fragment, 32, 32), debug-location !114 + MOV64mr $rsp, 1, $noreg, -8, $noreg, killed renamable $rbx :: (store 8 into %stack.0) + renamable $rsi = MOV64rm $rsp, 1, $noreg, -8, $noreg :: (load 8 from %stack.0) + + renamable $eax = MOV32rm killed renamable $rsi, 1, $noreg, 4, $noreg, debug-location !123 :: (load 4 from %ir.add.ptr, !tbaa !24) + $rdi = MOV64ri 0 + RETQ $eax, debug-location !128 + +... From 0482ca8ded8c112115c8a9c39a9668b69d3a4441 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Tue, 20 Aug 2019 09:45:09 +0000 Subject: [PATCH 125/289] Merging r369168: ------------------------------------------------------------------------ r369168 | spatel | 2019-08-17 01:10:34 +0200 (Sat, 17 Aug 2019) | 16 lines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [CodeGenPrepare] Fix use-after-free If OptimizeExtractBits() encountered a shift instruction with no operands at all, it would erase the instruction, but still return false. This previously didn’t matter because its caller would always return after processing the instruction, but https://reviews.llvm.org/D63233 changed the function’s caller to fall through if it returned false, which would then cause a use-after-free detectable by ASAN. This change makes OptimizeExtractBits return true if it removes a shift instruction with no users, terminating processing of the instruction. Patch by: @brentdax (Brent Royal-Gordon) Differential Revision: https://reviews.llvm.org/D66330 ------------------------------------------------------------------------ llvm-svn: 369355 --- llvm/lib/CodeGen/CodeGenPrepare.cpp | 3 ++- .../CodeGenPrepare/sink-shift-and-trunc.ll | 17 +++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/llvm/lib/CodeGen/CodeGenPrepare.cpp b/llvm/lib/CodeGen/CodeGenPrepare.cpp index 52b4bbea012b..e6f2aa9ef930 100644 --- a/llvm/lib/CodeGen/CodeGenPrepare.cpp +++ b/llvm/lib/CodeGen/CodeGenPrepare.cpp @@ -1682,10 +1682,11 @@ static bool OptimizeExtractBits(BinaryOperator *ShiftI, ConstantInt *CI, TheUse = InsertedShift; } - // If we removed all uses, nuke the shift. + // If we removed all uses, or there are none, nuke the shift. if (ShiftI->use_empty()) { salvageDebugInfo(*ShiftI); ShiftI->eraseFromParent(); + MadeChange = true; } return MadeChange; diff --git a/llvm/test/Transforms/CodeGenPrepare/sink-shift-and-trunc.ll b/llvm/test/Transforms/CodeGenPrepare/sink-shift-and-trunc.ll index 20a436edd105..609b6bf679a2 100644 --- a/llvm/test/Transforms/CodeGenPrepare/sink-shift-and-trunc.ll +++ b/llvm/test/Transforms/CodeGenPrepare/sink-shift-and-trunc.ll @@ -58,6 +58,23 @@ return: ; preds = %if.then17, %if.end1 ret i32 %retval.0, !dbg !63 } +; CodeGenPrepare was erasing the unused lshr instruction, but then further +; processing the instruction after it was freed. If this bug is still present, +; this test will always crash in an LLVM built with ASAN enabled, and may +; crash even if ASAN is not enabled. + +define i32 @shift_unused(i32 %a) { +; CHECK-LABEL: @shift_unused( +; CHECK-NEXT: BB2: +; CHECK-NEXT: ret i32 [[A:%.*]] +; + %as = lshr i32 %a, 3 + br label %BB2 + +BB2: + ret i32 %a +} + ; CHECK: [[shift1_loc]] = !DILocation(line: 1 ; CHECK: [[trunc1_loc]] = !DILocation(line: 2 ; CHECK: [[shift2_loc]] = !DILocation(line: 3 From 356a2b3eded28a80b3856644a72fef10df678cb1 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Tue, 20 Aug 2019 09:52:26 +0000 Subject: [PATCH 126/289] Merging r369084: ------------------------------------------------------------------------ r369084 | ctopper | 2019-08-16 06:47:44 +0200 (Fri, 16 Aug 2019) | 5 lines [X86] Manually reimplement getTargetInsertSubreg in X86DAGToDAGISel::matchBitExtract so we can call insertDAGNode on the target constant. This is needed to maintain the topological sort order. Fixes PR42992. ------------------------------------------------------------------------ llvm-svn: 369357 --- llvm/lib/Target/X86/X86ISelDAGToDAG.cpp | 8 ++++++-- llvm/test/CodeGen/X86/pr42992.ll | 17 +++++++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 llvm/test/CodeGen/X86/pr42992.ll diff --git a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp index fcf9b4148b4d..34ad589d205f 100644 --- a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp +++ b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp @@ -3333,8 +3333,12 @@ bool X86DAGToDAGISel::matchBitExtract(SDNode *Node) { SDValue ImplDef = SDValue( CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, DL, MVT::i32), 0); insertDAGNode(*CurDAG, SDValue(Node, 0), ImplDef); - NBits = CurDAG->getTargetInsertSubreg(X86::sub_8bit, DL, MVT::i32, ImplDef, - NBits); + + SDValue SRIdxVal = CurDAG->getTargetConstant(X86::sub_8bit, DL, MVT::i32); + insertDAGNode(*CurDAG, SDValue(Node, 0), SRIdxVal); + NBits = SDValue( + CurDAG->getMachineNode(TargetOpcode::INSERT_SUBREG, DL, MVT::i32, ImplDef, + NBits, SRIdxVal), 0); insertDAGNode(*CurDAG, SDValue(Node, 0), NBits); if (Subtarget->hasBMI2()) { diff --git a/llvm/test/CodeGen/X86/pr42992.ll b/llvm/test/CodeGen/X86/pr42992.ll new file mode 100644 index 000000000000..f85b5921b108 --- /dev/null +++ b/llvm/test/CodeGen/X86/pr42992.ll @@ -0,0 +1,17 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=bmi2 | FileCheck %s + +define i32 @hoge(i32 %a) { +; CHECK-LABEL: hoge: +; CHECK: # %bb.0: # %bb +; CHECK-NEXT: movl $15, %eax +; CHECK-NEXT: bzhil %edi, %eax, %eax +; CHECK-NEXT: shll $8, %eax +; CHECK-NEXT: retq +bb: + %tmp3 = shl nsw i32 -1, %a + %tmp4 = xor i32 %tmp3, -1 + %tmp5 = shl i32 %tmp4, 8 + %tmp6 = and i32 %tmp5, 3840 + ret i32 %tmp6 +} From 589f1c4de6296656b7433a88255b75c460d54260 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Tue, 20 Aug 2019 09:56:16 +0000 Subject: [PATCH 127/289] Merging r369199: ------------------------------------------------------------------------ r369199 | yhs | 2019-08-18 00:12:00 +0200 (Sun, 18 Aug 2019) | 26 lines [BPF] Fix bpf llvm-objdump issues. Commit https://reviews.llvm.org/D57939 ("[DWARF] Refactor RelocVisitor and fix computation of SHT_RELA-typed relocation entries) made a change for relocation resolution when operating on an object file. The change unfortunately broke BPF as given SymbolValue (S) and Addent (A), previously relocation is resolved to S + A and after the change, it is resolved to S This patch fixed the issue by resolving relocation correctly. It looks not all relocation resolution reaches here and I did not trace down exactly when. But I do find if the object file includes codes in two different ELF sections than default ".text", the above bug will be triggered. This patch included a trivial two function source code to demonstrate this issue. The relocation for .debug_loc is resolved incorrectly due to this and llvm-objdump cannot display source annotated assembly. Differential Revision: https://reviews.llvm.org/D66372 ------------------------------------------------------------------------ llvm-svn: 369359 --- llvm/lib/Object/RelocationResolver.cpp | 4 +- llvm/test/CodeGen/BPF/objdump_two_funcs.ll | 69 ++++++++++++++++++++++ 2 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 llvm/test/CodeGen/BPF/objdump_two_funcs.ll diff --git a/llvm/lib/Object/RelocationResolver.cpp b/llvm/lib/Object/RelocationResolver.cpp index 0a243f32e12c..41a0ac7fbd10 100644 --- a/llvm/lib/Object/RelocationResolver.cpp +++ b/llvm/lib/Object/RelocationResolver.cpp @@ -90,9 +90,9 @@ static bool supportsBPF(uint64_t Type) { static uint64_t resolveBPF(RelocationRef R, uint64_t S, uint64_t A) { switch (R.getType()) { case ELF::R_BPF_64_32: - return S & 0xFFFFFFFF; + return (S + A) & 0xFFFFFFFF; case ELF::R_BPF_64_64: - return S; + return S + A; default: llvm_unreachable("Invalid relocation type"); } diff --git a/llvm/test/CodeGen/BPF/objdump_two_funcs.ll b/llvm/test/CodeGen/BPF/objdump_two_funcs.ll new file mode 100644 index 000000000000..689cf6f707f7 --- /dev/null +++ b/llvm/test/CodeGen/BPF/objdump_two_funcs.ll @@ -0,0 +1,69 @@ +; RUN: llc -march=bpfel -filetype=obj -o - %s | llvm-objdump -S - | FileCheck %s +; RUN: llc -march=bpfeb -filetype=obj -o - %s | llvm-objdump -S - | FileCheck %s +; +; Source code: +; __attribute__((section("s1"))) +; int func1(int a) { +; return a * a; +; } +; __attribute__((section("s2"))) +; int func2(int a) { +; return a * a * a; +; } +; Compiler flag to generate IR: +; clang -target bpf -S -gdwarf-5 -gembed-source -emit-llvm -g -O2 bug.c + +; Function Attrs: norecurse nounwind readnone +define dso_local i32 @func1(i32 %a) local_unnamed_addr #0 section "s1" !dbg !7 { +entry: +; CHECK: func1: + call void @llvm.dbg.value(metadata i32 %a, metadata !12, metadata !DIExpression()), !dbg !13 + %mul = mul nsw i32 %a, %a, !dbg !14 + ret i32 %mul, !dbg !15 +; CHECK: ; return a * a; +} + +; Function Attrs: norecurse nounwind readnone +define dso_local i32 @func2(i32 %a) local_unnamed_addr #0 section "s2" !dbg !16 { +entry: +; CHECK: func2: + call void @llvm.dbg.value(metadata i32 %a, metadata !18, metadata !DIExpression()), !dbg !19 + %mul = mul nsw i32 %a, %a, !dbg !20 + %mul1 = mul nsw i32 %mul, %a, !dbg !21 + ret i32 %mul1, !dbg !22 +; CHECK: ; return a * a * a; +} + +; Function Attrs: nounwind readnone speculatable +declare void @llvm.dbg.value(metadata, metadata, metadata) #1 + +attributes #0 = { norecurse nounwind readnone "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } +attributes #1 = { nounwind readnone speculatable } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5} +!llvm.ident = !{!6} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 9.0.0 (trunk 366422) (llvm/trunk 366423)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None) +!1 = !DIFile(filename: "bug.c", directory: "/tmp/home/yhs/work/tests/llvm/reloc", checksumkind: CSK_MD5, checksum: "c7c9938d4e6989ca33db748213aab194", source: "__attribute__((section(\22s1\22)))\0Aint func1(int a) {\0A return a * a;\0A}\0A__attribute__((section(\22s2\22)))\0Aint func2(int a) {\0A return a * a * a;\0A}\0A") +!2 = !{} +!3 = !{i32 2, !"Dwarf Version", i32 5} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"wchar_size", i32 4} +!6 = !{!"clang version 9.0.0 (trunk 366422) (llvm/trunk 366423)"} +!7 = distinct !DISubprogram(name: "func1", scope: !1, file: !1, line: 2, type: !8, scopeLine: 2, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !11) +!8 = !DISubroutineType(types: !9) +!9 = !{!10, !10} +!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!11 = !{!12} +!12 = !DILocalVariable(name: "a", arg: 1, scope: !7, file: !1, line: 2, type: !10) +!13 = !DILocation(line: 0, scope: !7) +!14 = !DILocation(line: 3, column: 14, scope: !7) +!15 = !DILocation(line: 3, column: 5, scope: !7) +!16 = distinct !DISubprogram(name: "func2", scope: !1, file: !1, line: 6, type: !8, scopeLine: 6, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !17) +!17 = !{!18} +!18 = !DILocalVariable(name: "a", arg: 1, scope: !16, file: !1, line: 6, type: !10) +!19 = !DILocation(line: 0, scope: !16) +!20 = !DILocation(line: 7, column: 14, scope: !16) +!21 = !DILocation(line: 7, column: 18, scope: !16) +!22 = !DILocation(line: 7, column: 5, scope: !16) From 90dc09fc07fdfdb8c3d3199b9d564797d1b86c4b Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Tue, 20 Aug 2019 10:00:41 +0000 Subject: [PATCH 128/289] Merging r369043: ------------------------------------------------------------------------ r369043 | rnk | 2019-08-15 21:45:28 +0200 (Thu, 15 Aug 2019) | 15 lines [Sema] Implement DR2386 for C++17 structured binding Allow implementations to provide complete definitions of std::tuple_size, but to omit the 'value' member to signal that T is not tuple-like. The Microsoft standard library implements std::tuple_size this way. If the value member exists, clang still validates that it is an ICE, but if it does not, then the type is considered to not be tuple-like. Fixes PR33236 Reviewers: rsmith Differential Revision: https://reviews.llvm.org/D66040 ------------------------------------------------------------------------ llvm-svn: 369361 --- clang/lib/Sema/SemaDeclCXX.cpp | 11 ++++------- clang/test/CXX/dcl.decl/dcl.decomp/p3.cpp | 2 +- clang/test/CXX/drs/dr23xx.cpp | 21 +++++++++++++++++++++ 3 files changed, 26 insertions(+), 8 deletions(-) diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 2ffb0b4892a1..15984f89e22d 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -1030,8 +1030,10 @@ static IsTupleLike isTupleLike(Sema &S, SourceLocation Loc, QualType T, TemplateArgumentListInfo Args(Loc, Loc); Args.addArgument(getTrivialTypeTemplateArgument(S, Loc, T)); - // If there's no tuple_size specialization, it's not tuple-like. - if (lookupStdTypeTraitMember(S, R, Loc, "tuple_size", Args, /*DiagID*/0)) + // If there's no tuple_size specialization or the lookup of 'value' is empty, + // it's not tuple-like. + if (lookupStdTypeTraitMember(S, R, Loc, "tuple_size", Args, /*DiagID*/ 0) || + R.empty()) return IsTupleLike::NotTupleLike; // If we get this far, we've committed to the tuple interpretation, but @@ -1048,11 +1050,6 @@ static IsTupleLike isTupleLike(Sema &S, SourceLocation Loc, QualType T, } } Diagnoser(R, Args); - if (R.empty()) { - Diagnoser.diagnoseNotICE(S, Loc, SourceRange()); - return IsTupleLike::Error; - } - ExprResult E = S.BuildDeclarationNameExpr(CXXScopeSpec(), R, /*NeedsADL*/false); if (E.isInvalid()) diff --git a/clang/test/CXX/dcl.decl/dcl.decomp/p3.cpp b/clang/test/CXX/dcl.decl/dcl.decomp/p3.cpp index b3f0cf187446..9b030c1a2e13 100644 --- a/clang/test/CXX/dcl.decl/dcl.decomp/p3.cpp +++ b/clang/test/CXX/dcl.decl/dcl.decomp/p3.cpp @@ -12,7 +12,7 @@ void no_tuple_size_2() { auto [x, y] = A(); } // ok, decompose elementwise struct Bad1 { int a, b; }; template<> struct std::tuple_size {}; -void no_tuple_size_3() { auto [x, y] = Bad1(); } // expected-error {{cannot decompose this type; 'std::tuple_size::value' is not a valid integral constant expression}} +void no_tuple_size_3() { auto [x, y] = Bad1(); } // ok, omitting value is valid after DR2386 struct Bad2 {}; template<> struct std::tuple_size { const int value = 5; }; diff --git a/clang/test/CXX/drs/dr23xx.cpp b/clang/test/CXX/drs/dr23xx.cpp index 8e7a9a880bfb..763abd5368ef 100644 --- a/clang/test/CXX/drs/dr23xx.cpp +++ b/clang/test/CXX/drs/dr23xx.cpp @@ -40,6 +40,27 @@ namespace dr2353 { // dr2353: 9 #pragma clang __debug dump not_use_2 } +#if __cplusplus >= 201707L +// Otherwise, if the qualified-id std::tuple_size names a complete class +// type **with a member value**, the expression std::tuple_size::value shall +// be a well-formed integral constant expression +namespace dr2386 { // dr2386: 9 +struct Bad1 { int a, b; }; +struct Bad2 { int a, b; }; +} // namespace dr2386 +namespace std { +template struct tuple_size; +template <> struct std::tuple_size {}; +template <> struct std::tuple_size { + static const int value = 42; +}; +} // namespace std +namespace dr2386 { +void no_value() { auto [x, y] = Bad1(); } +void wrong_value() { auto [x, y] = Bad2(); } // expected-error {{decomposes into 42 elements}} +} // namespace dr2386 +#endif + namespace dr2387 { // dr2387: 9 #if __cplusplus >= 201402L template int a = 0; From d9e94797e27adfd1445f51d62c1b90eea5945981 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Tue, 20 Aug 2019 10:10:05 +0000 Subject: [PATCH 129/289] Merging r367412 and r367429: ------------------------------------------------------------------------ r367412 | rksimon | 2019-07-31 13:35:01 +0200 (Wed, 31 Jul 2019) | 1 line [X86][AVX] Add reduced test case for PR42833 ------------------------------------------------------------------------ ------------------------------------------------------------------------ r367429 | rksimon | 2019-07-31 14:55:39 +0200 (Wed, 31 Jul 2019) | 3 lines [X86][AVX] Ensure chained subvector insertions are the same size (PR42833) Before combining insert_subvector(insert_subvector(vec, sub0, c0), sub1, c1) patterns, ensure that the subvectors are all the same type. On AVX512 targets especially we might have a mixture of 128/256 subvector insertions. ------------------------------------------------------------------------ llvm-svn: 369362 --- llvm/lib/Target/X86/X86ISelLowering.cpp | 2 + llvm/test/CodeGen/X86/oddsubvector.ll | 236 ++++++++++++++++++++++++ 2 files changed, 238 insertions(+) diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index ff1e4ed85a41..ad68ddbeaa8b 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -5505,6 +5505,7 @@ static bool collectConcatOps(SDNode *N, SmallVectorImpl &Ops) { if (VT.getSizeInBits() == (SubVT.getSizeInBits() * 2) && Idx == (VT.getVectorNumElements() / 2) && Src.getOpcode() == ISD::INSERT_SUBVECTOR && + Src.getOperand(1).getValueType() == SubVT && isNullConstant(Src.getOperand(2))) { Ops.push_back(Src.getOperand(1)); Ops.push_back(Sub); @@ -43840,6 +43841,7 @@ static SDValue combineInsertSubvector(SDNode *N, SelectionDAG &DAG, Vec.getOpcode() == ISD::INSERT_SUBVECTOR && OpVT.getSizeInBits() == SubVecVT.getSizeInBits() * 2 && isNullConstant(Vec.getOperand(2)) && !Vec.getOperand(0).isUndef() && + Vec.getOperand(1).getValueSizeInBits() == SubVecVT.getSizeInBits() && Vec.hasOneUse()) { Vec = DAG.getNode(ISD::INSERT_SUBVECTOR, dl, OpVT, DAG.getUNDEF(OpVT), Vec.getOperand(1), Vec.getOperand(2)); diff --git a/llvm/test/CodeGen/X86/oddsubvector.ll b/llvm/test/CodeGen/X86/oddsubvector.ll index bb384e118dca..2db39b1b9369 100644 --- a/llvm/test/CodeGen/X86/oddsubvector.ll +++ b/llvm/test/CodeGen/X86/oddsubvector.ll @@ -190,3 +190,239 @@ define <16 x i32> @PR42819(<8 x i32>* %a0) { %3 = shufflevector <16 x i32> zeroinitializer, <16 x i32> %2, <16 x i32> ret <16 x i32> %3 } + +@b = dso_local local_unnamed_addr global i32 0, align 4 +@c = dso_local local_unnamed_addr global [49 x i32] zeroinitializer, align 16 +@d = dso_local local_unnamed_addr global [49 x i32] zeroinitializer, align 16 + +define void @PR42833() { +; SSE2-LABEL: PR42833: +; SSE2: # %bb.0: +; SSE2-NEXT: movdqa c+{{.*}}(%rip), %xmm1 +; SSE2-NEXT: movdqa c+{{.*}}(%rip), %xmm0 +; SSE2-NEXT: movd %xmm0, %eax +; SSE2-NEXT: addl {{.*}}(%rip), %eax +; SSE2-NEXT: movd %eax, %xmm2 +; SSE2-NEXT: movaps {{.*#+}} xmm3 = +; SSE2-NEXT: movss {{.*#+}} xmm3 = xmm2[0],xmm3[1,2,3] +; SSE2-NEXT: movdqa %xmm0, %xmm4 +; SSE2-NEXT: paddd %xmm3, %xmm4 +; SSE2-NEXT: pslld $23, %xmm3 +; SSE2-NEXT: paddd {{.*}}(%rip), %xmm3 +; SSE2-NEXT: cvttps2dq %xmm3, %xmm3 +; SSE2-NEXT: movdqa %xmm0, %xmm5 +; SSE2-NEXT: pmuludq %xmm3, %xmm5 +; SSE2-NEXT: pshufd {{.*#+}} xmm5 = xmm5[0,2,2,3] +; SSE2-NEXT: pshufd {{.*#+}} xmm3 = xmm3[1,1,3,3] +; SSE2-NEXT: pshufd {{.*#+}} xmm6 = xmm0[1,1,3,3] +; SSE2-NEXT: pmuludq %xmm3, %xmm6 +; SSE2-NEXT: pshufd {{.*#+}} xmm3 = xmm6[0,2,2,3] +; SSE2-NEXT: punpckldq {{.*#+}} xmm5 = xmm5[0],xmm3[0],xmm5[1],xmm3[1] +; SSE2-NEXT: movss {{.*#+}} xmm5 = xmm4[0],xmm5[1,2,3] +; SSE2-NEXT: movdqa d+{{.*}}(%rip), %xmm3 +; SSE2-NEXT: psubd %xmm1, %xmm3 +; SSE2-NEXT: paddd %xmm1, %xmm1 +; SSE2-NEXT: movdqa %xmm1, c+{{.*}}(%rip) +; SSE2-NEXT: movaps %xmm5, c+{{.*}}(%rip) +; SSE2-NEXT: movdqa c+{{.*}}(%rip), %xmm1 +; SSE2-NEXT: movdqa c+{{.*}}(%rip), %xmm4 +; SSE2-NEXT: movdqa d+{{.*}}(%rip), %xmm5 +; SSE2-NEXT: movdqa d+{{.*}}(%rip), %xmm6 +; SSE2-NEXT: movdqa d+{{.*}}(%rip), %xmm7 +; SSE2-NEXT: movss {{.*#+}} xmm0 = xmm2[0],xmm0[1,2,3] +; SSE2-NEXT: psubd %xmm0, %xmm7 +; SSE2-NEXT: psubd %xmm4, %xmm6 +; SSE2-NEXT: psubd %xmm1, %xmm5 +; SSE2-NEXT: movdqa %xmm5, d+{{.*}}(%rip) +; SSE2-NEXT: movdqa %xmm6, d+{{.*}}(%rip) +; SSE2-NEXT: movdqa %xmm3, d+{{.*}}(%rip) +; SSE2-NEXT: movdqa %xmm7, d+{{.*}}(%rip) +; SSE2-NEXT: paddd %xmm4, %xmm4 +; SSE2-NEXT: paddd %xmm1, %xmm1 +; SSE2-NEXT: movdqa %xmm1, c+{{.*}}(%rip) +; SSE2-NEXT: movdqa %xmm4, c+{{.*}}(%rip) +; SSE2-NEXT: retq +; +; SSE42-LABEL: PR42833: +; SSE42: # %bb.0: +; SSE42-NEXT: movdqa c+{{.*}}(%rip), %xmm1 +; SSE42-NEXT: movdqa c+{{.*}}(%rip), %xmm0 +; SSE42-NEXT: movd %xmm0, %eax +; SSE42-NEXT: addl {{.*}}(%rip), %eax +; SSE42-NEXT: movdqa {{.*#+}} xmm2 = +; SSE42-NEXT: pinsrd $0, %eax, %xmm2 +; SSE42-NEXT: movdqa %xmm0, %xmm3 +; SSE42-NEXT: paddd %xmm2, %xmm3 +; SSE42-NEXT: pslld $23, %xmm2 +; SSE42-NEXT: paddd {{.*}}(%rip), %xmm2 +; SSE42-NEXT: cvttps2dq %xmm2, %xmm2 +; SSE42-NEXT: pmulld %xmm0, %xmm2 +; SSE42-NEXT: pblendw {{.*#+}} xmm2 = xmm3[0,1],xmm2[2,3,4,5,6,7] +; SSE42-NEXT: movdqa d+{{.*}}(%rip), %xmm3 +; SSE42-NEXT: psubd %xmm1, %xmm3 +; SSE42-NEXT: paddd %xmm1, %xmm1 +; SSE42-NEXT: movdqa %xmm1, c+{{.*}}(%rip) +; SSE42-NEXT: movdqa %xmm2, c+{{.*}}(%rip) +; SSE42-NEXT: movdqa c+{{.*}}(%rip), %xmm1 +; SSE42-NEXT: movdqa c+{{.*}}(%rip), %xmm2 +; SSE42-NEXT: movdqa d+{{.*}}(%rip), %xmm4 +; SSE42-NEXT: movdqa d+{{.*}}(%rip), %xmm5 +; SSE42-NEXT: movdqa d+{{.*}}(%rip), %xmm6 +; SSE42-NEXT: pinsrd $0, %eax, %xmm0 +; SSE42-NEXT: psubd %xmm0, %xmm6 +; SSE42-NEXT: psubd %xmm2, %xmm5 +; SSE42-NEXT: psubd %xmm1, %xmm4 +; SSE42-NEXT: movdqa %xmm4, d+{{.*}}(%rip) +; SSE42-NEXT: movdqa %xmm5, d+{{.*}}(%rip) +; SSE42-NEXT: movdqa %xmm3, d+{{.*}}(%rip) +; SSE42-NEXT: movdqa %xmm6, d+{{.*}}(%rip) +; SSE42-NEXT: paddd %xmm2, %xmm2 +; SSE42-NEXT: paddd %xmm1, %xmm1 +; SSE42-NEXT: movdqa %xmm1, c+{{.*}}(%rip) +; SSE42-NEXT: movdqa %xmm2, c+{{.*}}(%rip) +; SSE42-NEXT: retq +; +; AVX1-LABEL: PR42833: +; AVX1: # %bb.0: +; AVX1-NEXT: vmovdqa c+{{.*}}(%rip), %xmm0 +; AVX1-NEXT: vmovd %xmm0, %eax +; AVX1-NEXT: addl {{.*}}(%rip), %eax +; AVX1-NEXT: vmovdqa {{.*#+}} xmm1 = +; AVX1-NEXT: vpinsrd $0, %eax, %xmm1, %xmm1 +; AVX1-NEXT: vpaddd %xmm1, %xmm0, %xmm2 +; AVX1-NEXT: vmovdqa c+{{.*}}(%rip), %xmm3 +; AVX1-NEXT: vpslld $23, %xmm1, %xmm1 +; AVX1-NEXT: vpaddd {{.*}}(%rip), %xmm1, %xmm1 +; AVX1-NEXT: vcvttps2dq %xmm1, %xmm1 +; AVX1-NEXT: vpmulld %xmm1, %xmm0, %xmm1 +; AVX1-NEXT: vpslld $1, %xmm3, %xmm3 +; AVX1-NEXT: vinsertf128 $1, %xmm3, %ymm1, %ymm1 +; AVX1-NEXT: vblendps {{.*#+}} ymm1 = ymm2[0],ymm1[1,2,3,4,5,6,7] +; AVX1-NEXT: vmovdqa d+{{.*}}(%rip), %xmm2 +; AVX1-NEXT: vpsubd c+{{.*}}(%rip), %xmm2, %xmm2 +; AVX1-NEXT: vmovups %ymm1, c+{{.*}}(%rip) +; AVX1-NEXT: vpinsrd $0, %eax, %xmm0, %xmm0 +; AVX1-NEXT: vmovdqa d+{{.*}}(%rip), %xmm1 +; AVX1-NEXT: vpsubd %xmm0, %xmm1, %xmm0 +; AVX1-NEXT: vmovdqa d+{{.*}}(%rip), %xmm1 +; AVX1-NEXT: vmovdqa c+{{.*}}(%rip), %xmm3 +; AVX1-NEXT: vpsubd %xmm3, %xmm1, %xmm1 +; AVX1-NEXT: vmovdqa d+{{.*}}(%rip), %xmm4 +; AVX1-NEXT: vmovdqa c+{{.*}}(%rip), %xmm5 +; AVX1-NEXT: vpsubd %xmm5, %xmm4, %xmm4 +; AVX1-NEXT: vmovdqa %xmm2, d+{{.*}}(%rip) +; AVX1-NEXT: vmovdqa %xmm4, d+{{.*}}(%rip) +; AVX1-NEXT: vmovdqa %xmm1, d+{{.*}}(%rip) +; AVX1-NEXT: vmovdqa %xmm0, d+{{.*}}(%rip) +; AVX1-NEXT: vpaddd %xmm3, %xmm3, %xmm0 +; AVX1-NEXT: vpaddd %xmm5, %xmm5, %xmm1 +; AVX1-NEXT: vmovdqa %xmm1, c+{{.*}}(%rip) +; AVX1-NEXT: vmovdqa %xmm0, c+{{.*}}(%rip) +; AVX1-NEXT: vzeroupper +; AVX1-NEXT: retq +; +; AVX2-LABEL: PR42833: +; AVX2: # %bb.0: +; AVX2-NEXT: movl {{.*}}(%rip), %eax +; AVX2-NEXT: vmovdqu c+{{.*}}(%rip), %ymm0 +; AVX2-NEXT: addl c+{{.*}}(%rip), %eax +; AVX2-NEXT: vmovd %eax, %xmm1 +; AVX2-NEXT: vpblendd {{.*#+}} ymm2 = ymm1[0],mem[1,2,3,4,5,6,7] +; AVX2-NEXT: vpaddd %ymm2, %ymm0, %ymm3 +; AVX2-NEXT: vpsllvd %ymm2, %ymm0, %ymm2 +; AVX2-NEXT: vpblendd {{.*#+}} ymm2 = ymm3[0],ymm2[1,2,3,4,5,6,7] +; AVX2-NEXT: vmovdqu %ymm2, c+{{.*}}(%rip) +; AVX2-NEXT: vmovdqu c+{{.*}}(%rip), %ymm2 +; AVX2-NEXT: vmovdqu d+{{.*}}(%rip), %ymm3 +; AVX2-NEXT: vmovdqu d+{{.*}}(%rip), %ymm4 +; AVX2-NEXT: vpblendd {{.*#+}} ymm0 = ymm1[0],ymm0[1,2,3,4,5,6,7] +; AVX2-NEXT: vpsubd %ymm0, %ymm4, %ymm0 +; AVX2-NEXT: vpsubd %ymm2, %ymm3, %ymm1 +; AVX2-NEXT: vmovdqu %ymm1, d+{{.*}}(%rip) +; AVX2-NEXT: vmovdqu %ymm0, d+{{.*}}(%rip) +; AVX2-NEXT: vpaddd %ymm2, %ymm2, %ymm0 +; AVX2-NEXT: vmovdqu %ymm0, c+{{.*}}(%rip) +; AVX2-NEXT: vzeroupper +; AVX2-NEXT: retq +; +; AVX512-LABEL: PR42833: +; AVX512: # %bb.0: +; AVX512-NEXT: movl {{.*}}(%rip), %eax +; AVX512-NEXT: vmovdqu c+{{.*}}(%rip), %ymm0 +; AVX512-NEXT: vmovdqu64 c+{{.*}}(%rip), %zmm1 +; AVX512-NEXT: addl c+{{.*}}(%rip), %eax +; AVX512-NEXT: vmovd %eax, %xmm2 +; AVX512-NEXT: vpblendd {{.*#+}} ymm2 = ymm2[0],mem[1,2,3,4,5,6,7] +; AVX512-NEXT: vpaddd %ymm2, %ymm0, %ymm3 +; AVX512-NEXT: vpsllvd %ymm2, %ymm0, %ymm0 +; AVX512-NEXT: vpblendd {{.*#+}} ymm0 = ymm3[0],ymm0[1,2,3,4,5,6,7] +; AVX512-NEXT: vmovdqa c+{{.*}}(%rip), %xmm2 +; AVX512-NEXT: vmovdqu %ymm0, c+{{.*}}(%rip) +; AVX512-NEXT: vmovdqu c+{{.*}}(%rip), %ymm0 +; AVX512-NEXT: vmovdqu64 d+{{.*}}(%rip), %zmm3 +; AVX512-NEXT: vpinsrd $0, %eax, %xmm2, %xmm2 +; AVX512-NEXT: vinserti32x4 $0, %xmm2, %zmm1, %zmm1 +; AVX512-NEXT: vinserti64x4 $1, %ymm0, %zmm1, %zmm1 +; AVX512-NEXT: vpsubd %zmm1, %zmm3, %zmm1 +; AVX512-NEXT: vmovdqu64 %zmm1, d+{{.*}}(%rip) +; AVX512-NEXT: vpaddd %ymm0, %ymm0, %ymm0 +; AVX512-NEXT: vmovdqu %ymm0, c+{{.*}}(%rip) +; AVX512-NEXT: vzeroupper +; AVX512-NEXT: retq +; +; XOP-LABEL: PR42833: +; XOP: # %bb.0: +; XOP-NEXT: vmovdqa c+{{.*}}(%rip), %xmm0 +; XOP-NEXT: vmovd %xmm0, %eax +; XOP-NEXT: addl {{.*}}(%rip), %eax +; XOP-NEXT: vmovdqa {{.*#+}} xmm1 = +; XOP-NEXT: vpinsrd $0, %eax, %xmm1, %xmm1 +; XOP-NEXT: vpaddd %xmm1, %xmm0, %xmm2 +; XOP-NEXT: vmovdqa c+{{.*}}(%rip), %xmm3 +; XOP-NEXT: vpshld %xmm1, %xmm0, %xmm1 +; XOP-NEXT: vpslld $1, %xmm3, %xmm3 +; XOP-NEXT: vinsertf128 $1, %xmm3, %ymm1, %ymm1 +; XOP-NEXT: vblendps {{.*#+}} ymm1 = ymm2[0],ymm1[1,2,3,4,5,6,7] +; XOP-NEXT: vmovdqa d+{{.*}}(%rip), %xmm2 +; XOP-NEXT: vpsubd c+{{.*}}(%rip), %xmm2, %xmm2 +; XOP-NEXT: vmovups %ymm1, c+{{.*}}(%rip) +; XOP-NEXT: vpinsrd $0, %eax, %xmm0, %xmm0 +; XOP-NEXT: vmovdqa d+{{.*}}(%rip), %xmm1 +; XOP-NEXT: vpsubd %xmm0, %xmm1, %xmm0 +; XOP-NEXT: vmovdqa d+{{.*}}(%rip), %xmm1 +; XOP-NEXT: vmovdqa c+{{.*}}(%rip), %xmm3 +; XOP-NEXT: vpsubd %xmm3, %xmm1, %xmm1 +; XOP-NEXT: vmovdqa d+{{.*}}(%rip), %xmm4 +; XOP-NEXT: vmovdqa c+{{.*}}(%rip), %xmm5 +; XOP-NEXT: vpsubd %xmm5, %xmm4, %xmm4 +; XOP-NEXT: vmovdqa %xmm2, d+{{.*}}(%rip) +; XOP-NEXT: vmovdqa %xmm4, d+{{.*}}(%rip) +; XOP-NEXT: vmovdqa %xmm1, d+{{.*}}(%rip) +; XOP-NEXT: vmovdqa %xmm0, d+{{.*}}(%rip) +; XOP-NEXT: vpaddd %xmm3, %xmm3, %xmm0 +; XOP-NEXT: vpaddd %xmm5, %xmm5, %xmm1 +; XOP-NEXT: vmovdqa %xmm1, c+{{.*}}(%rip) +; XOP-NEXT: vmovdqa %xmm0, c+{{.*}}(%rip) +; XOP-NEXT: vzeroupper +; XOP-NEXT: retq + %1 = load i32, i32* @b, align 4 + %2 = load <8 x i32>, <8 x i32>* bitcast (i32* getelementptr inbounds ([49 x i32], [49 x i32]* @c, i64 0, i64 32) to <8 x i32>*), align 16 + %3 = shufflevector <8 x i32> %2, <8 x i32> undef, <16 x i32> + %4 = extractelement <8 x i32> %2, i32 0 + %5 = add i32 %1, %4 + %6 = insertelement <8 x i32> , i32 %5, i32 0 + %7 = add <8 x i32> %2, %6 + %8 = shl <8 x i32> %2, %6 + %9 = shufflevector <8 x i32> %7, <8 x i32> %8, <8 x i32> + store <8 x i32> %9, <8 x i32>* bitcast (i32* getelementptr inbounds ([49 x i32], [49 x i32]* @c, i64 0, i64 32) to <8 x i32>*), align 16 + %10 = load <8 x i32>, <8 x i32>* bitcast (i32* getelementptr inbounds ([49 x i32], [49 x i32]* @c, i64 0, i64 40) to <8 x i32>*), align 16 + %11 = shufflevector <8 x i32> %10, <8 x i32> undef, <16 x i32> + %12 = load <16 x i32>, <16 x i32>* bitcast (i32* getelementptr inbounds ([49 x i32], [49 x i32]* @d, i64 0, i64 32) to <16 x i32>*), align 16 + %13 = insertelement <16 x i32> %3, i32 %5, i32 0 + %14 = shufflevector <16 x i32> %13, <16 x i32> %11, <16 x i32> + %15 = sub <16 x i32> %12, %14 + store <16 x i32> %15, <16 x i32>* bitcast (i32* getelementptr inbounds ([49 x i32], [49 x i32]* @d, i64 0, i64 32) to <16 x i32>*), align 16 + %16 = shl <8 x i32> %10, + store <8 x i32> %16, <8 x i32>* bitcast (i32* getelementptr inbounds ([49 x i32], [49 x i32]* @c, i64 0, i64 40) to <8 x i32>*), align 16 + ret void +} From 67a4a12d61bfb10b2410b53c5a43ef9b4a03de7d Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Tue, 20 Aug 2019 11:31:28 +0000 Subject: [PATCH 130/289] Merging r368867 and r368916: ------------------------------------------------------------------------ r368867 | marshall | 2019-08-14 18:21:27 +0200 (Wed, 14 Aug 2019) | 1 line Rework recursive_timed_mutex so that it uses __thread_id instead of using the lower-level __libcpp_thread_id. This is prep for fixing PR42918. Reviewed as https://reviews.llvm.org/D65895 ------------------------------------------------------------------------ ------------------------------------------------------------------------ r368916 | marshall | 2019-08-14 22:54:56 +0200 (Wed, 14 Aug 2019) | 1 line Fix thread comparison by making sure we never pass our special 'not a thread' value to the underlying implementation. Fixes PR#42918. ------------------------------------------------------------------------ llvm-svn: 369369 --- libcxx/include/__threading_support | 81 ++++++++++++++++++++++++++++++ libcxx/include/mutex | 6 +-- libcxx/include/thread | 74 ++------------------------- libcxx/src/mutex.cpp | 12 ++--- 4 files changed, 95 insertions(+), 78 deletions(-) diff --git a/libcxx/include/__threading_support b/libcxx/include/__threading_support index 589fe2096fd4..0331b7c736de 100644 --- a/libcxx/include/__threading_support +++ b/libcxx/include/__threading_support @@ -12,6 +12,7 @@ #include <__config> #include +#include #include #ifndef _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER @@ -394,6 +395,86 @@ int __libcpp_tls_set(__libcpp_tls_key __key, void *__p) #endif // !_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL || _LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL +class _LIBCPP_TYPE_VIS thread; +class _LIBCPP_TYPE_VIS __thread_id; + +namespace this_thread +{ + +_LIBCPP_INLINE_VISIBILITY __thread_id get_id() _NOEXCEPT; + +} // this_thread + +template<> struct hash<__thread_id>; + +class _LIBCPP_TEMPLATE_VIS __thread_id +{ + // FIXME: pthread_t is a pointer on Darwin but a long on Linux. + // NULL is the no-thread value on Darwin. Someone needs to check + // on other platforms. We assume 0 works everywhere for now. + __libcpp_thread_id __id_; + +public: + _LIBCPP_INLINE_VISIBILITY + __thread_id() _NOEXCEPT : __id_(0) {} + + friend _LIBCPP_INLINE_VISIBILITY + bool operator==(__thread_id __x, __thread_id __y) _NOEXCEPT + { // don't pass id==0 to underlying routines + if (__x.__id_ == 0) return __y.__id_ == 0; + if (__y.__id_ == 0) return false; + return __libcpp_thread_id_equal(__x.__id_, __y.__id_); + } + friend _LIBCPP_INLINE_VISIBILITY + bool operator!=(__thread_id __x, __thread_id __y) _NOEXCEPT + {return !(__x == __y);} + friend _LIBCPP_INLINE_VISIBILITY + bool operator< (__thread_id __x, __thread_id __y) _NOEXCEPT + { // id==0 is always less than any other thread_id + if (__x.__id_ == 0) return __y.__id_ != 0; + if (__y.__id_ == 0) return false; + return __libcpp_thread_id_less(__x.__id_, __y.__id_); + } + friend _LIBCPP_INLINE_VISIBILITY + bool operator<=(__thread_id __x, __thread_id __y) _NOEXCEPT + {return !(__y < __x);} + friend _LIBCPP_INLINE_VISIBILITY + bool operator> (__thread_id __x, __thread_id __y) _NOEXCEPT + {return __y < __x ;} + friend _LIBCPP_INLINE_VISIBILITY + bool operator>=(__thread_id __x, __thread_id __y) _NOEXCEPT + {return !(__x < __y);} + + _LIBCPP_INLINE_VISIBILITY + void __reset() { __id_ = 0; } + + template + friend + _LIBCPP_INLINE_VISIBILITY + basic_ostream<_CharT, _Traits>& + operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id); + +private: + _LIBCPP_INLINE_VISIBILITY + __thread_id(__libcpp_thread_id __id) : __id_(__id) {} + + friend __thread_id this_thread::get_id() _NOEXCEPT; + friend class _LIBCPP_TYPE_VIS thread; + friend struct _LIBCPP_TEMPLATE_VIS hash<__thread_id>; +}; + +namespace this_thread +{ + +inline _LIBCPP_INLINE_VISIBILITY +__thread_id +get_id() _NOEXCEPT +{ + return __libcpp_thread_get_current_id(); +} + +} // this_thread + _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS diff --git a/libcxx/include/mutex b/libcxx/include/mutex index 20c3ffc38b63..dca62202db11 100644 --- a/libcxx/include/mutex +++ b/libcxx/include/mutex @@ -280,7 +280,7 @@ class _LIBCPP_TYPE_VIS recursive_timed_mutex mutex __m_; condition_variable __cv_; size_t __count_; - __libcpp_thread_id __id_; + __thread_id __id_; public: recursive_timed_mutex(); ~recursive_timed_mutex(); @@ -307,9 +307,9 @@ bool recursive_timed_mutex::try_lock_until(const chrono::time_point<_Clock, _Duration>& __t) { using namespace chrono; - __libcpp_thread_id __id = __libcpp_thread_get_current_id(); + __thread_id __id = this_thread::get_id(); unique_lock lk(__m_); - if (__libcpp_thread_id_equal(__id, __id_)) + if (__id == __id_) { if (__count_ == numeric_limits::max()) return false; diff --git a/libcxx/include/thread b/libcxx/include/thread index 3d8d2ac9ce50..0b914317b037 100644 --- a/libcxx/include/thread +++ b/libcxx/include/thread @@ -200,64 +200,6 @@ __thread_specific_ptr<_Tp>::set_pointer(pointer __p) __libcpp_tls_set(__key_, __p); } -class _LIBCPP_TYPE_VIS thread; -class _LIBCPP_TYPE_VIS __thread_id; - -namespace this_thread -{ - -_LIBCPP_INLINE_VISIBILITY __thread_id get_id() _NOEXCEPT; - -} // this_thread - -template<> struct hash<__thread_id>; - -class _LIBCPP_TEMPLATE_VIS __thread_id -{ - // FIXME: pthread_t is a pointer on Darwin but a long on Linux. - // NULL is the no-thread value on Darwin. Someone needs to check - // on other platforms. We assume 0 works everywhere for now. - __libcpp_thread_id __id_; - -public: - _LIBCPP_INLINE_VISIBILITY - __thread_id() _NOEXCEPT : __id_(0) {} - - friend _LIBCPP_INLINE_VISIBILITY - bool operator==(__thread_id __x, __thread_id __y) _NOEXCEPT - {return __libcpp_thread_id_equal(__x.__id_, __y.__id_);} - friend _LIBCPP_INLINE_VISIBILITY - bool operator!=(__thread_id __x, __thread_id __y) _NOEXCEPT - {return !(__x == __y);} - friend _LIBCPP_INLINE_VISIBILITY - bool operator< (__thread_id __x, __thread_id __y) _NOEXCEPT - {return __libcpp_thread_id_less(__x.__id_, __y.__id_);} - friend _LIBCPP_INLINE_VISIBILITY - bool operator<=(__thread_id __x, __thread_id __y) _NOEXCEPT - {return !(__y < __x);} - friend _LIBCPP_INLINE_VISIBILITY - bool operator> (__thread_id __x, __thread_id __y) _NOEXCEPT - {return __y < __x ;} - friend _LIBCPP_INLINE_VISIBILITY - bool operator>=(__thread_id __x, __thread_id __y) _NOEXCEPT - {return !(__x < __y);} - - template - friend - _LIBCPP_INLINE_VISIBILITY - basic_ostream<_CharT, _Traits>& - operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id) - {return __os << __id.__id_;} - -private: - _LIBCPP_INLINE_VISIBILITY - __thread_id(__libcpp_thread_id __id) : __id_(__id) {} - - friend __thread_id this_thread::get_id() _NOEXCEPT; - friend class _LIBCPP_TYPE_VIS thread; - friend struct _LIBCPP_TEMPLATE_VIS hash<__thread_id>; -}; - template<> struct _LIBCPP_TEMPLATE_VIS hash<__thread_id> : public unary_function<__thread_id, size_t> @@ -269,17 +211,11 @@ struct _LIBCPP_TEMPLATE_VIS hash<__thread_id> } }; -namespace this_thread -{ - -inline _LIBCPP_INLINE_VISIBILITY -__thread_id -get_id() _NOEXCEPT -{ - return __libcpp_thread_get_current_id(); -} - -} // this_thread +template +_LIBCPP_INLINE_VISIBILITY +basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, __thread_id __id) +{return __os << __id.__id_;} class _LIBCPP_TYPE_VIS thread { diff --git a/libcxx/src/mutex.cpp b/libcxx/src/mutex.cpp index 0d69d7cacfa1..ceb4980c9147 100644 --- a/libcxx/src/mutex.cpp +++ b/libcxx/src/mutex.cpp @@ -132,7 +132,7 @@ timed_mutex::unlock() _NOEXCEPT recursive_timed_mutex::recursive_timed_mutex() : __count_(0), - __id_(0) + __id_{} { } @@ -144,9 +144,9 @@ recursive_timed_mutex::~recursive_timed_mutex() void recursive_timed_mutex::lock() { - __libcpp_thread_id id = __libcpp_thread_get_current_id(); + __thread_id id = this_thread::get_id(); unique_lock lk(__m_); - if (__libcpp_thread_id_equal(id, __id_)) + if (id ==__id_) { if (__count_ == numeric_limits::max()) __throw_system_error(EAGAIN, "recursive_timed_mutex lock limit reached"); @@ -162,9 +162,9 @@ recursive_timed_mutex::lock() bool recursive_timed_mutex::try_lock() _NOEXCEPT { - __libcpp_thread_id id = __libcpp_thread_get_current_id(); + __thread_id id = this_thread::get_id(); unique_lock lk(__m_, try_to_lock); - if (lk.owns_lock() && (__count_ == 0 || __libcpp_thread_id_equal(id, __id_))) + if (lk.owns_lock() && (__count_ == 0 || id == __id_)) { if (__count_ == numeric_limits::max()) return false; @@ -181,7 +181,7 @@ recursive_timed_mutex::unlock() _NOEXCEPT unique_lock lk(__m_); if (--__count_ == 0) { - __id_ = 0; + __id_.__reset(); lk.unlock(); __cv_.notify_one(); } From 7dc092de885c28aa41d2a793737cbe8c036b437e Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Wed, 21 Aug 2019 07:27:19 +0000 Subject: [PATCH 131/289] Merging r369399: ------------------------------------------------------------------------ r369399 | marshall | 2019-08-20 18:16:23 +0200 (Tue, 20 Aug 2019) | 1 line Fix availability of __thread_id on builds with external threading. Reviewed as https://reviews.llvm.org/D66480 ------------------------------------------------------------------------ llvm-svn: 369498 --- libcxx/include/__threading_support | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/libcxx/include/__threading_support b/libcxx/include/__threading_support index 0331b7c736de..46ac7d8b362c 100644 --- a/libcxx/include/__threading_support +++ b/libcxx/include/__threading_support @@ -23,16 +23,11 @@ # include <__external_threading> #elif !defined(_LIBCPP_HAS_NO_THREADS) -typedef ::timespec __libcpp_timespec_t; - #if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) # include # include #endif -_LIBCPP_PUSH_MACROS -#include <__undef_macros> - #if defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \ defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL) || \ defined(_LIBCPP_HAS_THREAD_API_WIN32) @@ -47,8 +42,16 @@ _LIBCPP_PUSH_MACROS #define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS #endif +typedef ::timespec __libcpp_timespec_t; +#endif // !defined(_LIBCPP_HAS_NO_THREADS) + +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD +#if !defined(_LIBCPP_HAS_NO_THREADS) + #if defined(_LIBCPP_HAS_THREAD_API_PTHREAD) // Mutex typedef pthread_mutex_t __libcpp_mutex_t; @@ -109,7 +112,7 @@ typedef void* __libcpp_thread_t; typedef long __libcpp_tls_key; #define _LIBCPP_TLS_DESTRUCTOR_CC __stdcall -#endif +#endif // defined(_LIBCPP_HAS_THREAD_API_PTHREAD) // Mutex _LIBCPP_THREAD_ABI_VISIBILITY @@ -475,10 +478,10 @@ get_id() _NOEXCEPT } // this_thread +#endif // !_LIBCPP_HAS_NO_THREADS + _LIBCPP_END_NAMESPACE_STD _LIBCPP_POP_MACROS -#endif // !_LIBCPP_HAS_NO_THREADS - #endif // _LIBCPP_THREADING_SUPPORT From 5c10d7361c198f7eef0ed22ff849404cd08b3d49 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Wed, 21 Aug 2019 07:33:40 +0000 Subject: [PATCH 132/289] Merging r369251: ------------------------------------------------------------------------ r369251 | stulova | 2019-08-19 13:43:16 +0200 (Mon, 19 Aug 2019) | 10 lines [OpenCL] Fix addr space deduction for pointers/references to arrays. Rewrite the logic for detecting if we are deducing addr space of a pointee type to take into account special logic for arrays. For pointers/references to arrays we can have any number of parentheses expressions as well as nested pointers. Differential Revision: https://reviews.llvm.org/D66137 ------------------------------------------------------------------------ llvm-svn: 369499 --- clang/lib/Sema/SemaType.cpp | 18 +++++++++++++-- .../SemaOpenCLCXX/address-space-deduction.cl | 22 +++++++++++++++++++ 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 29acf6177eb9..2b9d06814d7a 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -7390,8 +7390,22 @@ static void deduceOpenCLImplicitAddrSpace(TypeProcessingState &State, bool IsPointee = ChunkIndex > 0 && (D.getTypeObject(ChunkIndex - 1).Kind == DeclaratorChunk::Pointer || - D.getTypeObject(ChunkIndex - 1).Kind == DeclaratorChunk::BlockPointer || - D.getTypeObject(ChunkIndex - 1).Kind == DeclaratorChunk::Reference); + D.getTypeObject(ChunkIndex - 1).Kind == DeclaratorChunk::Reference || + D.getTypeObject(ChunkIndex - 1).Kind == DeclaratorChunk::BlockPointer); + // For pointers/references to arrays the next chunk is always an array + // followed by any number of parentheses. + if (!IsPointee && ChunkIndex > 1) { + auto AdjustedCI = ChunkIndex - 1; + if (D.getTypeObject(AdjustedCI).Kind == DeclaratorChunk::Array) + AdjustedCI--; + // Skip over all parentheses. + while (AdjustedCI > 0 && + D.getTypeObject(AdjustedCI).Kind == DeclaratorChunk::Paren) + AdjustedCI--; + if (D.getTypeObject(AdjustedCI).Kind == DeclaratorChunk::Pointer || + D.getTypeObject(AdjustedCI).Kind == DeclaratorChunk::Reference) + IsPointee = true; + } bool IsFuncReturnType = ChunkIndex > 0 && D.getTypeObject(ChunkIndex - 1).Kind == DeclaratorChunk::Function; diff --git a/clang/test/SemaOpenCLCXX/address-space-deduction.cl b/clang/test/SemaOpenCLCXX/address-space-deduction.cl index 0b64b5cdece9..ac6b2cabbd0c 100644 --- a/clang/test/SemaOpenCLCXX/address-space-deduction.cl +++ b/clang/test/SemaOpenCLCXX/address-space-deduction.cl @@ -78,3 +78,25 @@ __kernel void test() { int foo[10]; xxx(&foo[0]); } + +// Addr space for pointer/reference to an array +//CHECK: FunctionDecl {{.*}} t1 'void (const __generic float (&)[2])' +void t1(const float (&fYZ)[2]); +//CHECK: FunctionDecl {{.*}} t2 'void (const __generic float (*)[2])' +void t2(const float (*fYZ)[2]); +//CHECK: FunctionDecl {{.*}} t3 'void (__generic float (((*)))[2])' +void t3(float(((*fYZ)))[2]); +//CHECK: FunctionDecl {{.*}} t4 'void (__generic float (((*__generic *)))[2])' +void t4(float(((**fYZ)))[2]); +//CHECK: FunctionDecl {{.*}} t5 'void (__generic float (*__generic (*))[2])' +void t5(float (*(*fYZ))[2]); + +__kernel void k() { + __local float x[2]; + __local float(*p)[2]; + t1(x); + t2(&x); + t3(&x); + t4(&p); + t5(&p); +} From f3a5f2397d67207a1a1ebcdaba66372770653bf2 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Thu, 22 Aug 2019 10:32:01 +0000 Subject: [PATCH 133/289] Merging r369537: ------------------------------------------------------------------------ r369537 | davidspickett | 2019-08-21 17:38:24 +0200 (Wed, 21 Aug 2019) | 7 lines [libcxx] Only declare contents of threading API when _LIBCPP_HAS_THREAD_API_EXTERNAL is not defined. When it is defined they will be declared by the __external_threading header instead. Differential revision: https://reviews.llvm.org/D66518 ------------------------------------------------------------------------ llvm-svn: 369639 --- libcxx/include/__threading_support | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libcxx/include/__threading_support b/libcxx/include/__threading_support index 46ac7d8b362c..0d1f1e681f50 100644 --- a/libcxx/include/__threading_support +++ b/libcxx/include/__threading_support @@ -79,7 +79,7 @@ typedef pthread_t __libcpp_thread_t; typedef pthread_key_t __libcpp_tls_key; #define _LIBCPP_TLS_DESTRUCTOR_CC -#else +#elif !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) // Mutex typedef void* __libcpp_mutex_t; #define _LIBCPP_MUTEX_INITIALIZER 0 @@ -112,8 +112,9 @@ typedef void* __libcpp_thread_t; typedef long __libcpp_tls_key; #define _LIBCPP_TLS_DESTRUCTOR_CC __stdcall -#endif // defined(_LIBCPP_HAS_THREAD_API_PTHREAD) +#endif // !defined(_LIBCPP_HAS_THREAD_API_PTHREAD) && !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) +#if !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) // Mutex _LIBCPP_THREAD_ABI_VISIBILITY int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m); @@ -208,6 +209,8 @@ void *__libcpp_tls_get(__libcpp_tls_key __key); _LIBCPP_THREAD_ABI_VISIBILITY int __libcpp_tls_set(__libcpp_tls_key __key, void *__p); +#endif // !defined(_LIBCPP_HAS_THREAD_API_EXTERNAL) + #if (!defined(_LIBCPP_HAS_THREAD_LIBRARY_EXTERNAL) || \ defined(_LIBCPP_BUILDING_THREAD_LIBRARY_EXTERNAL)) && \ defined(_LIBCPP_HAS_THREAD_API_PTHREAD) From 74ed1f26415671db4bc236bb54195878245fc8c8 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Thu, 22 Aug 2019 13:42:47 +0000 Subject: [PATCH 134/289] Merging r369093: ------------------------------------------------------------------------ r369093 | lewis-revill | 2019-08-16 12:23:56 +0200 (Fri, 16 Aug 2019) | 11 lines [RISCV] Add inline asm constraint A for RISC-V This allows the constraint A to be used in inline asm for RISC-V, which allows an address held in a register to be used. This patch adds the minimal amount of code required to get operands with the right constraints to compile. Differential Revision: https://reviews.llvm.org/D54295 ------------------------------------------------------------------------ llvm-svn: 369649 --- clang/lib/Basic/Targets/RISCV.cpp | 4 ++++ clang/test/CodeGen/riscv-inline-asm.c | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/clang/lib/Basic/Targets/RISCV.cpp b/clang/lib/Basic/Targets/RISCV.cpp index 939ac46d671b..930b825e94d2 100644 --- a/clang/lib/Basic/Targets/RISCV.cpp +++ b/clang/lib/Basic/Targets/RISCV.cpp @@ -60,6 +60,10 @@ bool RISCVTargetInfo::validateAsmConstraint( // A floating-point register. Info.setAllowsRegister(); return true; + case 'A': + // An address that is held in a general-purpose register. + Info.setAllowsMemory(); + return true; } } diff --git a/clang/test/CodeGen/riscv-inline-asm.c b/clang/test/CodeGen/riscv-inline-asm.c index f79527337bdf..2c92d15ca90a 100644 --- a/clang/test/CodeGen/riscv-inline-asm.c +++ b/clang/test/CodeGen/riscv-inline-asm.c @@ -38,3 +38,9 @@ void test_f() { // CHECK: call void asm sideeffect "", "f"(double [[FLT_ARG]]) asm volatile ("" :: "f"(d)); } + +void test_A(int *p) { +// CHECK-LABEL: define void @test_A(i32* %p) +// CHECK: call void asm sideeffect "", "*A"(i32* %p) + asm volatile("" :: "A"(*p)); +} From 79c1eb901169b0e77e21ceca44e9b2f62aa735c7 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Thu, 22 Aug 2019 13:49:53 +0000 Subject: [PATCH 135/289] Merging r369095: ------------------------------------------------------------------------ r369095 | lewis-revill | 2019-08-16 12:28:34 +0200 (Fri, 16 Aug 2019) | 11 lines [RISCV] Lower inline asm constraint A for RISC-V This allows arguments with the constraint A to be lowered to input nodes for RISC-V, which implies a memory address stored in a register. This patch adds the minimal amount of code required to get operands with the right constraints to compile. https://reviews.llvm.org/D54296 ------------------------------------------------------------------------ llvm-svn: 369651 --- llvm/include/llvm/IR/InlineAsm.h | 1 + llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp | 3 +++ llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 17 ++++++++++++++ llvm/lib/Target/RISCV/RISCVISelLowering.h | 3 +++ llvm/test/CodeGen/RISCV/inline-asm.ll | 25 +++++++++++++++++++++ 5 files changed, 49 insertions(+) diff --git a/llvm/include/llvm/IR/InlineAsm.h b/llvm/include/llvm/IR/InlineAsm.h index 2aac807623a9..72d8ad1501ae 100644 --- a/llvm/include/llvm/IR/InlineAsm.h +++ b/llvm/include/llvm/IR/InlineAsm.h @@ -244,6 +244,7 @@ class InlineAsm final : public Value { Constraint_m, Constraint_o, Constraint_v, + Constraint_A, Constraint_Q, Constraint_R, Constraint_S, diff --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp index d0a3af375a6d..8439278b4ed5 100644 --- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp @@ -179,6 +179,9 @@ bool RISCVDAGToDAGISel::SelectInlineAsmMemoryOperand( // operand and need no special handling. OutOps.push_back(Op); return false; + case InlineAsm::Constraint_A: + OutOps.push_back(Op); + return false; default: break; } diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp index e695f79f5cf4..2b0f64fa6db6 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp @@ -2413,6 +2413,8 @@ RISCVTargetLowering::getConstraintType(StringRef Constraint) const { case 'J': case 'K': return C_Immediate; + case 'A': + return C_Memory; } } return TargetLowering::getConstraintType(Constraint); @@ -2442,6 +2444,21 @@ RISCVTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT); } +unsigned +RISCVTargetLowering::getInlineAsmMemConstraint(StringRef ConstraintCode) const { + // Currently only support length 1 constraints. + if (ConstraintCode.size() == 1) { + switch (ConstraintCode[0]) { + case 'A': + return InlineAsm::Constraint_A; + default: + break; + } + } + + return TargetLowering::getInlineAsmMemConstraint(ConstraintCode); +} + void RISCVTargetLowering::LowerAsmOperandForConstraint( SDValue Op, std::string &Constraint, std::vector &Ops, SelectionDAG &DAG) const { diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.h b/llvm/lib/Target/RISCV/RISCVISelLowering.h index f28c4753c1d9..e2059e70831d 100644 --- a/llvm/lib/Target/RISCV/RISCVISelLowering.h +++ b/llvm/lib/Target/RISCV/RISCVISelLowering.h @@ -93,6 +93,9 @@ class RISCVTargetLowering : public TargetLowering { const char *getTargetNodeName(unsigned Opcode) const override; ConstraintType getConstraintType(StringRef Constraint) const override; + + unsigned getInlineAsmMemConstraint(StringRef ConstraintCode) const override; + std::pair getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const override; diff --git a/llvm/test/CodeGen/RISCV/inline-asm.ll b/llvm/test/CodeGen/RISCV/inline-asm.ll index 10f8a3452aba..394033602154 100644 --- a/llvm/test/CodeGen/RISCV/inline-asm.ll +++ b/llvm/test/CodeGen/RISCV/inline-asm.ll @@ -150,6 +150,31 @@ define void @constraint_K() nounwind { ret void } +define void @constraint_A(i8* %a) nounwind { +; RV32I-LABEL: constraint_A: +; RV32I: # %bb.0: +; RV32I-NEXT: #APP +; RV32I-NEXT: sb s0, 0(a0) +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: #APP +; RV32I-NEXT: lb s1, 0(a0) +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: ret +; +; RV64I-LABEL: constraint_A: +; RV64I: # %bb.0: +; RV64I-NEXT: #APP +; RV64I-NEXT: sb s0, 0(a0) +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: #APP +; RV64I-NEXT: lb s1, 0(a0) +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ret + tail call void asm sideeffect "sb s0, $0", "*A"(i8* %a) + tail call void asm sideeffect "lb s1, $0", "*A"(i8* %a) + ret void +} + define i32 @modifier_z_zero(i32 %a) nounwind { ; RV32I-LABEL: modifier_z_zero: ; RV32I: # %bb.0: From ee7601a873d1ec8a451045ced78eae295f3c117d Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Thu, 22 Aug 2019 14:28:05 +0000 Subject: [PATCH 136/289] Merging r369426 and r369443: ------------------------------------------------------------------------ r369426 | mstorsjo | 2019-08-20 20:58:05 +0200 (Tue, 20 Aug 2019) | 5 lines [TargetMachine] Don't try to create COFFSTUB references on windows on non-COFF This avoids spurious relocation types for windows/elf targets. Differential Revision: https://reviews.llvm.org/D66401 ------------------------------------------------------------------------ ------------------------------------------------------------------------ r369443 | mstorsjo | 2019-08-20 22:58:02 +0200 (Tue, 20 Aug 2019) | 11 lines [test] Fix tests when run on windows after SVN r369426. NFC. When running tests on windows, invoking "llc -march=" will implicitly use windows as the target os, making these tests misbehave after this change. Fix the issue by using more specific -mtriple values instead of plain -march in these tests. This should hopefully fix buildbot failures like http://lab.llvm.org:8011/builders/clang-x64-windows-msvc/builds/9816. ------------------------------------------------------------------------ llvm-svn: 369654 --- llvm/lib/Target/TargetMachine.cpp | 8 +++++--- llvm/lib/Target/X86/X86Subtarget.cpp | 3 +++ .../propagate-attributes-bitcast-function.ll | 2 +- .../AMDGPU/propagate-attributes-clone.ll | 2 +- .../AMDGPU/propagate-attributes-single-set.ll | 2 +- llvm/test/CodeGen/Hexagon/pic-jt-big.ll | 2 +- llvm/test/CodeGen/Hexagon/pic-sdata.ll | 4 ++-- llvm/test/CodeGen/SPARC/tls.ll | 18 +++++++++--------- llvm/test/CodeGen/X86/mingw-refptr.ll | 7 +++++++ 9 files changed, 30 insertions(+), 18 deletions(-) diff --git a/llvm/lib/Target/TargetMachine.cpp b/llvm/lib/Target/TargetMachine.cpp index 634866d93570..28d783afe56c 100644 --- a/llvm/lib/Target/TargetMachine.cpp +++ b/llvm/lib/Target/TargetMachine.cpp @@ -140,8 +140,8 @@ bool TargetMachine::shouldAssumeDSOLocal(const Module &M, // don't assume the variables to be DSO local unless we actually know // that for sure. This only has to be done for variables; for functions // the linker can insert thunks for calling functions from another DLL. - if (TT.isWindowsGNUEnvironment() && GV && GV->isDeclarationForLinker() && - isa(GV)) + if (TT.isWindowsGNUEnvironment() && TT.isOSBinFormatCOFF() && GV && + GV->isDeclarationForLinker() && isa(GV)) return false; // On COFF, don't mark 'extern_weak' symbols as DSO local. If these symbols @@ -154,7 +154,9 @@ bool TargetMachine::shouldAssumeDSOLocal(const Module &M, // Make an exception for windows OS in the triple: Some firmware builds use // *-win32-macho triples. This (accidentally?) produced windows relocations // without GOT tables in older clang versions; Keep this behaviour. - if (TT.isOSBinFormatCOFF() || (TT.isOSWindows() && TT.isOSBinFormatMachO())) + // Some JIT users use *-win32-elf triples; these shouldn't use GOT tables + // either. + if (TT.isOSBinFormatCOFF() || TT.isOSWindows()) return true; // Most PIC code sequences that assume that a symbol is local cannot diff --git a/llvm/lib/Target/X86/X86Subtarget.cpp b/llvm/lib/Target/X86/X86Subtarget.cpp index d5bb56603df9..61fc3d05b8b3 100644 --- a/llvm/lib/Target/X86/X86Subtarget.cpp +++ b/llvm/lib/Target/X86/X86Subtarget.cpp @@ -146,6 +146,9 @@ unsigned char X86Subtarget::classifyGlobalReference(const GlobalValue *GV, return X86II::MO_DLLIMPORT; return X86II::MO_COFFSTUB; } + // Some JIT users use *-win32-elf triples; these shouldn't use GOT tables. + if (isOSWindows()) + return X86II::MO_NO_FLAG; if (is64Bit()) { // ELF supports a large, truly PIC code model with non-PC relative GOT diff --git a/llvm/test/CodeGen/AMDGPU/propagate-attributes-bitcast-function.ll b/llvm/test/CodeGen/AMDGPU/propagate-attributes-bitcast-function.ll index c1d8009d08b1..173bc72db851 100644 --- a/llvm/test/CodeGen/AMDGPU/propagate-attributes-bitcast-function.ll +++ b/llvm/test/CodeGen/AMDGPU/propagate-attributes-bitcast-function.ll @@ -1,4 +1,4 @@ -; RUN: llc -march=amdgcn -mcpu=gfx1010 -verify-machineinstrs < %s | FileCheck -check-prefix=GCN %s +; RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1010 -verify-machineinstrs < %s | FileCheck -check-prefix=GCN %s ; GCN: foo1: ; v_cndmask_b32_e64 v0, 0, 1, vcc_lo{{$}} diff --git a/llvm/test/CodeGen/AMDGPU/propagate-attributes-clone.ll b/llvm/test/CodeGen/AMDGPU/propagate-attributes-clone.ll index b9c36217aaa9..cb0406c5b1f8 100644 --- a/llvm/test/CodeGen/AMDGPU/propagate-attributes-clone.ll +++ b/llvm/test/CodeGen/AMDGPU/propagate-attributes-clone.ll @@ -1,5 +1,5 @@ ; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -O1 < %s | FileCheck -check-prefix=OPT %s -; RUN: llc -march=amdgcn -mcpu=gfx1010 -verify-machineinstrs < %s | FileCheck -check-prefix=LLC %s +; RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1010 -verify-machineinstrs < %s | FileCheck -check-prefix=LLC %s ; OPT: declare void @foo4() local_unnamed_addr #0 ; OPT: define internal fastcc void @foo3.2() unnamed_addr #1 diff --git a/llvm/test/CodeGen/AMDGPU/propagate-attributes-single-set.ll b/llvm/test/CodeGen/AMDGPU/propagate-attributes-single-set.ll index 348825865336..cb4283c8c67a 100644 --- a/llvm/test/CodeGen/AMDGPU/propagate-attributes-single-set.ll +++ b/llvm/test/CodeGen/AMDGPU/propagate-attributes-single-set.ll @@ -1,5 +1,5 @@ ; RUN: opt -S -mtriple=amdgcn-amd-amdhsa -O1 < %s | FileCheck -check-prefix=OPT %s -; RUN: llc -march=amdgcn -mcpu=gfx1010 -verify-machineinstrs < %s | FileCheck -check-prefix=LLC %s +; RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1010 -verify-machineinstrs < %s | FileCheck -check-prefix=LLC %s ; OPT: declare void @foo4() local_unnamed_addr #0 ; OPT: define void @foo3() local_unnamed_addr #1 diff --git a/llvm/test/CodeGen/Hexagon/pic-jt-big.ll b/llvm/test/CodeGen/Hexagon/pic-jt-big.ll index f5b4c2df52c8..25ee04521b64 100644 --- a/llvm/test/CodeGen/Hexagon/pic-jt-big.ll +++ b/llvm/test/CodeGen/Hexagon/pic-jt-big.ll @@ -1,4 +1,4 @@ -; RUN: llc -march=hexagon -relocation-model=pic < %s | FileCheck %s +; RUN: llc -mtriple=hexagon-unknown-elf -relocation-model=pic < %s | FileCheck %s ; CHECK: r{{[0-9]+}} = add({{pc|PC}},##.LJTI{{[0-9_]+}}@PCREL) ; CHECK: r{{[0-9]+}} = memw(r{{[0-9]}}+##g0@GOT diff --git a/llvm/test/CodeGen/Hexagon/pic-sdata.ll b/llvm/test/CodeGen/Hexagon/pic-sdata.ll index 3e4dc2dc93e9..446734b9ca01 100644 --- a/llvm/test/CodeGen/Hexagon/pic-sdata.ll +++ b/llvm/test/CodeGen/Hexagon/pic-sdata.ll @@ -1,5 +1,5 @@ -; RUN: llc -march=hexagon -hexagon-small-data-threshold=8 -relocation-model=static < %s | FileCheck --check-prefixes=CHECK,STATIC %s -; RUN: llc -march=hexagon -hexagon-small-data-threshold=8 -relocation-model=pic < %s | FileCheck --check-prefixes=CHECK,PIC %s +; RUN: llc -mtriple=hexagon-unknown-elf -hexagon-small-data-threshold=8 -relocation-model=static < %s | FileCheck --check-prefixes=CHECK,STATIC %s +; RUN: llc -mtriple=hexagon-unknown-elf -hexagon-small-data-threshold=8 -relocation-model=pic < %s | FileCheck --check-prefixes=CHECK,PIC %s ; If a global has a specified section, it should probably be placed in that ; section, but with PIC any accesses to globals in small data should still diff --git a/llvm/test/CodeGen/SPARC/tls.ll b/llvm/test/CodeGen/SPARC/tls.ll index 1b1af2e99c38..843769df8d93 100644 --- a/llvm/test/CodeGen/SPARC/tls.ll +++ b/llvm/test/CodeGen/SPARC/tls.ll @@ -1,12 +1,12 @@ -; RUN: llc <%s -march=sparc -relocation-model=static | FileCheck %s --check-prefix=v8abs -; RUN: llc <%s -march=sparcv9 -relocation-model=static | FileCheck %s --check-prefix=v9abs -; RUN: llc <%s -march=sparc -relocation-model=pic | FileCheck %s --check-prefix=pic -; RUN: llc <%s -march=sparcv9 -relocation-model=pic | FileCheck %s --check-prefix=pic - -; RUN: llc <%s -march=sparc -relocation-model=static -filetype=obj | llvm-readobj -r --symbols | FileCheck %s --check-prefix=v8abs-obj -; RUN: llc <%s -march=sparcv9 -relocation-model=static -filetype=obj | llvm-readobj -r --symbols | FileCheck %s --check-prefix=v9abs-obj -; RUN: llc <%s -march=sparc -relocation-model=pic -filetype=obj | llvm-readobj -r --symbols | FileCheck %s --check-prefix=pic-obj -; RUN: llc <%s -march=sparcv9 -relocation-model=pic -filetype=obj | llvm-readobj -r --symbols | FileCheck %s --check-prefix=pic-obj +; RUN: llc <%s -mtriple=sparc-unknown-linux -relocation-model=static | FileCheck %s --check-prefix=v8abs +; RUN: llc <%s -mtriple=sparcv9-unknown-linux -relocation-model=static | FileCheck %s --check-prefix=v9abs +; RUN: llc <%s -mtriple=sparc-unknown-linux -relocation-model=pic | FileCheck %s --check-prefix=pic +; RUN: llc <%s -mtriple=sparcv9-unknown-linux -relocation-model=pic | FileCheck %s --check-prefix=pic + +; RUN: llc <%s -mtriple=sparc-unknown-linux -relocation-model=static -filetype=obj | llvm-readobj -r --symbols | FileCheck %s --check-prefix=v8abs-obj +; RUN: llc <%s -mtriple=sparcv9-unknown-linux -relocation-model=static -filetype=obj | llvm-readobj -r --symbols | FileCheck %s --check-prefix=v9abs-obj +; RUN: llc <%s -mtriple=sparc-unknown-linux -relocation-model=pic -filetype=obj | llvm-readobj -r --symbols | FileCheck %s --check-prefix=pic-obj +; RUN: llc <%s -mtriple=sparcv9-unknown-linux -relocation-model=pic -filetype=obj | llvm-readobj -r --symbols | FileCheck %s --check-prefix=pic-obj @local_symbol = internal thread_local global i32 0 @extern_symbol = external thread_local global i32 diff --git a/llvm/test/CodeGen/X86/mingw-refptr.ll b/llvm/test/CodeGen/X86/mingw-refptr.ll index 158462dd2831..8d5712b2a7ed 100644 --- a/llvm/test/CodeGen/X86/mingw-refptr.ll +++ b/llvm/test/CodeGen/X86/mingw-refptr.ll @@ -1,5 +1,6 @@ ; RUN: llc < %s -mtriple=x86_64-w64-mingw32 | FileCheck %s -check-prefix=CHECK-X64 ; RUN: llc < %s -mtriple=i686-w64-mingw32 | FileCheck %s -check-prefix=CHECK-X86 +; RUN: llc < %s -mtriple=i686-w64-mingw32-none-elf | FileCheck %s -check-prefix=CHECK-X86-ELF @var = external local_unnamed_addr global i32, align 4 @dsolocalvar = external dso_local local_unnamed_addr global i32, align 4 @@ -16,6 +17,9 @@ define dso_local i32 @getVar() { ; CHECK-X86: movl .refptr._var, %eax ; CHECK-X86: movl (%eax), %eax ; CHECK-X86: retl +; CHECK-X86-ELF-LABEL: getVar: +; CHECK-X86-ELF: movl var, %eax +; CHECK-X86-ELF: retl entry: %0 = load i32, i32* @var, align 4 ret i32 %0 @@ -66,6 +70,9 @@ define dso_local i32 @getExtVar() { ; CHECK-X86: movl __imp__extvar, %eax ; CHECK-X86: movl (%eax), %eax ; CHECK-X86: retl +; CHECK-X86-ELF-LABEL: getExtVar: +; CHECK-X86-ELF: movl extvar, %eax +; CHECK-X86-ELF: retl entry: %0 = load i32, i32* @extvar, align 4 ret i32 %0 From 07507c2e39bc0b28e6fdcf915d3da500b50dd974 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Thu, 22 Aug 2019 15:52:41 +0000 Subject: [PATCH 137/289] Merging r367580: ------------------------------------------------------------------------ r367580 | atanasyan | 2019-08-01 18:04:29 +0200 (Thu, 01 Aug 2019) | 18 lines [mips] Fix lowering load/store instruction in PIC case If an operand of the `lw/sw` instructions is a symbol, these instructions incorrectly lowered using not-position-independent chain of commands. For PIC code we should use `lw/addiu` instructions with the `R_MIPS_GOT16` and `R_MIPS_LO16` relocations respectively. Instead of that LLVM generates position dependent code with the `R_MIPS_HI16` and `R_MIPS_LO16` relocations. This patch provides a fix for the bug by handling PIC case separately in the `MipsAsmParser::expandMemInst`. The main idea is to generate a chain of PIC instructions to load a symbol address into a register and then load the address content. The fix is not optimal and does not fix all PIC-related problems. This is a task for subsequent patches. Differential Revision: https://reviews.llvm.org/D65524 ------------------------------------------------------------------------ llvm-svn: 369663 --- .../Target/Mips/AsmParser/MipsAsmParser.cpp | 19 +++++- llvm/test/MC/Mips/mips-expansions.s | 59 +++++++++++++++++++ llvm/test/MC/Mips/mips64-expansions.s | 53 +++++++++++++++++ 3 files changed, 130 insertions(+), 1 deletion(-) diff --git a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp index 1f7d095bf49b..aee434cb0067 100644 --- a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -3625,8 +3625,25 @@ void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, TOut.emitRRR(isGP64bit() ? Mips::DADDu : Mips::ADDu, TmpReg, TmpReg, BaseReg, IDLoc, STI); TOut.emitRRI(Inst.getOpcode(), DstReg, TmpReg, LoOffset, IDLoc, STI); + return; + } + + assert(OffsetOp.isExpr() && "expected expression operand kind"); + if (inPicMode()) { + // FIXME: + // a) Fix lw/sw $reg, symbol($reg) instruction expanding. + // b) If expression includes offset (sym + number), do not + // encode the offset into a relocation. Take it in account + // in the last load/store instruction. + // c) Check that immediates of R_MIPS_GOT16/R_MIPS_LO16 relocations + // do not exceed 16-bit. + // d) Use R_MIPS_GOT_PAGE/R_MIPS_GOT_OFST relocations instead + // of R_MIPS_GOT_DISP in appropriate cases to reduce number + // of GOT entries. + expandLoadAddress(TmpReg, Mips::NoRegister, OffsetOp, !ABI.ArePtrs64bit(), + IDLoc, Out, STI); + TOut.emitRRI(Inst.getOpcode(), DstReg, TmpReg, 0, IDLoc, STI); } else { - assert(OffsetOp.isExpr() && "expected expression operand kind"); const MCExpr *ExprOffset = OffsetOp.getExpr(); MCOperand LoOperand = MCOperand::createExpr( MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext())); diff --git a/llvm/test/MC/Mips/mips-expansions.s b/llvm/test/MC/Mips/mips-expansions.s index 91a637bfe221..798461c5f99c 100644 --- a/llvm/test/MC/Mips/mips-expansions.s +++ b/llvm/test/MC/Mips/mips-expansions.s @@ -50,6 +50,7 @@ # CHECK-LE: lhu $4, 4($4) # LW/SW and LDC1/SDC1 of symbol address, done by MipsAsmParser::expandMemInst(): +# NON-PIC code .set noat lw $10, symbol($4) # CHECK-LE: lui $10, %hi(symbol) # encoding: [A,A,0x0a,0x3c] @@ -105,6 +106,64 @@ # CHECK-LE: lui $1, %hi(symbol) # CHECK-LE: sdc1 $f0, %lo(symbol)($1) +# PIC code + .option pic2 + .set noat + lw $10, symbol($4) +# CHECK-LE: lw $10, %got(symbol)($gp) # encoding: [A,A,0x8a,0x8f] +# CHECK-LE: # fixup A - offset: 0, value: %got(symbol), kind: fixup_Mips_GOT +# CHECK-LE-FIXME: addu $10, $10, $4 # encoding: [0x21,0x50,0x44,0x01] +# CHECK-LE: lw $10, 0($10) # encoding: [0x00,0x00,0x4a,0x8d] + .set at + sw $10, symbol($9) +# CHECK-LE: lw $1, %got(symbol)($gp) # encoding: [A,A,0x81,0x8f] +# CHECK-LE: # fixup A - offset: 0, value: %got(symbol), kind: fixup_Mips_GOT +# CHECK-LE-FIXME: addu $1, $1, $9 # encoding: [0x21,0x08,0x29,0x00] +# CHECK-LE: sw $10, 0($1) # encoding: [0x00,0x00,0x2a,0xac] + + lw $8, 1f+8 +# CHECK-LE: lw $8, %got(($tmp0)+8)($gp) # encoding: [A,A,0x88,0x8f] +# CHECK-LE: # fixup A - offset: 0, value: %got(($tmp0)+8), kind: fixup_Mips_GOT +# CHECK-LE: addiu $8, $8, %lo(($tmp0)+8) # encoding: [A,A,0x08,0x25] +# CHECK-LE: # fixup A - offset: 0, value: %lo(($tmp0)+8), kind: fixup_Mips_LO16 +# CHECK-LE: lw $8, 0($8) # encoding: [0x00,0x00,0x08,0x8d] + sw $8, 1f+8 +# CHECK-LE: lw $1, %got(($tmp0)+8)($gp) # encoding: [A,A,0x81,0x8f] +# CHECK-LE: # fixup A - offset: 0, value: %got(($tmp0)+8), kind: fixup_Mips_GOT +# CHECK-LE: addiu $1, $1, %lo(($tmp0)+8) # encoding: [A,A,0x21,0x24] +# CHECK-LE: # fixup A - offset: 0, value: %lo(($tmp0)+8), kind: fixup_Mips_LO16 +# CHECK-LE: sw $8, 0($1) # encoding: [0x00,0x00,0x28,0xac] + + lw $10, 655483($4) +# CHECK-LE: lui $10, 10 # encoding: [0x0a,0x00,0x0a,0x3c] +# CHECK-LE: addu $10, $10, $4 # encoding: [0x21,0x50,0x44,0x01] +# CHECK-LE: lw $10, 123($10) # encoding: [0x7b,0x00,0x4a,0x8d] + sw $10, 123456($9) +# CHECK-LE: lui $1, 2 # encoding: [0x02,0x00,0x01,0x3c] +# CHECK-LE: addu $1, $1, $9 # encoding: [0x21,0x08,0x29,0x00] +# CHECK-LE: sw $10, -7616($1) # encoding: [0x40,0xe2,0x2a,0xac] + + lw $8, symbol+8 +# CHECK-LE: lw $8, %got(symbol+8)($gp) # encoding: [A,A,0x88,0x8f] +# CHECK-LE: # fixup A - offset: 0, value: %got(symbol+8), kind: fixup_Mips_GOT +# CHECK-LE: addiu $8, $8, 8 # encoding: [0x08,0x00,0x08,0x25] +# CHECK-LE: lw $8, 0($8) # encoding: [0x00,0x00,0x08,0x8d] + sw $8, symbol+8 +# CHECK-LE: lw $1, %got(symbol+8)($gp) # encoding: [A,A,0x81,0x8f] +# CHECK-LE: # fixup A - offset: 0, value: %got(symbol+8), kind: fixup_Mips_GOT +# CHECK-LE: addiu $1, $1, 8 # encoding: [0x08,0x00,0x21,0x24] +# CHECK-LE: sw $8, 0($1) # encoding: [0x00,0x00,0x28,0xac] + + ldc1 $f0, symbol +# CHECK-LE: lw $1, %got(symbol)($gp) # encoding: [A,A,0x81,0x8f] +# CHECK-LE: # fixup A - offset: 0, value: %got(symbol), kind: fixup_Mips_GOT +# CHECK-LE: ldc1 $f0, 0($1) # encoding: [0x00,0x00,0x20,0xd4] + sdc1 $f0, symbol +# CHECK-LE: lw $1, %got(symbol)($gp) # encoding: [A,A,0x81,0x8f] +# CHECK-LE: # fixup A - offset: 0, value: %got(symbol), kind: fixup_Mips_GOT +# CHECK-LE: sdc1 $f0, 0($1) # encoding: [0x00,0x00,0x20,0xf4] + .option pic0 + # Test BNE with an immediate as the 2nd operand. bne $2, 0, 1332 # CHECK-LE: bnez $2, 1332 # encoding: [0x4d,0x01,0x40,0x14] diff --git a/llvm/test/MC/Mips/mips64-expansions.s b/llvm/test/MC/Mips/mips64-expansions.s index 4f0d3f15773c..4c24379f2dde 100644 --- a/llvm/test/MC/Mips/mips64-expansions.s +++ b/llvm/test/MC/Mips/mips64-expansions.s @@ -466,3 +466,56 @@ sym: # CHECK-NEXT: dsll $4, $4, 16 # CHECK-NEXT: daddu $4, $4, $3 # CHECK-NEXT: lhu $4, -32764($4) + +# LW/SW and LDC1/SDC1 of symbol address, done by MipsAsmParser::expandMemInst(): + .option pic2 + lw $10, symbol($4) +# CHECK: ld $10, %got_disp(symbol)($gp) # encoding: [A,A,0x8a,0xdf] +# CHECK: # fixup A - offset: 0, value: %got_disp(symbol), kind: fixup_Mips_GOT_DISP +# CHECK-FIXME: daddu $10, $10, $4 # encoding: [0x2d,0x50,0x44,0x01] +# CHECK: lw $10, 0($10) # encoding: [0x00,0x00,0x4a,0x8d] + sw $10, symbol($9) +# CHECK: ld $1, %got_disp(symbol)($gp) # encoding: [A,A,0x81,0xdf] +# CHECK: # fixup A - offset: 0, value: %got_disp(symbol), kind: fixup_Mips_GOT_DISP +# CHECK-FIXME: daddu $1, $1, $9 # encoding: [0x2d,0x08,0x29,0x00] +# CHECK: sw $10, 0($1) # encoding: [0x00,0x00,0x2a,0xac] + + lw $8, sym+8 +# CHECK: ld $8, %got_disp(sym)($gp) # encoding: [A,A,0x88,0xdf] +# CHECK: # fixup A - offset: 0, value: %got_disp(sym), kind: fixup_Mips_GOT_DISP +# CHECK: daddiu $8, $8, 8 # encoding: [0x08,0x00,0x08,0x65] +# CHECK: lw $8, 0($8) # encoding: [0x00,0x00,0x08,0x8d] + sw $8, sym+8 +# CHECK: ld $1, %got_disp(sym)($gp) # encoding: [A,A,0x81,0xdf] +# CHECK: # fixup A - offset: 0, value: %got_disp(sym), kind: fixup_Mips_GOT_DISP +# CHECK: daddiu $1, $1, 8 # encoding: [0x08,0x00,0x21,0x64] +# CHECK: sw $8, 0($1) # encoding: [0x00,0x00,0x28,0xac] + + lw $10, 655483($4) +# CHECK: lui $10, 10 # encoding: [0x0a,0x00,0x0a,0x3c] +# CHECK: daddu $10, $10, $4 # encoding: [0x2d,0x50,0x44,0x01] +# CHECK: lw $10, 123($10) # encoding: [0x7b,0x00,0x4a,0x8d] + sw $10, 123456($9) +# CHECK: lui $1, 2 # encoding: [0x02,0x00,0x01,0x3c] +# CHECK: daddu $1, $1, $9 # encoding: [0x2d,0x08,0x29,0x00] +# CHECK: sw $10, -7616($1) # encoding: [0x40,0xe2,0x2a,0xac] + + lw $8, symbol+8 +# CHECK: ld $8, %got_disp(symbol)($gp) # encoding: [A,A,0x88,0xdf] +# CHECK: # fixup A - offset: 0, value: %got_disp(symbol), kind: fixup_Mips_GOT_DISP +# CHECK: daddiu $8, $8, 8 # encoding: [0x08,0x00,0x08,0x65] +# CHECK: lw $8, 0($8) # encoding: [0x00,0x00,0x08,0x8d] + sw $8, symbol+8 +# CHECK: ld $1, %got_disp(symbol)($gp) # encoding: [A,A,0x81,0xdf] +# CHECK: # fixup A - offset: 0, value: %got_disp(symbol), kind: fixup_Mips_GOT_DISP +# CHECK: daddiu $1, $1, 8 # encoding: [0x08,0x00,0x21,0x64] +# CHECK: sw $8, 0($1) # encoding: [0x00,0x00,0x28,0xac] + + ldc1 $f0, symbol +# CHECK: ld $1, %got_disp(symbol)($gp) # encoding: [A,A,0x81,0xdf] +# CHECK: # fixup A - offset: 0, value: %got_disp(symbol), kind: fixup_Mips_GOT_DISP +# CHECK: ldc1 $f0, 0($1) # encoding: [0x00,0x00,0x20,0xd4] + sdc1 $f0, symbol +# CHECK: ld $1, %got_disp(symbol)($gp) # encoding: [A,A,0x81,0xdf] +# CHECK: # fixup A - offset: 0, value: %got_disp(symbol), kind: fixup_Mips_GOT_DISP +# CHECK: sdc1 $f0, 0($1) # encoding: [0x00,0x00,0x20,0xf4] From 6e6e769e9cb2697888a0d7c8e5fc44ee9f105dd5 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Fri, 23 Aug 2019 07:57:37 +0000 Subject: [PATCH 138/289] Merging r369641: ------------------------------------------------------------------------ r369641 | yaxunl | 2019-08-22 13:18:59 +0200 (Thu, 22 Aug 2019) | 4 lines [OpenCL] Fix declaration of enqueue_marker Differential Revision: https://reviews.llvm.org/D66512 ------------------------------------------------------------------------ llvm-svn: 369738 --- clang/lib/Headers/opencl-c.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/Headers/opencl-c.h b/clang/lib/Headers/opencl-c.h index 8741bccec9ad..06c5ab6a72f0 100644 --- a/clang/lib/Headers/opencl-c.h +++ b/clang/lib/Headers/opencl-c.h @@ -15350,7 +15350,7 @@ ndrange_t __ovld ndrange_3D(const size_t[3]); ndrange_t __ovld ndrange_3D(const size_t[3], const size_t[3]); ndrange_t __ovld ndrange_3D(const size_t[3], const size_t[3], const size_t[3]); -int __ovld enqueue_marker(queue_t, uint, const __private clk_event_t*, __private clk_event_t*); +int __ovld enqueue_marker(queue_t, uint, const clk_event_t*, clk_event_t*); void __ovld retain_event(clk_event_t); From ab6d19bd53a3177a83e86cb5693efe5f2a8c7bbb Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Fri, 23 Aug 2019 09:44:42 +0000 Subject: [PATCH 139/289] Merging r368145: ------------------------------------------------------------------------ r368145 | ruiu | 2019-08-07 12:16:21 +0200 (Wed, 07 Aug 2019) | 3 lines Handle /align option. Differential Revision: https://reviews.llvm.org/D65736 ------------------------------------------------------------------------ llvm-svn: 369743 --- lld/COFF/Config.h | 1 + lld/COFF/Driver.cpp | 8 ++++++++ lld/COFF/Writer.cpp | 10 ++++++---- lld/test/COFF/align.s | 45 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 60 insertions(+), 4 deletions(-) create mode 100644 lld/test/COFF/align.s diff --git a/lld/COFF/Config.h b/lld/COFF/Config.h index 1b0e24042710..4b62cd05f4fc 100644 --- a/lld/COFF/Config.h +++ b/lld/COFF/Config.h @@ -189,6 +189,7 @@ struct Configuration { // Used for /thinlto-object-suffix-replace: std::pair thinLTOObjectSuffixReplace; + uint64_t align = 4096; uint64_t imageBase = -1; uint64_t fileAlign = 512; uint64_t stackReserve = 1024 * 1024; diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp index 7214d12bde8a..467eef2326e2 100644 --- a/lld/COFF/Driver.cpp +++ b/lld/COFF/Driver.cpp @@ -36,6 +36,7 @@ #include "llvm/Option/Option.h" #include "llvm/Support/Debug.h" #include "llvm/Support/LEB128.h" +#include "llvm/Support/MathExtras.h" #include "llvm/Support/Path.h" #include "llvm/Support/Process.h" #include "llvm/Support/TarWriter.h" @@ -1421,6 +1422,13 @@ void LinkerDriver::link(ArrayRef argsArr) { for (auto *arg : args.filtered(OPT_section)) parseSection(arg->getValue()); + // Handle /align + if (auto *arg = args.getLastArg(OPT_align)) { + parseNumbers(arg->getValue(), &config->align); + if (!isPowerOf2_64(config->align)) + error("/align: not a power of two: " + StringRef(arg->getValue())); + } + // Handle /aligncomm for (auto *arg : args.filtered(OPT_aligncomm)) parseAligncomm(arg->getValue()); diff --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp index cc75db0f519c..9bc2f092c94c 100644 --- a/lld/COFF/Writer.cpp +++ b/lld/COFF/Writer.cpp @@ -1205,9 +1205,11 @@ void Writer::assignAddresses() { sizeOfHeaders += config->is64() ? sizeof(pe32plus_header) : sizeof(pe32_header); sizeOfHeaders = alignTo(sizeOfHeaders, config->fileAlign); - uint64_t rva = pageSize; // The first page is kept unmapped. fileSize = sizeOfHeaders; + // The first page is kept unmapped. + uint64_t rva = alignTo(sizeOfHeaders, config->align); + for (OutputSection *sec : outputSections) { if (sec == relocSec) addBaserels(); @@ -1237,10 +1239,10 @@ void Writer::assignAddresses() { sec->header.SizeOfRawData = rawSize; if (rawSize != 0) sec->header.PointerToRawData = fileSize; - rva += alignTo(virtualSize, pageSize); + rva += alignTo(virtualSize, config->align); fileSize += alignTo(rawSize, config->fileAlign); } - sizeOfImage = alignTo(rva, pageSize); + sizeOfImage = alignTo(rva, config->align); // Assign addresses to sections in MergeChunks. for (MergeChunk *mc : MergeChunk::instances) @@ -1309,7 +1311,7 @@ template void Writer::writeHeader() { pe->MinorLinkerVersion = 0; pe->ImageBase = config->imageBase; - pe->SectionAlignment = pageSize; + pe->SectionAlignment = config->align; pe->FileAlignment = config->fileAlign; pe->MajorImageVersion = config->majorImageVersion; pe->MinorImageVersion = config->minorImageVersion; diff --git a/lld/test/COFF/align.s b/lld/test/COFF/align.s new file mode 100644 index 000000000000..67ca349e0030 --- /dev/null +++ b/lld/test/COFF/align.s @@ -0,0 +1,45 @@ +# RUN: yaml2obj < %s > %t.obj +# RUN: lld-link /out:%t.exe /entry:main /align:32 %t.obj +# RUN: llvm-readobj --file-headers %t.exe | FileCheck %s + +# CHECK: SectionAlignment: 32 + +--- !COFF +header: + Machine: IMAGE_FILE_MACHINE_AMD64 + Characteristics: [] +sections: + - Name: .text + Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] + Alignment: 4096 + SectionData: 0000000000000000 + Relocations: + - VirtualAddress: 0 + SymbolName: __ImageBase + Type: IMAGE_REL_AMD64_ADDR64 +symbols: + - Name: .text + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 8 + NumberOfRelocations: 1 + NumberOfLinenumbers: 0 + CheckSum: 0 + Number: 0 + - Name: main + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_EXTERNAL + - Name: __ImageBase + Value: 0 + SectionNumber: 0 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_EXTERNAL +... From 884e989454d46fa608a8c07855c68a429b2cd372 Mon Sep 17 00:00:00 2001 From: Alex Denisov <1101.debian@gmail.com> Date: Fri, 23 Aug 2019 10:01:52 +0000 Subject: [PATCH 140/289] Add Mull project to the release notes llvm-svn: 369744 --- llvm/docs/ReleaseNotes.rst | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst index f33af9ac3e68..d99a780b1a15 100644 --- a/llvm/docs/ReleaseNotes.rst +++ b/llvm/docs/ReleaseNotes.rst @@ -209,8 +209,11 @@ Changes to LLDB External Open Source Projects Using LLVM 9 ========================================== -* A project... +Mull - Mutation Testing tool for C and C++ +------------------------------------------ +`Mull `_ is a LLVM-based tool for +mutation testing with a strong focus on C and C++ languages. Additional Information ====================== From 2ae73f11631a5b5d87295a03a23366ac843d6fac Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Fri, 23 Aug 2019 12:56:03 +0000 Subject: [PATCH 141/289] Merging r369445: ------------------------------------------------------------------------ r369445 | mstorsjo | 2019-08-20 23:08:14 +0200 (Tue, 20 Aug 2019) | 9 lines [COFF] Check errorCount before committing the output file This avoids producing an output file if errors appeared late in the linking process (e.g. while fixing relocations, or as in the test, while checking for multiple resources). If an output file is produced, build tools might not retry building it on rebuilds, even if a previous build failed due to the error return code. Differential Revision: https://reviews.llvm.org/D66491 ------------------------------------------------------------------------ llvm-svn: 369752 --- lld/COFF/Writer.cpp | 3 +++ lld/test/COFF/multiple-resource-objs.test | 2 ++ 2 files changed, 5 insertions(+) diff --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp index 9bc2f092c94c..5736281958fa 100644 --- a/lld/COFF/Writer.cpp +++ b/lld/COFF/Writer.cpp @@ -626,6 +626,9 @@ void Writer::run() { writeMapFile(outputSections); + if (errorCount()) + return; + ScopedTimer t2(diskCommitTimer); if (auto e = buffer->commit()) fatal("failed to write the output file: " + toString(std::move(e))); diff --git a/lld/test/COFF/multiple-resource-objs.test b/lld/test/COFF/multiple-resource-objs.test index 4263c64be4d4..be5f9a280657 100644 --- a/lld/test/COFF/multiple-resource-objs.test +++ b/lld/test/COFF/multiple-resource-objs.test @@ -1,7 +1,9 @@ # RUN: llvm-cvtres /out:%t_resource.obj %S/Inputs/resource.res # RUN: llvm-cvtres /out:%t_id.obj %S/Inputs/id.res +# RUN: rm -f %t.exe # RUN: not lld-link /out:%t.exe /dll /noentry %t_id.obj %t_resource.obj 2>&1 | \ # RUN: FileCheck --check-prefix=TWOOBJ %s +# RUN: not test -f %t.exe TWOOBJ: error: {{.*}}_resource.obj: more than one resource obj file not allowed, already got {{.*}}_id.obj From 9f06b98219e478aa7b7dfe5270baff572a36259e Mon Sep 17 00:00:00 2001 From: Nico Weber Date: Fri, 23 Aug 2019 13:04:58 +0000 Subject: [PATCH 142/289] Mention r363078 in the lld release notes. llvm-svn: 369753 --- lld/docs/ReleaseNotes.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lld/docs/ReleaseNotes.rst b/lld/docs/ReleaseNotes.rst index 2d358bf8f246..ea3876f81292 100644 --- a/lld/docs/ReleaseNotes.rst +++ b/lld/docs/ReleaseNotes.rst @@ -51,6 +51,12 @@ COFF Improvements input files define resources with the same type, name, and language. This can be demoted to a warning using ``/force:multipleres``. +* lld-link now rejects more than one resource obj input files, matching + link.exe. Previously, lld-link would silently ignore all but one. + If you hit this: Don't pass resource obj files to the linker, instead pass + res files to the linker directly. Don't put res files in static libraries, + pass them on the command line. + * Having more than two ``/natvis:`` now works correctly; it used to not work for larger binaries before. From d0b88fce0a2175316792359b54d41864be416d16 Mon Sep 17 00:00:00 2001 From: Anastasia Stulova Date: Fri, 23 Aug 2019 13:54:19 +0000 Subject: [PATCH 143/289] [Docs][OpenCL] Release 9.0 notes for OpenCL Differential Revision: https://reviews.llvm.org/D66294 llvm-svn: 369758 --- clang/docs/ReleaseNotes.rst | 93 +++++++++++++++++++++++++++++++++++-- 1 file changed, 90 insertions(+), 3 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 018bc2a3716a..f715abaddcd9 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -46,6 +46,8 @@ sections with improvements to Clang's support for those languages. Major New Features ------------------ +- Experimental support for :ref:`C++ for OpenCL ` has been + added. - ... Improvements to Clang's diagnostics @@ -133,6 +135,14 @@ C11 Feature Support C++ Language Changes in Clang ----------------------------- +- Support for the address space attribute in various C++ features was improved, + refer to :ref:`C++ for OpenCL ` for more details. The following + features deviated from OpenCL: + + (1) Address spaces as method qualifiers are not accepted yet; + + (2) There is no address space deduction. + - ... C++1z Feature Support @@ -152,10 +162,87 @@ Objective-C Language Changes in Clang // clang used to encode this as "^{NSArray=#}" instead of "@". const char *s0 = @encode(MyArray *); -OpenCL C Language Changes in Clang ----------------------------------- +OpenCL Kernel Language Changes in Clang +--------------------------------------- -... +OpenCL C +^^^^^^^^ + +- Enabled use of variadic macro as a Clang extension. + +- Added initial support for implicitly including OpenCL builtin + fuctions using efficient trie lookup generated by TableGen. + A corresponding frontend-only flag ``-fdeclare-opencl-builtins`` + has been added to enable trie during parsing. + +- Refactored header file to be used for common parts between + regular header added using ``-finclude-default-header`` and trie + based declarations added using ``-fdeclare-opencl-builtins``. + +- Improved string formatting diagnostics in printf for vector types. + +- Simplified the internal representation of blocks, including their + generation in IR. Furthermore, indirect calls to block function + has been changed to direct function calls. + +- Added diagnostics for conversions of nested pointers with + different address spaces. + +- Added ``cl_arm_integer_dot_product`` extension. + +- Fixed global samplers in OpenCL v2.0. + +- Improved math builtin functions with parameters of type ``long + long`` for x86. + +.. _openclcpp: + +C++ for OpenCL +^^^^^^^^^^^^^^ + +Experimental support for C++17 features in OpenCL has been added +and backwards compatibility with OpenCL C v2.0 was enabled. +The documentation has been added for supported language features +into :doc:`LanguageExtensions` and :doc:`UsersManual`. + +Implemented features are: + +- Address space behavior is improved in majority of C++ features: + + - Templates parameters and arguments; + + - Reference types; + + - Type deduction; + + - Objects and member functions, including special member + functions; + + - Builtin operators; + + - Method qualifiers now include address space; + + - Address space deduction has been extended for C++ use cases; + + - Improved overload ranking rules; + + - All standard cast operators now prevent converting address + spaces (except for conversions allowed implicitly). They + can still be cast using C-style cast. + +- Vector types as in OpenCL C, including compound vector + initialization. + +- OpenCL-specific types: images, samplers, events, pipes, are + accepted. Note that blocks are not supported yet. + +- OpenCL standard header in Clang can be compiled in C++ mode. + +- Global constructors can be invoked from the host side using + a specific, compiler-generated kernel. + +- Overloads with generic address space are added to all atomic + builtin functions, including the ones prior to OpenCL v2.0. ABI Changes in Clang -------------------- From c95063dc4a64a2e5e0e1873b53439e5e87719ed0 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Mon, 26 Aug 2019 07:56:27 +0000 Subject: [PATCH 144/289] Merging r369349: ------------------------------------------------------------------------ r369349 | ibiryukov | 2019-08-20 10:54:30 +0200 (Tue, 20 Aug 2019) | 36 lines [clangd] Skip function bodies inside processed files while indexing Summary: This significantly improves performance of background indexing. We do not collect references and declarations inside the processed files, so this does not affect the final indexing results. The idea is borrowed from libclang, which has a similar optimization in its indexing functionality. Measurements show a nice decrease in indexing time, up to ~40% for building the whole index. These are not proper benchmarks, so one should not rely on these results too much. 1. Rebuilding the whole index for LLVM: - Before. Total time: 14m58s. ./bin/clangd -pch-storage=memory < ./clangd.input 23917.67s user 515.86s system 2718% cpu 14:58.68 total - After. Total time: 8m41s. ./bin/clangd -pch-storage=memory < ./clangd.input 13627.29s user 288.10s system 2672% cpu 8:40.67 total 2. Rebuilding index after removing shards matching '*clangd*' (case-insensitively): - Before. Total time: 30s. ./bin/clangd -pch-storage=memory < ./clangd.input 130.94s user 6.82s system 452% cpu 30.423 total - After. Total time: 26s. ./bin/clangd -pch-storage=memory < ./clangd.input 80.51s user 5.40s system 333% cpu 25.777 total Reviewers: kadircet, sammccall Reviewed By: kadircet Subscribers: MaskRay, jkorous, arphaman, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D66226 ------------------------------------------------------------------------ llvm-svn: 369879 --- .../clangd/index/IndexAction.cpp | 50 ++++++++++++++++++- .../clangd/index/SymbolCollector.cpp | 28 +++++------ .../clangd/index/SymbolCollector.h | 5 ++ 3 files changed, 67 insertions(+), 16 deletions(-) diff --git a/clang-tools-extra/clangd/index/IndexAction.cpp b/clang-tools-extra/clangd/index/IndexAction.cpp index 84b69e9cbaf1..a7429484300a 100644 --- a/clang-tools-extra/clangd/index/IndexAction.cpp +++ b/clang-tools-extra/clangd/index/IndexAction.cpp @@ -11,9 +11,17 @@ #include "Logger.h" #include "index/Relation.h" #include "index/SymbolOrigin.h" +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/ASTContext.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Basic/SourceManager.h" #include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/MultiplexConsumer.h" #include "clang/Index/IndexingAction.h" #include "clang/Tooling/Tooling.h" +#include "llvm/ADT/STLExtras.h" +#include +#include #include namespace clang { @@ -113,6 +121,40 @@ struct IncludeGraphCollector : public PPCallbacks { IncludeGraph &IG; }; +/// Returns an ASTConsumer that wraps \p Inner and additionally instructs the +/// parser to skip bodies of functions in the files that should not be +/// processed. +static std::unique_ptr +skipProcessedFunctions(std::unique_ptr Inner, + std::function ShouldIndexFile) { + class SkipProcessedFunctions : public ASTConsumer { + public: + SkipProcessedFunctions(std::function FileFilter) + : ShouldIndexFile(std::move(FileFilter)), Context(nullptr) { + assert(this->ShouldIndexFile); + } + + void Initialize(ASTContext &Context) override { this->Context = &Context; } + bool shouldSkipFunctionBody(Decl *D) override { + assert(Context && "Initialize() was never called."); + auto &SM = Context->getSourceManager(); + auto FID = SM.getFileID(SM.getExpansionLoc(D->getLocation())); + if (!FID.isValid()) + return false; + return !ShouldIndexFile(FID); + } + + private: + std::function ShouldIndexFile; + const ASTContext *Context; + }; + std::vector> Consumers; + Consumers.push_back( + llvm::make_unique(ShouldIndexFile)); + Consumers.push_back(std::move(Inner)); + return llvm::make_unique(std::move(Consumers)); +} + // Wraps the index action and reports index data after each translation unit. class IndexAction : public WrapperFrontendAction { public: @@ -137,7 +179,9 @@ class IndexAction : public WrapperFrontendAction { if (IncludeGraphCallback != nullptr) CI.getPreprocessor().addPPCallbacks( llvm::make_unique(CI.getSourceManager(), IG)); - return WrapperFrontendAction::CreateASTConsumer(CI, InFile); + return skipProcessedFunctions( + WrapperFrontendAction::CreateASTConsumer(CI, InFile), + [this](FileID FID) { return Collector->shouldIndexFile(FID); }); } bool BeginInvocation(CompilerInstance &CI) override { @@ -147,6 +191,10 @@ class IndexAction : public WrapperFrontendAction { // Avoids some analyses too. Set in two places as we're late to the party. CI.getDiagnosticOpts().IgnoreWarnings = true; CI.getDiagnostics().setIgnoreAllWarnings(true); + // Instruct the parser to ask our ASTConsumer if it should skip function + // bodies. The ASTConsumer will take care of skipping only functions inside + // the files that we have already processed. + CI.getFrontendOpts().SkipFunctionBodies = true; return WrapperFrontendAction::BeginInvocation(CI); } diff --git a/clang-tools-extra/clangd/index/SymbolCollector.cpp b/clang-tools-extra/clangd/index/SymbolCollector.cpp index cca8b004ca36..269a2f564e24 100644 --- a/clang-tools-extra/clangd/index/SymbolCollector.cpp +++ b/clang-tools-extra/clangd/index/SymbolCollector.cpp @@ -146,17 +146,6 @@ getTokenRange(SourceLocation TokLoc, const SourceManager &SM, CreatePosition(TokLoc.getLocWithOffset(TokenLength))}; } -bool shouldIndexFile(const SourceManager &SM, FileID FID, - const SymbolCollector::Options &Opts, - llvm::DenseMap *FilesToIndexCache) { - if (!Opts.FileFilter) - return true; - auto I = FilesToIndexCache->try_emplace(FID); - if (I.second) - I.first->second = Opts.FileFilter(SM, FID); - return I.first->second; -} - // Return the symbol location of the token at \p TokLoc. llvm::Optional getTokenLocation(SourceLocation TokLoc, const SourceManager &SM, @@ -409,7 +398,7 @@ bool SymbolCollector::handleMacroOccurence(const IdentifierInfo *Name, S.SymInfo = index::getSymbolInfoForMacro(*MI); std::string FileURI; // FIXME: use the result to filter out symbols. - shouldIndexFile(SM, SM.getFileID(Loc), Opts, &FilesToIndexCache); + shouldIndexFile(SM.getFileID(Loc)); if (auto DeclLoc = getTokenLocation(DefLoc, SM, Opts, PP->getLangOpts(), FileURI)) S.CanonicalDeclaration = *DeclLoc; @@ -539,7 +528,7 @@ void SymbolCollector::finish() { for (const auto &LocAndRole : It.second) { auto FileID = SM.getFileID(LocAndRole.first); // FIXME: use the result to filter out references. - shouldIndexFile(SM, FileID, Opts, &FilesToIndexCache); + shouldIndexFile(FileID); if (auto FileURI = GetURI(FileID)) { auto Range = getTokenRange(LocAndRole.first, SM, ASTCtx->getLangOpts()); @@ -589,7 +578,7 @@ const Symbol *SymbolCollector::addDeclaration(const NamedDecl &ND, SymbolID ID, auto Loc = findNameLoc(&ND); assert(Loc.isValid() && "Invalid source location for NamedDecl"); // FIXME: use the result to filter out symbols. - shouldIndexFile(SM, SM.getFileID(Loc), Opts, &FilesToIndexCache); + shouldIndexFile(SM.getFileID(Loc)); if (auto DeclLoc = getTokenLocation(Loc, SM, Opts, ASTCtx->getLangOpts(), FileURI)) S.CanonicalDeclaration = *DeclLoc; @@ -649,7 +638,7 @@ void SymbolCollector::addDefinition(const NamedDecl &ND, auto Loc = findNameLoc(&ND); const auto &SM = ND.getASTContext().getSourceManager(); // FIXME: use the result to filter out symbols. - shouldIndexFile(SM, SM.getFileID(Loc), Opts, &FilesToIndexCache); + shouldIndexFile(SM.getFileID(Loc)); if (auto DefLoc = getTokenLocation(Loc, SM, Opts, ASTCtx->getLangOpts(), FileURI)) S.Definition = *DefLoc; @@ -741,5 +730,14 @@ bool SymbolCollector::isDontIncludeMeHeader(llvm::StringRef Content) { return false; } +bool SymbolCollector::shouldIndexFile(FileID FID) { + if (!Opts.FileFilter) + return true; + auto I = FilesToIndexCache.try_emplace(FID); + if (I.second) + I.first->second = Opts.FileFilter(ASTCtx->getSourceManager(), FID); + return I.first->second; +} + } // namespace clangd } // namespace clang diff --git a/clang-tools-extra/clangd/index/SymbolCollector.h b/clang-tools-extra/clangd/index/SymbolCollector.h index e97485ec418e..87acf3418677 100644 --- a/clang-tools-extra/clangd/index/SymbolCollector.h +++ b/clang-tools-extra/clangd/index/SymbolCollector.h @@ -112,6 +112,11 @@ class SymbolCollector : public index::IndexDataConsumer { RefSlab takeRefs() { return std::move(Refs).build(); } RelationSlab takeRelations() { return std::move(Relations).build(); } + /// Returns true if we are interested in references and declarations from \p + /// FID. If this function return false, bodies of functions inside those files + /// will be skipped to decrease indexing time. + bool shouldIndexFile(FileID FID); + void finish() override; private: From 565fc9f2e94e71e7012dacf845f8402cf265faef Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Mon, 26 Aug 2019 08:33:44 +0000 Subject: [PATCH 145/289] Merging r366573: ------------------------------------------------------------------------ r366573 | nico | 2019-07-19 15:29:10 +0200 (Fri, 19 Jul 2019) | 6 lines lld-link: Demangle symbols from archives in diagnostics Also add test coverage for thin archives (which are the only way I could come up with to test at least some of the diagnostic changes). Differential Revision: https://reviews.llvm.org/D64927 ------------------------------------------------------------------------ llvm-svn: 369881 --- lld/COFF/Driver.cpp | 15 +++++++-------- lld/COFF/Driver.h | 2 +- lld/COFF/InputFiles.cpp | 9 ++++----- lld/COFF/InputFiles.h | 2 +- lld/COFF/SymbolTable.cpp | 8 ++++---- lld/COFF/SymbolTable.h | 2 +- lld/COFF/Symbols.cpp | 11 +++++++---- lld/COFF/Symbols.h | 1 + lld/test/COFF/thin-archive.s | 8 ++++++-- 9 files changed, 32 insertions(+), 26 deletions(-) diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp index 467eef2326e2..66ed1613192a 100644 --- a/lld/COFF/Driver.cpp +++ b/lld/COFF/Driver.cpp @@ -271,13 +271,12 @@ void LinkerDriver::addArchiveBuffer(MemoryBufferRef mb, StringRef symName, } void LinkerDriver::enqueueArchiveMember(const Archive::Child &c, - StringRef symName, + const Archive::Symbol &sym, StringRef parentName) { - auto reportBufferError = [=](Error &&e, - StringRef childName) { + auto reportBufferError = [=](Error &&e, StringRef childName) { fatal("could not get the buffer for the member defining symbol " + - symName + ": " + parentName + "(" + childName + "): " + + toString(sym) + ": " + parentName + "(" + childName + "): " + toString(std::move(e))); }; @@ -288,7 +287,7 @@ void LinkerDriver::enqueueArchiveMember(const Archive::Child &c, reportBufferError(mbOrErr.takeError(), check(c.getFullName())); MemoryBufferRef mb = mbOrErr.get(); enqueueTask([=]() { - driver->addArchiveBuffer(mb, symName, parentName, offsetInArchive); + driver->addArchiveBuffer(mb, toString(sym), parentName, offsetInArchive); }); return; } @@ -296,15 +295,15 @@ void LinkerDriver::enqueueArchiveMember(const Archive::Child &c, std::string childName = CHECK( c.getFullName(), "could not get the filename for the member defining symbol " + - symName); + toString(sym)); auto future = std::make_shared>( createFutureForFile(childName)); enqueueTask([=]() { auto mbOrErr = future->get(); if (mbOrErr.second) reportBufferError(errorCodeToError(mbOrErr.second), childName); - driver->addArchiveBuffer(takeBuffer(std::move(mbOrErr.first)), symName, - parentName, /* OffsetInArchive */ 0); + driver->addArchiveBuffer(takeBuffer(std::move(mbOrErr.first)), + toString(sym), parentName, /*OffsetInArchive=*/0); }); } diff --git a/lld/COFF/Driver.h b/lld/COFF/Driver.h index 6100c3ca0c9e..01bfb02a5c33 100644 --- a/lld/COFF/Driver.h +++ b/lld/COFF/Driver.h @@ -72,7 +72,7 @@ class LinkerDriver { void parseDirectives(InputFile *file); // Used by ArchiveFile to enqueue members. - void enqueueArchiveMember(const Archive::Child &c, StringRef symName, + void enqueueArchiveMember(const Archive::Child &c, const Archive::Symbol &sym, StringRef parentName); MemoryBufferRef takeBuffer(std::unique_ptr mb); diff --git a/lld/COFF/InputFiles.cpp b/lld/COFF/InputFiles.cpp index c00d5c5b494e..c72fa587a026 100644 --- a/lld/COFF/InputFiles.cpp +++ b/lld/COFF/InputFiles.cpp @@ -85,16 +85,15 @@ void ArchiveFile::parse() { } // Returns a buffer pointing to a member file containing a given symbol. -void ArchiveFile::addMember(const Archive::Symbol *sym) { - const Archive::Child &c = - CHECK(sym->getMember(), - "could not get the member for symbol " + sym->getName()); +void ArchiveFile::addMember(const Archive::Symbol &sym) { + const Archive::Child &c = CHECK( + sym.getMember(), "could not get the member for symbol " + toString(sym)); // Return an empty buffer if we have already returned the same buffer. if (!seen.insert(c.getChildOffset()).second) return; - driver->enqueueArchiveMember(c, sym->getName(), getName()); + driver->enqueueArchiveMember(c, sym, getName()); } std::vector getArchiveMembers(Archive *file) { diff --git a/lld/COFF/InputFiles.h b/lld/COFF/InputFiles.h index dfad9814a397..8d3a021a3789 100644 --- a/lld/COFF/InputFiles.h +++ b/lld/COFF/InputFiles.h @@ -96,7 +96,7 @@ class ArchiveFile : public InputFile { // Enqueues an archive member load for the given symbol. If we've already // enqueued a load for the same archive member, this function does nothing, // which ensures that we don't load the same member more than once. - void addMember(const Archive::Symbol *sym); + void addMember(const Archive::Symbol &sym); private: std::unique_ptr file; diff --git a/lld/COFF/SymbolTable.cpp b/lld/COFF/SymbolTable.cpp index 0aff164ee567..07ebf6ea550f 100644 --- a/lld/COFF/SymbolTable.cpp +++ b/lld/COFF/SymbolTable.cpp @@ -179,7 +179,7 @@ void SymbolTable::loadMinGWAutomaticImports() { log("Loading lazy " + l->getName() + " from " + l->file->getName() + " for automatic import"); l->pendingArchiveLoad = true; - l->file->addMember(&l->sym); + l->file->addMember(l->sym); } } @@ -363,13 +363,13 @@ Symbol *SymbolTable::addUndefined(StringRef name, InputFile *f, if (auto *l = dyn_cast(s)) { if (!s->pendingArchiveLoad) { s->pendingArchiveLoad = true; - l->file->addMember(&l->sym); + l->file->addMember(l->sym); } } return s; } -void SymbolTable::addLazy(ArchiveFile *f, const Archive::Symbol sym) { +void SymbolTable::addLazy(ArchiveFile *f, const Archive::Symbol &sym) { StringRef name = sym.getName(); Symbol *s; bool wasInserted; @@ -382,7 +382,7 @@ void SymbolTable::addLazy(ArchiveFile *f, const Archive::Symbol sym) { if (!u || u->weakAlias || s->pendingArchiveLoad) return; s->pendingArchiveLoad = true; - f->addMember(&sym); + f->addMember(sym); } void SymbolTable::reportDuplicate(Symbol *existing, InputFile *newFile) { diff --git a/lld/COFF/SymbolTable.h b/lld/COFF/SymbolTable.h index 88f47cbe9e78..50e7e9ba1d5c 100644 --- a/lld/COFF/SymbolTable.h +++ b/lld/COFF/SymbolTable.h @@ -83,7 +83,7 @@ class SymbolTable { Symbol *addAbsolute(StringRef n, uint64_t va); Symbol *addUndefined(StringRef name, InputFile *f, bool isWeakAlias); - void addLazy(ArchiveFile *f, const Archive::Symbol sym); + void addLazy(ArchiveFile *f, const Archive::Symbol &sym); Symbol *addAbsolute(StringRef n, COFFSymbolRef s); Symbol *addRegular(InputFile *f, StringRef n, const llvm::object::coff_symbol_generic *s = nullptr, diff --git a/lld/COFF/Symbols.cpp b/lld/COFF/Symbols.cpp index 3583d4cb28c1..c1eb75ff7001 100644 --- a/lld/COFF/Symbols.cpp +++ b/lld/COFF/Symbols.cpp @@ -20,18 +20,21 @@ using namespace llvm::object; using namespace lld::coff; +namespace lld { + static_assert(sizeof(SymbolUnion) <= 48, "symbols should be optimized for memory usage"); // Returns a symbol name for an error message. -std::string lld::toString(coff::Symbol &b) { +static std::string demangle(StringRef symName) { if (config->demangle) - if (Optional s = lld::demangleMSVC(b.getName())) + if (Optional s = demangleMSVC(symName)) return *s; - return b.getName(); + return symName; } +std::string toString(coff::Symbol &b) { return demangle(b.getName()); } +std::string toString(const Archive::Symbol &b) { return demangle(b.getName()); } -namespace lld { namespace coff { StringRef Symbol::getName() { diff --git a/lld/COFF/Symbols.h b/lld/COFF/Symbols.h index 86cd4f585e50..77ae2f157d34 100644 --- a/lld/COFF/Symbols.h +++ b/lld/COFF/Symbols.h @@ -430,6 +430,7 @@ void replaceSymbol(Symbol *s, ArgT &&... arg) { } // namespace coff std::string toString(coff::Symbol &b); +std::string toString(const coff::Archive::Symbol &b); } // namespace lld #endif diff --git a/lld/test/COFF/thin-archive.s b/lld/test/COFF/thin-archive.s index f24911de401a..6eb896c57da6 100644 --- a/lld/test/COFF/thin-archive.s +++ b/lld/test/COFF/thin-archive.s @@ -11,14 +11,18 @@ # RUN: FileCheck --allow-empty %s # RUN: lld-link /entry:main %t.main.obj %t_thin.lib /out:%t.exe 2>&1 | \ # RUN: FileCheck --allow-empty %s -# RUN: lld-link /entry:main %t.main.obj /wholearchive:%t_thin.lib /out:%t.exe 2>&1 | \ -# RUN: FileCheck --allow-empty %s # RUN: rm %t.lib.obj # RUN: lld-link /entry:main %t.main.obj %t.lib /out:%t.exe 2>&1 | \ # RUN: FileCheck --allow-empty %s +# RUN: not lld-link /entry:main %t.main.obj %t_thin.lib /out:%t.exe 2>&1 | \ +# RUN: FileCheck --check-prefix=NOOBJ %s +# RUN: not lld-link /entry:main %t.main.obj %t_thin.lib /out:%t.exe \ +# RUN: /demangle:no 2>&1 | FileCheck --check-prefix=NOOBJNODEMANGLE %s # CHECK-NOT: error: could not get the buffer for the member defining +# NOOBJ: error: could not get the buffer for the member defining symbol int __cdecl f(void): {{.*}}.lib({{.*}}.lib.obj): +# NOOBJNODEMANGLE: error: could not get the buffer for the member defining symbol ?f@@YAHXZ: {{.*}}.lib({{.*}}.lib.obj): .text From c343ded3e4a8c9098ddb3212bd7e01f85e7fb457 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Mon, 26 Aug 2019 08:35:17 +0000 Subject: [PATCH 146/289] Merging r366836: ------------------------------------------------------------------------ r366836 | nico | 2019-07-23 21:00:01 +0200 (Tue, 23 Jul 2019) | 24 lines ld.lld: Demangle symbols from archives in diagnostics This ports r366573 from COFF to ELF. There are now to toString(Archive::Symbol), one doing MSVC demangling in COFF and one doing Itanium demangling in ELF, so rename these two to toCOFFString() and to toELFString() to not get a duplicate symbol. Nothing ever passes a raw Archive::Symbol to CHECK(), so these not being part of the normal toString() machinery seems ok. There are two code paths in the ELF linker that emits this type of diagnostic: 1. The "normal" one in InputFiles.cpp. This is covered by the tweaked test. 2. An additional one that's only used for libcalls if there's at least one bitcode in the link, and if the libcall symbol is lazy, and lazily loaded from an archive (i.e. not from a lazy .o file). (This code path was added in r339301.) Since all libcall names so far are C symbols and never mangled, the change there is not observable and hence not covered by tests. Differential Revision: https://reviews.llvm.org/D65095 ------------------------------------------------------------------------ llvm-svn: 369882 --- lld/COFF/Driver.cpp | 10 +++++--- lld/COFF/InputFiles.cpp | 5 ++-- lld/COFF/Symbols.cpp | 4 ++- lld/COFF/Symbols.h | 10 ++++++-- lld/ELF/InputFiles.cpp | 4 +-- lld/ELF/Symbols.cpp | 29 ++++++++++++++-------- lld/ELF/Symbols.h | 6 ++++- lld/test/ELF/archive-thin-missing-member.s | 14 ++++++----- 8 files changed, 53 insertions(+), 29 deletions(-) diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp index 66ed1613192a..d68760e4b11b 100644 --- a/lld/COFF/Driver.cpp +++ b/lld/COFF/Driver.cpp @@ -276,7 +276,7 @@ void LinkerDriver::enqueueArchiveMember(const Archive::Child &c, auto reportBufferError = [=](Error &&e, StringRef childName) { fatal("could not get the buffer for the member defining symbol " + - toString(sym) + ": " + parentName + "(" + childName + "): " + + toCOFFString(sym) + ": " + parentName + "(" + childName + "): " + toString(std::move(e))); }; @@ -287,7 +287,8 @@ void LinkerDriver::enqueueArchiveMember(const Archive::Child &c, reportBufferError(mbOrErr.takeError(), check(c.getFullName())); MemoryBufferRef mb = mbOrErr.get(); enqueueTask([=]() { - driver->addArchiveBuffer(mb, toString(sym), parentName, offsetInArchive); + driver->addArchiveBuffer(mb, toCOFFString(sym), parentName, + offsetInArchive); }); return; } @@ -295,7 +296,7 @@ void LinkerDriver::enqueueArchiveMember(const Archive::Child &c, std::string childName = CHECK( c.getFullName(), "could not get the filename for the member defining symbol " + - toString(sym)); + toCOFFString(sym)); auto future = std::make_shared>( createFutureForFile(childName)); enqueueTask([=]() { @@ -303,7 +304,8 @@ void LinkerDriver::enqueueArchiveMember(const Archive::Child &c, if (mbOrErr.second) reportBufferError(errorCodeToError(mbOrErr.second), childName); driver->addArchiveBuffer(takeBuffer(std::move(mbOrErr.first)), - toString(sym), parentName, /*OffsetInArchive=*/0); + toCOFFString(sym), parentName, + /*OffsetInArchive=*/0); }); } diff --git a/lld/COFF/InputFiles.cpp b/lld/COFF/InputFiles.cpp index c72fa587a026..d02fedfd178b 100644 --- a/lld/COFF/InputFiles.cpp +++ b/lld/COFF/InputFiles.cpp @@ -86,8 +86,9 @@ void ArchiveFile::parse() { // Returns a buffer pointing to a member file containing a given symbol. void ArchiveFile::addMember(const Archive::Symbol &sym) { - const Archive::Child &c = CHECK( - sym.getMember(), "could not get the member for symbol " + toString(sym)); + const Archive::Child &c = + CHECK(sym.getMember(), + "could not get the member for symbol " + toCOFFString(sym)); // Return an empty buffer if we have already returned the same buffer. if (!seen.insert(c.getChildOffset()).second) diff --git a/lld/COFF/Symbols.cpp b/lld/COFF/Symbols.cpp index c1eb75ff7001..acb3b32203e5 100644 --- a/lld/COFF/Symbols.cpp +++ b/lld/COFF/Symbols.cpp @@ -33,7 +33,9 @@ static std::string demangle(StringRef symName) { return symName; } std::string toString(coff::Symbol &b) { return demangle(b.getName()); } -std::string toString(const Archive::Symbol &b) { return demangle(b.getName()); } +std::string toCOFFString(const Archive::Symbol &b) { + return demangle(b.getName()); +} namespace coff { diff --git a/lld/COFF/Symbols.h b/lld/COFF/Symbols.h index 77ae2f157d34..10d2b8149cd8 100644 --- a/lld/COFF/Symbols.h +++ b/lld/COFF/Symbols.h @@ -21,6 +21,14 @@ #include namespace lld { + +std::string toString(coff::Symbol &b); + +// There are two different ways to convert an Archive::Symbol to a string: +// One for Microsoft name mangling and one for Itanium name mangling. +// Call the functions toCOFFString and toELFString, not just toString. +std::string toCOFFString(const coff::Archive::Symbol &b); + namespace coff { using llvm::object::Archive; @@ -429,8 +437,6 @@ void replaceSymbol(Symbol *s, ArgT &&... arg) { } } // namespace coff -std::string toString(coff::Symbol &b); -std::string toString(const coff::Archive::Symbol &b); } // namespace lld #endif diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 98b88283cf09..f9cbf1569090 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -1144,7 +1144,7 @@ void ArchiveFile::fetch(const Archive::Symbol &sym) { Archive::Child c = CHECK(sym.getMember(), toString(this) + ": could not get the member for symbol " + - sym.getName()); + toELFString(sym)); if (!seen.insert(c.getChildOffset()).second) return; @@ -1153,7 +1153,7 @@ void ArchiveFile::fetch(const Archive::Symbol &sym) { CHECK(c.getMemoryBufferRef(), toString(this) + ": could not get the buffer for the member defining symbol " + - sym.getName()); + toELFString(sym)); if (tar && c.getParent()->isThin()) tar->append(relativeToRoot(CHECK(c.getFullName(), this)), mb.getBuffer()); diff --git a/lld/ELF/Symbols.cpp b/lld/ELF/Symbols.cpp index 62c552e04828..22677303c322 100644 --- a/lld/ELF/Symbols.cpp +++ b/lld/ELF/Symbols.cpp @@ -42,6 +42,20 @@ Defined *ElfSym::relaIpltEnd; Defined *ElfSym::riscvGlobalPointer; Defined *ElfSym::tlsModuleBase; +// Returns a symbol for an error message. +static std::string demangle(StringRef symName) { + if (config->demangle) + if (Optional s = demangleItanium(symName)) + return *s; + return symName; +} +namespace lld { +std::string toString(const Symbol &b) { return demangle(b.getName()); } +std::string toELFString(const Archive::Symbol &b) { + return demangle(b.getName()); +} +} // namespace lld + static uint64_t getSymVA(const Symbol &sym, int64_t &addend) { switch (sym.kind()) { case Symbol::DefinedKind: { @@ -250,12 +264,13 @@ void Symbol::fetch() const { } MemoryBufferRef LazyArchive::getMemberBuffer() { - Archive::Child c = CHECK( - sym.getMember(), "could not get the member for symbol " + sym.getName()); + Archive::Child c = + CHECK(sym.getMember(), + "could not get the member for symbol " + toELFString(sym)); return CHECK(c.getMemoryBufferRef(), "could not get the buffer for the member defining symbol " + - sym.getName()); + toELFString(sym)); } uint8_t Symbol::computeBinding() const { @@ -331,14 +346,6 @@ void elf::maybeWarnUnorderableSymbol(const Symbol *sym) { report(": unable to order discarded symbol: "); } -// Returns a symbol for an error message. -std::string lld::toString(const Symbol &b) { - if (config->demangle) - if (Optional s = demangleItanium(b.getName())) - return *s; - return b.getName(); -} - static uint8_t getMinVisibility(uint8_t va, uint8_t vb) { if (va == STV_DEFAULT) return vb; diff --git a/lld/ELF/Symbols.h b/lld/ELF/Symbols.h index d640495b0e01..9c1eb387c2f4 100644 --- a/lld/ELF/Symbols.h +++ b/lld/ELF/Symbols.h @@ -33,7 +33,11 @@ class Undefined; } // namespace elf std::string toString(const elf::Symbol &); -std::string toString(const elf::InputFile *); + +// There are two different ways to convert an Archive::Symbol to a string: +// One for Microsoft name mangling and one for Itanium name mangling. +// Call the functions toCOFFString and toELFString, not just toString. +std::string toELFString(const elf::Archive::Symbol &); namespace elf { diff --git a/lld/test/ELF/archive-thin-missing-member.s b/lld/test/ELF/archive-thin-missing-member.s index d96fbc45415b..4db1376cfaf2 100644 --- a/lld/test/ELF/archive-thin-missing-member.s +++ b/lld/test/ELF/archive-thin-missing-member.s @@ -8,17 +8,19 @@ # RUN: rm %t.o # Test error when loading symbols from missing thin archive member. -# RUN: not ld.lld %t-no-syms.a -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR1 +# RUN: not ld.lld --entry=_Z1fi %t-no-syms.a -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR1 # ERR1: {{.*}}-no-syms.a: could not get the buffer for a child of the archive: '{{.*}}.o': {{[Nn]}}o such file or directory # Test error when thin archive has symbol table but member is missing. -# RUN: not ld.lld -m elf_amd64_fbsd %t-syms.a -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR2 -# ERR2: {{.*}}-syms.a: could not get the buffer for the member defining symbol _start: '{{.*}}.o': {{[Nn]}}o such file or directory +# RUN: not ld.lld --entry=_Z1fi -m elf_amd64_fbsd %t-syms.a -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR2 +# ERR2: {{.*}}-syms.a: could not get the buffer for the member defining symbol f(int): '{{.*}}.o': {{[Nn]}}o such file or directory +# RUN: not ld.lld --entry=_Z1fi --no-demangle -m elf_amd64_fbsd %t-syms.a -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR2MANGLE +# ERR2MANGLE: {{.*}}-syms.a: could not get the buffer for the member defining symbol _Z1fi: '{{.*}}.o': {{[Nn]}}o such file or directory # Test error when thin archive is linked using --whole-archive but member is missing. -# RUN: not ld.lld --whole-archive %t-syms.a -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR3 +# RUN: not ld.lld --entry=_Z1fi --whole-archive %t-syms.a -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR3 # ERR3: {{.*}}-syms.a: could not get the buffer for a child of the archive: '{{.*}}.o': {{[Nn]}}o such file or directory -.global _start -_start: +.global _Z1fi +_Z1fi: nop From 71d51526fd05347c5ed2d8dd43926d0184bdfa07 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Mon, 26 Aug 2019 08:36:43 +0000 Subject: [PATCH 147/289] Merging r369694: ------------------------------------------------------------------------ r369694 | akhuang | 2019-08-22 21:40:07 +0200 (Thu, 22 Aug 2019) | 1 line [COFF] Add libcall symbols to the link when LTO is being used ------------------------------------------------------------------------ llvm-svn: 369883 --- lld/COFF/Driver.cpp | 15 +++++++++++++++ lld/COFF/SymbolTable.cpp | 12 ++++++++++++ lld/COFF/SymbolTable.h | 1 + lld/COFF/Symbols.cpp | 9 +++++++++ lld/COFF/Symbols.h | 2 ++ lld/test/COFF/Inputs/libcall-archive.ll | 6 ++++++ lld/test/COFF/Inputs/libcall-archive.s | 2 ++ lld/test/COFF/libcall-archive.ll | 22 ++++++++++++++++++++++ 8 files changed, 69 insertions(+) create mode 100644 lld/test/COFF/Inputs/libcall-archive.ll create mode 100644 lld/test/COFF/Inputs/libcall-archive.s create mode 100644 lld/test/COFF/libcall-archive.ll diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp index d68760e4b11b..eb3aff1a8b76 100644 --- a/lld/COFF/Driver.cpp +++ b/lld/COFF/Driver.cpp @@ -1055,6 +1055,12 @@ void LinkerDriver::maybeExportMinGWSymbols(const opt::InputArgList &args) { }); } +static const char *libcallRoutineNames[] = { +#define HANDLE_LIBCALL(code, name) name, +#include "llvm/IR/RuntimeLibcalls.def" +#undef HANDLE_LIBCALL +}; + void LinkerDriver::link(ArrayRef argsArr) { // Needed for LTO. InitializeAllTargetInfos(); @@ -1757,6 +1763,15 @@ void LinkerDriver::link(ArrayRef argsArr) { u->weakAlias = symtab->addUndefined(to); } + // If any inputs are bitcode files, the LTO code generator may create + // references to library functions that are not explicit in the bitcode + // file's symbol table. If any of those library functions are defined in a + // bitcode file in an archive member, we need to arrange to use LTO to + // compile those archive members by adding them to the link beforehand. + if (!BitcodeFile::instances.empty()) + for (const char *s : libcallRoutineNames) + symtab->addLibcall(s); + // Windows specific -- if __load_config_used can be resolved, resolve it. if (symtab->findUnderscore("_load_config_used")) addUndefined(mangle("_load_config_used")); diff --git a/lld/COFF/SymbolTable.cpp b/lld/COFF/SymbolTable.cpp index 07ebf6ea550f..3f3e6607479c 100644 --- a/lld/COFF/SymbolTable.cpp +++ b/lld/COFF/SymbolTable.cpp @@ -505,6 +505,18 @@ Symbol *SymbolTable::addImportThunk(StringRef name, DefinedImportData *id, return nullptr; } +void SymbolTable::addLibcall(StringRef name) { + Symbol *sym = findUnderscore(name); + if (!sym) + return; + + if (Lazy *l = dyn_cast(sym)) { + MemoryBufferRef mb = l->getMemberBuffer(); + if (identify_magic(mb.getBuffer()) == llvm::file_magic::bitcode) + addUndefined(sym->getName()); + } +} + std::vector SymbolTable::getChunks() { std::vector res; for (ObjFile *file : ObjFile::instances) { diff --git a/lld/COFF/SymbolTable.h b/lld/COFF/SymbolTable.h index 50e7e9ba1d5c..f0a7aaf35a0e 100644 --- a/lld/COFF/SymbolTable.h +++ b/lld/COFF/SymbolTable.h @@ -97,6 +97,7 @@ class SymbolTable { Symbol *addImportData(StringRef n, ImportFile *f); Symbol *addImportThunk(StringRef name, DefinedImportData *s, uint16_t machine); + void addLibcall(StringRef name); void reportDuplicate(Symbol *existing, InputFile *newFile); diff --git a/lld/COFF/Symbols.cpp b/lld/COFF/Symbols.cpp index acb3b32203e5..1af11820a7e6 100644 --- a/lld/COFF/Symbols.cpp +++ b/lld/COFF/Symbols.cpp @@ -118,5 +118,14 @@ Defined *Undefined::getWeakAlias() { return d; return nullptr; } + +MemoryBufferRef Lazy::getMemberBuffer() { + Archive::Child c = + CHECK(sym.getMember(), + "could not get the member for symbol " + toCOFFString(sym)); + return CHECK(c.getMemoryBufferRef(), + "could not get the buffer for the member defining symbol " + + toCOFFString(sym)); +} } // namespace coff } // namespace lld diff --git a/lld/COFF/Symbols.h b/lld/COFF/Symbols.h index 10d2b8149cd8..78c357aa2a58 100644 --- a/lld/COFF/Symbols.h +++ b/lld/COFF/Symbols.h @@ -265,6 +265,8 @@ class Lazy : public Symbol { static bool classof(const Symbol *s) { return s->kind() == LazyKind; } + MemoryBufferRef getMemberBuffer(); + ArchiveFile *file; private: diff --git a/lld/test/COFF/Inputs/libcall-archive.ll b/lld/test/COFF/Inputs/libcall-archive.ll new file mode 100644 index 000000000000..3f8a24df4c37 --- /dev/null +++ b/lld/test/COFF/Inputs/libcall-archive.ll @@ -0,0 +1,6 @@ +target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32" +target triple = "i686-unknown-windows" + +define void @memcpy() { + ret void +} diff --git a/lld/test/COFF/Inputs/libcall-archive.s b/lld/test/COFF/Inputs/libcall-archive.s new file mode 100644 index 000000000000..487cf2009f85 --- /dev/null +++ b/lld/test/COFF/Inputs/libcall-archive.s @@ -0,0 +1,2 @@ +.globl ___sync_val_compare_and_swap_8 +___sync_val_compare_and_swap_8: diff --git a/lld/test/COFF/libcall-archive.ll b/lld/test/COFF/libcall-archive.ll new file mode 100644 index 000000000000..631503d0dd9a --- /dev/null +++ b/lld/test/COFF/libcall-archive.ll @@ -0,0 +1,22 @@ +; REQUIRES: x86 +; RUN: rm -f %t.a +; RUN: llvm-as -o %t.obj %s +; RUN: llvm-as -o %t2.obj %S/Inputs/libcall-archive.ll +; RUN: llvm-mc -filetype=obj -triple=i686-unknown-windows -o %t3.obj %S/Inputs/libcall-archive.s +; RUN: llvm-ar rcs %t.a %t2.obj %t3.obj +; RUN: lld-link -out:%t.exe -subsystem:console -entry:start -safeseh:no -lldmap:- %t.obj %t.a | FileCheck %s + +; CHECK-NOT: ___sync_val_compare_and_swap_8 +; CHECK: _start +; CHECK: _memcpy + +target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32" +target triple = "i686-unknown-windows" + +define void @start(i8* %a, i8* %b) { +entry: + call void @llvm.memcpy.p0i8.p0i8.i64(i8* %a, i8* %b, i64 1024, i1 false) + ret void +} + +declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture, i64, i1) From 82fecfdb8819cedb18499d9fa76ae313b21e1495 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Mon, 26 Aug 2019 11:49:09 +0000 Subject: [PATCH 148/289] Release notes: -ftime-trace By Aras Pranckevicius! llvm-svn: 369895 --- clang/docs/ReleaseNotes.rst | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index f715abaddcd9..f57680993dda 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -70,7 +70,12 @@ Non-comprehensive list of changes in this release New Compiler Flags ------------------ -- ... +- ``-ftime-trace`` and ``ftime-trace-granularity=N`` + Emits flame chart style compilation time report in chrome://tracing and + speedscope.app compatible format. A trace .json file is written next to the + compiled object file, containing hierarchical time information about frontend + activities (file parsing, template instantiation) and backend activities + (modules and functions being optimized, optimization passes). Deprecated Compiler Flags ------------------------- From 9d3cb76114f3bd8e7096021ee8b6d41b563288e9 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Mon, 26 Aug 2019 11:58:46 +0000 Subject: [PATCH 149/289] ReleaseNotes: __declspec(allocator) By Amy Huang! llvm-svn: 369896 --- clang/docs/ReleaseNotes.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index f57680993dda..646844355c75 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -109,6 +109,9 @@ Windows Support ``clang-cl /diagnostic:caret /c test.cc`` for example now produces ``clang: error: no such file or directory: '/diagnostic:caret'; did you mean '/diagnostics:caret'?`` +- clang now parses the ``__declspec(allocator)`` specifier and generates debug + information, so that memory usage can be tracked in Visual Studio. + - The ``-print-search-dirs`` option now separates elements with semicolons, as is the norm for path lists on Windows From a3a8bf9beb52348f5286663c772d51ae8fb39357 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Mon, 26 Aug 2019 12:15:54 +0000 Subject: [PATCH 150/289] Merge r369708 - [Sanitizer] checks ASLR on FreeBSD llvm-svn: 369897 --- compiler-rt/lib/asan/asan_rtl.cc | 2 +- compiler-rt/lib/msan/msan.cc | 2 +- .../lib/sanitizer_common/sanitizer_linux.cc | 29 +++++++++++++++++++ 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/compiler-rt/lib/asan/asan_rtl.cc b/compiler-rt/lib/asan/asan_rtl.cc index db8dcd0689a5..c502965c1893 100644 --- a/compiler-rt/lib/asan/asan_rtl.cc +++ b/compiler-rt/lib/asan/asan_rtl.cc @@ -402,7 +402,6 @@ static void AsanInitInternal() { asan_init_is_running = true; CacheBinaryName(); - CheckASLR(); // Initialize flags. This must be done early, because most of the // initialization steps look at flags(). @@ -450,6 +449,7 @@ static void AsanInitInternal() { SetLowLevelAllocateCallback(OnLowLevelAllocate); InitializeAsanInterceptors(); + CheckASLR(); // Enable system log ("adb logcat") on Android. // Doing this before interceptors are initialized crashes in: diff --git a/compiler-rt/lib/msan/msan.cc b/compiler-rt/lib/msan/msan.cc index c62e5cd4c518..d83e441e683b 100644 --- a/compiler-rt/lib/msan/msan.cc +++ b/compiler-rt/lib/msan/msan.cc @@ -403,7 +403,6 @@ void __msan_init() { AvoidCVE_2016_2143(); CacheBinaryName(); - CheckASLR(); InitializeFlags(); // Install tool-specific callbacks in sanitizer_common. @@ -412,6 +411,7 @@ void __msan_init() { __sanitizer_set_report_path(common_flags()->log_path); InitializeInterceptors(); + CheckASLR(); InitTlsSize(); InstallDeadlySignalHandlers(MsanOnDeadlySignal); InstallAtExitHandler(); // Needs __cxa_atexit interceptor. diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc index 455fd4c861de..73960fee5be6 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc @@ -2011,6 +2011,35 @@ void CheckASLR() { CHECK_NE(personality(old_personality | ADDR_NO_RANDOMIZE), -1); ReExec(); } +#elif SANITIZER_FREEBSD + int aslr_pie; + uptr len = sizeof(aslr_pie); +#if SANITIZER_WORDSIZE == 64 + if (UNLIKELY(internal_sysctlbyname("kern.elf64.aslr.pie_enable", + &aslr_pie, &len, NULL, 0) == -1)) { + // We're making things less 'dramatic' here since + // the OID is not necessarily guaranteed to be here + // just yet regarding FreeBSD release + return; + } + + if (aslr_pie > 0) { + Printf("This sanitizer is not compatible with enabled ASLR " + "and binaries compiled with PIE\n"); + Die(); + } +#endif + // there might be 32 bits compat for 64 bits + if (UNLIKELY(internal_sysctlbyname("kern.elf32.aslr.pie_enable", + &aslr_pie, &len, NULL, 0) == -1)) { + return; + } + + if (aslr_pie > 0) { + Printf("This sanitizer is not compatible with enabled ASLR " + "and binaries compiled with PIE\n"); + Die(); + } #else // Do nothing #endif From 35c6deb00444d91a4a7b9ec2fc89242c4a097bb0 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Mon, 26 Aug 2019 12:21:33 +0000 Subject: [PATCH 151/289] Merging r369364: ------------------------------------------------------------------------ r369364 | miyuki | 2019-08-20 12:19:55 +0200 (Tue, 20 Aug 2019) | 6 lines [libcxx] Fix build breakage on mips Fixes https://bugs.llvm.org/show_bug.cgi?id=43011 caused by https://reviews.llvm.org/D63284. Committing as obvious. ------------------------------------------------------------------------ llvm-svn: 369898 --- libcxx/include/__locale | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcxx/include/__locale b/libcxx/include/__locale index d382e4d8a94b..2b6982fc6810 100644 --- a/libcxx/include/__locale +++ b/libcxx/include/__locale @@ -409,7 +409,7 @@ public: static const mask xdigit = _ISxdigit; static const mask blank = _ISblank; #if defined(__mips__) - static const mask __regex_word = static_cast(_ISbit(15)); + static const mask __regex_word = static_cast(_ISbit(15)); #else static const mask __regex_word = 0x80; #endif From 588351435cb310327bdceae70e5acdce481644b8 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Mon, 26 Aug 2019 12:31:37 +0000 Subject: [PATCH 152/289] Merging r366447: ------------------------------------------------------------------------ r366447 | jdevlieghere | 2019-07-18 17:17:42 +0200 (Thu, 18 Jul 2019) | 19 lines [CMake] Don't set Python_ADDITIONAL_VERSIONS Until recently, Python_ADDITIONAL_VERSIONS was used to limit LLVM's Python support to 2.7. Now that both LLVM and LLDB both support Python 3, there's no longer a need to put an arbitrary limit on this. However, instead of removing the variable, r365692 expanded the list, which has the (presumably unintentional) side-effect of expression preference for Python 3. Instead, as Michal proposed in the original code review, we should just not set the list at all, and let CMake pick whatever Python interpreter you have in your path. This patch removes the Python_ADDITIONAL_VERSIONS variable in llvm, clang and lld. I've also updated the docs with the default behavior and how to force a different Python version to be used. Differential revision: https://reviews.llvm.org/D64894 ------------------------------------------------------------------------ llvm-svn: 369899 --- llvm/CMakeLists.txt | 2 -- llvm/docs/GettingStarted.rst | 5 +++++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/llvm/CMakeLists.txt b/llvm/CMakeLists.txt index 7daabb428fc7..15f1311ec3a6 100644 --- a/llvm/CMakeLists.txt +++ b/llvm/CMakeLists.txt @@ -642,8 +642,6 @@ option(LLVM_ENABLE_PLUGINS "Enable plugin support" ${LLVM_ENABLE_PLUGINS_default include(HandleLLVMOptions) -# We support both Python 2 and 3. -set(Python_ADDITIONAL_VERSIONS 3.7 3.6 3.5 2.7) include(FindPythonInterp) if( NOT PYTHONINTERP_FOUND ) message(FATAL_ERROR diff --git a/llvm/docs/GettingStarted.rst b/llvm/docs/GettingStarted.rst index 742c7b96bc89..5f95095c7191 100644 --- a/llvm/docs/GettingStarted.rst +++ b/llvm/docs/GettingStarted.rst @@ -598,6 +598,11 @@ used by people developing LLVM. | CMAKE_INSTALL_PREFIX | Specifies the install directory to target when | | | running the install action of the build files. | +-------------------------+----------------------------------------------------+ +| PYTHON_EXECUTABLE | Forces CMake to use a specific Python version by | +| | passing a path to a Python interpreter. By default | +| | the Python version of the interpreter in your PATH | +| | is used. | ++-------------------------+----------------------------------------------------+ | LLVM_TARGETS_TO_BUILD | A semicolon delimited list controlling which | | | targets will be built and linked into llvm. | | | The default list is defined as | From cfcc2fea3c82d1890a5cc97cf31cb5a4d1536750 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Mon, 26 Aug 2019 12:31:59 +0000 Subject: [PATCH 153/289] Merging r366447: ------------------------------------------------------------------------ r366447 | jdevlieghere | 2019-07-18 17:17:42 +0200 (Thu, 18 Jul 2019) | 19 lines [CMake] Don't set Python_ADDITIONAL_VERSIONS Until recently, Python_ADDITIONAL_VERSIONS was used to limit LLVM's Python support to 2.7. Now that both LLVM and LLDB both support Python 3, there's no longer a need to put an arbitrary limit on this. However, instead of removing the variable, r365692 expanded the list, which has the (presumably unintentional) side-effect of expression preference for Python 3. Instead, as Michal proposed in the original code review, we should just not set the list at all, and let CMake pick whatever Python interpreter you have in your path. This patch removes the Python_ADDITIONAL_VERSIONS variable in llvm, clang and lld. I've also updated the docs with the default behavior and how to force a different Python version to be used. Differential revision: https://reviews.llvm.org/D64894 ------------------------------------------------------------------------ llvm-svn: 369900 --- clang/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/clang/CMakeLists.txt b/clang/CMakeLists.txt index 6cf28d8cbbb4..60937aa9db38 100644 --- a/clang/CMakeLists.txt +++ b/clang/CMakeLists.txt @@ -129,7 +129,6 @@ if( CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR ) set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib${LLVM_LIBDIR_SUFFIX} ) if(LLVM_INCLUDE_TESTS) - set(Python_ADDITIONAL_VERSIONS 2.7) include(FindPythonInterp) if(NOT PYTHONINTERP_FOUND) message(FATAL_ERROR From 6d070f2350849c0a0744076f165043f20c4115ee Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Mon, 26 Aug 2019 12:32:18 +0000 Subject: [PATCH 154/289] Merging r366447: ------------------------------------------------------------------------ r366447 | jdevlieghere | 2019-07-18 17:17:42 +0200 (Thu, 18 Jul 2019) | 19 lines [CMake] Don't set Python_ADDITIONAL_VERSIONS Until recently, Python_ADDITIONAL_VERSIONS was used to limit LLVM's Python support to 2.7. Now that both LLVM and LLDB both support Python 3, there's no longer a need to put an arbitrary limit on this. However, instead of removing the variable, r365692 expanded the list, which has the (presumably unintentional) side-effect of expression preference for Python 3. Instead, as Michal proposed in the original code review, we should just not set the list at all, and let CMake pick whatever Python interpreter you have in your path. This patch removes the Python_ADDITIONAL_VERSIONS variable in llvm, clang and lld. I've also updated the docs with the default behavior and how to force a different Python version to be used. Differential revision: https://reviews.llvm.org/D64894 ------------------------------------------------------------------------ llvm-svn: 369901 --- lld/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/lld/CMakeLists.txt b/lld/CMakeLists.txt index e2fbdbfbbb47..641f71c114ae 100644 --- a/lld/CMakeLists.txt +++ b/lld/CMakeLists.txt @@ -56,7 +56,6 @@ if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) include(HandleLLVMOptions) if(LLVM_INCLUDE_TESTS) - set(Python_ADDITIONAL_VERSIONS 2.7) include(FindPythonInterp) if(NOT PYTHONINTERP_FOUND) message(FATAL_ERROR From 23c8505c9c648c2a08923426fe0ac98c3d5957d1 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Mon, 26 Aug 2019 12:32:35 +0000 Subject: [PATCH 155/289] Merging r366447: ------------------------------------------------------------------------ r366447 | jdevlieghere | 2019-07-18 17:17:42 +0200 (Thu, 18 Jul 2019) | 19 lines [CMake] Don't set Python_ADDITIONAL_VERSIONS Until recently, Python_ADDITIONAL_VERSIONS was used to limit LLVM's Python support to 2.7. Now that both LLVM and LLDB both support Python 3, there's no longer a need to put an arbitrary limit on this. However, instead of removing the variable, r365692 expanded the list, which has the (presumably unintentional) side-effect of expression preference for Python 3. Instead, as Michal proposed in the original code review, we should just not set the list at all, and let CMake pick whatever Python interpreter you have in your path. This patch removes the Python_ADDITIONAL_VERSIONS variable in llvm, clang and lld. I've also updated the docs with the default behavior and how to force a different Python version to be used. Differential revision: https://reviews.llvm.org/D64894 ------------------------------------------------------------------------ llvm-svn: 369902 --- compiler-rt/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/compiler-rt/CMakeLists.txt b/compiler-rt/CMakeLists.txt index ae4ed3857dbb..f26ae25ada30 100644 --- a/compiler-rt/CMakeLists.txt +++ b/compiler-rt/CMakeLists.txt @@ -80,7 +80,6 @@ if (COMPILER_RT_STANDALONE_BUILD) endif() # Find Python interpreter. - set(Python_ADDITIONAL_VERSIONS 2.7 2.6 2.5) include(FindPythonInterp) if(NOT PYTHONINTERP_FOUND) message(FATAL_ERROR " From 094e9b462f1c58a3e160e1ca7acaf17f041cb0c3 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Mon, 26 Aug 2019 12:36:40 +0000 Subject: [PATCH 156/289] Merging r367115, r367125, r367127, and r367153. ------------------------------------------------------------------------ r367115 | jdevlieghere | 2019-07-26 16:26:33 +0200 (Fri, 26 Jul 2019) | 6 lines [CMake] Loosen Python version check and ignore patch version Some versions of macOS report a different patch version for the system provided interpreter and libraries. Differential revision: https://reviews.llvm.org/D65230 ------------------------------------------------------------------------ ------------------------------------------------------------------------ r367125 | jdevlieghere | 2019-07-26 18:15:19 +0200 (Fri, 26 Jul 2019) | 3 lines [CMake] Print Python version on Windows Trying to figure out what's causing the Windows bot to fail. ------------------------------------------------------------------------ ------------------------------------------------------------------------ r367127 | jdevlieghere | 2019-07-26 18:32:49 +0200 (Fri, 26 Jul 2019) | 4 lines [CMake] Fix find_python_libs_windows Exporting PYTHON_INCLUDE_DIR to the Python scope somehow got lost in my last change. Add it back again. This should fix the Windows bot! ------------------------------------------------------------------------ ------------------------------------------------------------------------ r367153 | jdevlieghere | 2019-07-26 22:58:10 +0200 (Fri, 26 Jul 2019) | 5 lines [CMake] Print the correct variables This didn't get updated after we decided to set PYTHON_MAJOR_VERSION and PYTHON_MINOR_VERSION in find_python_libs_windows, instead of parsing the variables ourselves. ------------------------------------------------------------------------ llvm-svn: 369903 --- lldb/cmake/modules/LLDBConfig.cmake | 47 +++++++++++++++++++++++------ 1 file changed, 37 insertions(+), 10 deletions(-) diff --git a/lldb/cmake/modules/LLDBConfig.cmake b/lldb/cmake/modules/LLDBConfig.cmake index b9b1ccec2c67..0dca557601f3 100644 --- a/lldb/cmake/modules/LLDBConfig.cmake +++ b/lldb/cmake/modules/LLDBConfig.cmake @@ -140,7 +140,6 @@ function(find_python_libs_windows) PYTHONLIBS_VERSION_STRING "${python_version_str}") message(STATUS "Found Python library version ${PYTHONLIBS_VERSION_STRING}") string(REGEX REPLACE "([0-9]+)[.]([0-9]+)[.][0-9]+" "python\\1\\2" PYTHONLIBS_BASE_NAME "${PYTHONLIBS_VERSION_STRING}") - set(PYTHONLIBS_VERSION_STRING "${PYTHONLIBS_VERSION_STRING}" PARENT_SCOPE) unset(python_version_str) else() message(WARNING "Unable to find ${PYTHON_INCLUDE_DIR}/patchlevel.h, Python installation is corrupt.") @@ -175,13 +174,32 @@ function(find_python_libs_windows) return() endif() - set (PYTHON_EXECUTABLE ${PYTHON_EXE} PARENT_SCOPE) - set (PYTHON_LIBRARY ${PYTHON_LIB} PARENT_SCOPE) - set (PYTHON_DLL ${PYTHON_DLL} PARENT_SCOPE) - set (PYTHON_INCLUDE_DIR ${PYTHON_INCLUDE_DIR} PARENT_SCOPE) + # Find the version of the Python interpreter. + execute_process(COMMAND "${PYTHON_EXE}" -c + "import sys; sys.stdout.write(';'.join([str(x) for x in sys.version_info[:3]]))" + OUTPUT_VARIABLE PYTHON_VERSION_OUTPUT + RESULT_VARIABLE PYTHON_VERSION_RESULT + ERROR_QUIET) + if(NOT PYTHON_VERSION_RESULT) + string(REPLACE ";" "." PYTHON_VERSION_STRING "${PYTHON_VERSION_OUTPUT}") + list(GET PYTHON_VERSION_OUTPUT 0 PYTHON_VERSION_MAJOR) + list(GET PYTHON_VERSION_OUTPUT 1 PYTHON_VERSION_MINOR) + list(GET PYTHON_VERSION_OUTPUT 2 PYTHON_VERSION_PATCH) + endif() - message(STATUS "LLDB Found PythonExecutable: ${PYTHON_EXE}") - message(STATUS "LLDB Found PythonLibs: ${PYTHON_LIB}") + # Set the same variables as FindPythonInterp and FindPythonLibs. + set(PYTHON_EXECUTABLE ${PYTHON_EXE} PARENT_SCOPE) + set(PYTHON_LIBRARY ${PYTHON_LIB} PARENT_SCOPE) + set(PYTHON_DLL ${PYTHON_DLL} PARENT_SCOPE) + set(PYTHON_INCLUDE_DIR ${PYTHON_INCLUDE_DIR} PARENT_SCOPE) + set(PYTHONLIBS_VERSION_STRING "${PYTHONLIBS_VERSION_STRING}" PARENT_SCOPE) + set(PYTHON_VERSION_STRING ${PYTHON_VERSION_STRING} PARENT_SCOPE) + set(PYTHON_VERSION_MAJOR ${PYTHON_VERSION_MAJOR} PARENT_SCOPE) + set(PYTHON_VERSION_MINOR ${PYTHON_VERSION_MINOR} PARENT_SCOPE) + set(PYTHON_VERSION_PATCH ${PYTHON_VERSION_PATCH} PARENT_SCOPE) + + message(STATUS "LLDB Found PythonExecutable: ${PYTHON_EXECUTABLE} (${PYTHON_VERSION_STRING})") + message(STATUS "LLDB Found PythonLibs: ${PYTHON_LIB} (${PYTHONLIBS_VERSION_STRING})") message(STATUS "LLDB Found PythonDLL: ${PYTHON_DLL}") message(STATUS "LLDB Found PythonIncludeDirs: ${PYTHON_INCLUDE_DIR}") endfunction(find_python_libs_windows) @@ -199,9 +217,18 @@ if (NOT LLDB_DISABLE_PYTHON) find_package(PythonLibs REQUIRED) endif() - if (NOT PYTHON_VERSION_STRING VERSION_EQUAL PYTHONLIBS_VERSION_STRING AND - NOT CMAKE_CROSSCOMPILING) - message(FATAL_ERROR "Found incompatible Python interpreter (${PYTHON_VERSION_STRING}) and Python libraries (${PYTHONLIBS_VERSION_STRING})") + if (NOT CMAKE_CROSSCOMPILING) + string(REPLACE "." ";" pythonlibs_version_list ${PYTHONLIBS_VERSION_STRING}) + list(GET pythonlibs_version_list 0 pythonlibs_major) + list(GET pythonlibs_version_list 1 pythonlibs_minor) + + # Ignore the patch version. Some versions of macOS report a different patch + # version for the system provided interpreter and libraries. + if (NOT PYTHON_VERSION_MAJOR VERSION_EQUAL pythonlibs_major OR + NOT PYTHON_VERSION_MINOR VERSION_EQUAL pythonlibs_minor) + message(FATAL_ERROR "Found incompatible Python interpreter (${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR})" + " and Python libraries (${pythonlibs_major}.${pythonlibs_minor})") + endif() endif() if (PYTHON_INCLUDE_DIR) From eb67eeafead368a96d00f7d27f319eeaa95ab367 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Mon, 26 Aug 2019 14:47:37 +0000 Subject: [PATCH 157/289] ReleaseNotes: ARM and AArch64 From Kristof! llvm-svn: 369912 --- llvm/docs/ReleaseNotes.rst | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst index d99a780b1a15..94621312b74c 100644 --- a/llvm/docs/ReleaseNotes.rst +++ b/llvm/docs/ReleaseNotes.rst @@ -106,10 +106,21 @@ Changes to building LLVM * Building LLVM with Visual Studio now requires version 2017 or later. +Changes to the AArch64 Backend +------------------------------ + +* Assembly-level support was added for: Scalable Vector Extension 2 (SVE2) and + Memory Tagging Extensions (MTE). + Changes to the ARM Backend -------------------------- - During this release ... +* Assembly-level support was added for the Armv8.1-M architecture, including + the M-Profile Vector Extension (MVE). + +* A pipeline model was added for Cortex-M4. This pipeline model is also used to + tune for cores where this gives a benefit too: Cortex-M3, SC300, Cortex-M33 + and Cortex-M35P. Changes to the MIPS Target From af1c50dd7124f5529d8cf2be777b22e315a7290f Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Mon, 26 Aug 2019 15:05:12 +0000 Subject: [PATCH 158/289] Merge 'r369779 - [OpenCL] Renamed value of std flag in C++ mode' llvm-svn: 369913 --- clang/include/clang/Frontend/LangStandards.def | 2 +- clang/test/Driver/unknown-std.cl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/include/clang/Frontend/LangStandards.def b/clang/include/clang/Frontend/LangStandards.def index 72ea23562ebd..fef7d4dd9ab1 100644 --- a/clang/include/clang/Frontend/LangStandards.def +++ b/clang/include/clang/Frontend/LangStandards.def @@ -165,7 +165,7 @@ LANGSTANDARD(opencl12, "cl1.2", LANGSTANDARD(opencl20, "cl2.0", OpenCL, "OpenCL 2.0", LineComment | C99 | Digraphs | HexFloat | OpenCL) -LANGSTANDARD(openclcpp, "c++", +LANGSTANDARD(openclcpp, "clc++", OpenCL, "C++ for OpenCL", LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | CPlusPlus17 | Digraphs | HexFloat | OpenCL) diff --git a/clang/test/Driver/unknown-std.cl b/clang/test/Driver/unknown-std.cl index 285582ee0af6..6f371bac13ac 100644 --- a/clang/test/Driver/unknown-std.cl +++ b/clang/test/Driver/unknown-std.cl @@ -10,7 +10,7 @@ // CHECK-NEXT: note: use 'cl1.1' for 'OpenCL 1.1' standard // CHECK-NEXT: note: use 'cl1.2' for 'OpenCL 1.2' standard // CHECK-NEXT: note: use 'cl2.0' for 'OpenCL 2.0' standard -// CHECK-NEXT: note: use 'c++' for 'C++ for OpenCL' standard +// CHECK-NEXT: note: use 'clc++' for 'C++ for OpenCL' standard // Make sure that no other output is present. // CHECK-NOT: {{^.+$}} From b2b72eca6623ebb9d70052a8546508c34fccb42c Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Mon, 26 Aug 2019 16:04:59 +0000 Subject: [PATCH 159/289] Merging r369829: ------------------------------------------------------------------------ r369829 | rsmith | 2019-08-24 03:23:57 +0200 (Sat, 24 Aug 2019) | 3 lines PR40674: fix assertion failure if a structured binding declaration has a tuple-like decomposition that produces value-dependent reference bindings. ------------------------------------------------------------------------ llvm-svn: 369921 --- clang/lib/Sema/SemaDeclCXX.cpp | 3 ++- clang/test/CXX/dcl.decl/dcl.decomp/p3.cpp | 8 +++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 15984f89e22d..2f9e4f961f4d 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -1225,7 +1225,8 @@ static bool checkTupleLikeDecomposition(Sema &S, if (E.isInvalid()) return true; RefVD->setInit(E.get()); - RefVD->checkInitIsICE(); + if (!E.get()->isValueDependent()) + RefVD->checkInitIsICE(); E = S.BuildDeclarationNameExpr(CXXScopeSpec(), DeclarationNameInfo(B->getDeclName(), Loc), diff --git a/clang/test/CXX/dcl.decl/dcl.decomp/p3.cpp b/clang/test/CXX/dcl.decl/dcl.decomp/p3.cpp index 9b030c1a2e13..ce5eefc6bfdb 100644 --- a/clang/test/CXX/dcl.decl/dcl.decomp/p3.cpp +++ b/clang/test/CXX/dcl.decl/dcl.decomp/p3.cpp @@ -127,7 +127,7 @@ void referenced_type() { using ConstInt3 = decltype(bcr2); } -struct C { template int get(); }; +struct C { template int get() const; }; template<> struct std::tuple_size { static const int value = 1; }; template<> struct std::tuple_element<0, C> { typedef int type; }; @@ -138,6 +138,12 @@ int member_get() { return c; } +constexpr C c = C(); +template void dependent_binding_PR40674() { + const auto &[c] = *p; + (void)c; +} + struct D { // FIXME: Emit a note here explaining why this was ignored. template struct get {}; From 56003877b708b3eead1ed0099f2ab9378771b746 Mon Sep 17 00:00:00 2001 From: Sam McCall Date: Tue, 27 Aug 2019 07:01:25 +0000 Subject: [PATCH 160/289] [clangd] Release notes for 9.x llvm-svn: 370024 --- clang-tools-extra/docs/ReleaseNotes.rst | 93 ++++++++++++++++++++++++- 1 file changed, 92 insertions(+), 1 deletion(-) diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 0f52c53d443c..465c0aba4bb1 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -47,7 +47,98 @@ Major New Features Improvements to clangd ---------------------- -The improvements are... +- Background indexing is on by default + + When using clangd, it will build an index of your code base (all files listed + in your compile database). This index enables go-to-definition, + find-references, and even code completion to find symbols across your project. + + This feature can consume a lot of CPU. It can be disabled using the + ``--background-index=false`` flag, and respects ``-j`` to use fewer threads. + The index is written to ``.clangd/index`` in the project root. + +- Contextual code actions + + Extract variable, expand ``auto``, expand macro, convert string to raw string. + More to come in the future! + +- Clang-tidy warnings are available + + These will be produced for projects that have a ``.clang-tidy`` file in their + source tree, as described in the :doc:`clang-tidy documentation `. + +- Improved diagnostics + + Errors from headers are now shown (on the #including line). + The message now indicates if fixes are available. + Navigation between errors and associated notes is improved (for editors that + support ``Diagnostic.relatedInformation``). + +- Suggested includes + + When a class or other name is not found, clangd may suggest to fix this by + adding the corresponding ``#include`` directive. + +- Semantic highlighting + + clangd can push syntax information to the editor, allowing it to highlight + e.g. member variables differently from locals. (requires editor support) + + This implements the proposed protocol from + https://github.com/microsoft/vscode-languageserver-node/pull/367 + +- Type hierachy + + Navigation to base/derived types is possible in editors that support the + proposed protocol from + https://github.com/microsoft/vscode-languageserver-node/pull/426 + +- Improvements to include insertion + + Only headers with ``#include``-guards will be inserted, and the feature can + be disabled with the ``--header-insertion=never`` flag. + + Standard library headers should now be inserted more accurately, particularly + for C++ other than libstdc++, and for the C standard library. + +- Code completion + + Overloads are bundled into a single completion item by default. (for editors + that support signature-help). + + Redundant const/non-const overloads are no longer shown. + + Before clangd is warmed up (during preamble build), limited identifier- and + index-based code completion is available. + +- Format-on-type + + A new implementation of format-on-type is triggered by hitting enter: it + attempts to reformat the previous line and reindent the new line. + (Requires editor support). + +- Toolchain header detection + + Projects that use an embedded gcc toolchain may only work when used with the + corresponding standard library. clangd can now query the toolchain to find + these headers. + The compilation database must correctly specify this toolchain, and the + ``--query-driver=/path/to/toolchain/bin/*`` flag must be passed to clangd. + +- Miscellaneous improvements + + Hover now produces richer Markdown-formatted text (for supported editors). + + Rename is safer and more helpful, though is still within one file only. + + Files without extensions (e.g. C++ standard library) are handled better. + + clangd can understand offsets in UTF-8 or UTF-32 through command-line flags or + protocol extensions. (Useful with editors/platforms that don't speak UTF-16). + + Editors that support edits near the cursor in code-completion can set the + ``textDocument.completion.editsNearCursor`` capability to ``true``, and clangd + will provide completions that correct ``.`` to ``->``, and vice-versa. Improvements to clang-doc ------------------------- From 263e040cea404517b6863b078497487ac99e77e4 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Tue, 27 Aug 2019 09:54:32 +0000 Subject: [PATCH 161/289] Merging r369749: ------------------------------------------------------------------------ r369749 | stulova | 2019-08-23 13:43:49 +0200 (Fri, 23 Aug 2019) | 5 lines [Docs][OpenCL] Several corrections to C++ for OpenCL Differential Revision:https://reviews.llvm.org/D64418 ------------------------------------------------------------------------ llvm-svn: 370031 --- clang/docs/LanguageExtensions.rst | 120 ++++++++++++++++-------------- clang/docs/UsersManual.rst | 17 +++-- 2 files changed, 74 insertions(+), 63 deletions(-) diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst index 616dce6c11c8..0fec251c4bdc 100644 --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -1525,8 +1525,8 @@ OpenCL Features C++ for OpenCL -------------- -This functionality is built on top of OpenCL C v2.0 and C++17. Regular C++ -features can be used in OpenCL kernel code. All functionality from OpenCL C +This functionality is built on top of OpenCL C v2.0 and C++17 enabling most of +regular C++ features in OpenCL kernel code. Most functionality from OpenCL C is inherited. This section describes minor differences to OpenCL C and any limitations related to C++ support as well as interactions between OpenCL and C++ features that are not documented elsewhere. @@ -1537,6 +1537,7 @@ Restrictions to C++17 The following features are not supported: - Virtual functions +- Exceptions - ``dynamic_cast`` operator - Non-placement ``new``/``delete`` operators - Standard C++ libraries. Currently there is no solution for alternative C++ @@ -1552,20 +1553,24 @@ Address space behavior Address spaces are part of the type qualifiers; many rules are just inherited from the qualifier behavior documented in OpenCL C v2.0 s6.5 and Embedded C extension ISO/IEC JTC1 SC22 WG14 N1021 s3.1. Note that since the address space -behavior in C++ is not documented formally yet, Clang extends existing concept +behavior in C++ is not documented formally, Clang extends the existing concept from C and OpenCL. For example conversion rules are extended from qualification -conversion but the compatibility is determined using sets and overlapping from -Embedded C (ISO/IEC JTC1 SC22 WG14 N1021 s3.1.3). For OpenCL it means that -implicit conversions are allowed from named to ``__generic`` but not vice versa -(OpenCL C v2.0 s6.5.5) except for ``__constant`` address space. Most of the -rules are built on top of this behavior. +conversion but the compatibility is determined using notation of sets and +overlapping of address spaces from Embedded C (ISO/IEC JTC1 SC22 WG14 N1021 +s3.1.3). For OpenCL it means that implicit conversions are allowed from +a named address space (except for ``__constant``) to ``__generic`` (OpenCL C +v2.0 6.5.5). Reverse conversion is only allowed explicitly. The ``__constant`` +address space does not overlap with any other and therefore no valid conversion +between ``__constant`` and other address spaces exists. Most of the rules +follow this logic. **Casts** -C style cast will follow OpenCL C v2.0 rules (s6.5.5). All cast operators will -permit implicit conversion to ``__generic``. However converting from named -address spaces to ``__generic`` can only be done using ``addrspace_cast``. Note -that conversions between ``__constant`` and any other is still disallowed. +C-style casts follow OpenCL C v2.0 rules (s6.5.5). All cast operators +permit conversion to ``__generic`` implicitly. However converting from +``__generic`` to named address spaces can only be done using ``addrspace_cast``. +Note that conversions between ``__constant`` and any other address space +are disallowed. .. _opencl_cpp_addrsp_deduction: @@ -1578,7 +1583,7 @@ Address spaces are not deduced for: - non-pointer/non-reference class members except for static data members that are deduced to ``__global`` address space. - non-pointer/non-reference alias declarations. -- ``decltype`` expression. +- ``decltype`` expressions. .. code-block:: c++ @@ -1607,7 +1612,7 @@ TODO: Add example for type alias and decltype! **References** -References types can be qualified with an address space. +Reference types can be qualified with an address space. .. code-block:: c++ @@ -1622,29 +1627,29 @@ rules from address space pointer conversion (OpenCL v2.0 s6.5.5). **Default address space** All non-static member functions take an implicit object parameter ``this`` that -is a pointer type. By default this pointer parameter is in ``__generic`` address -space. All concrete objects passed as an argument to ``this`` parameter will be -converted to ``__generic`` address space first if the conversion is valid. -Therefore programs using objects in ``__constant`` address space won't be compiled -unless address space is explicitly specified using address space qualifiers on -member functions +is a pointer type. By default this pointer parameter is in the ``__generic`` +address space. All concrete objects passed as an argument to ``this`` parameter +will be converted to the ``__generic`` address space first if such conversion is +valid. Therefore programs using objects in the ``__constant`` address space will +not be compiled unless the address space is explicitly specified using address +space qualifiers on member functions (see :ref:`Member function qualifier `) as the conversion between ``__constant`` and ``__generic`` is disallowed. Member function -qualifiers can also be used in case conversion to ``__generic`` address space is -undesirable (even if it is legal), for example to take advantage of memory bank -accesses. Note this not only applies to regular member functions but to -constructors and destructors too. +qualifiers can also be used in case conversion to the ``__generic`` address space +is undesirable (even if it is legal). For example, a method can be implemented to +exploit memory access coalescing for segments with memory bank. This not only +applies to regular member functions but to constructors and destructors too. .. _opencl_cpp_addrspace_method_qual: **Member function qualifier** -Clang allows specifying address space qualifier on member functions to signal that -they are to be used with objects constructed in some specific address space. This -works just the same as qualifying member functions with ``const`` or any other -qualifiers. The overloading resolution will select overload with most specific -address space if multiple candidates are provided. If there is no conversion to -to an address space among existing overloads compilation will fail with a +Clang allows specifying an address space qualifier on member functions to signal +that they are to be used with objects constructed in some specific address space. +This works just the same as qualifying member functions with ``const`` or any +other qualifiers. The overloading resolution will select the candidate with the +most specific address space if multiple candidates are provided. If there is no +conversion to an address space among candidates, compilation will fail with a diagnostic. .. code-block:: c++ @@ -1667,7 +1672,7 @@ diagnostic. **Implicit special members** All implicit special members (default, copy, or move constructor, copy or move -assignment, destructor) will be generated with ``__generic`` address space. +assignment, destructor) will be generated with the ``__generic`` address space. .. code-block:: c++ @@ -1682,15 +1687,15 @@ assignment, destructor) will be generated with ``__generic`` address space. **Builtin operators** -All builtin operators are available in the specific address spaces, thus no conversion -to ``__generic`` is performed. +All builtin operators are available in the specific address spaces, thus no +conversion to ``__generic`` is performed. **Templates** -There is no deduction of address spaces in non-pointer/non-reference template parameters -and dependent types (see :ref:`Deduction `). The address -space of template parameter is deduced during the type deduction if it's not explicitly -provided in instantiation. +There is no deduction of address spaces in non-pointer/non-reference template +parameters and dependent types (see :ref:`Deduction `). +The address space of a template parameter is deduced during type deduction if +it is not explicitly provided in the instantiation. .. code-block:: c++ @@ -1701,13 +1706,14 @@ provided in instantiation. 5 6 __global int g; 7 void bar(){ - 8 foo(&g); // error: template instantiation failed as function scope variable appears to - 9 // be declared in __global address space (see line 3) + 8 foo(&g); // error: template instantiation failed as function scope variable + 9 // appears to be declared in __global address space (see line 3) 10 } -It is not legal to specify multiple different address spaces between template definition and -instantiation. If multiple different address spaces are specified in template definition and -instantiation compilation of such program will fail with a diagnostic. +It is not legal to specify multiple different address spaces between template +definition and instantiation. If multiple different address spaces are specified in +template definition and instantiation, compilation of such a program will fail with +a diagnostic. .. code-block:: c++ @@ -1717,11 +1723,12 @@ instantiation compilation of such program will fail with a diagnostic. } void bar() { - foo<__global int>(); // error: conflicting address space qualifiers are provided __global - // and __private + foo<__global int>(); // error: conflicting address space qualifiers are provided + // __global and __private } -Once template is instantiated regular restrictions for address spaces will apply. +Once a template has been instantiated, regular restrictions for address spaces will +apply. .. code-block:: c++ @@ -1731,15 +1738,15 @@ Once template is instantiated regular restrictions for address spaces will apply } void bar(){ - foo<__global int>(); // error: function scope variable cannot be declared in __global - // address space + foo<__global int>(); // error: function scope variable cannot be declared in + // __global address space } **Temporary materialization** -All temporaries are materialized in ``__private`` address space. If a reference with some -other address space is bound to them, the conversion will be generated in case it's valid -otherwise compilation will fail with a diagnostic. +All temporaries are materialized in the ``__private`` address space. If a +reference with another address space is bound to them, the conversion will be +generated in case it is valid, otherwise compilation will fail with a diagnostic. .. code-block:: c++ @@ -1763,26 +1770,29 @@ TODO Constructing and destroying global objects ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Global objects are constructed before the first kernel using the global +Global objects must be constructed before the first kernel using the global objects is executed and destroyed just after the last kernel using the program objects is executed. In OpenCL v2.0 drivers there is no specific API for invoking global constructors. However, an easy workaround would be -to enqueue constructor initialization kernel that has a name +to enqueue a constructor initialization kernel that has a name ``@_GLOBAL__sub_I_``. This kernel is only present if there are any global objects to be initialized in the compiled binary. One way to check this is by passing ``CL_PROGRAM_KERNEL_NAMES`` to ``clGetProgramInfo`` (OpenCL v2.0 s5.8.7). -Note that if multiple files are compiled and linked into libraries multiple +Note that if multiple files are compiled and linked into libraries, multiple kernels that initialize global objects for multiple modules would have to be invoked. +Applications are currently required to run initialization of global objects +manually before running any kernels in which the objects are used. + .. code-block:: console clang -cl-std=clc++ test.cl -If there are any global objects to be initialized the final binary will -contain ``@_GLOBAL__sub_I_test.cl`` kernel to be enqueued. +If there are any global objects to be initialized, the final binary will +contain the ``@_GLOBAL__sub_I_test.cl`` kernel to be enqueued. Global destructors can not be invoked in OpenCL v2.0 drivers. However, all memory used for program scope objects is released on ``clReleaseProgram``. diff --git a/clang/docs/UsersManual.rst b/clang/docs/UsersManual.rst index aad4ebf6e4a5..7b9a4e67177b 100644 --- a/clang/docs/UsersManual.rst +++ b/clang/docs/UsersManual.rst @@ -2397,8 +2397,8 @@ Compiling to bitcode can be done as follows: This will produce a generic test.bc file that can be used in vendor toolchains to perform machine code generation. -Clang currently supports OpenCL C language standards up to v2.0. Starting from Clang9 -C++ mode is available for OpenCL (see :ref:`C++ for OpenCL `). +Clang currently supports OpenCL C language standards up to v2.0. Starting from +clang 9 a C++ mode is available for OpenCL (see :ref:`C++ for OpenCL `). OpenCL Specific Options ----------------------- @@ -2762,21 +2762,22 @@ There are some standard OpenCL functions that are implemented as Clang builtins: C++ for OpenCL -------------- -Starting from Clang9 kernel code can contain C++17 features: classes, templates, +Starting from clang 9 kernel code can contain C++17 features: classes, templates, function overloading, type deduction, etc. Please note that this is not an implementation of `OpenCL C++ `_ and there is no plan to support it in clang in any new releases in the near future. -There are only a few restrictions on allowed C++ features. For detailed information -please refer to documentation on Extensions (:doc:`LanguageExtensions`). +For detailed information about restrictions to allowed C++ features please +refer to :doc:`LanguageExtensions`. Since C++ features are to be used on top of OpenCL C functionality, all existing restrictions from OpenCL C v2.0 will inherently apply. All OpenCL C builtin types -and function libraries are supported and can be used in the new mode. +and function libraries are supported and can be used in this mode. -To enable the new mode pass the following command line option when compiling ``.cl`` -file ``-cl-std=clc++``, ``-cl-std=CLC++``, ``-std=clc++`` or ``-std=CLC++``. +To enable the C++ for OpenCL mode, pass one of following command line options when +compiling ``.cl`` file ``-cl-std=clc++``, ``-cl-std=CLC++``, ``-std=clc++`` or +``-std=CLC++``. .. code-block:: c++ From d2fb9bb5541db98c88b80b955676881b1c4dac0e Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Tue, 27 Aug 2019 10:38:25 +0000 Subject: [PATCH 162/289] Merging r369834: ------------------------------------------------------------------------ r369834 | rsmith | 2019-08-24 04:30:00 +0200 (Sat, 24 Aug 2019) | 8 lines PR42513: Enter the proper DeclContext before substituting into an default template argument expression. We already did this for type template parameters and template template parameters, but apparently forgot to do so for non-type template parameters. This causes the substituted default argument expression to be substituted in the proper context, and in particular to properly mark its subexpressions as odr-used. ------------------------------------------------------------------------ llvm-svn: 370038 --- clang/lib/Sema/SemaTemplate.cpp | 1 + .../cxx1z-class-template-argument-deduction.cpp | 9 ++++++--- .../SemaTemplate/temp_arg_nontype_cxx11.cpp | 17 +++++++++++++++++ 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index ec4b63a2e508..135ca2b25cbe 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -4692,6 +4692,7 @@ SubstDefaultTemplateArgument(Sema &SemaRef, for (unsigned i = 0, e = Param->getDepth(); i != e; ++i) TemplateArgLists.addOuterTemplateArguments(None); + Sema::ContextRAII SavedContext(SemaRef, Template->getDeclContext()); EnterExpressionEvaluationContext ConstantEvaluated( SemaRef, Sema::ExpressionEvaluationContext::ConstantEvaluated); return SemaRef.SubstExpr(Param->getDefaultArgument(), TemplateArgLists); diff --git a/clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp b/clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp index c5deb9fe9195..85312cf1049f 100644 --- a/clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp +++ b/clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp @@ -268,13 +268,16 @@ namespace tuple_tests { // Don't get caught by surprise when X<...> doesn't even exist in the // selected specialization! namespace libcxx_2 { - template struct tuple { // expected-note {{candidate}} + template struct tuple { template struct X { static const bool value = false; }; + // Substitution into X::value succeeds but produces the + // value-dependent expression + // tuple::X<>::value + // FIXME: Is that the right behavior? template::value> tuple(U &&...u); - // expected-note@-1 {{substitution failure [with T = <>, U = ]: cannot reference member of primary template because deduced class template specialization 'tuple<>' is an explicit specialization}} }; template <> class tuple<> {}; - tuple a = {1, 2, 3}; // expected-error {{no viable constructor or deduction guide}} + tuple a = {1, 2, 3}; // expected-error {{excess elements in struct initializer}} } namespace libcxx_3 { diff --git a/clang/test/SemaTemplate/temp_arg_nontype_cxx11.cpp b/clang/test/SemaTemplate/temp_arg_nontype_cxx11.cpp index 313114e2cb8e..460b6def5d6f 100644 --- a/clang/test/SemaTemplate/temp_arg_nontype_cxx11.cpp +++ b/clang/test/SemaTemplate/temp_arg_nontype_cxx11.cpp @@ -48,3 +48,20 @@ void Useage() { } } +namespace PR42513 { + template void f(); + constexpr int WidgetCtor(struct X1*); + + struct X1 { + friend constexpr int WidgetCtor(X1*); + }; + template + struct StandardWidget { + friend constexpr int WidgetCtor(X1*) { + return 0; + } + }; + template struct StandardWidget; + + void use() { f(); } +} From 244e6c1ea8a63561551f96185827e27e51471900 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Tue, 27 Aug 2019 14:30:02 +0000 Subject: [PATCH 163/289] Merging r370036: ------------------------------------------------------------------------ r370036 | tnorthover | 2019-08-27 12:21:11 +0200 (Tue, 27 Aug 2019) | 8 lines AArch64: avoid creating cycle in DAG for post-increment NEON ops. Inserting a value into Visited has the effect of terminating a search for predecessors if that node is seen. This is legitimate for the base address, and acts as a slight performance optimization, but the vector-building node can be paert of a legitimate cycle so we shouldn't stop searching there. PR43056. ------------------------------------------------------------------------ llvm-svn: 370063 --- .../Target/AArch64/AArch64ISelLowering.cpp | 2 +- .../AArch64/arm64-indexed-vector-ldst.ll | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp index 6c250aea39f0..0ebcb4b37eb0 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -10579,7 +10579,7 @@ static SDValue performPostLD1Combine(SDNode *N, // are predecessors to each other or the Vector. SmallPtrSet Visited; SmallVector Worklist; - Visited.insert(N); + Visited.insert(Addr.getNode()); Worklist.push_back(User); Worklist.push_back(LD); Worklist.push_back(Vector.getNode()); diff --git a/llvm/test/CodeGen/AArch64/arm64-indexed-vector-ldst.ll b/llvm/test/CodeGen/AArch64/arm64-indexed-vector-ldst.ll index 8b6a4cae7ed5..f3ac9b21f53b 100644 --- a/llvm/test/CodeGen/AArch64/arm64-indexed-vector-ldst.ll +++ b/llvm/test/CodeGen/AArch64/arm64-indexed-vector-ldst.ll @@ -6319,3 +6319,22 @@ define void @test_ld1lane_build_i8(i8* %a, i8* %b, i8* %c, i8* %d, i8* %e, i8* store <8 x i8> %sub, <8 x i8>* %p ret void } + +define <4 x i32> @test_inc_cycle(<4 x i32> %vec, i32* %in) { +; CHECK-LABEL: test_inc_cycle: +; CHECK: ld1.s { v0 }[0], [x0]{{$}} + + %elt = load i32, i32* %in + %newvec = insertelement <4 x i32> %vec, i32 %elt, i32 0 + + ; %inc cannot be %elt directly because we check that the load is only + ; used by the insert before trying to form post-inc. + %inc.vec = bitcast <4 x i32> %newvec to <2 x i64> + %inc = extractelement <2 x i64> %inc.vec, i32 0 + %newaddr = getelementptr i32, i32* %in, i64 %inc + store i32* %newaddr, i32** @var + + ret <4 x i32> %newvec +} + +@var = global i32* null From 7527c1198883d6c1f1251704cb84b2eb302be854 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Tue, 27 Aug 2019 14:36:51 +0000 Subject: [PATCH 164/289] ReleaseNotes: PowerPC By Lei Huang! llvm-svn: 370065 --- llvm/docs/ReleaseNotes.rst | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst index 94621312b74c..268528ed1f9b 100644 --- a/llvm/docs/ReleaseNotes.rst +++ b/llvm/docs/ReleaseNotes.rst @@ -144,7 +144,30 @@ Changes to the MIPS Target Changes to the PowerPC Target ----------------------------- - During this release ... +* Improved handling of TOC pointer spills for indirect calls + +* Improve precision of square root reciprocal estimate + +* Enabled MachinePipeliner support for P9 with -ppc-enable-pipeliner. + +* MMX/SSE/SSE2 intrinsics headers have been ported to PowerPC using Altivec. + +* Machine verification failures cleaned, EXPENSIVE_CHECKS will run + MachineVerification by default now. + +* PowerPC scheduling enhancements, with customized PPC specific scheduler + strategy. + +* Inner most loop now always align to 32 bytes. + +* Enhancements of hardware loops interaction with LSR. + +* New builtins added, eg: __builtin_setrnd. + +* Various codegen improvements for both scalar and vector code + +* Various new exploitations and bug fixes, eg: exploited P9 maddld. + Changes to the SystemZ Target ----------------------------- From 79bfd169f714eaffd29a3732783f85bcd4b2d853 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Tue, 27 Aug 2019 16:26:35 +0000 Subject: [PATCH 165/289] ReleaseNotes: RISCV By Alex Bradbury! llvm-svn: 370076 --- llvm/docs/ReleaseNotes.rst | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst index 268528ed1f9b..970992624f67 100644 --- a/llvm/docs/ReleaseNotes.rst +++ b/llvm/docs/ReleaseNotes.rst @@ -55,6 +55,8 @@ Non-comprehensive list of changes in this release * The CMake parameter ``CLANG_ANALYZER_ENABLE_Z3_SOLVER`` has been replaced by ``LLVM_ENABLE_Z3_SOLVER``. +* The RISCV target is no longer "experimental" (see below for more details). + .. NOTE If you would like to document a larger change, then you can add a @@ -216,6 +218,18 @@ Changes to the WebAssembly Target During this release ... +Changes to the RISCV Target +--------------------------------- + +The RISCV target is no longer "experimental"! It's now built by default, +rather than needing to be enabled with ``LLVM_EXPERIMENTAL_TARGETS_TO_BUILD``. + +The backend has full codegen support for the RV32I and RV64I base RISC-V +instruction set variants, with the MAFDC standard extensions. We support the +hard and soft-float ABIs for these targets. Testing has been performed with +both Linux and bare-metal targets, including the compilation of a large corpus +of Linux applications (through buildroot). + Changes to the OCaml bindings ----------------------------- From 8fee65e51e40762bf0c9bb62ec0b2abdc45bde1b Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Tue, 27 Aug 2019 16:42:28 +0000 Subject: [PATCH 166/289] ReleaseNotes: Zig llvm-svn: 370077 --- llvm/docs/ReleaseNotes.rst | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst index 970992624f67..b3e0523eedd3 100644 --- a/llvm/docs/ReleaseNotes.rst +++ b/llvm/docs/ReleaseNotes.rst @@ -263,6 +263,19 @@ Mull - Mutation Testing tool for C and C++ `Mull `_ is a LLVM-based tool for mutation testing with a strong focus on C and C++ languages. +Zig Programming Language +------------------------ + +`Zig `_ is a system programming language intended to be +an alternative to C. It provides high level features such as generics, compile +time function execution, and partial evaluation, while exposing low level LLVM +IR features such as aliases and intrinsics. Zig uses Clang to provide automatic +import of .h symbols, including inline functions and simple macros. Zig uses +LLD combined with lazily building compiler-rt to provide out-of-the-box +cross-compiling for all supported targets. + + + Additional Information ====================== From caa3819116415c162578267d94fbe69a63ea867b Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Wed, 28 Aug 2019 08:12:39 +0000 Subject: [PATCH 167/289] [analyzer] Add 9.0.0. release notes. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit By Kristóf Umann! Differential revision: https://reviews.llvm.org/D66765 llvm-svn: 370166 --- clang/docs/ClangStaticAnalyzer.rst | 2 ++ clang/docs/ReleaseNotes.rst | 49 +++++++++++++++++++++++++++++- 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/clang/docs/ClangStaticAnalyzer.rst b/clang/docs/ClangStaticAnalyzer.rst index 7a309dc4acd9..3a4f332e5789 100644 --- a/clang/docs/ClangStaticAnalyzer.rst +++ b/clang/docs/ClangStaticAnalyzer.rst @@ -2,6 +2,8 @@ Clang Static Analyzer ===================== +.. _clang-static-analyzer-docs: + The Clang Static Analyzer is a source code analysis tool that finds bugs in C, C++, and Objective-C programs. It implements *path-sensitive*, *inter-procedural analysis* based on *symbolic execution* technique. diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 646844355c75..8fec01d3e14d 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -325,10 +325,57 @@ libclang Static Analyzer --------------- +- Fixed a bug where an incorrect checker name would be displayed for a bug + report.` + +- New checker: 'security.insecureAPI.DeprecatedOrUnsafeBufferHandling' to detect + uses of unsafe/deprecated buffer handling functions for C code using the C11 + standard or newer. + +- New checker: 'osx.MIGChecker' to find violations of the Mach Interface + Generator calling convention + +- New checker: 'optin.osx.OSObjectCStyleCast' to find C-style casts of of XNU + libkern OSObjects + +- New package: 'apiModeling.llvm' contains modeling checkers to improve the + accuracy of reports on LLVM's own codebase. + +- The Static Analyzer received a + :ref:`developer documentation `. + - The UninitializedObject checker is now considered as stable. (moved from the 'alpha.cplusplus' to the 'optin.cplusplus' package) -... +- New frontend flags: The list of available checkers are now split into 3 + different frontend flags: + + - ``-analyzer-checker-help``: The list of user-facing, stable checkers. + + - ``-analyzer-checker-help-alpha``: The list of in-development + checkers not yet advised to be turned on. + + - ``-analyzer-checker-help-developer``: Checkers never meant to be + enabled/disabled by hand + development checkers. + +- New frontend flags: While they have always been around, for the first time, + checker and package options are listable: + + - ``-analyzer-checker-option-help``: The list of user-facing, stable checker + and package options. + + - ``-analyzer-checker-option-help-alpha``: The list of in-development checker + options not yet advised to be used. + + - ``-analyzer-checker-option-help-developer``: Options never meant to be + enabled/disabled by hand + development options. + +- New frontend flag: ``-analyzer-werror`` to turn analyzer warnings into errors. + +- Numerous fixes to increase the stability of the experimental cross translation + unit analysis (CTU). + +- CTU now handles virtual functions as well. .. _release-notes-ubsan: From 4a24003424a7385f9ee76d486b471817ba1e90ba Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Wed, 28 Aug 2019 08:21:46 +0000 Subject: [PATCH 168/289] ReleaseNotes: ORC note, by Lang llvm-svn: 370167 --- llvm/docs/ReleaseNotes.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst index b3e0523eedd3..7eef9d9bd812 100644 --- a/llvm/docs/ReleaseNotes.rst +++ b/llvm/docs/ReleaseNotes.rst @@ -57,6 +57,8 @@ Non-comprehensive list of changes in this release * The RISCV target is no longer "experimental" (see below for more details). +* The ORCv1 JIT API has been deprecated. Please see + `Transitioning from ORCv1 to ORCv2 `_. .. NOTE If you would like to document a larger change, then you can add a From 845db805960ab3e6aee669e00ed5614dc1b6824c Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Wed, 28 Aug 2019 09:25:24 +0000 Subject: [PATCH 169/289] Merging r370176: ------------------------------------------------------------------------ r370176 | hans | 2019-08-28 11:21:56 +0200 (Wed, 28 Aug 2019) | 15 lines [LLVM-C] Fix ByVal Attribute crashing With the introduction of the typed byval attribute change there was no way that the LLVM-C API could create the correct class Attribute. If a program that uses the C API creates a ByVal attribute and annotates a function with that attribute LLVM will crash when it assembles or write that module containing the function out as bitcode. This change is a minimal fix to at least allow code to work, this is because the byval change is on the 9.0 and I don't want to introduce new LLVM-C API this late in the release cycle. By Jakob Bornecrantz! Differential revision: https://reviews.llvm.org/D66144 ------------------------------------------------------------------------ llvm-svn: 370178 --- llvm/lib/IR/Core.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/llvm/lib/IR/Core.cpp b/llvm/lib/IR/Core.cpp index 310935b5213a..af9ba7b3ca69 100644 --- a/llvm/lib/IR/Core.cpp +++ b/llvm/lib/IR/Core.cpp @@ -140,7 +140,16 @@ unsigned LLVMGetLastEnumAttributeKind(void) { LLVMAttributeRef LLVMCreateEnumAttribute(LLVMContextRef C, unsigned KindID, uint64_t Val) { - return wrap(Attribute::get(*unwrap(C), (Attribute::AttrKind)KindID, Val)); + auto &Ctx = *unwrap(C); + auto AttrKind = (Attribute::AttrKind)KindID; + + if (AttrKind == Attribute::AttrKind::ByVal) { + // After r362128, byval attributes need to have a type attribute. Provide a + // NULL one until a proper API is added for this. + return wrap(Attribute::getWithByValType(Ctx, NULL)); + } else { + return wrap(Attribute::get(Ctx, AttrKind, Val)); + } } unsigned LLVMGetEnumAttributeKind(LLVMAttributeRef A) { From 67afb7cbf1663e69befb2b215bb4173a31ff1670 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Wed, 28 Aug 2019 09:46:17 +0000 Subject: [PATCH 170/289] Merging r370073: ------------------------------------------------------------------------ r370073 | lenary | 2019-08-27 17:41:16 +0200 (Tue, 27 Aug 2019) | 13 lines [RISCV] Set MaxAtomicInlineWidth and MaxAtomicPromoteWidth for RV32/RV64 targets with atomics Summary: This ensures that libcalls aren't generated when the target supports atomics. Atomics aren't in the base RV32I/RV64I instruction sets, so MaxAtomicInlineWidth and MaxAtomicPromoteWidth are set only when the atomics extension is being targeted. This must be done in setMaxAtomicWidth, as this should be done after handleTargetFeatures has been called. Reviewers: jfb, jyknight, wmi, asb Reviewed By: asb Subscribers: pzheng, MaskRay, s.egerton, lenary, dexonsmith, psnobl, benna, Jim, JohnLLVM, rbar, johnrusso, simoncook, apazos, sabuasal, niosHD, kito-cheng, shiva0217, jrtc27, zzheng, edward-jones, rogfer01, MartinMosbeck, brucehoult, the_o, rkruppe, PkmX, jocewei, lewis-revill, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D57450 ------------------------------------------------------------------------ llvm-svn: 370181 --- clang/lib/Basic/Targets/RISCV.h | 14 +++++ clang/test/CodeGen/riscv-atomics.c | 68 ++++++++++++++++++++ clang/test/Driver/riscv32-toolchain.c | 89 +++++++++++++++++++++++++++ clang/test/Driver/riscv64-toolchain.c | 89 +++++++++++++++++++++++++++ 4 files changed, 260 insertions(+) create mode 100644 clang/test/CodeGen/riscv-atomics.c diff --git a/clang/lib/Basic/Targets/RISCV.h b/clang/lib/Basic/Targets/RISCV.h index ce193feaeb98..9118494a87ab 100644 --- a/clang/lib/Basic/Targets/RISCV.h +++ b/clang/lib/Basic/Targets/RISCV.h @@ -93,6 +93,13 @@ class LLVM_LIBRARY_VISIBILITY RISCV32TargetInfo : public RISCVTargetInfo { } return false; } + + void setMaxAtomicWidth() override { + MaxAtomicPromoteWidth = 128; + + if (HasA) + MaxAtomicInlineWidth = 32; + } }; class LLVM_LIBRARY_VISIBILITY RISCV64TargetInfo : public RISCVTargetInfo { public: @@ -110,6 +117,13 @@ class LLVM_LIBRARY_VISIBILITY RISCV64TargetInfo : public RISCVTargetInfo { } return false; } + + void setMaxAtomicWidth() override { + MaxAtomicPromoteWidth = 128; + + if (HasA) + MaxAtomicInlineWidth = 64; + } }; } // namespace targets } // namespace clang diff --git a/clang/test/CodeGen/riscv-atomics.c b/clang/test/CodeGen/riscv-atomics.c new file mode 100644 index 000000000000..9966543be1b6 --- /dev/null +++ b/clang/test/CodeGen/riscv-atomics.c @@ -0,0 +1,68 @@ +// RUN: %clang_cc1 -triple riscv32 -O1 -emit-llvm %s -o - \ +// RUN: | FileCheck %s -check-prefix=RV32I +// RUN: %clang_cc1 -triple riscv32 -target-feature +a -O1 -emit-llvm %s -o - \ +// RUN: | FileCheck %s -check-prefix=RV32IA +// RUN: %clang_cc1 -triple riscv64 -O1 -emit-llvm %s -o - \ +// RUN: | FileCheck %s -check-prefix=RV64I +// RUN: %clang_cc1 -triple riscv64 -target-feature +a -O1 -emit-llvm %s -o - \ +// RUN: | FileCheck %s -check-prefix=RV64IA + +// This test demonstrates that MaxAtomicInlineWidth is set appropriately when +// the atomics instruction set extension is enabled. + +#include +#include + +void test_i8_atomics(_Atomic(int8_t) * a, int8_t b) { + // RV32I: call zeroext i8 @__atomic_load_1 + // RV32I: call void @__atomic_store_1 + // RV32I: call zeroext i8 @__atomic_fetch_add_1 + // RV32IA: load atomic i8, i8* %a seq_cst, align 1 + // RV32IA: store atomic i8 %b, i8* %a seq_cst, align 1 + // RV32IA: atomicrmw add i8* %a, i8 %b seq_cst + // RV64I: call zeroext i8 @__atomic_load_1 + // RV64I: call void @__atomic_store_1 + // RV64I: call zeroext i8 @__atomic_fetch_add_1 + // RV64IA: load atomic i8, i8* %a seq_cst, align 1 + // RV64IA: store atomic i8 %b, i8* %a seq_cst, align 1 + // RV64IA: atomicrmw add i8* %a, i8 %b seq_cst + __c11_atomic_load(a, memory_order_seq_cst); + __c11_atomic_store(a, b, memory_order_seq_cst); + __c11_atomic_fetch_add(a, b, memory_order_seq_cst); +} + +void test_i32_atomics(_Atomic(int32_t) * a, int32_t b) { + // RV32I: call i32 @__atomic_load_4 + // RV32I: call void @__atomic_store_4 + // RV32I: call i32 @__atomic_fetch_add_4 + // RV32IA: load atomic i32, i32* %a seq_cst, align 4 + // RV32IA: store atomic i32 %b, i32* %a seq_cst, align 4 + // RV32IA: atomicrmw add i32* %a, i32 %b seq_cst + // RV64I: call signext i32 @__atomic_load_4 + // RV64I: call void @__atomic_store_4 + // RV64I: call signext i32 @__atomic_fetch_add_4 + // RV64IA: load atomic i32, i32* %a seq_cst, align 4 + // RV64IA: store atomic i32 %b, i32* %a seq_cst, align 4 + // RV64IA: atomicrmw add i32* %a, i32 %b seq_cst + __c11_atomic_load(a, memory_order_seq_cst); + __c11_atomic_store(a, b, memory_order_seq_cst); + __c11_atomic_fetch_add(a, b, memory_order_seq_cst); +} + +void test_i64_atomics(_Atomic(int64_t) * a, int64_t b) { + // RV32I: call i64 @__atomic_load_8 + // RV32I: call void @__atomic_store_8 + // RV32I: call i64 @__atomic_fetch_add_8 + // RV32IA: call i64 @__atomic_load_8 + // RV32IA: call void @__atomic_store_8 + // RV32IA: call i64 @__atomic_fetch_add_8 + // RV64I: call i64 @__atomic_load_8 + // RV64I: call void @__atomic_store_8 + // RV64I: call i64 @__atomic_fetch_add_8 + // RV64IA: load atomic i64, i64* %a seq_cst, align 8 + // RV64IA: store atomic i64 %b, i64* %a seq_cst, align 8 + // RV64IA: atomicrmw add i64* %a, i64 %b seq_cst + __c11_atomic_load(a, memory_order_seq_cst); + __c11_atomic_store(a, b, memory_order_seq_cst); + __c11_atomic_fetch_add(a, b, memory_order_seq_cst); +} diff --git a/clang/test/Driver/riscv32-toolchain.c b/clang/test/Driver/riscv32-toolchain.c index d4160d1b5826..117c773ec970 100644 --- a/clang/test/Driver/riscv32-toolchain.c +++ b/clang/test/Driver/riscv32-toolchain.c @@ -105,6 +105,10 @@ typedef __builtin_va_list va_list; typedef __SIZE_TYPE__ size_t; typedef __PTRDIFF_TYPE__ ptrdiff_t; typedef __WCHAR_TYPE__ wchar_t; +typedef __WINT_TYPE__ wint_t; + + +// Check Alignments // CHECK: @align_c = dso_local global i32 1 int align_c = __alignof(char); @@ -118,6 +122,9 @@ int align_i = __alignof(int); // CHECK: @align_wc = dso_local global i32 4 int align_wc = __alignof(wchar_t); +// CHECK: @align_wi = dso_local global i32 4 +int align_wi = __alignof(wint_t); + // CHECK: @align_l = dso_local global i32 4 int align_l = __alignof(long); @@ -139,6 +146,88 @@ int align_ld = __alignof(long double); // CHECK: @align_vl = dso_local global i32 4 int align_vl = __alignof(va_list); +// CHECK: @align_a_c = dso_local global i32 1 +int align_a_c = __alignof(_Atomic(char)); + +// CHECK: @align_a_s = dso_local global i32 2 +int align_a_s = __alignof(_Atomic(short)); + +// CHECK: @align_a_i = dso_local global i32 4 +int align_a_i = __alignof(_Atomic(int)); + +// CHECK: @align_a_wc = dso_local global i32 4 +int align_a_wc = __alignof(_Atomic(wchar_t)); + +// CHECK: @align_a_wi = dso_local global i32 4 +int align_a_wi = __alignof(_Atomic(wint_t)); + +// CHECK: @align_a_l = dso_local global i32 4 +int align_a_l = __alignof(_Atomic(long)); + +// CHECK: @align_a_ll = dso_local global i32 8 +int align_a_ll = __alignof(_Atomic(long long)); + +// CHECK: @align_a_p = dso_local global i32 4 +int align_a_p = __alignof(_Atomic(void*)); + +// CHECK: @align_a_f = dso_local global i32 4 +int align_a_f = __alignof(_Atomic(float)); + +// CHECK: @align_a_d = dso_local global i32 8 +int align_a_d = __alignof(_Atomic(double)); + +// CHECK: @align_a_ld = dso_local global i32 16 +int align_a_ld = __alignof(_Atomic(long double)); + +// CHECK: @align_a_s4 = dso_local global i32 4 +int align_a_s4 = __alignof(_Atomic(struct { char s[4]; })); + +// CHECK: @align_a_s8 = dso_local global i32 8 +int align_a_s8 = __alignof(_Atomic(struct { char s[8]; })); + +// CHECK: @align_a_s16 = dso_local global i32 16 +int align_a_s16 = __alignof(_Atomic(struct { char s[16]; })); + +// CHECK: @align_a_s32 = dso_local global i32 1 +int align_a_s32 = __alignof(_Atomic(struct { char s[32]; })); + + +// Check Sizes + +// CHECK: @size_a_c = dso_local global i32 1 +int size_a_c = sizeof(_Atomic(char)); + +// CHECK: @size_a_s = dso_local global i32 2 +int size_a_s = sizeof(_Atomic(short)); + +// CHECK: @size_a_i = dso_local global i32 4 +int size_a_i = sizeof(_Atomic(int)); + +// CHECK: @size_a_wc = dso_local global i32 4 +int size_a_wc = sizeof(_Atomic(wchar_t)); + +// CHECK: @size_a_wi = dso_local global i32 4 +int size_a_wi = sizeof(_Atomic(wint_t)); + +// CHECK: @size_a_l = dso_local global i32 4 +int size_a_l = sizeof(_Atomic(long)); + +// CHECK: @size_a_ll = dso_local global i32 8 +int size_a_ll = sizeof(_Atomic(long long)); + +// CHECK: @size_a_p = dso_local global i32 4 +int size_a_p = sizeof(_Atomic(void*)); + +// CHECK: @size_a_f = dso_local global i32 4 +int size_a_f = sizeof(_Atomic(float)); + +// CHECK: @size_a_d = dso_local global i32 8 +int size_a_d = sizeof(_Atomic(double)); + +// CHECK: @size_a_ld = dso_local global i32 16 +int size_a_ld = sizeof(_Atomic(long double)); + + // Check types // CHECK: zeroext i8 @check_char() diff --git a/clang/test/Driver/riscv64-toolchain.c b/clang/test/Driver/riscv64-toolchain.c index b8069858eba2..3d574947c68a 100644 --- a/clang/test/Driver/riscv64-toolchain.c +++ b/clang/test/Driver/riscv64-toolchain.c @@ -105,6 +105,10 @@ typedef __builtin_va_list va_list; typedef __SIZE_TYPE__ size_t; typedef __PTRDIFF_TYPE__ ptrdiff_t; typedef __WCHAR_TYPE__ wchar_t; +typedef __WINT_TYPE__ wint_t; + + +// Check Alignments // CHECK: @align_c = dso_local global i32 1 int align_c = __alignof(char); @@ -118,6 +122,9 @@ int align_i = __alignof(int); // CHECK: @align_wc = dso_local global i32 4 int align_wc = __alignof(wchar_t); +// CHECK: @align_wi = dso_local global i32 4 +int align_wi = __alignof(wint_t); + // CHECK: @align_l = dso_local global i32 8 int align_l = __alignof(long); @@ -139,6 +146,88 @@ int align_ld = __alignof(long double); // CHECK: @align_vl = dso_local global i32 8 int align_vl = __alignof(va_list); +// CHECK: @align_a_c = dso_local global i32 1 +int align_a_c = __alignof(_Atomic(char)); + +// CHECK: @align_a_s = dso_local global i32 2 +int align_a_s = __alignof(_Atomic(short)); + +// CHECK: @align_a_i = dso_local global i32 4 +int align_a_i = __alignof(_Atomic(int)); + +// CHECK: @align_a_wc = dso_local global i32 4 +int align_a_wc = __alignof(_Atomic(wchar_t)); + +// CHECK: @align_a_wi = dso_local global i32 4 +int align_a_wi = __alignof(_Atomic(wint_t)); + +// CHECK: @align_a_l = dso_local global i32 8 +int align_a_l = __alignof(_Atomic(long)); + +// CHECK: @align_a_ll = dso_local global i32 8 +int align_a_ll = __alignof(_Atomic(long long)); + +// CHECK: @align_a_p = dso_local global i32 8 +int align_a_p = __alignof(_Atomic(void*)); + +// CHECK @align_a_f = dso_local global i32 4 +int align_a_f = __alignof(_Atomic(float)); + +// CHECK: @align_a_d = dso_local global i32 8 +int align_a_d = __alignof(_Atomic(double)); + +// CHECK: @align_a_ld = dso_local global i32 16 +int align_a_ld = __alignof(_Atomic(long double)); + +// CHECK: @align_a_s4 = dso_local global i32 4 +int align_a_s4 = __alignof(_Atomic(struct { char _[4]; })); + +// CHECK: @align_a_s8 = dso_local global i32 8 +int align_a_s8 = __alignof(_Atomic(struct { char _[8]; })); + +// CHECK: @align_a_s16 = dso_local global i32 16 +int align_a_s16 = __alignof(_Atomic(struct { char _[16]; })); + +// CHECK: @align_a_s32 = dso_local global i32 1 +int align_a_s32 = __alignof(_Atomic(struct { char _[32]; })); + + +// Check Sizes + +// CHECK: @size_a_c = dso_local global i32 1 +int size_a_c = sizeof(_Atomic(char)); + +// CHECK: @size_a_s = dso_local global i32 2 +int size_a_s = sizeof(_Atomic(short)); + +// CHECK: @size_a_i = dso_local global i32 4 +int size_a_i = sizeof(_Atomic(int)); + +// CHECK: @size_a_wc = dso_local global i32 4 +int size_a_wc = sizeof(_Atomic(wchar_t)); + +// CHECK: @size_a_wi = dso_local global i32 4 +int size_a_wi = sizeof(_Atomic(wint_t)); + +// CHECK: @size_a_l = dso_local global i32 8 +int size_a_l = sizeof(_Atomic(long)); + +// CHECK: @size_a_ll = dso_local global i32 8 +int size_a_ll = sizeof(_Atomic(long long)); + +// CHECK: @size_a_p = dso_local global i32 8 +int size_a_p = sizeof(_Atomic(void*)); + +// CHECK: @size_a_f = dso_local global i32 4 +int size_a_f = sizeof(_Atomic(float)); + +// CHECK: @size_a_d = dso_local global i32 8 +int size_a_d = sizeof(_Atomic(double)); + +// CHECK: @size_a_ld = dso_local global i32 16 +int size_a_ld = sizeof(_Atomic(long double)); + + // Check types // CHECK: define dso_local zeroext i8 @check_char() From e82a53603ae3fed2215a44b5ac603db00a780c02 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Wed, 28 Aug 2019 09:55:07 +0000 Subject: [PATCH 171/289] Merging r369886: ------------------------------------------------------------------------ r369886 | bjope | 2019-08-26 11:29:53 +0200 (Mon, 26 Aug 2019) | 23 lines [LoopUnroll] Handle certain PHIs in full unrolling properly Summary: When reconstructing the CFG of the loop after unrolling, LoopUnroll could in some cases remove the phi operands of loop-carried values instead of preserving them, resulting in undef phi values after loop unrolling. When doing this reconstruction, avoid removing incoming phi values for phis in the successor blocks if the successor is the block we are jumping to anyway. Patch-by: ebevhan Reviewers: fhahn, efriedma Reviewed By: fhahn Subscribers: bjope, lebedev.ri, zzheng, dmgreen, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D66334 ------------------------------------------------------------------------ llvm-svn: 370182 --- llvm/lib/Transforms/Utils/LoopUnroll.cpp | 8 +- .../unroll-header-exiting-with-phis.ll | 107 ++++++++++++++++++ 2 files changed, 112 insertions(+), 3 deletions(-) create mode 100644 llvm/test/Transforms/LoopUnroll/unroll-header-exiting-with-phis.ll diff --git a/llvm/lib/Transforms/Utils/LoopUnroll.cpp b/llvm/lib/Transforms/Utils/LoopUnroll.cpp index e39ade523714..4a1edb3700c0 100644 --- a/llvm/lib/Transforms/Utils/LoopUnroll.cpp +++ b/llvm/lib/Transforms/Utils/LoopUnroll.cpp @@ -711,7 +711,7 @@ LoopUnrollResult llvm::UnrollLoop(Loop *L, UnrollLoopOptions ULO, LoopInfo *LI, auto setDest = [LoopExit, ContinueOnTrue](BasicBlock *Src, BasicBlock *Dest, ArrayRef NextBlocks, - BasicBlock *CurrentHeader, + BasicBlock *BlockInLoop, bool NeedConditional) { auto *Term = cast(Src->getTerminator()); if (NeedConditional) { @@ -723,7 +723,9 @@ LoopUnrollResult llvm::UnrollLoop(Loop *L, UnrollLoopOptions ULO, LoopInfo *LI, if (Dest != LoopExit) { BasicBlock *BB = Src; for (BasicBlock *Succ : successors(BB)) { - if (Succ == CurrentHeader) + // Preserve the incoming value from BB if we are jumping to the block + // in the current loop. + if (Succ == BlockInLoop) continue; for (PHINode &Phi : Succ->phis()) Phi.removeIncomingValue(BB, false); @@ -794,7 +796,7 @@ LoopUnrollResult llvm::UnrollLoop(Loop *L, UnrollLoopOptions ULO, LoopInfo *LI, // unconditional branch for some iterations. NeedConditional = false; - setDest(Headers[i], Dest, Headers, Headers[i], NeedConditional); + setDest(Headers[i], Dest, Headers, HeaderSucc[i], NeedConditional); } // Set up latches to branch to the new header in the unrolled iterations or diff --git a/llvm/test/Transforms/LoopUnroll/unroll-header-exiting-with-phis.ll b/llvm/test/Transforms/LoopUnroll/unroll-header-exiting-with-phis.ll new file mode 100644 index 000000000000..e1fba5f6689c --- /dev/null +++ b/llvm/test/Transforms/LoopUnroll/unroll-header-exiting-with-phis.ll @@ -0,0 +1,107 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -S -loop-unroll -unroll-allow-partial | FileCheck %s + +; The phi which acts as input to func should not be undef. It should +; have its loop-carried value (the load in for.cond) replaced accordingly +; after unrolling the loop. + +define i16 @full_unroll(i16* %A) { +; CHECK-LABEL: @full_unroll( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[FOR_COND:%.*]] +; CHECK: for.cond: +; CHECK-NEXT: [[TMP2:%.*]] = load i16, i16* [[A:%.*]] +; CHECK-NEXT: br label [[FOR_COND_CLEANUP3:%.*]] +; CHECK: for.cond.cleanup: +; CHECK-NEXT: [[DOTLCSSA10_LCSSA:%.*]] = phi i16 [ [[TMP2_2:%.*]], [[FOR_COND_CLEANUP3_2:%.*]] ] +; CHECK-NEXT: [[TMP3:%.*]] = call i16 @func(i16 [[DOTLCSSA10_LCSSA]]) +; CHECK-NEXT: ret i16 0 +; CHECK: for.cond.cleanup3: +; CHECK-NEXT: [[PTR_1:%.*]] = getelementptr inbounds i16, i16* [[A]], i64 1 +; CHECK-NEXT: [[TMP2_1:%.*]] = load i16, i16* [[PTR_1]] +; CHECK-NEXT: br label [[FOR_COND_CLEANUP3_1:%.*]] +; CHECK: for.cond.cleanup3.1: +; CHECK-NEXT: [[PTR_2:%.*]] = getelementptr inbounds i16, i16* [[A]], i64 2 +; CHECK-NEXT: [[TMP2_2]] = load i16, i16* [[PTR_2]] +; CHECK-NEXT: br label [[FOR_COND_CLEANUP3_2]] +; CHECK: for.cond.cleanup3.2: +; CHECK-NEXT: [[PTR_3:%.*]] = getelementptr inbounds i16, i16* [[A]], i64 3 +; CHECK-NEXT: [[TMP2_3:%.*]] = load i16, i16* [[PTR_3]] +; CHECK-NEXT: br i1 false, label [[FOR_COND_CLEANUP3_3:%.*]], label [[FOR_COND_CLEANUP:%.*]] +; CHECK: for.cond.cleanup3.3: +; CHECK-NEXT: unreachable +; +entry: + br label %for.cond + +for.cond: ; preds = %for.cond.cleanup3, %entry + %.lcssa10 = phi i16 [ 123, %entry ], [ %.lcssa, %for.cond.cleanup3 ] + %i.0 = phi i64 [ 0, %entry ], [ %inc9, %for.cond.cleanup3 ] + %ptr = getelementptr inbounds i16, i16* %A, i64 %i.0 + %tmp2 = load i16, i16* %ptr + %cmp = icmp ult i64 %i.0, 3 + br i1 %cmp, label %for.cond.cleanup3, label %for.cond.cleanup + +for.cond.cleanup: ; preds = %for.cond + %.lcssa10.lcssa = phi i16 [ %.lcssa10, %for.cond ] + %tmp3 = call i16 (i16) @func(i16 %.lcssa10.lcssa) + ret i16 0 + +for.cond.cleanup3: ; preds = %for.cond + %.lcssa = phi i16 [ %tmp2, %for.cond ] + %inc9 = add i64 %i.0, 1 + br label %for.cond +} + +define i16 @partial_unroll(i16* %A) { +; CHECK-LABEL: @partial_unroll( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[FOR_COND:%.*]] +; CHECK: for.cond: +; CHECK-NEXT: [[I_0:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INC9_2:%.*]], [[FOR_COND_CLEANUP3_2:%.*]] ] +; CHECK-NEXT: [[PTR:%.*]] = getelementptr inbounds i16, i16* [[A:%.*]], i64 [[I_0]] +; CHECK-NEXT: [[TMP2:%.*]] = load i16, i16* [[PTR]] +; CHECK-NEXT: br label [[FOR_COND_CLEANUP3:%.*]] +; CHECK: for.cond.cleanup: +; CHECK-NEXT: [[DOTLCSSA10_LCSSA:%.*]] = phi i16 [ [[TMP2_1:%.*]], [[FOR_COND_CLEANUP3_1:%.*]] ] +; CHECK-NEXT: [[TMP3:%.*]] = call i16 @func(i16 [[DOTLCSSA10_LCSSA]]) +; CHECK-NEXT: ret i16 0 +; CHECK: for.cond.cleanup3: +; CHECK-NEXT: [[INC9:%.*]] = add nuw nsw i64 [[I_0]], 1 +; CHECK-NEXT: [[PTR_1:%.*]] = getelementptr inbounds i16, i16* [[A]], i64 [[INC9]] +; CHECK-NEXT: [[TMP2_1]] = load i16, i16* [[PTR_1]] +; CHECK-NEXT: br label [[FOR_COND_CLEANUP3_1]] +; CHECK: for.cond.cleanup3.1: +; CHECK-NEXT: [[INC9_1:%.*]] = add nuw nsw i64 [[INC9]], 1 +; CHECK-NEXT: [[PTR_2:%.*]] = getelementptr inbounds i16, i16* [[A]], i64 [[INC9_1]] +; CHECK-NEXT: [[TMP2_2:%.*]] = load i16, i16* [[PTR_2]] +; CHECK-NEXT: [[CMP_2:%.*]] = icmp ult i64 [[INC9_1]], 200 +; CHECK-NEXT: br i1 [[CMP_2]], label [[FOR_COND_CLEANUP3_2]], label [[FOR_COND_CLEANUP:%.*]] +; CHECK: for.cond.cleanup3.2: +; CHECK-NEXT: [[INC9_2]] = add nuw nsw i64 [[INC9_1]], 1 +; CHECK-NEXT: br label [[FOR_COND]] +; +entry: + br label %for.cond + +for.cond: ; preds = %for.cond.cleanup3, %entry + %.lcssa10 = phi i16 [ 123, %entry ], [ %.lcssa, %for.cond.cleanup3 ] + %i.0 = phi i64 [ 0, %entry ], [ %inc9, %for.cond.cleanup3 ] + %ptr = getelementptr inbounds i16, i16* %A, i64 %i.0 + %tmp2 = load i16, i16* %ptr + %cmp = icmp ult i64 %i.0, 200 + br i1 %cmp, label %for.cond.cleanup3, label %for.cond.cleanup + +for.cond.cleanup: ; preds = %for.cond + %.lcssa10.lcssa = phi i16 [ %.lcssa10, %for.cond ] + %tmp3 = call i16 (i16) @func(i16 %.lcssa10.lcssa) + ret i16 0 + +for.cond.cleanup3: ; preds = %for.cond + %.lcssa = phi i16 [ %tmp2, %for.cond ] + %inc9 = add i64 %i.0, 1 + br label %for.cond +} + +declare i16 @func(i16) + From f7a1e48471343b304b01d769a30b23883a2729fc Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Wed, 28 Aug 2019 13:58:21 +0000 Subject: [PATCH 172/289] Merging r370204: ------------------------------------------------------------------------ r370204 | hans | 2019-08-28 15:55:10 +0200 (Wed, 28 Aug 2019) | 6 lines [SelectionDAG] Don't generate libcalls for wide shifts on Windows (PR42711) Neither libgcc or compiler-rt are usually used on Windows, so these functions can't be called. Differential revision: https://reviews.llvm.org/D66880 ------------------------------------------------------------------------ llvm-svn: 370205 --- llvm/lib/Target/AArch64/AArch64ISelLowering.cpp | 8 ++++++++ llvm/lib/Target/AArch64/AArch64ISelLowering.h | 6 +----- llvm/lib/Target/X86/X86ISelLowering.cpp | 8 ++++++++ llvm/lib/Target/X86/X86ISelLowering.h | 6 +----- llvm/test/CodeGen/AArch64/shift_minsize.ll | 6 ++++++ llvm/test/CodeGen/X86/shift_minsize.ll | 8 +++++++- 6 files changed, 31 insertions(+), 11 deletions(-) diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp index 0ebcb4b37eb0..03923878fd51 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -11995,6 +11995,14 @@ bool AArch64TargetLowering::isMaskAndCmp0FoldingBeneficial( return Mask->getValue().isPowerOf2(); } +bool AArch64TargetLowering::shouldExpandShift(SelectionDAG &DAG, + SDNode *N) const { + if (DAG.getMachineFunction().getFunction().hasMinSize() && + !Subtarget->isTargetWindows()) + return false; + return true; +} + void AArch64TargetLowering::initializeSplitCSR(MachineBasicBlock *Entry) const { // Update IsSplitCSR in AArch64unctionInfo. AArch64FunctionInfo *AFI = Entry->getParent()->getInfo(); diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.h b/llvm/lib/Target/AArch64/AArch64ISelLowering.h index 4421c31f65c9..86f313933d85 100644 --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.h +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.h @@ -480,11 +480,7 @@ class AArch64TargetLowering : public TargetLowering { return VT.getSizeInBits() >= 64; // vector 'bic' } - bool shouldExpandShift(SelectionDAG &DAG, SDNode *N) const override { - if (DAG.getMachineFunction().getFunction().hasMinSize()) - return false; - return true; - } + bool shouldExpandShift(SelectionDAG &DAG, SDNode *N) const override; bool shouldTransformSignedTruncationCheck(EVT XVT, unsigned KeptBits) const override { diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index ad68ddbeaa8b..6f8240e745ce 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -5059,6 +5059,14 @@ bool X86TargetLowering::shouldFoldMaskToVariableShiftPair(SDValue Y) const { return true; } +bool X86TargetLowering::shouldExpandShift(SelectionDAG &DAG, + SDNode *N) const { + if (DAG.getMachineFunction().getFunction().hasMinSize() && + !Subtarget.isOSWindows()) + return false; + return true; +} + bool X86TargetLowering::shouldSplatInsEltVarIndex(EVT VT) const { // Any legal vector type can be splatted more efficiently than // loading/spilling from memory. diff --git a/llvm/lib/Target/X86/X86ISelLowering.h b/llvm/lib/Target/X86/X86ISelLowering.h index e0be03bc3f9d..db36bcb929e3 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.h +++ b/llvm/lib/Target/X86/X86ISelLowering.h @@ -863,11 +863,7 @@ namespace llvm { return VTIsOk(XVT) && VTIsOk(KeptBitsVT); } - bool shouldExpandShift(SelectionDAG &DAG, SDNode *N) const override { - if (DAG.getMachineFunction().getFunction().hasMinSize()) - return false; - return true; - } + bool shouldExpandShift(SelectionDAG &DAG, SDNode *N) const override; bool shouldSplatInsEltVarIndex(EVT VT) const override; diff --git a/llvm/test/CodeGen/AArch64/shift_minsize.ll b/llvm/test/CodeGen/AArch64/shift_minsize.ll index d1b95e87577b..2728b3f4c733 100644 --- a/llvm/test/CodeGen/AArch64/shift_minsize.ll +++ b/llvm/test/CodeGen/AArch64/shift_minsize.ll @@ -1,5 +1,10 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc < %s -mtriple=aarch64-unknown-unknown | FileCheck %s +; RUN: llc < %s -mtriple=aarch64-windows | FileCheck %s -check-prefix=CHECK-WIN + +; The Windows runtime doesn't have these. +; CHECK-WIN-NOT: __ashlti3 +; CHECK-WIN-NOT: __ashrti3 define i64 @f0(i64 %val, i64 %amt) minsize optsize { ; CHECK-LABEL: f0: @@ -53,6 +58,7 @@ define dso_local { i64, i64 } @shl128(i64 %x.coerce0, i64 %x.coerce1, i8 signext ; CHECK-NEXT: bl __ashlti3 ; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload ; CHECK-NEXT: ret + entry: %x.sroa.2.0.insert.ext = zext i64 %x.coerce1 to i128 %x.sroa.2.0.insert.shift = shl nuw i128 %x.sroa.2.0.insert.ext, 64 diff --git a/llvm/test/CodeGen/X86/shift_minsize.ll b/llvm/test/CodeGen/X86/shift_minsize.ll index 5ba46544645f..548c2d37707a 100644 --- a/llvm/test/CodeGen/X86/shift_minsize.ll +++ b/llvm/test/CodeGen/X86/shift_minsize.ll @@ -1,5 +1,11 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py -; RUN: llc < %s -mtriple=x86_64-unknown | FileCheck %s +; RUN: llc < %s -mtriple=x86_64-unknown | FileCheck %s +; RUN: llc < %s -mtriple=x86_64--windows-msvc | FileCheck %s -check-prefix=CHECK-WIN + +; The Windows runtime doesn't have these. +; CHECK-WIN-NOT: __ashlti3 +; CHECK-WIN-NOT: __ashrti3 +; CHECK-WIN-NOT: __lshrti3 define i64 @f0(i64 %val, i64 %amt) minsize optsize { ; CHECK-LABEL: f0: From e7a52d72c7b1256b9ae3057bf900b0af22b5b39e Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Wed, 28 Aug 2019 14:49:27 +0000 Subject: [PATCH 173/289] Merging r370035: ------------------------------------------------------------------------ r370035 | devnexen | 2019-08-27 12:04:03 +0200 (Tue, 27 Aug 2019) | 7 lines [ReleaseNotes] MemorySanitizer support of ASLR on FreeBSD Reviewers: sylvestre.ledru, kcc Reviewed By: sylvestre.ledru Differential Revision: https://reviews.llvm.org/D66792 ------------------------------------------------------------------------ llvm-svn: 370213 --- clang/docs/MemorySanitizer.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/clang/docs/MemorySanitizer.rst b/clang/docs/MemorySanitizer.rst index f513b009a32f..8a88198d3e92 100644 --- a/clang/docs/MemorySanitizer.rst +++ b/clang/docs/MemorySanitizer.rst @@ -204,6 +204,9 @@ Limitations non-position-independent executables, and could fail on some Linux kernel versions with disabled ASLR. Refer to documentation for older versions for more details. +* MemorySanitizer might be incompatible with position-independent executables + from FreeBSD 13 but there is a check done at runtime and throws a warning + in this case. Current Status ============== From 44b3f6722e23abe0ad3555e56bb5e22e860c1aea Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Thu, 29 Aug 2019 08:58:14 +0000 Subject: [PATCH 174/289] Merging r370271: ------------------------------------------------------------------------ r370271 | tstellar | 2019-08-29 00:59:04 +0200 (Thu, 29 Aug 2019) | 6 lines [LLVM-C] Fix omission of INSTALL_WITH_TOOLCHAIN to llvm_add_library() Due to a misstake with r365902 that tried to simplify the install with toolchain logic LLVM-C.dll was no longer being installed. Patch By: Jakob Bornecrantz ------------------------------------------------------------------------ llvm-svn: 370306 --- llvm/tools/llvm-shlib/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/tools/llvm-shlib/CMakeLists.txt b/llvm/tools/llvm-shlib/CMakeLists.txt index 4905ed08157f..901f55c99d59 100644 --- a/llvm/tools/llvm-shlib/CMakeLists.txt +++ b/llvm/tools/llvm-shlib/CMakeLists.txt @@ -182,6 +182,6 @@ if(MSVC) VERBATIM ) # Finally link the target. - add_llvm_library(LLVM-C SHARED ${SOURCES} DEPENDS intrinsics_gen) + add_llvm_library(LLVM-C SHARED INSTALL_WITH_TOOLCHAIN ${SOURCES} DEPENDS intrinsics_gen) endif() From 9c8b896a1a7579f2a15ca6c92d66a13d963b090d Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Thu, 29 Aug 2019 09:20:22 +0000 Subject: [PATCH 175/289] Merging r368964: ------------------------------------------------------------------------ r368964 | maskray | 2019-08-15 07:22:23 +0200 (Thu, 15 Aug 2019) | 11 lines [ELF][PPC] Improve error message for unknown relocations Like rLLD354040. Previously, for unrecognized relocation types, in -no-pie mode: foo.o: unrecognized reloc 256 In -pie/-shared mode: error: can't create dynamic relocation R_PPC_xxx against symbol: yyy in readonly segment ------------------------------------------------------------------------ llvm-svn: 370312 --- lld/ELF/Arch/PPC.cpp | 13 +++++++++++-- lld/ELF/Arch/PPC64.cpp | 21 +++++++++++++++++++-- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/lld/ELF/Arch/PPC.cpp b/lld/ELF/Arch/PPC.cpp index 46c5891e4f8a..cf4ad4049926 100644 --- a/lld/ELF/Arch/PPC.cpp +++ b/lld/ELF/Arch/PPC.cpp @@ -190,6 +190,13 @@ bool PPC::inBranchRange(RelType type, uint64_t src, uint64_t dst) const { RelExpr PPC::getRelExpr(RelType type, const Symbol &s, const uint8_t *loc) const { switch (type) { + case R_PPC_NONE: + return R_NONE; + case R_PPC_ADDR16_HA: + case R_PPC_ADDR16_HI: + case R_PPC_ADDR16_LO: + case R_PPC_ADDR32: + return R_ABS; case R_PPC_DTPREL16: case R_PPC_DTPREL16_HA: case R_PPC_DTPREL16_HI: @@ -227,7 +234,9 @@ RelExpr PPC::getRelExpr(RelType type, const Symbol &s, case R_PPC_TPREL16_HI: return R_TLS; default: - return R_ABS; + error(getErrorLocation(loc) + "unknown relocation (" + Twine(type) + + ") against symbol " + toString(s)); + return R_NONE; } } @@ -319,7 +328,7 @@ void PPC::relocateOne(uint8_t *loc, RelType type, uint64_t val) const { break; } default: - error(getErrorLocation(loc) + "unrecognized relocation " + toString(type)); + llvm_unreachable("unknown relocation"); } } diff --git a/lld/ELF/Arch/PPC64.cpp b/lld/ELF/Arch/PPC64.cpp index 70d284cfad71..ee5942f6fefd 100644 --- a/lld/ELF/Arch/PPC64.cpp +++ b/lld/ELF/Arch/PPC64.cpp @@ -532,6 +532,21 @@ void PPC64::relaxTlsIeToLe(uint8_t *loc, RelType type, uint64_t val) const { RelExpr PPC64::getRelExpr(RelType type, const Symbol &s, const uint8_t *loc) const { switch (type) { + case R_PPC64_NONE: + return R_NONE; + case R_PPC64_ADDR16: + case R_PPC64_ADDR16_DS: + case R_PPC64_ADDR16_HA: + case R_PPC64_ADDR16_HI: + case R_PPC64_ADDR16_HIGHER: + case R_PPC64_ADDR16_HIGHERA: + case R_PPC64_ADDR16_HIGHEST: + case R_PPC64_ADDR16_HIGHESTA: + case R_PPC64_ADDR16_LO: + case R_PPC64_ADDR16_LO_DS: + case R_PPC64_ADDR32: + case R_PPC64_ADDR64: + return R_ABS; case R_PPC64_GOT16: case R_PPC64_GOT16_DS: case R_PPC64_GOT16_HA: @@ -607,7 +622,9 @@ RelExpr PPC64::getRelExpr(RelType type, const Symbol &s, case R_PPC64_TLS: return R_TLSIE_HINT; default: - return R_ABS; + error(getErrorLocation(loc) + "unknown relocation (" + Twine(type) + + ") against symbol " + toString(s)); + return R_NONE; } } @@ -870,7 +887,7 @@ void PPC64::relocateOne(uint8_t *loc, RelType type, uint64_t val) const { write64(loc, val - dynamicThreadPointerOffset); break; default: - error(getErrorLocation(loc) + "unrecognized relocation " + toString(type)); + llvm_unreachable("unknown relocation"); } } From a384ddbc3af5dd7d54b6bc340ef2099686dc14fa Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Thu, 29 Aug 2019 09:21:39 +0000 Subject: [PATCH 176/289] Merging r369184: ------------------------------------------------------------------------ r369184 | maskray | 2019-08-17 08:28:03 +0200 (Sat, 17 Aug 2019) | 9 lines [ELF][PPC] Fix getRelExpr for R_PPC64_REL16_HI Fixes https://github.com/ClangBuiltLinux/linux/issues/640 R_PPC64_REL16_HI was incorrectly computed as an R_ABS relocation. rLLD368964 made it a linker failure. Change it to use R_PC to fix the failures. Add ppc64-reloc-rel.s for these R_PPC64_REL* tests. ------------------------------------------------------------------------ llvm-svn: 370313 --- lld/ELF/Arch/PPC64.cpp | 1 + lld/test/ELF/ppc64-reloc-rel.s | 58 ++++++++++++++++++++++++ lld/test/ELF/ppc64-relocs.s | 81 ++++------------------------------ 3 files changed, 68 insertions(+), 72 deletions(-) create mode 100644 lld/test/ELF/ppc64-reloc-rel.s diff --git a/lld/ELF/Arch/PPC64.cpp b/lld/ELF/Arch/PPC64.cpp index ee5942f6fefd..0f382dcd6b3c 100644 --- a/lld/ELF/Arch/PPC64.cpp +++ b/lld/ELF/Arch/PPC64.cpp @@ -569,6 +569,7 @@ RelExpr PPC64::getRelExpr(RelType type, const Symbol &s, return R_PPC64_CALL_PLT; case R_PPC64_REL16_LO: case R_PPC64_REL16_HA: + case R_PPC64_REL16_HI: case R_PPC64_REL32: case R_PPC64_REL64: return R_PC; diff --git a/lld/test/ELF/ppc64-reloc-rel.s b/lld/test/ELF/ppc64-reloc-rel.s new file mode 100644 index 000000000000..3e3c5c94ef89 --- /dev/null +++ b/lld/test/ELF/ppc64-reloc-rel.s @@ -0,0 +1,58 @@ +# REQUIRES: ppc + +# RUN: llvm-mc -filetype=obj -triple=powerpc64le %s -o %t.o +# RUN: ld.lld %t.o --defsym=foo=rel16+0x8000 -o %t +# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s +# RUN: llvm-readobj -r %t.o | FileCheck --check-prefix=REL %s +# RUN: llvm-readelf -S %t | FileCheck --check-prefix=SEC %s +# RUN: llvm-readelf -x .eh_frame %t | FileCheck --check-prefix=HEX %s + +.section .R_PPC64_REL14,"ax",@progbits +# FIXME This does not produce a relocation + beq 1f +1: +# CHECK-LABEL: Disassembly of section .R_PPC64_REL14: +# CHECK: bt 2, .+4 + +.section .R_PPC64_REL16,"ax",@progbits +.globl rel16 +rel16: + li 3, foo-rel16-1@ha # R_PPC64_REL16_HA + li 3, foo-rel16@ha + li 4, foo-rel16+0x7fff@h # R_PPC64_REL16_HI + li 4, foo-rel16+0x8000@h + li 5, foo-rel16-1@l # R_PPC64_REL16_LO + li 5, foo-rel16@l +# CHECK-LABEL: Disassembly of section .R_PPC64_REL16: +# CHECK: li 3, 0 +# CHECK-NEXT: li 3, 1 +# CHECK-NEXT: li 4, 0 +# CHECK-NEXT: li 4, 1 +# CHECK-NEXT: li 5, 32767 +# CHECK-NEXT: li 5, -32768 + +.section .R_PPC64_REL24,"ax",@progbits + b rel16 +# CHECK-LABEL: Disassembly of section .R_PPC64_REL24: +# CHECK: b .+67108840 + +.section .REL32_AND_REL64,"ax",@progbits + .cfi_startproc + .cfi_personality 148, rel64 + nop + .cfi_endproc +rel64: + li 3, 0 +# REL: .rela.eh_frame { +# REL-NEXT: 0x12 R_PPC64_REL64 .REL32_AND_REL64 0x4 +# REL-NEXT: 0x28 R_PPC64_REL32 .REL32_AND_REL64 0x0 +# REL-NEXT: } + +# SEC: .REL32_AND_REL64 PROGBITS 0000000010010020 + +## CIE Personality Address: 0x10010020-(0x10000168+2)+4 = 0xfeba +## FDE PC Begin: 0x10010020-(0x10000178+8) = 0xfea0 +# HEX: section '.eh_frame': +# HEX-NEXT: 0x10000158 +# HEX-NEXT: 0x10000168 {{....}}bafe 00000000 +# HEX-NEXT: 0x10000178 {{[0-9a-f]+}} {{[0-9a-f]+}} a0fe0000 diff --git a/lld/test/ELF/ppc64-relocs.s b/lld/test/ELF/ppc64-relocs.s index 5e8c529e9614..8e69e08df68b 100644 --- a/lld/test/ELF/ppc64-relocs.s +++ b/lld/test/ELF/ppc64-relocs.s @@ -18,16 +18,9 @@ _start: li 3,42 sc -.section .rodata,"a",@progbits - .p2align 2 -.LJTI0_0: - .long .LBB0_2-.LJTI0_0 - -.section .toc,"aw",@progbits +.section .toc,"aw",@progbits .L1: -.quad 22, 37, 89, 47 -.LC0: - .tc .LJTI0_0[TC],.LJTI0_0 + .quad 22, 37, 89, 47 .section .R_PPC64_TOC16_LO_DS,"ax",@progbits ld 1, .L1@toc@l(2) @@ -53,91 +46,47 @@ _start: # CHECK-LABEL: Disassembly of section .R_PPC64_TOC16_HA: # CHECK: 10010018: addis 1, 2, 0 -.section .R_PPC64_REL24,"ax",@progbits - b 1f -1: - -# CHECK-LABEL: Disassembly of section .R_PPC64_REL24: -# CHECK: 1001001c: b .+4 - -.section .R_PPC64_REL14,"ax",@progbits - beq 1f -1: - -# CHECK-LABEL: Disassembly of section .R_PPC64_REL14: -# CHECK: 10010020: bt 2, .+4 - .section .R_PPC64_ADDR16_LO,"ax",@progbits li 1, .Lfoo@l # CHECK-LABEL: Disassembly of section .R_PPC64_ADDR16_LO: -# CHECK: 10010024: li 1, 0 +# CHECK: li 1, 0 .section .R_PPC64_ADDR16_HI,"ax",@progbits li 1, .Lfoo@h # CHECK-LABEL: Disassembly of section .R_PPC64_ADDR16_HI: -# CHECK: 10010028: li 1, 4097 +# CHECK: li 1, 4097 .section .R_PPC64_ADDR16_HA,"ax",@progbits li 1, .Lfoo@ha # CHECK-LABEL: Disassembly of section .R_PPC64_ADDR16_HA: -# CHECK: 1001002c: li 1, 4097 +# CHECK: li 1, 4097 .section .R_PPC64_ADDR16_HIGHER,"ax",@progbits li 1, .Lfoo@higher # CHECK-LABEL: Disassembly of section .R_PPC64_ADDR16_HIGHER: -# CHECK: 10010030: li 1, 0 +# CHECK: li 1, 0 .section .R_PPC64_ADDR16_HIGHERA,"ax",@progbits li 1, .Lfoo@highera # CHECK-LABEL: Disassembly of section .R_PPC64_ADDR16_HIGHERA: -# CHECK: 10010034: li 1, 0 +# CHECK: li 1, 0 .section .R_PPC64_ADDR16_HIGHEST,"ax",@progbits li 1, .Lfoo@highest # CHECK-LABEL: Disassembly of section .R_PPC64_ADDR16_HIGHEST: -# CHECK: 10010038: li 1, 0 +# CHECK: li 1, 0 .section .R_PPC64_ADDR16_HIGHESTA,"ax",@progbits li 1, .Lfoo@highesta # CHECK-LABEL: Disassembly of section .R_PPC64_ADDR16_HIGHESTA: -# CHECK: 1001003c: li 1, 0 - -.section .R_PPC64_REL32, "ax",@progbits - addis 5, 2, .LC0@toc@ha - ld 5, .LC0@toc@l(5) -.LBB0_2: - add 3, 3, 4 - -# DATALE: '.rodata': -# DATALE: 0x100001c8 80fe0000 - -# DATABE: '.rodata': -# DATABE: 0x100001c8 0000fe80 - -# Address of rodata + value stored at rodata entry -# should equal address of LBB0_2. -# 0x10000190 + 0xfeb4 = 0x10010044 -# CHECK-LABEL: Disassembly of section .R_PPC64_REL32: -# CHECK: 10010040: addis 5, 2, 0 -# CHECK: 10010044: ld 5, -32736(5) -# CHECK: 10010048: add 3, 3, 4 - -.section .R_PPC64_REL64, "ax",@progbits - .cfi_startproc - .cfi_personality 148, __foo - li 0, 1 - li 3, 55 - sc - .cfi_endproc -__foo: - li 3,0 +# CHECK: li 1, 0 .section .R_PPC64_TOC,"a",@progbits .quad .TOC.@tocbase @@ -150,15 +99,3 @@ __foo: # DATABE-LABEL: section '.R_PPC64_TOC': # DATABE: 00000000 10028000 - -# Check that the personality (relocated by R_PPC64_REL64) in the .eh_frame -# equals the address of __foo. -# 0x100001ea + 0xfe6e = 0x10010058 -# DATALE: section '.eh_frame': -# DATALE: 0x100001e8 {{....}}6efe - -# DATABE: section '.eh_frame': -# DATABE: 0x100001e8 {{[0-9a-f]+ [0-9a-f]+}} fe6e{{....}} - -# CHECK: __foo -# CHECK-NEXT: 10010058: li 3, 0 From f8ed27f549e3d0fd934420586108f9a4e2aaa674 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Thu, 29 Aug 2019 10:04:58 +0000 Subject: [PATCH 177/289] ReleaseNotes from Sam Parker llvm-svn: 370318 --- llvm/docs/ReleaseNotes.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst index 7eef9d9bd812..b0e91443737c 100644 --- a/llvm/docs/ReleaseNotes.rst +++ b/llvm/docs/ReleaseNotes.rst @@ -60,6 +60,9 @@ Non-comprehensive list of changes in this release * The ORCv1 JIT API has been deprecated. Please see `Transitioning from ORCv1 to ORCv2 `_. +* Support for target-independent hardware loops in IR has been added, with + PowerPC and Arm implementations. + .. NOTE If you would like to document a larger change, then you can add a subsection about it right here. You can copy the following boilerplate @@ -126,6 +129,8 @@ Changes to the ARM Backend tune for cores where this gives a benefit too: Cortex-M3, SC300, Cortex-M33 and Cortex-M35P. +* Code generation support for M-profile low-overhead loops. + Changes to the MIPS Target -------------------------- From 9adebd4b0beaffcd73e1af83879cb10380158f02 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Thu, 29 Aug 2019 12:19:19 +0000 Subject: [PATCH 178/289] ReleaseNotes: omitting range checks for switches with unreachable defaults llvm-svn: 370342 --- llvm/docs/ReleaseNotes.rst | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst index b0e91443737c..7130242cc496 100644 --- a/llvm/docs/ReleaseNotes.rst +++ b/llvm/docs/ReleaseNotes.rst @@ -85,6 +85,36 @@ Noteworthy optimizations `bug 42763 _` and `post commit discussion _`. +* LLVM will now omit range checks for jump tables when lowering switches with + unreachable default destination. For example, the switch dispatch in the C++ + code below + + .. code-block:: c + + int g(int); + enum e { A, B, C, D, E }; + int f(e x, int y, int z) { + switch(x) { + case A: return g(y); + case B: return g(z); + case C: return g(y+z); + case D: return g(x-z); + case E: return g(x+z); + } + } + + will result in the following x86_64 machine code when compiled with Clang. + This is because falling off the end of a non-void function is undefined + behaviour in C++, and the end of the function therefore being treated as + unreachable: + + .. code-block:: asm + + _Z1f1eii: + mov eax, edi + jmp qword ptr [8*rax + .LJTI0_0] + + Changes to the LLVM IR ---------------------- From 9f45ba86fd2033b393f4fe03cbdb5c302a695492 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Thu, 29 Aug 2019 12:37:46 +0000 Subject: [PATCH 179/289] ReleaseNotes: sinking of instructions without uses llvm-svn: 370344 --- llvm/docs/ReleaseNotes.rst | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst index 7130242cc496..2e81b0b3e6c0 100644 --- a/llvm/docs/ReleaseNotes.rst +++ b/llvm/docs/ReleaseNotes.rst @@ -115,6 +115,26 @@ Noteworthy optimizations jmp qword ptr [8*rax + .LJTI0_0] +* LLVM can now sink similar instructions to a common successor block also when + the instructions have no uses, such as calls to void functions. This allows + code such as + + .. code-block:: c + + void g(int); + enum e { A, B, C, D }; + void f(e x, int y, int z) { + switch(x) { + case A: g(6); break; + case B: g(3); break; + case C: g(9); break; + case D: g(2); break; + } + } + + to be optimized to a single call to ``g``, with the argument loaded from a + lookup table. + Changes to the LLVM IR ---------------------- From 7552a3968e0a137abdb7d83f65c06e9d4285b9b1 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Thu, 29 Aug 2019 12:44:53 +0000 Subject: [PATCH 180/289] ReleaseNotes: reduce the indent llvm-svn: 370346 --- llvm/docs/ReleaseNotes.rst | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst index 2e81b0b3e6c0..aa0dd9bb8e38 100644 --- a/llvm/docs/ReleaseNotes.rst +++ b/llvm/docs/ReleaseNotes.rst @@ -94,13 +94,13 @@ Noteworthy optimizations int g(int); enum e { A, B, C, D, E }; int f(e x, int y, int z) { - switch(x) { - case A: return g(y); - case B: return g(z); - case C: return g(y+z); - case D: return g(x-z); - case E: return g(x+z); - } + switch(x) { + case A: return g(y); + case B: return g(z); + case C: return g(y+z); + case D: return g(x-z); + case E: return g(x+z); + } } will result in the following x86_64 machine code when compiled with Clang. @@ -124,12 +124,12 @@ Noteworthy optimizations void g(int); enum e { A, B, C, D }; void f(e x, int y, int z) { - switch(x) { - case A: g(6); break; - case B: g(3); break; - case C: g(9); break; - case D: g(2); break; - } + switch(x) { + case A: g(6); break; + case B: g(3); break; + case C: g(9); break; + case D: g(2); break; + } } to be optimized to a single call to ``g``, with the argument loaded from a From 2f35f0004e2dc37a5ea4afda755a58ad68f29f08 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Thu, 29 Aug 2019 13:03:14 +0000 Subject: [PATCH 181/289] ReleaseNotes: matching wide stores (r362472) llvm-svn: 370352 --- llvm/docs/ReleaseNotes.rst | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst index aa0dd9bb8e38..b9630087cb7e 100644 --- a/llvm/docs/ReleaseNotes.rst +++ b/llvm/docs/ReleaseNotes.rst @@ -85,6 +85,30 @@ Noteworthy optimizations `bug 42763 _` and `post commit discussion _`. +* LLVM will now pattern match wide scalar values stored by a succession of + narrow stores. For example, Clang will compile the following function that + writes a 32-bit value in big-endian order in a portable manner: + + .. code-block:: c + + void write32be(unsigned char *dst, uint32_t x) { + dst[0] = x >> 24; + dst[1] = x >> 16; + dst[2] = x >> 8; + dst[3] = x >> 0; + } + + into the x86_64 code below: + + .. code-block:: asm + + write32be: + bswap esi + mov dword ptr [rdi], esi + ret + + (The corresponding read patterns have been matched since LLVM 5.) + * LLVM will now omit range checks for jump tables when lowering switches with unreachable default destination. For example, the switch dispatch in the C++ code below From 529706393a921093fd01593202b0d77005a6c906 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Thu, 29 Aug 2019 13:23:59 +0000 Subject: [PATCH 182/289] ReleaseNotes: remove in-progress warning and empty sections llvm-svn: 370356 --- llvm/docs/ReleaseNotes.rst | 52 +++----------------------------------- 1 file changed, 3 insertions(+), 49 deletions(-) diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst index b9630087cb7e..feb5f00ed1c0 100644 --- a/llvm/docs/ReleaseNotes.rst +++ b/llvm/docs/ReleaseNotes.rst @@ -5,12 +5,6 @@ LLVM 9.0.0 Release Notes .. contents:: :local: -.. warning:: - These are in-progress notes for the upcoming LLVM 9 release. - Release notes for previous releases can be found on - `the Download Page `_. - - Introduction ============ @@ -26,19 +20,9 @@ have questions or comments, the `LLVM Developer's Mailing List `_ is a good place to send them. -Note that if you are reading this file from a Subversion checkout or the main -LLVM web page, this document applies to the *next* release, not the current -one. To see the release notes for a specific release, please see the `releases -page `_. Non-comprehensive list of changes in this release ================================================= -.. NOTE - For small 1-3 sentence descriptions, just add an entry at the end of - this list. If your description won't fit comfortably in one bullet - point (e.g. maybe you would like to give an example of the - functionality, or simply have a lot to talk about), see the `NOTE` below - for adding a new subsection. * The optimizer will now convert calls to ``memcmp`` into a calls to ``bcmp`` in some circumstances. Users who are building freestanding code (not depending on @@ -63,15 +47,6 @@ Non-comprehensive list of changes in this release * Support for target-independent hardware loops in IR has been added, with PowerPC and Arm implementations. -.. NOTE - If you would like to document a larger change, then you can add a - subsection about it right here. You can copy the following boilerplate - and un-indent it (the indentation causes it to be inside this comment). - - Special New Feature - ------------------- - - Makes programs 10x faster by doing Special New Thing. Noteworthy optimizations ------------------------ @@ -83,7 +58,7 @@ Noteworthy optimizations behavior, but up until now had not been actively utilized for optimization purposes in this exact way. For more information, please see: `bug 42763 _` and - `post commit discussion _`. + `post commit discussion _`. * LLVM will now pattern match wide scalar values stored by a succession of narrow stores. For example, Clang will compile the following function that @@ -279,7 +254,7 @@ Changes to the X86 Target * Fixed a bug in generating DWARF unwind information for 32 bit MinGW Changes to the AMDGPU Target ------------------------------ +---------------------------- * Function call support is now enabled by default @@ -289,18 +264,9 @@ Changes to the AMDGPU Target * Support for gfx10 -Changes to the AVR Target ------------------------------ - - During this release ... - -Changes to the WebAssembly Target ---------------------------------- - - During this release ... Changes to the RISCV Target ---------------------------------- +--------------------------- The RISCV target is no longer "experimental"! It's now built by default, rather than needing to be enabled with ``LLVM_EXPERIMENTAL_TARGETS_TO_BUILD``. @@ -312,18 +278,6 @@ both Linux and bare-metal targets, including the compilation of a large corpus of Linux applications (through buildroot). -Changes to the OCaml bindings ------------------------------ - - - -Changes to the C API --------------------- - - -Changes to the DAG infrastructure ---------------------------------- - Changes to LLDB =============== From e7ecc55143200dfff5d605562fc5df857470db97 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Thu, 29 Aug 2019 13:41:38 +0000 Subject: [PATCH 183/289] ReleaseNotes: cleanups llvm-svn: 370357 --- llvm/docs/ReleaseNotes.rst | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst index feb5f00ed1c0..41b60c3bc69b 100644 --- a/llvm/docs/ReleaseNotes.rst +++ b/llvm/docs/ReleaseNotes.rst @@ -24,22 +24,18 @@ them. Non-comprehensive list of changes in this release ================================================= -* The optimizer will now convert calls to ``memcmp`` into a calls to ``bcmp`` in - some circumstances. Users who are building freestanding code (not depending on - the platform's libc) without specifying ``-ffreestanding`` may need to either - pass ``-fno-builtin-bcmp``, or provide a ``bcmp`` function. - * Two new extension points, namely ``EP_FullLinkTimeOptimizationEarly`` and ``EP_FullLinkTimeOptimizationLast`` are available for plugins to specialize the legacy pass manager full LTO pipeline. -* **llvm-objcopy/llvm-strip** got support for COFF object files/executables, +* ``llvm-objcopy/llvm-strip`` got support for COFF object files/executables, supporting the most common copying/stripping options. * The CMake parameter ``CLANG_ANALYZER_ENABLE_Z3_SOLVER`` has been replaced by ``LLVM_ENABLE_Z3_SOLVER``. -* The RISCV target is no longer "experimental" (see below for more details). +* The RISCV target is no longer "experimental" (see + `Changes to the RISCV Target`_ below for more details). * The ORCv1 JIT API has been deprecated. Please see `Transitioning from ORCv1 to ORCv2 `_. @@ -57,8 +53,13 @@ Noteworthy optimizations able to cast away 'const'. This is (and has always been) undefined behavior, but up until now had not been actively utilized for optimization purposes in this exact way. For more information, please see: - `bug 42763 _` and - `post commit discussion _`. + `bug 42763 `_ and + `post commit discussion `_. + +* The optimizer will now convert calls to ``memcmp`` into a calls to ``bcmp`` in + some circumstances. Users who are building freestanding code (not depending on + the platform's libc) without specifying ``-ffreestanding`` may need to either + pass ``-fno-builtin-bcmp``, or provide a ``bcmp`` function. * LLVM will now pattern match wide scalar values stored by a succession of narrow stores. For example, Clang will compile the following function that @@ -206,7 +207,7 @@ Changes to the PowerPC Target * Improve precision of square root reciprocal estimate -* Enabled MachinePipeliner support for P9 with -ppc-enable-pipeliner. +* Enabled MachinePipeliner support for P9 with ``-ppc-enable-pipeliner``. * MMX/SSE/SSE2 intrinsics headers have been ported to PowerPC using Altivec. @@ -220,11 +221,11 @@ Changes to the PowerPC Target * Enhancements of hardware loops interaction with LSR. -* New builtins added, eg: __builtin_setrnd. +* New builtins added, eg: ``__builtin_setrnd``. * Various codegen improvements for both scalar and vector code -* Various new exploitations and bug fixes, eg: exploited P9 maddld. +* Various new exploitations and bug fixes, e.g: exploited P9 ``maddld``. Changes to the SystemZ Target @@ -295,7 +296,7 @@ External Open Source Projects Using LLVM 9 Mull - Mutation Testing tool for C and C++ ------------------------------------------ -`Mull `_ is a LLVM-based tool for +`Mull `_ is an LLVM-based tool for mutation testing with a strong focus on C and C++ languages. Zig Programming Language From 78ecdd5bfdf464a3065b6a20556e7d67bc88e1aa Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Thu, 29 Aug 2019 13:49:56 +0000 Subject: [PATCH 184/289] ReleaseNotes: drop in-progress warning and empty sections llvm-svn: 370358 --- clang/docs/ReleaseNotes.rst | 88 ++----------------------------------- 1 file changed, 3 insertions(+), 85 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 8fec01d3e14d..f8a8298db2f6 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -1,6 +1,6 @@ -======================================= -Clang 9.0.0 (In-Progress) Release Notes -======================================= +========================= +Clang 9.0.0 Release Notes +========================= .. contents:: :local: @@ -8,11 +8,6 @@ Clang 9.0.0 (In-Progress) Release Notes Written by the `LLVM Team `_ -.. warning:: - - These are in-progress notes for the upcoming Clang 9 release. - Release notes for previous releases can be found on - `the Download Page `_. Introduction ============ @@ -30,10 +25,6 @@ For more information about Clang or LLVM, including information about the latest release, please see the `Clang Web Site `_ or the `LLVM Web Site `_. -Note that if you are reading this file from a Subversion checkout or the -main Clang web page, this document applies to the *next* release, not -the current one. To see the release notes for a specific release, please -see the `releases page `_. What's New in Clang 9.0.0? ========================== @@ -48,12 +39,7 @@ Major New Features - Experimental support for :ref:`C++ for OpenCL ` has been added. -- ... - -Improvements to Clang's diagnostics -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -- ... Non-comprehensive list of changes in this release ------------------------------------------------- @@ -64,8 +50,6 @@ Non-comprehensive list of changes in this release However, to retrieve Clang's version, please favor the one of the macro defined in :ref:`clang namespaced version macros `. -- ... - New Compiler Flags ------------------ @@ -77,30 +61,12 @@ New Compiler Flags activities (file parsing, template instantiation) and backend activities (modules and functions being optimized, optimization passes). -Deprecated Compiler Flags -------------------------- - -The following options are deprecated and ignored. They will be removed in -future versions of Clang. - -- ... Modified Compiler Flags ----------------------- - ``clang -dumpversion`` now returns the version of Clang itself. -- ... - -New Pragmas in Clang --------------------- - -- ... - -Attribute Changes in Clang --------------------------- - -- ... Windows Support --------------- @@ -133,12 +99,6 @@ C Language Changes in Clang still a few unsupported corner cases in Clang's integrated assembler and IfConverter. Please file bugs for any issues you run into. -- ... - -C11 Feature Support -^^^^^^^^^^^^^^^^^^^ - -... C++ Language Changes in Clang ----------------------------- @@ -151,12 +111,6 @@ C++ Language Changes in Clang (2) There is no address space deduction. -- ... - -C++1z Feature Support -^^^^^^^^^^^^^^^^^^^^^ - -... Objective-C Language Changes in Clang ------------------------------------- @@ -252,10 +206,6 @@ Implemented features are: - Overloads with generic address space are added to all atomic builtin functions, including the ones prior to OpenCL v2.0. -ABI Changes in Clang --------------------- - -- ... OpenMP Support in Clang ----------------------- @@ -295,12 +245,6 @@ release of Clang. Users of the build system should adjust accordingly. library instead of statically linking clang's components. This option will reduce the size of binary distributions at the expense of compiler performance. -- ... - -AST Matchers ------------- - -- ... clang-format ------------ @@ -377,32 +321,6 @@ Static Analyzer - CTU now handles virtual functions as well. -.. _release-notes-ubsan: - -Undefined Behavior Sanitizer (UBSan) ------------------------------------- - -- ... - -Core Analysis Improvements -========================== - -- ... - -New Issues Found -================ - -- ... - -Python Binding Changes ----------------------- - -The following methods have been added: - -- ... - -Significant Known Problems -========================== Linux Kernel ============ From d6c7f875f97c4ea68ae2eea9f760b97a9a72e0f6 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Thu, 29 Aug 2019 14:18:54 +0000 Subject: [PATCH 185/289] ReleaseNotes: fixes llvm-svn: 370360 --- clang/docs/ReleaseNotes.rst | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index f8a8298db2f6..dd2f146f088b 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -89,7 +89,7 @@ Windows Support C Language Changes in Clang --------------------------- -- ``__FILE_NAME__`` macro has been added as a Clang specific extension supported +- The ``__FILE_NAME__`` macro has been added as a Clang specific extension supported in all C-family languages. This macro is similar to ``__FILE__`` except it will always provide the last path component when possible. @@ -117,7 +117,7 @@ Objective-C Language Changes in Clang - Fixed encoding of ObjC pointer types that are pointers to typedefs. -.. code-block:: objc + .. code-block:: objc typedef NSArray MyArray; @@ -251,15 +251,15 @@ clang-format - Add language support for clang-formatting C# files. - Add Microsoft coding style to encapsulate default C# formatting style. -- Added new option `PPDIS_BeforeHash` (in configuration: `BeforeHash`) to - `IndentPPDirectives` which indents preprocessor directives before the hash. -- Added new option `AlignConsecutiveMacros` to align the C/C++ preprocessor +- Added new option ``PPDIS_BeforeHash`` (in configuration: ``BeforeHash``) to + ``IndentPPDirectives`` which indents preprocessor directives before the hash. +- Added new option ``AlignConsecutiveMacros`` to align the C/C++ preprocessor macros of consecutive lines. libclang -------- -- When `CINDEXTEST_INCLUDE_ATTRIBUTED_TYPES` is not provided when making a +- When ``CINDEXTEST_INCLUDE_ATTRIBUTED_TYPES`` is not provided when making a CXType, the equivalent type of the AttributedType is returned instead of the modified type if the user does not want attribute sugar. The equivalent type represents the minimally-desugared type which the AttributedType is @@ -270,26 +270,26 @@ Static Analyzer --------------- - Fixed a bug where an incorrect checker name would be displayed for a bug - report.` + report. -- New checker: 'security.insecureAPI.DeprecatedOrUnsafeBufferHandling' to detect +- New checker: ``security.insecureAPI.DeprecatedOrUnsafeBufferHandling`` to detect uses of unsafe/deprecated buffer handling functions for C code using the C11 standard or newer. -- New checker: 'osx.MIGChecker' to find violations of the Mach Interface +- New checker: ``osx.MIGChecker`` to find violations of the Mach Interface Generator calling convention -- New checker: 'optin.osx.OSObjectCStyleCast' to find C-style casts of of XNU +- New checker: ``optin.osx.OSObjectCStyleCast`` to find C-style casts of of XNU libkern OSObjects -- New package: 'apiModeling.llvm' contains modeling checkers to improve the +- New package: ``apiModeling.llvm`` contains modeling checkers to improve the accuracy of reports on LLVM's own codebase. -- The Static Analyzer received a +- The Static Analyzer received :ref:`developer documentation `. - The UninitializedObject checker is now considered as stable. - (moved from the 'alpha.cplusplus' to the 'optin.cplusplus' package) + (moved from the ``alpha.cplusplus`` to the ``optin.cplusplus`` package) - New frontend flags: The list of available checkers are now split into 3 different frontend flags: From 6f2f9290cb6bbe7b939b4a5db86936c1ac23973b Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Thu, 29 Aug 2019 14:22:53 +0000 Subject: [PATCH 186/289] ReleaseNotes: remove in-progress warnings and empty sections llvm-svn: 370362 --- clang-tools-extra/docs/ReleaseNotes.rst | 48 ++----------------------- 1 file changed, 3 insertions(+), 45 deletions(-) diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 465c0aba4bb1..b2de68be4087 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -1,6 +1,6 @@ -=================================================== -Extra Clang Tools 9.0.0 (In-Progress) Release Notes -=================================================== +===================================== +Extra Clang Tools 9.0.0 Release Notes +===================================== .. contents:: :local: @@ -8,12 +8,6 @@ Extra Clang Tools 9.0.0 (In-Progress) Release Notes Written by the `LLVM Team `_ -.. warning:: - - These are in-progress notes for the upcoming Extra Clang Tools 9 release. - Release notes for previous releases can be found on - `the Download Page `_. - Introduction ============ @@ -27,10 +21,6 @@ For more information about Clang or LLVM, including information about the latest release, please see the `Clang Web Site `_ or the `LLVM Web Site `_. -Note that if you are reading this file from a Subversion checkout or the -main Clang web page, this document applies to the *next* release, not -the current one. To see the release notes for a specific release, please -see the `releases page `_. What's New in Extra Clang Tools 9.0.0? ====================================== @@ -39,10 +29,6 @@ Some of the major new features and improvements to Extra Clang Tools are listed here. Generic improvements to Extra Clang Tools as a whole or to its underlying infrastructure are described first, followed by tool-specific sections. -Major New Features ------------------- - -... Improvements to clangd ---------------------- @@ -140,20 +126,6 @@ Improvements to clangd ``textDocument.completion.editsNearCursor`` capability to ``true``, and clangd will provide completions that correct ``.`` to ``->``, and vice-versa. -Improvements to clang-doc -------------------------- - -The improvements are... - -Improvements to clang-query ---------------------------- - -The improvements are... - -Improvements to clang-rename ----------------------------- - -The improvements are... Improvements to clang-tidy -------------------------- @@ -340,20 +312,6 @@ Improvements to clang-tidy :doc:`objc-property-declaration ` check have been removed. -Improvements to include-fixer ------------------------------ - -The improvements are... - -Improvements to clang-include-fixer ------------------------------------ - -The improvements are... - -Improvements to modularize --------------------------- - -The improvements are... Improvements to pp-trace ------------------------ From 2857b97ea454ba57433708af1b634a805a9a7c60 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Thu, 29 Aug 2019 14:31:27 +0000 Subject: [PATCH 187/289] ReleaseNotes: remove in-progress warning, remove empty sections llvm-svn: 370364 --- lld/docs/ReleaseNotes.rst | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/lld/docs/ReleaseNotes.rst b/lld/docs/ReleaseNotes.rst index ea3876f81292..ce61cc0d4d74 100644 --- a/lld/docs/ReleaseNotes.rst +++ b/lld/docs/ReleaseNotes.rst @@ -5,11 +5,6 @@ lld 9.0.0 Release Notes .. contents:: :local: -.. warning:: - These are in-progress notes for the upcoming LLVM 9.0.0 release. - Release notes for previous releases can be found on - `the Download Page `_. - Introduction ============ @@ -37,8 +32,6 @@ ELF Improvements into corresponding PT_MIPS_REGINFO, PT_MIPS_OPTIONS, and PT_MIPS_ABIFLAGS segments. -* ... - COFF Improvements ----------------- @@ -76,8 +69,6 @@ COFF Improvements * The generated thunks for delayimports now share the majority of code among thunks, significantly reducing the overhead of using delayimport -* ... - MinGW Improvements ------------------ @@ -95,13 +86,3 @@ MinGW Improvements name, with the new option ``-pdb=`` with an empty value to the option. (The old existing syntax ``-pdb `` was more cumbersome to use with an empty parameter value.) - -MachO Improvements ------------------- - -* Item 1. - -WebAssembly Improvements ------------------------- - -* ... From a400f310c285484689422c07dc7b450ee33b7024 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Thu, 29 Aug 2019 14:34:13 +0000 Subject: [PATCH 188/289] ReleaseNotes: remove in-progress warning and empty sections llvm-svn: 370366 --- libcxx/docs/ReleaseNotes.rst | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/libcxx/docs/ReleaseNotes.rst b/libcxx/docs/ReleaseNotes.rst index 29cee441839d..2322a93665ac 100644 --- a/libcxx/docs/ReleaseNotes.rst +++ b/libcxx/docs/ReleaseNotes.rst @@ -1,6 +1,6 @@ -======================================== -Libc++ 9.0.0 (In-Progress) Release Notes -======================================== +========================== +Libc++ 9.0.0 Release Notes +========================== .. contents:: :local: @@ -8,11 +8,6 @@ Libc++ 9.0.0 (In-Progress) Release Notes Written by the `Libc++ Team `_ -.. warning:: - - These are in-progress notes for the upcoming libc++ 9 release. - Release notes for previous releases can be found on - `the Download Page `_. Introduction ============ @@ -27,17 +22,6 @@ be downloaded from the `LLVM releases web site `_. For more information about libc++, please see the `Libc++ Web Site `_ or the `LLVM Web Site `_. -Note that if you are reading this file from a Subversion checkout or the -main Libc++ web page, this document applies to the *next* release, not -the current one. To see the release notes for a specific release, please -see the `releases page `_. What's New in Libc++ 9.0.0? =========================== - -New Features ------------- - -API Changes ------------ -- ... From 16d2d313fa340f33300e1d0eaec5b966af016c23 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Thu, 29 Aug 2019 14:52:23 +0000 Subject: [PATCH 189/289] Merging r370367: ------------------------------------------------------------------------ r370367 | kadircet | 2019-08-29 16:38:02 +0200 (Thu, 29 Aug 2019) | 13 lines [clangd][NFC] Update background-index command line description Summary: We didn't change this in D64019 just in case we revert it back. Deleting it now. Reviewers: hokein, sammccall Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D66943 ------------------------------------------------------------------------ llvm-svn: 370370 --- clang-tools-extra/clangd/tool/ClangdMain.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/clang-tools-extra/clangd/tool/ClangdMain.cpp b/clang-tools-extra/clangd/tool/ClangdMain.cpp index c047a9531e6a..7336daa253ad 100644 --- a/clang-tools-extra/clangd/tool/ClangdMain.cpp +++ b/clang-tools-extra/clangd/tool/ClangdMain.cpp @@ -122,8 +122,7 @@ opt ShowOrigins{ opt EnableBackgroundIndex{ "background-index", cat(Features), - desc("Index project code in the background and persist index on disk. " - "Experimental"), + desc("Index project code in the background and persist index on disk."), init(true), }; From 3c8c55701d057d48f45dfa4a2c95d07529700583 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Fri, 30 Aug 2019 07:27:12 +0000 Subject: [PATCH 190/289] Merging r368164: ------------------------------------------------------------------------ r368164 | s.desmalen | 2019-08-07 14:41:38 +0200 (Wed, 07 Aug 2019) | 13 lines [AArch64][WinCFI] Do not pair callee-save instructions in LoadStoreOptimizer Prevent the LoadStoreOptimizer from pairing any load/store instructions with instructions from the prologue/epilogue if the CFI information has encoded the operations as separate instructions. This would otherwise lead to a mismatch of the actual prologue size from the size as recorded in the Windows CFI. Reviewers: efriedma, mstorsjo, ssijaric Reviewed By: efriedma Differential Revision: https://reviews.llvm.org/D65817 ------------------------------------------------------------------------ llvm-svn: 370438 --- llvm/lib/Target/AArch64/AArch64InstrInfo.cpp | 12 ++++++++++++ llvm/test/CodeGen/AArch64/wineh1.mir | 12 ++++++++++-- llvm/test/CodeGen/AArch64/wineh2.mir | 4 ++-- .../COFF/AArch64/arm64-register-variables.ll | 4 ++-- 4 files changed, 26 insertions(+), 6 deletions(-) diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp index 215e96a82d0e..fa9e5d808c4f 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp @@ -32,6 +32,7 @@ #include "llvm/CodeGen/TargetSubtargetInfo.h" #include "llvm/IR/DebugLoc.h" #include "llvm/IR/GlobalValue.h" +#include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCInstrDesc.h" #include "llvm/Support/Casting.h" @@ -1928,6 +1929,17 @@ bool AArch64InstrInfo::isCandidateToMergeOrPair(const MachineInstr &MI) const { if (isLdStPairSuppressed(MI)) return false; + // Do not pair any callee-save store/reload instructions in the + // prologue/epilogue if the CFI information encoded the operations as separate + // instructions, as that will cause the size of the actual prologue to mismatch + // with the prologue size recorded in the Windows CFI. + const MCAsmInfo *MAI = MI.getMF()->getTarget().getMCAsmInfo(); + bool NeedsWinCFI = MAI->usesWindowsCFI() && + MI.getMF()->getFunction().needsUnwindTableEntry(); + if (NeedsWinCFI && (MI.getFlag(MachineInstr::FrameSetup) || + MI.getFlag(MachineInstr::FrameDestroy))) + return false; + // On some CPUs quad load/store pairs are slower than two single load/stores. if (Subtarget.isPaired128Slow()) { switch (MI.getOpcode()) { diff --git a/llvm/test/CodeGen/AArch64/wineh1.mir b/llvm/test/CodeGen/AArch64/wineh1.mir index b01d4cb529c1..1ffaa25d30d8 100644 --- a/llvm/test/CodeGen/AArch64/wineh1.mir +++ b/llvm/test/CodeGen/AArch64/wineh1.mir @@ -1,5 +1,7 @@ # RUN: llc -o - %s -mtriple=aarch64-windows -start-after=prologepilog -filetype=obj \ # RUN: | llvm-readobj --unwind | FileCheck %s +# RUN: llc -o - %s -mtriple=aarch64-windows -run-pass=aarch64-ldst-opt \ +# RUN: | FileCheck %s --check-prefix=CHECK-LDSTOPT # This test case checks the basic validity of the .xdata section. It's # documented at: # https://docs.microsoft.com/en-us/cpp/build/arm64-exception-handling @@ -7,7 +9,7 @@ # We expect to see the following in the .xdata section: # CHECK: ExceptionData { -# CHECK-NEXT: FunctionLength: 92 +# CHECK-NEXT: FunctionLength: 96 # CHECK-NEXT: Version: 0 # CHECK-NEXT: ExceptionData: No # CHECK-NEXT: EpiloguePacked: No @@ -24,7 +26,7 @@ # CHECK-NEXT: ] # CHECK-NEXT: EpilogueScopes [ # CHECK-NEXT: EpilogueScope { -# CHECK-NEXT: StartOffset: 15 +# CHECK-NEXT: StartOffset: 16 # CHECK-NEXT: EpilogueStartIndex: 13 # CHECK-NEXT: Opcodes [ # CHECK-NEXT: 0xc808 ; ldp x19, x20, [sp, #64] @@ -39,6 +41,12 @@ # CHECK-NEXT: } # CHECK-NEXT: ] # CHECK-NEXT: } + +# Check that the load-store optimizer does not merge the two +# callee-saved stores in the prologue. +# CHECK-LDSTOPT: name: test +# CHECK-LDSTOPT: frame-setup STRXui killed $x21, $sp, 6 +# CHECK-LDSTOPT: frame-setup STRXui killed $x22, $sp, 7 ... --- name: test diff --git a/llvm/test/CodeGen/AArch64/wineh2.mir b/llvm/test/CodeGen/AArch64/wineh2.mir index 9352181c473f..05a232f753f3 100644 --- a/llvm/test/CodeGen/AArch64/wineh2.mir +++ b/llvm/test/CodeGen/AArch64/wineh2.mir @@ -3,7 +3,7 @@ # Test that the pre/post increment save of a flating point register is correct. # CHECK: ExceptionData { -# CHECK-NEXT: FunctionLength: 136 +# CHECK-NEXT: FunctionLength: 144 # CHECK-NEXT: Version: 0 # CHECK-NEXT: ExceptionData: No # CHECK-NEXT: EpiloguePacked: No @@ -23,7 +23,7 @@ # CHECK-NEXT: ] # CHECK-NEXT: EpilogueScopes [ # CHECK-NEXT: EpilogueScope { -# CHECK-NEXT: StartOffset: 25 +# CHECK-NEXT: StartOffset: 26 # CHECK-NEXT: EpilogueStartIndex: 19 # CHECK-NEXT: Opcodes [ # CHECK-NEXT: 0xc80e ; ldp x19, x20, [sp, #112] diff --git a/llvm/test/DebugInfo/COFF/AArch64/arm64-register-variables.ll b/llvm/test/DebugInfo/COFF/AArch64/arm64-register-variables.ll index daa7da201d53..c02eea5da504 100644 --- a/llvm/test/DebugInfo/COFF/AArch64/arm64-register-variables.ll +++ b/llvm/test/DebugInfo/COFF/AArch64/arm64-register-variables.ll @@ -28,9 +28,9 @@ ; OBJ: OffsetInParent: 0 ; OBJ: BasePointerOffset: 12 ; OBJ: LocalVariableAddrRange { -; OBJ: OffsetStart: .text+0x10 +; OBJ: OffsetStart: .text+0x14 ; OBJ: ISectStart: 0x0 -; OBJ: Range: 0x2C +; OBJ: Range: 0x30 ; OBJ: } ; OBJ: } From 92734ca8d6272ffb137061b8a21ea381292093e1 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Fri, 30 Aug 2019 07:34:24 +0000 Subject: [PATCH 191/289] =?UTF-8?q?ReleaseNotes:=20pocl=20and=20TCE;=20by?= =?UTF-8?q?=20Pekka=20J=C3=A4=C3=A4skel=C3=A4inen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit llvm-svn: 370439 --- llvm/docs/ReleaseNotes.rst | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst index 41b60c3bc69b..f7a99bd41cbb 100644 --- a/llvm/docs/ReleaseNotes.rst +++ b/llvm/docs/ReleaseNotes.rst @@ -299,6 +299,35 @@ Mull - Mutation Testing tool for C and C++ `Mull `_ is an LLVM-based tool for mutation testing with a strong focus on C and C++ languages. +Portable Computing Language (pocl) +---------------------------------- + +In addition to producing an easily portable open source OpenCL +implementation, another major goal of `pocl `_ +is improving performance portability of OpenCL programs with +compiler optimizations, reducing the need for target-dependent manual +optimizations. An important part of pocl is a set of LLVM passes used to +statically parallelize multiple work-items with the kernel compiler, even in +the presence of work-group barriers. This enables static parallelization of +the fine-grained static concurrency in the work groups in multiple ways. + +TTA-based Co-design Environment (TCE) +------------------------------------- + +`TCE `_ is an open source toolset for designing customized +processors based on the Transport Triggered Architecture (TTA). +The toolset provides a complete co-design flow from C/C++ +programs down to synthesizable VHDL/Verilog and parallel program binaries. +Processor customization points include register files, function units, +supported operations, and the interconnection network. + +TCE uses Clang and LLVM for C/C++/OpenCL C language support, target independent +optimizations and also for parts of code generation. It generates new +LLVM-based code generators "on the fly" for the designed TTA processors and +loads them in to the compiler backend as runtime libraries to avoid +per-target recompilation of larger parts of the compiler chain. + + Zig Programming Language ------------------------ @@ -311,7 +340,6 @@ LLD combined with lazily building compiler-rt to provide out-of-the-box cross-compiling for all supported targets. - Additional Information ====================== From 25f22e70b01f78407dafa773db27a98b86fb0113 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Fri, 30 Aug 2019 09:02:10 +0000 Subject: [PATCH 192/289] Merging r370404: ------------------------------------------------------------------------ r370404 | rksimon | 2019-08-29 22:22:08 +0200 (Thu, 29 Aug 2019) | 3 lines [X86][SSE] combinePMULDQ - pmuldq(x, 0) -> zero vector (PR43159) ISD::isBuildVectorAllZeros permits undef elements to be present, which means we can't return it as a zero vector. PMULDQ/PMULUDQ is an extending multiply so a multiply by zero of the lower 32-bits should result in a zero 64-bit element. ------------------------------------------------------------------------ llvm-svn: 370445 --- llvm/lib/Target/X86/X86ISelLowering.cpp | 8 +- llvm/test/CodeGen/X86/combine-pmuldq.ll | 115 ++++++++++++++++++++++++ 2 files changed, 120 insertions(+), 3 deletions(-) diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index 6f8240e745ce..eecf34902ddc 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -44104,7 +44104,8 @@ static SDValue combineScalarToVector(SDNode *N, SelectionDAG &DAG) { // Simplify PMULDQ and PMULUDQ operations. static SDValue combinePMULDQ(SDNode *N, SelectionDAG &DAG, - TargetLowering::DAGCombinerInfo &DCI) { + TargetLowering::DAGCombinerInfo &DCI, + const X86Subtarget &Subtarget) { SDValue LHS = N->getOperand(0); SDValue RHS = N->getOperand(1); @@ -44114,8 +44115,9 @@ static SDValue combinePMULDQ(SDNode *N, SelectionDAG &DAG, return DAG.getNode(N->getOpcode(), SDLoc(N), N->getValueType(0), RHS, LHS); // Multiply by zero. + // Don't return RHS as it may contain UNDEFs. if (ISD::isBuildVectorAllZeros(RHS.getNode())) - return RHS; + return getZeroVector(N->getSimpleValueType(0), Subtarget, DAG, SDLoc(N)); // Aggressively peek through ops to get at the demanded low bits. APInt DemandedMask = APInt::getLowBitsSet(64, 32); @@ -44323,7 +44325,7 @@ SDValue X86TargetLowering::PerformDAGCombine(SDNode *N, case X86ISD::PCMPEQ: case X86ISD::PCMPGT: return combineVectorCompare(N, DAG, Subtarget); case X86ISD::PMULDQ: - case X86ISD::PMULUDQ: return combinePMULDQ(N, DAG, DCI); + case X86ISD::PMULUDQ: return combinePMULDQ(N, DAG, DCI, Subtarget); } return SDValue(); diff --git a/llvm/test/CodeGen/X86/combine-pmuldq.ll b/llvm/test/CodeGen/X86/combine-pmuldq.ll index 5b5ae387f41e..82387c936233 100644 --- a/llvm/test/CodeGen/X86/combine-pmuldq.ll +++ b/llvm/test/CodeGen/X86/combine-pmuldq.ll @@ -172,3 +172,118 @@ bb34: ; preds = %bb10 %tmp35 = add <4 x i64> %tmp29, %tmp28 ret void } + +define i32 @PR43159(<4 x i32>* %a0) { +; SSE-LABEL: PR43159: +; SSE: # %bb.0: # %entry +; SSE-NEXT: movdqa (%rdi), %xmm0 +; SSE-NEXT: movdqa {{.*#+}} xmm1 = [1645975491,344322273,2164392969,1916962805] +; SSE-NEXT: pshufd {{.*#+}} xmm2 = xmm1[1,1,3,3] +; SSE-NEXT: pshufd {{.*#+}} xmm3 = xmm0[1,1,3,3] +; SSE-NEXT: pmuludq %xmm2, %xmm3 +; SSE-NEXT: movdqa %xmm0, %xmm2 +; SSE-NEXT: psrld $1, %xmm2 +; SSE-NEXT: pblendw {{.*#+}} xmm2 = xmm0[0,1,2,3],xmm2[4,5],xmm0[6,7] +; SSE-NEXT: pmuludq %xmm1, %xmm2 +; SSE-NEXT: pshufd {{.*#+}} xmm1 = xmm2[1,1,3,3] +; SSE-NEXT: pblendw {{.*#+}} xmm1 = xmm1[0,1],xmm3[2,3],xmm1[4,5],xmm3[6,7] +; SSE-NEXT: psubd %xmm1, %xmm0 +; SSE-NEXT: pshufd {{.*#+}} xmm0 = xmm0[1,1,3,3] +; SSE-NEXT: pmuludq {{.*}}(%rip), %xmm0 +; SSE-NEXT: pxor %xmm2, %xmm2 +; SSE-NEXT: pblendw {{.*#+}} xmm2 = xmm2[0,1],xmm0[2,3],xmm2[4,5],xmm0[6,7] +; SSE-NEXT: paddd %xmm1, %xmm2 +; SSE-NEXT: movdqa %xmm2, %xmm0 +; SSE-NEXT: psrld $7, %xmm0 +; SSE-NEXT: psrld $6, %xmm2 +; SSE-NEXT: movd %xmm2, %edi +; SSE-NEXT: pextrd $1, %xmm0, %esi +; SSE-NEXT: pextrd $2, %xmm2, %edx +; SSE-NEXT: pextrd $3, %xmm0, %ecx +; SSE-NEXT: jmp foo # TAILCALL +; +; AVX2-LABEL: PR43159: +; AVX2: # %bb.0: # %entry +; AVX2-NEXT: vmovdqa (%rdi), %xmm0 +; AVX2-NEXT: vmovdqa {{.*#+}} xmm1 = [1645975491,344322273,2164392969,1916962805] +; AVX2-NEXT: vpshufd {{.*#+}} xmm2 = xmm1[1,1,3,3] +; AVX2-NEXT: vpsrlvd {{.*}}(%rip), %xmm0, %xmm3 +; AVX2-NEXT: vpshufd {{.*#+}} xmm4 = xmm3[1,1,3,3] +; AVX2-NEXT: vpmuludq %xmm2, %xmm4, %xmm2 +; AVX2-NEXT: vpmuludq %xmm1, %xmm3, %xmm1 +; AVX2-NEXT: vpshufd {{.*#+}} xmm1 = xmm1[1,1,3,3] +; AVX2-NEXT: vpblendd {{.*#+}} xmm1 = xmm1[0],xmm2[1],xmm1[2],xmm2[3] +; AVX2-NEXT: vpsubd %xmm1, %xmm0, %xmm0 +; AVX2-NEXT: vpshufd {{.*#+}} xmm0 = xmm0[1,1,3,3] +; AVX2-NEXT: vpbroadcastd {{.*#+}} xmm2 = [2147483648,2147483648,2147483648,2147483648] +; AVX2-NEXT: vpmuludq %xmm2, %xmm0, %xmm0 +; AVX2-NEXT: vpxor %xmm2, %xmm2, %xmm2 +; AVX2-NEXT: vpblendd {{.*#+}} xmm0 = xmm2[0],xmm0[1],xmm2[2],xmm0[3] +; AVX2-NEXT: vpaddd %xmm1, %xmm0, %xmm0 +; AVX2-NEXT: vpsrlvd {{.*}}(%rip), %xmm0, %xmm0 +; AVX2-NEXT: vmovd %xmm0, %edi +; AVX2-NEXT: vpextrd $1, %xmm0, %esi +; AVX2-NEXT: vpextrd $2, %xmm0, %edx +; AVX2-NEXT: vpextrd $3, %xmm0, %ecx +; AVX2-NEXT: jmp foo # TAILCALL +; +; AVX512VL-LABEL: PR43159: +; AVX512VL: # %bb.0: # %entry +; AVX512VL-NEXT: vmovdqa (%rdi), %xmm0 +; AVX512VL-NEXT: vmovdqa {{.*#+}} xmm1 = [1645975491,344322273,2164392969,1916962805] +; AVX512VL-NEXT: vpshufd {{.*#+}} xmm2 = xmm1[1,1,3,3] +; AVX512VL-NEXT: vpsrlvd {{.*}}(%rip), %xmm0, %xmm3 +; AVX512VL-NEXT: vpshufd {{.*#+}} xmm4 = xmm3[1,1,3,3] +; AVX512VL-NEXT: vpmuludq %xmm2, %xmm4, %xmm2 +; AVX512VL-NEXT: vpmuludq %xmm1, %xmm3, %xmm1 +; AVX512VL-NEXT: vpshufd {{.*#+}} xmm1 = xmm1[1,1,3,3] +; AVX512VL-NEXT: vpblendd {{.*#+}} xmm1 = xmm1[0],xmm2[1],xmm1[2],xmm2[3] +; AVX512VL-NEXT: vpsubd %xmm1, %xmm0, %xmm0 +; AVX512VL-NEXT: vpshufd {{.*#+}} xmm0 = xmm0[1,1,3,3] +; AVX512VL-NEXT: vpbroadcastd {{.*#+}} xmm2 = [2147483648,2147483648,2147483648,2147483648] +; AVX512VL-NEXT: vpmuludq %xmm2, %xmm0, %xmm0 +; AVX512VL-NEXT: vpxor %xmm2, %xmm2, %xmm2 +; AVX512VL-NEXT: vpblendd {{.*#+}} xmm0 = xmm2[0],xmm0[1],xmm2[2],xmm0[3] +; AVX512VL-NEXT: vpaddd %xmm1, %xmm0, %xmm0 +; AVX512VL-NEXT: vpsrlvd {{.*}}(%rip), %xmm0, %xmm0 +; AVX512VL-NEXT: vmovd %xmm0, %edi +; AVX512VL-NEXT: vpextrd $1, %xmm0, %esi +; AVX512VL-NEXT: vpextrd $2, %xmm0, %edx +; AVX512VL-NEXT: vpextrd $3, %xmm0, %ecx +; AVX512VL-NEXT: jmp foo # TAILCALL +; +; AVX512DQVL-LABEL: PR43159: +; AVX512DQVL: # %bb.0: # %entry +; AVX512DQVL-NEXT: vmovdqa (%rdi), %xmm0 +; AVX512DQVL-NEXT: vmovdqa {{.*#+}} xmm1 = [1645975491,344322273,2164392969,1916962805] +; AVX512DQVL-NEXT: vpshufd {{.*#+}} xmm2 = xmm1[1,1,3,3] +; AVX512DQVL-NEXT: vpsrlvd {{.*}}(%rip), %xmm0, %xmm3 +; AVX512DQVL-NEXT: vpshufd {{.*#+}} xmm4 = xmm3[1,1,3,3] +; AVX512DQVL-NEXT: vpmuludq %xmm2, %xmm4, %xmm2 +; AVX512DQVL-NEXT: vpmuludq %xmm1, %xmm3, %xmm1 +; AVX512DQVL-NEXT: vpshufd {{.*#+}} xmm1 = xmm1[1,1,3,3] +; AVX512DQVL-NEXT: vpblendd {{.*#+}} xmm1 = xmm1[0],xmm2[1],xmm1[2],xmm2[3] +; AVX512DQVL-NEXT: vpsubd %xmm1, %xmm0, %xmm0 +; AVX512DQVL-NEXT: vpshufd {{.*#+}} xmm0 = xmm0[1,1,3,3] +; AVX512DQVL-NEXT: vpbroadcastd {{.*#+}} xmm2 = [2147483648,2147483648,2147483648,2147483648] +; AVX512DQVL-NEXT: vpmuludq %xmm2, %xmm0, %xmm0 +; AVX512DQVL-NEXT: vpxor %xmm2, %xmm2, %xmm2 +; AVX512DQVL-NEXT: vpblendd {{.*#+}} xmm0 = xmm2[0],xmm0[1],xmm2[2],xmm0[3] +; AVX512DQVL-NEXT: vpaddd %xmm1, %xmm0, %xmm0 +; AVX512DQVL-NEXT: vpsrlvd {{.*}}(%rip), %xmm0, %xmm0 +; AVX512DQVL-NEXT: vmovd %xmm0, %edi +; AVX512DQVL-NEXT: vpextrd $1, %xmm0, %esi +; AVX512DQVL-NEXT: vpextrd $2, %xmm0, %edx +; AVX512DQVL-NEXT: vpextrd $3, %xmm0, %ecx +; AVX512DQVL-NEXT: jmp foo # TAILCALL +entry: + %0 = load <4 x i32>, <4 x i32>* %a0, align 16 + %div = udiv <4 x i32> %0, + %ext0 = extractelement <4 x i32> %div, i32 0 + %ext1 = extractelement <4 x i32> %div, i32 1 + %ext2 = extractelement <4 x i32> %div, i32 2 + %ext3 = extractelement <4 x i32> %div, i32 3 + %call = tail call i32 @foo(i32 %ext0, i32 %ext1, i32 %ext2, i32 %ext3) + ret i32 %call +} +declare dso_local i32 @foo(i32, i32, i32, i32) From 892dfd7d4e3b9668bcde192a68c358449ffe41f9 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Fri, 30 Aug 2019 09:06:49 +0000 Subject: [PATCH 193/289] Merging r370355: ------------------------------------------------------------------------ r370355 | joerg | 2019-08-29 15:22:30 +0200 (Thu, 29 Aug 2019) | 5 lines Allow replaceAndRecursivelySimplify to list unsimplified visitees. This is part of D65280 and split it to avoid ABI changes on the 9.0 release branch. ------------------------------------------------------------------------ llvm-svn: 370447 --- .../llvm/Analysis/InstructionSimplify.h | 11 ++++--- llvm/lib/Analysis/InstructionSimplify.cpp | 30 +++++++++++-------- 2 files changed, 25 insertions(+), 16 deletions(-) diff --git a/llvm/include/llvm/Analysis/InstructionSimplify.h b/llvm/include/llvm/Analysis/InstructionSimplify.h index 054ffca7215e..c36ad4c50df9 100644 --- a/llvm/include/llvm/Analysis/InstructionSimplify.h +++ b/llvm/include/llvm/Analysis/InstructionSimplify.h @@ -31,6 +31,7 @@ #ifndef LLVM_ANALYSIS_INSTRUCTIONSIMPLIFY_H #define LLVM_ANALYSIS_INSTRUCTIONSIMPLIFY_H +#include "llvm/ADT/SetVector.h" #include "llvm/IR/Instruction.h" #include "llvm/IR/Operator.h" #include "llvm/IR/User.h" @@ -263,12 +264,14 @@ Value *SimplifyInstruction(Instruction *I, const SimplifyQuery &Q, /// This first performs a normal RAUW of I with SimpleV. It then recursively /// attempts to simplify those users updated by the operation. The 'I' /// instruction must not be equal to the simplified value 'SimpleV'. +/// If UnsimplifiedUsers is provided, instructions that could not be simplified +/// are added to it. /// /// The function returns true if any simplifications were performed. -bool replaceAndRecursivelySimplify(Instruction *I, Value *SimpleV, - const TargetLibraryInfo *TLI = nullptr, - const DominatorTree *DT = nullptr, - AssumptionCache *AC = nullptr); +bool replaceAndRecursivelySimplify( + Instruction *I, Value *SimpleV, const TargetLibraryInfo *TLI = nullptr, + const DominatorTree *DT = nullptr, AssumptionCache *AC = nullptr, + SmallSetVector *UnsimplifiedUsers = nullptr); /// Recursively attempt to simplify an instruction. /// diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp index e34bf6f4e43f..941a68c5e6fd 100644 --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -5221,14 +5221,16 @@ Value *llvm::SimplifyInstruction(Instruction *I, const SimplifyQuery &SQ, /// If we have a pre-simplified value in 'SimpleV', that is forcibly used to /// replace the instruction 'I'. Otherwise, we simply add 'I' to the list of /// instructions to process and attempt to simplify it using -/// InstructionSimplify. +/// InstructionSimplify. Recursively visited users which could not be +/// simplified themselves are to the optional UnsimplifiedUsers set for +/// further processing by the caller. /// /// This routine returns 'true' only when *it* simplifies something. The passed /// in simplified value does not count toward this. -static bool replaceAndRecursivelySimplifyImpl(Instruction *I, Value *SimpleV, - const TargetLibraryInfo *TLI, - const DominatorTree *DT, - AssumptionCache *AC) { +static bool replaceAndRecursivelySimplifyImpl( + Instruction *I, Value *SimpleV, const TargetLibraryInfo *TLI, + const DominatorTree *DT, AssumptionCache *AC, + SmallSetVector *UnsimplifiedUsers = nullptr) { bool Simplified = false; SmallSetVector Worklist; const DataLayout &DL = I->getModule()->getDataLayout(); @@ -5258,8 +5260,11 @@ static bool replaceAndRecursivelySimplifyImpl(Instruction *I, Value *SimpleV, // See if this instruction simplifies. SimpleV = SimplifyInstruction(I, {DL, TLI, DT, AC}); - if (!SimpleV) + if (!SimpleV) { + if (UnsimplifiedUsers) + UnsimplifiedUsers->insert(I); continue; + } Simplified = true; @@ -5285,16 +5290,17 @@ bool llvm::recursivelySimplifyInstruction(Instruction *I, const TargetLibraryInfo *TLI, const DominatorTree *DT, AssumptionCache *AC) { - return replaceAndRecursivelySimplifyImpl(I, nullptr, TLI, DT, AC); + return replaceAndRecursivelySimplifyImpl(I, nullptr, TLI, DT, AC, nullptr); } -bool llvm::replaceAndRecursivelySimplify(Instruction *I, Value *SimpleV, - const TargetLibraryInfo *TLI, - const DominatorTree *DT, - AssumptionCache *AC) { +bool llvm::replaceAndRecursivelySimplify( + Instruction *I, Value *SimpleV, const TargetLibraryInfo *TLI, + const DominatorTree *DT, AssumptionCache *AC, + SmallSetVector *UnsimplifiedUsers) { assert(I != SimpleV && "replaceAndRecursivelySimplify(X,X) is not valid!"); assert(SimpleV && "Must provide a simplified value."); - return replaceAndRecursivelySimplifyImpl(I, SimpleV, TLI, DT, AC); + return replaceAndRecursivelySimplifyImpl(I, SimpleV, TLI, DT, AC, + UnsimplifiedUsers); } namespace llvm { From bb081fe66dbc9e298d6882ebc414c28ae96844ec Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Fri, 30 Aug 2019 09:22:24 +0000 Subject: [PATCH 194/289] Re-generate {Attribute,ClangCommandLine,Diagnostics}Reference.rst $ bin/clang-tblgen -gen-diag-docs -I../cfe.src/include \ -I../cfe.src/include/clang/Basic/ \ ../cfe.src/include/clang/Basic/Diagnostic.td -o \ ../cfe.src/docs/DiagnosticsReference.rst && \ bin/clang-tblgen -gen-attr-docs -I../cfe.src/include \ ../cfe.src/include/clang/Basic/Attr.td -o \ ../cfe.src/docs/AttributeReference.rst && \ bin/clang-tblgen -gen-opt-docs -I../cfe.src/include \ -I../cfe.src/include/clang/Driver -I../llvm.src/include \ ../cfe.src/include/clang/Driver/ClangOptionDocs.td -o \ ../cfe.src/docs/ClangCommandLineReference.rst llvm-svn: 370450 --- clang/docs/DiagnosticsReference.rst | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/clang/docs/DiagnosticsReference.rst b/clang/docs/DiagnosticsReference.rst index 0b6241213083..fe0325bed2a7 100644 --- a/clang/docs/DiagnosticsReference.rst +++ b/clang/docs/DiagnosticsReference.rst @@ -6028,6 +6028,17 @@ Some of the diagnostics controlled by this flag are enabled by default. Controls `-Wincomplete-umbrella`_, `-Wnon-modular-include-in-module`_. +-Wincomplete-setjmp-declaration +------------------------------- +This diagnostic is enabled by default. + +**Diagnostic text:** + ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ +|:warning:`warning:` |nbsp| :diagtext:`declaration of built-in function '`:placeholder:`A`:diagtext:`' requires the declaration of the 'jmp\_buf' type, commonly provided in the header .`| ++---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ + + -Wincomplete-umbrella --------------------- This diagnostic is enabled by default. From 1cf7a88045ced9f19f5e6dc0add51723d39eef7f Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Fri, 30 Aug 2019 15:15:53 +0000 Subject: [PATCH 195/289] index.rst: Remove non-release warning llvm-svn: 370477 --- llvm/docs/index.rst | 5 ----- 1 file changed, 5 deletions(-) diff --git a/llvm/docs/index.rst b/llvm/docs/index.rst index cf1476789047..02779ff4534f 100644 --- a/llvm/docs/index.rst +++ b/llvm/docs/index.rst @@ -1,11 +1,6 @@ Overview ======== -.. warning:: - - If you are using a released version of LLVM, see `the download page - `_ to find your documentation. - The LLVM compiler infrastructure supports a wide range of projects, from industrial strength compilers to specialized JIT applications to small research projects. From fa0bc006900f17df3c11a40a3eb69e6330433b0e Mon Sep 17 00:00:00 2001 From: Zoe Carver Date: Fri, 30 Aug 2019 20:04:14 +0000 Subject: [PATCH 196/289] Update libc++ release notes This patch updates the libc++ release notes. I have picked out several features/fixes/updates that I think are worth mentioning. llvm-svn: 370514 --- libcxx/docs/ReleaseNotes.rst | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/libcxx/docs/ReleaseNotes.rst b/libcxx/docs/ReleaseNotes.rst index 2322a93665ac..6bf62b7fa4ae 100644 --- a/libcxx/docs/ReleaseNotes.rst +++ b/libcxx/docs/ReleaseNotes.rst @@ -25,3 +25,36 @@ For more information about libc++, please see the `Libc++ Web Site What's New in Libc++ 9.0.0? =========================== + +Fixes +----- + +* Minor fixes to ``std::chrono`` operators. +* libc++ now correctly handles Objective-C++ ARC qualifiers in ``std::is_pointer``. +* ``std::span`` general updates and fixes. +* Updates to the ``std::abs`` implementation. +* ``std::to_chars`` now adds leading zeros. +* Ensure ``std::tuple`` is trivially constructible. +* ``std::aligned_union`` now works in C++03. +* Output of nullptr to ``std::basic_ostream`` is formatted properly. + +Features +-------- + +* Implemented P0608: sane variant converting constructor. +* Added ``ssize`` function. +* Added ``front`` and ``back`` methods in ``std::span``. +* ``std::is_unbounded_array`` and ``std::is_bounded_array`` added to type traits. +* ``std::atomic`` now includes many new features and specialization including improved Freestanding support. +* Added ``std::midpoint`` and ``std::lerp`` math functions. +* Added the function ``std::is_constant_evaluated``. +* Erase-like algorithms now return size type. +* Added ``contains`` method to container types. +* ``std::swap`` is now a constant expression. + +Updates +------- + +* libc++ dropped support for GCC 4.9; we now support GCC 5.1 and above. +* libc++ added explicit support for WebAssembly System Interface (WASI). +* Progress towards full support of rvalues and variadics in C++03 mode. ``std::move`` and ``std::forward`` now both work in C++03 mode. From 4bc0d50adffae18787390319029d5a49cfa3b480 Mon Sep 17 00:00:00 2001 From: Rui Ueyama Date: Thu, 5 Sep 2019 09:00:16 +0000 Subject: [PATCH 197/289] Update ReleaseNotes for lld 9.0. llvm-svn: 371034 --- lld/docs/ReleaseNotes.rst | 195 +++++++++++++++++++++++++++++++++----- 1 file changed, 170 insertions(+), 25 deletions(-) diff --git a/lld/docs/ReleaseNotes.rst b/lld/docs/ReleaseNotes.rst index ce61cc0d4d74..7b994e9f7bbf 100644 --- a/lld/docs/ReleaseNotes.rst +++ b/lld/docs/ReleaseNotes.rst @@ -8,10 +8,12 @@ lld 9.0.0 Release Notes Introduction ============ -This document contains the release notes for the lld linker, release 9.0.0. -Here we describe the status of lld, including major improvements -from the previous release. All lld releases may be downloaded -from the `LLVM releases web site `_. +lld is a high-performance linker that supports ELF (Unix), COFF +(Windows), Mach-O (macOS), MinGW and WebAssembly. lld is +command-line-compatible with GNU linkers and Microsoft link.exe and is +significantly faster than the system default linkers. + +lld 9.0 has lots of feature improvements and bug fixes. Non-comprehensive list of changes in this release ================================================= @@ -22,52 +24,189 @@ ELF Improvements * ld.lld now has typo suggestions for flags: ``$ ld.lld --call-shared`` now prints ``unknown argument '--call-shared', did you mean '--call_shared'``. + (`r361518 `_) + +* ``--allow-shlib-undefined`` and ``--no-allow-shlib-undefined`` + options are added. ``--no-allow-shlib-undefined`` is the default for + executables. + (`r352826 `_) + +* ``-nmagic`` and ``-omagic`` options are fully supported. + (`r360593 `_) + +* Segment layout has changed. PT_GNU_RELRO, which was previously + placed in the middle of readable/writable PT_LOAD segments, is now + placed at the beginning of them. This change permits lld-produced + ELF files to be read correctly by GNU strip older than 2.31, which + has a bug to discard a PT_GNU_RELRO in the former layout. + +* ``-z common-page-size`` is supported. + (`r360593 `_) + +* Diagnostics messages have improved. A new flag ``--vs-diagnostics`` + alters the format of diagnostic output to enable source hyperlinks + in Microsoft Visual Studio IDE. + +* Linker script compatibility with GNU BFD linker has generally improved. + +* The clang ``--dependent-library`` form of autolinking is supported. + + This feature is added to implement the Windows-style autolinking for + Unix. On Unix, in order to use a library, you usually have to + include a header file provided by the library and then explicitly + link the library with the linker ``-l`` option. On Windows, header + files usually contain pragmas that list needed libraries. Compilers + copies that information to object files, so that linkers can + automatically link needed libraries. ``--dependent-library`` is + added for implementing that Windows semantics on Unix. + (`r360984 `_) + +* AArch64 BTI and PAC are supported. + (`r362793 `_) * lld now supports replacing ``JAL`` with ``JALX`` instructions in case - of MIPS - microMIPS cross-mode jumps. + of MIPS ↔ microMIPS cross-mode jumps. + (`r354311 `_) * lld now creates LA25 thunks for MIPS R6 code. + (`r354312 `_) * Put MIPS-specific .reginfo, .MIPS.options, and .MIPS.abiflags sections into corresponding PT_MIPS_REGINFO, PT_MIPS_OPTIONS, and PT_MIPS_ABIFLAGS segments. +* The quality of RISC-V and PowerPC ports have greatly improved. Many + applications can now be linked by lld. PowerPC64 is now almost + production ready. + +* The Linux kernel for arm32_7, arm64, ppc64le and x86_64 can now be + linked by lld. + +* x86-64 TLSDESC is supported. + (`r361911 `_, + `r362078 `_) + +* DF_STATIC_TLS flag is set for i386 and x86-64 when needed. + (`r353293 `_, + `r353378 `_) + +* The experimental partitioning feature is added to allow a program to + be split into multiple pieces. + + The feature allows you semi-automatically split a single program + into multiple ELF files called "partitions". Since all partitions + share the same memory address space and don't use PLT/GOT, split + programs run as fast as regular programs. + + With the mechanism, you can start a program only with a "main" + partition and load remaining partitions on-demand. For example, you + can split a web browser into a main partition and a PDF reader + sub-partition and load the PDF reader partition only when a user + tries to open a PDF file. + + See https://lld.llvm.org/Partitions.html for more information. + +* If "-" is given as an output filename, lld write the final result + to the standard output. Previously, it created a file "-" in the + current directory. + (`r351852 `_) + +* ``-z ifunc-noplt`` option is added to reduce IFunc function call + overhead in a freestanding environment such as the OS kernel. + + Functions resolved by the IFunc mechanism are usually dispatched via + PLT and thus slower than regular functions because of the cost of + indirection. With ``-z ifunc-noplt``, you can eliminate it by doing + text relocations at load-time. You need a special loader to utilize + this feature. This feature is added for the FreeBSD kernel but can + be used by any operating systems. + (`r360685 `_) + +* ``--undefined-glob`` option is added. The new option is an extension + to ``--undefined`` to take a glob pattern instead of a single symbol + name. + (`r363396 `_) + + COFF Improvements ----------------- * Like the ELF driver, lld-link now has typo suggestions for flags. + (`r361518 `_) -* lld-link now correctly reports duplicate symbol errors for obj files - that were compiled with /Gy. +* lld-link now correctly reports duplicate symbol errors for object + files that were compiled with ``/Gy``. + (`r352590 `_) -* lld-link now correctly reports duplicate symbol errors when several res - input files define resources with the same type, name, and language. - This can be demoted to a warning using ``/force:multipleres``. +* lld-link now correctly reports duplicate symbol errors when several + resource (.res) input files define resources with the same type, + name and language. This can be demoted to a warning using + ``/force:multipleres``. + (`r359829 `_) -* lld-link now rejects more than one resource obj input files, matching - link.exe. Previously, lld-link would silently ignore all but one. - If you hit this: Don't pass resource obj files to the linker, instead pass - res files to the linker directly. Don't put res files in static libraries, - pass them on the command line. +* lld-link now rejects more than one resource object input files, + matching link.exe. Previously, lld-link would silently ignore all + but one. If you hit this: Don't pass resource object files to the + linker, instead pass res files to the linker directly. Don't put + resource files in static libraries, pass them on the command line. + (`r359749 `_) * Having more than two ``/natvis:`` now works correctly; it used to not work for larger binaries before. + (`r327895 `_) * Undefined symbols are now printed only in demangled form. Pass ``/demangle:no`` to see raw symbol names instead. - -* The following flags have been added: ``/functionpadmin``, ``/swaprun:``, - ``/threads:no`` + (`r355878 `_) * Several speed and memory usage improvements. -* Range extension thunks are now created for ARM64, if needed +* Range extension thunks are now created for ARM64, if needed. * lld-link now supports resource object files created by GNU windres and - MS cvtres, not only llvm-cvtres + MS cvtres, not only llvm-cvtres. * The generated thunks for delayimports now share the majority of code - among thunks, significantly reducing the overhead of using delayimport + among thunks, significantly reducing the overhead of using delayimport. + (`r365823 `_) + +* ``IMAGE_REL_ARM{,64}_REL32`` relocations are supported. + (`r352325 `_) + +* Range extension thunks for AArch64 are now supported, so lld can + create large executables for Windows/ARM64. + (`r352929 `_) + +* The following flags have been added: + ``/functionpadmin`` (`r354716 `_), + ``/swaprun:`` (`r359192 `_), + ``/threads:no`` (`r355029 `_), + ``/filealign`` (`r361634 `_) + +WebAssembly Improvements +------------------------ + +* Imports from custom module names are supported. + (`r352828 `_) + +* Symbols that are in llvm.used are no exported by default. + (`r353364 `_) + +* Initial support for PIC and dynamic linking has landed. + (`r357022 `_) + +* wasm-ld now add ``__start_``/``__stop_`` symbols for data sections. + (`r361236 `_) + +* wasm-ld now doesn't report an error on archives without a symbol index. + (`r364338 `_) + +* The following flags have been added: + ``--emit-relocs`` (`r361635 `_), + ``--wrap`` (`r361639 `_), + ``--trace`` and ``--trace-symbol`` + (`r353264 `_). + MinGW Improvements ------------------ @@ -77,12 +216,18 @@ MinGW Improvements DWARF exception handling with libgcc and gcc's crtend.o. * lld now also handles DWARF unwind info generated by GCC, when linking - with libgcc - -* Many more GNU ld options are now supported, which e.g. allows the lld - MinGW frontend to be called by GCC + with libgcc. * PDB output can be requested without manually specifying the PDB file name, with the new option ``-pdb=`` with an empty value to the option. (The old existing syntax ``-pdb `` was more cumbersome to use with an empty parameter value.) + +* ``--no-insert-timestamp`` option is added as an alias to ``/timestamp:0``. + (`r353145 `_) + +* Many more GNU ld options are now supported, which e.g. allows the lld + MinGW frontend to be called by GCC. + +* The following options are added: ``--exclude-all-symbols``, + ``--appcontainer``, ``--emit-relocs``, ``--wrap``, ``--undefined`` From 9831a1cc917273e21b31be3f97da2771596a2816 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Thu, 5 Sep 2019 09:25:04 +0000 Subject: [PATCH 198/289] ReleaseNotes tweaks llvm-svn: 371037 --- lld/docs/ReleaseNotes.rst | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/lld/docs/ReleaseNotes.rst b/lld/docs/ReleaseNotes.rst index 7b994e9f7bbf..768c088203fa 100644 --- a/lld/docs/ReleaseNotes.rst +++ b/lld/docs/ReleaseNotes.rst @@ -13,7 +13,7 @@ lld is a high-performance linker that supports ELF (Unix), COFF command-line-compatible with GNU linkers and Microsoft link.exe and is significantly faster than the system default linkers. -lld 9.0 has lots of feature improvements and bug fixes. +lld 9 has lots of feature improvements and bug fixes. Non-comprehensive list of changes in this release ================================================= @@ -56,7 +56,7 @@ ELF Improvements include a header file provided by the library and then explicitly link the library with the linker ``-l`` option. On Windows, header files usually contain pragmas that list needed libraries. Compilers - copies that information to object files, so that linkers can + copy that information to object files, so that linkers can automatically link needed libraries. ``--dependent-library`` is added for implementing that Windows semantics on Unix. (`r360984 `_) @@ -65,7 +65,7 @@ ELF Improvements (`r362793 `_) * lld now supports replacing ``JAL`` with ``JALX`` instructions in case - of MIPS ↔ microMIPS cross-mode jumps. + of MIPS-microMIPS cross-mode jumps. (`r354311 `_) * lld now creates LA25 thunks for MIPS R6 code. @@ -93,7 +93,7 @@ ELF Improvements * The experimental partitioning feature is added to allow a program to be split into multiple pieces. - The feature allows you semi-automatically split a single program + The feature allows you to semi-automatically split a single program into multiple ELF files called "partitions". Since all partitions share the same memory address space and don't use PLT/GOT, split programs run as fast as regular programs. @@ -104,9 +104,9 @@ ELF Improvements sub-partition and load the PDF reader partition only when a user tries to open a PDF file. - See https://lld.llvm.org/Partitions.html for more information. + See `the documentation `_ for more information. -* If "-" is given as an output filename, lld write the final result +* If "-" is given as an output filename, lld writes the final result to the standard output. Previously, it created a file "-" in the current directory. (`r351852 `_) @@ -161,8 +161,6 @@ COFF Improvements * Several speed and memory usage improvements. -* Range extension thunks are now created for ARM64, if needed. - * lld-link now supports resource object files created by GNU windres and MS cvtres, not only llvm-cvtres. @@ -189,7 +187,7 @@ WebAssembly Improvements * Imports from custom module names are supported. (`r352828 `_) -* Symbols that are in llvm.used are no exported by default. +* Symbols that are in llvm.used are now exported by default. (`r353364 `_) * Initial support for PIC and dynamic linking has landed. From 8b1a3a38388f66de44a1c76d2def01daa5333f76 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Thu, 5 Sep 2019 09:48:06 +0000 Subject: [PATCH 199/289] Merging r370850: ------------------------------------------------------------------------ r370850 | hans | 2019-09-04 10:19:30 +0200 (Wed, 04 Sep 2019) | 20 lines Re-commit r363191 "[MS] Pretend constexpr variable template specializations are inline" While the next Visual Studio update (16.3) will fix this issue, that hasn't shipped yet. Until then Clang wouldn't work with MSVC's headers which seems unfortunate. Let's keep this in until VS 16.3 ships. (See also PR42843.) > Fixes link errors with clang and the latest Visual C++ 14.21.27702 > headers, which was reported as PR42027. > > I chose to intentionally make these things linkonce_odr, i.e. > discardable, so that we don't emit definitions of these things in every > translation unit that includes STL headers. > > Note that this is *not* what MSVC does: MSVC has not yet implemented C++ > DR2387, so they emit fully specialized constexpr variable templates with > static / internal linkage. > > Reviewers: rsmith > > Differential Revision: https://reviews.llvm.org/D63175 ------------------------------------------------------------------------ llvm-svn: 371040 --- clang/lib/AST/ASTContext.cpp | 23 +++++++++++++++---- .../CodeGenCXX/ms-constexpr-var-template.cpp | 11 +++++++++ 2 files changed, 30 insertions(+), 4 deletions(-) create mode 100644 clang/test/CodeGenCXX/ms-constexpr-var-template.cpp diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 468c7f47657d..93bdaafc2ac6 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -9814,10 +9814,25 @@ static GVALinkage basicGVALinkageForVariable(const ASTContext &Context, return StrongLinkage; case TSK_ExplicitSpecialization: - return Context.getTargetInfo().getCXXABI().isMicrosoft() && - VD->isStaticDataMember() - ? GVA_StrongODR - : StrongLinkage; + if (Context.getTargetInfo().getCXXABI().isMicrosoft()) { + // If this is a fully specialized constexpr variable template, pretend it + // was marked inline. MSVC 14.21.27702 headers define _Is_integral in a + // header this way, and we don't want to emit non-discardable definitions + // of these variables in every TU that includes . This + // behavior is non-conforming, since another TU could use an extern + // template declaration for this variable, but for constexpr variables, + // it's unlikely for a user to want to do that. This behavior can be + // removed if the headers change to explicitly mark such variable template + // specializations inline. + if (isa(VD) && VD->isConstexpr()) + return GVA_DiscardableODR; + + // Use ODR linkage for static data members of fully specialized templates + // to prevent duplicate definition errors with MSVC. + if (VD->isStaticDataMember()) + return GVA_StrongODR; + } + return StrongLinkage; case TSK_ExplicitInstantiationDefinition: return GVA_StrongODR; diff --git a/clang/test/CodeGenCXX/ms-constexpr-var-template.cpp b/clang/test/CodeGenCXX/ms-constexpr-var-template.cpp new file mode 100644 index 000000000000..a40f7aacac03 --- /dev/null +++ b/clang/test/CodeGenCXX/ms-constexpr-var-template.cpp @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -emit-llvm -triple=x86_64-windows-msvc -fms-compatibility %s -o - | FileCheck %s + +template constexpr bool _Is_integer = false; +template <> constexpr bool _Is_integer = true; +template <> constexpr bool _Is_integer = false; +extern "C" const bool *escape = &_Is_integer; + +// CHECK: @"??$_Is_integer@H@@3_NB" = linkonce_odr dso_local constant i8 1, comdat, align 1 +// Should not emit _Is_integer, since it's not referenced. +// CHECK-NOT: @"??$_Is_integer@D@@3_NB" +// CHECK: @escape = dso_local global i8* @"??$_Is_integer@H@@3_NB", align 8 From 1b8425cf6f834c14645231d3c2f58fc441f2b524 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Thu, 5 Sep 2019 09:51:30 +0000 Subject: [PATCH 200/289] Merging r369310: ------------------------------------------------------------------------ r369310 | hubert.reinterpretcast | 2019-08-20 01:12:48 +0200 (Tue, 20 Aug 2019) | 24 lines [cmake] Link in LLVMPasses due to dependency by LLVMOrcJIT; NFC Summary: rL367756 (f5c40cb) increases the dependency of LLVMOrcJIT on LLVMPasses. In particular, symbols defined in LLVMPasses that are referenced by the destructor of `PassBuilder` are now referenced by LLVMOrcJIT through `Speculation.cpp.o`. We believe that referencing symbols defined in LLVMPasses in the destructor of `PassBuilder` is valid, and that adding to the set of such symbols is legitimate. To support such cases, this patch adds LLVMPasses to the set of libraries being linked when linking in LLVMOrcJIT causes such symbols from LLVMPasses to be referenced. Reviewers: Whitney, anhtuyen, pree-jackie Reviewed By: pree-jackie Subscribers: mgorny, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D66441 ------------------------------------------------------------------------ llvm-svn: 371042 --- llvm/lib/ExecutionEngine/Orc/CMakeLists.txt | 1 + llvm/tools/lli/CMakeLists.txt | 1 + llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt | 1 + 3 files changed, 3 insertions(+) diff --git a/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt b/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt index 2c1a772da372..d65dc877bf8b 100644 --- a/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt +++ b/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt @@ -33,4 +33,5 @@ target_link_libraries(LLVMOrcJIT PRIVATE LLVMBitReader LLVMBitWriter + LLVMPasses ) diff --git a/llvm/tools/lli/CMakeLists.txt b/llvm/tools/lli/CMakeLists.txt index 42f6c2b2ede4..476c09229e63 100644 --- a/llvm/tools/lli/CMakeLists.txt +++ b/llvm/tools/lli/CMakeLists.txt @@ -12,6 +12,7 @@ set(LLVM_LINK_COMPONENTS MCJIT Object OrcJIT + Passes RuntimeDyld SelectionDAG Support diff --git a/llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt b/llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt index 76b18fd1ba9a..945c9926d26e 100644 --- a/llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt +++ b/llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt @@ -4,6 +4,7 @@ set(LLVM_LINK_COMPONENTS ExecutionEngine Object OrcJIT + Passes RuntimeDyld Support native From 5a661d61f333976d79b6455d7cb27a216166ee67 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Thu, 5 Sep 2019 09:54:36 +0000 Subject: [PATCH 201/289] Merging r370753: ------------------------------------------------------------------------ r370753 | jonpa | 2019-09-03 15:31:22 +0200 (Tue, 03 Sep 2019) | 6 lines [SystemZ] Recognize INLINEASM_BR in backend. SystemZInstrInfo::analyzeBranch() needs to check for INLINEASM_BR instructions, or it will crash. Review: Ulrich Weigand ------------------------------------------------------------------------ llvm-svn: 371043 --- llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp | 4 ++-- llvm/test/CodeGen/SystemZ/asm-20.ll | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) create mode 100644 llvm/test/CodeGen/SystemZ/asm-20.ll diff --git a/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp b/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp index 57c1cf4ec70a..5f7576894e54 100644 --- a/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp +++ b/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp @@ -462,8 +462,8 @@ bool SystemZInstrInfo::analyzeBranch(MachineBasicBlock &MBB, break; // A terminator that isn't a branch can't easily be handled by this - // analysis. - if (!I->isBranch()) + // analysis. Asm goto is not understood / optimized. + if (!I->isBranch() || I->getOpcode() == SystemZ::INLINEASM_BR) return true; // Can't handle indirect branches. diff --git a/llvm/test/CodeGen/SystemZ/asm-20.ll b/llvm/test/CodeGen/SystemZ/asm-20.ll new file mode 100644 index 000000000000..402c038f022e --- /dev/null +++ b/llvm/test/CodeGen/SystemZ/asm-20.ll @@ -0,0 +1,15 @@ +; Test that asm goto can be compiled. +; +; RUN: llc < %s -mtriple=s390x-linux-gnu + +define i32 @c() { +entry: + callbr void asm sideeffect "", "X"(i8* blockaddress(@c, %d)) + to label %asm.fallthrough [label %d] + +asm.fallthrough: ; preds = %entry + br label %d + +d: ; preds = %asm.fallthrough, %entry + ret i32 undef +} From f8b1c25240f6e571d0215fb9b87417337c1b24b3 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Thu, 5 Sep 2019 09:57:35 +0000 Subject: [PATCH 202/289] Merging r370720 and r370721: ------------------------------------------------------------------------ r370720 | bjope | 2019-09-03 11:33:40 +0200 (Tue, 03 Sep 2019) | 13 lines [LV] Precommit test case showing miscompile from PR43166. NFC Summary: Precommit test case showing miscompile from PR43166. Reviewers: fhahn, Ayal Reviewed By: fhahn Subscribers: rkruppe, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D67072 ------------------------------------------------------------------------ ------------------------------------------------------------------------ r370721 | bjope | 2019-09-03 11:33:55 +0200 (Tue, 03 Sep 2019) | 20 lines [LV] Fix miscompiles by adding non-header PHI nodes to AllowedExit Summary: Fold-tail currently supports reduction last-vector-value live-out's, but has yet to support last-scalar-value live-outs, including non-header phi's. As it relies on AllowedExit in order to detect them and bail out we need to add the non-header PHI nodes to AllowedExit, otherwise we end up with miscompiles. Solves https://bugs.llvm.org/show_bug.cgi?id=43166 Reviewers: fhahn, Ayal Reviewed By: fhahn, Ayal Subscribers: anna, hiraditya, rkruppe, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D67074 ------------------------------------------------------------------------ llvm-svn: 371044 --- .../Vectorize/LoopVectorizationLegality.h | 4 +- .../Vectorize/LoopVectorizationLegality.cpp | 1 + .../pr43166-fold-tail-by-masking.ll | 165 ++++++++++++++++++ 3 files changed, 168 insertions(+), 2 deletions(-) create mode 100644 llvm/test/Transforms/LoopVectorize/pr43166-fold-tail-by-masking.ll diff --git a/llvm/include/llvm/Transforms/Vectorize/LoopVectorizationLegality.h b/llvm/include/llvm/Transforms/Vectorize/LoopVectorizationLegality.h index b144006e2628..d7c1c2738ffe 100644 --- a/llvm/include/llvm/Transforms/Vectorize/LoopVectorizationLegality.h +++ b/llvm/include/llvm/Transforms/Vectorize/LoopVectorizationLegality.h @@ -452,8 +452,8 @@ class LoopVectorizationLegality { /// Holds the widest induction type encountered. Type *WidestIndTy = nullptr; - /// Allowed outside users. This holds the induction and reduction - /// vars which can be accessed from outside the loop. + /// Allowed outside users. This holds the variables that can be accessed from + /// outside the loop. SmallPtrSet AllowedExit; /// Can we assume the absence of NaNs. diff --git a/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp b/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp index 6ef8dc2d3cd7..138f18e49c92 100644 --- a/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp +++ b/llvm/lib/Transforms/Vectorize/LoopVectorizationLegality.cpp @@ -631,6 +631,7 @@ bool LoopVectorizationLegality::canVectorizeInstrs() { // Unsafe cyclic dependencies with header phis are identified during // legalization for reduction, induction and first order // recurrences. + AllowedExit.insert(&I); continue; } diff --git a/llvm/test/Transforms/LoopVectorize/pr43166-fold-tail-by-masking.ll b/llvm/test/Transforms/LoopVectorize/pr43166-fold-tail-by-masking.ll new file mode 100644 index 000000000000..d3a8b91ec8e7 --- /dev/null +++ b/llvm/test/Transforms/LoopVectorize/pr43166-fold-tail-by-masking.ll @@ -0,0 +1,165 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -loop-vectorize -force-vector-width=4 -S | FileCheck %s + + +; Test cases below are reduced (and slightly modified) reproducers based on a +; problem seen when compiling a C program like this: +; +; #include +; #include +; +; int y = 0; +; int b = 1; +; int d = 1; +; +; int main() { +; #pragma clang loop vectorize_width(4) +; for (int i = 0; i < 3; ++i) { +; b = (y == 0) ? d : (d / y); +; } +; +; if (b == 1) +; printf("GOOD!\n"); +; else +; printf("BAD!\n"); +; } +; +; When compiled+executed using +; build-all/bin/clang -O1 lv-bug.c && ./a.out +; the result is "GOOD!" +; +; When compiled+executed using +; build-all/bin/clang -O1 lv-bug.c -fvectorize && ./a.out +; the result is "BAD!" + + +; This test case miscompiled with clang 8.0.0 (see PR43166), now we get +; loop not vectorized: Cannot fold tail by masking in the presence of live outs. +; instead. +define i64 @test1(i64 %y) { +; CHECK-LABEL: @test1( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[FOR_BODY:%.*]] +; CHECK: for.body: +; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[COND_END:%.*]] ] +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[Y:%.*]], 0 +; CHECK-NEXT: br i1 [[CMP]], label [[COND_END]], label [[COND_FALSE:%.*]] +; CHECK: cond.false: +; CHECK-NEXT: [[DIV:%.*]] = xor i64 3, [[Y]] +; CHECK-NEXT: br label [[COND_END]] +; CHECK: cond.end: +; CHECK-NEXT: [[COND:%.*]] = phi i64 [ [[DIV]], [[COND_FALSE]] ], [ 77, [[FOR_BODY]] ] +; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I]], 1 +; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 3 +; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY]] +; CHECK: for.cond.cleanup: +; CHECK-NEXT: [[COND_LCSSA:%.*]] = phi i64 [ [[COND]], [[COND_END]] ] +; CHECK-NEXT: ret i64 [[COND_LCSSA]] +; +entry: + br label %for.body + +for.body: + %i = phi i32 [ 0, %entry ], [ %inc, %cond.end ] + %cmp = icmp eq i64 %y, 0 + br i1 %cmp, label %cond.end, label %cond.false + +cond.false: + %div = xor i64 3, %y + br label %cond.end + +cond.end: + %cond = phi i64 [ %div, %cond.false ], [ 77, %for.body ] + %inc = add nuw nsw i32 %i, 1 + %exitcond = icmp eq i32 %inc, 3 + br i1 %exitcond, label %for.cond.cleanup, label %for.body + +for.cond.cleanup: + ret i64 %cond +} + +; This test case miscompiled with clang 8.0.0 (see PR43166), now we get +; loop not vectorized: Cannot fold tail by masking in the presence of live outs. +; instead. +define i64 @test2(i64 %y) { +; CHECK-LABEL: @test2( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[FOR_BODY:%.*]] +; CHECK: for.body: +; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[COND_END:%.*]] ] +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[Y:%.*]], 0 +; CHECK-NEXT: br i1 [[CMP]], label [[COND_END]], label [[COND_FALSE:%.*]] +; CHECK: cond.false: +; CHECK-NEXT: br label [[COND_END]] +; CHECK: cond.end: +; CHECK-NEXT: [[COND:%.*]] = phi i64 [ 55, [[COND_FALSE]] ], [ 77, [[FOR_BODY]] ] +; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I]], 1 +; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 3 +; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY]] +; CHECK: for.cond.cleanup: +; CHECK-NEXT: [[COND_LCSSA:%.*]] = phi i64 [ [[COND]], [[COND_END]] ] +; CHECK-NEXT: ret i64 [[COND_LCSSA]] +; +entry: + br label %for.body + +for.body: + %i = phi i32 [ 0, %entry ], [ %inc, %cond.end ] + %cmp = icmp eq i64 %y, 0 + br i1 %cmp, label %cond.end, label %cond.false + +cond.false: + br label %cond.end + +cond.end: + %cond = phi i64 [ 55, %cond.false ], [ 77, %for.body ] + %inc = add nuw nsw i32 %i, 1 + %exitcond = icmp eq i32 %inc, 3 + br i1 %exitcond, label %for.cond.cleanup, label %for.body + +for.cond.cleanup: + ret i64 %cond +} + +; This test case miscompiled with clang 8.0.0 (see PR43166), now we get +; loop not vectorized: Cannot fold tail by masking in the presence of live outs. +; instead. +define i32 @test3(i64 %y) { +; CHECK-LABEL: @test3( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[FOR_BODY:%.*]] +; CHECK: for.body: +; CHECK-NEXT: [[I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[COND_END:%.*]] ] +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[Y:%.*]], 0 +; CHECK-NEXT: br i1 [[CMP]], label [[COND_END]], label [[COND_FALSE:%.*]] +; CHECK: cond.false: +; CHECK-NEXT: br label [[COND_END]] +; CHECK: cond.end: +; CHECK-NEXT: [[COND:%.*]] = phi i32 [ 55, [[COND_FALSE]] ], [ [[I]], [[FOR_BODY]] ] +; CHECK-NEXT: [[INC]] = add nuw nsw i32 [[I]], 1 +; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[INC]], 3 +; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY]] +; CHECK: for.cond.cleanup: +; CHECK-NEXT: [[COND_LCSSA:%.*]] = phi i32 [ [[COND]], [[COND_END]] ] +; CHECK-NEXT: ret i32 [[COND_LCSSA]] +; +entry: + br label %for.body + +for.body: + %i = phi i32 [ 0, %entry ], [ %inc, %cond.end ] + %cmp = icmp eq i64 %y, 0 + br i1 %cmp, label %cond.end, label %cond.false + +cond.false: + br label %cond.end + +cond.end: + %cond = phi i32 [ 55, %cond.false ], [ %i, %for.body ] + %inc = add nuw nsw i32 %i, 1 + %exitcond = icmp eq i32 %inc, 3 + br i1 %exitcond, label %for.cond.cleanup, label %for.body + +for.cond.cleanup: + ret i32 %cond +} From d8975f4f47d169223f9185e3ebf296ee7ebd93bb Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Thu, 5 Sep 2019 10:50:25 +0000 Subject: [PATCH 203/289] Merging r370430: ------------------------------------------------------------------------ r370430 | djg | 2019-08-30 06:33:22 +0200 (Fri, 30 Aug 2019) | 12 lines [CodeGen] Fix lowering for returning the result of an extractvalue When the number of return values exceeds the number of registers available, SelectionDAGBuilder::visitRet transforms a function's return to use a pointer to a buffer to hold return values. When the returned value is an operator such as extractvalue, the value may have a non-zero result number. Add that number to the indexing when obtaining the values to store. This fixes https://bugs.llvm.org/show_bug.cgi?id=43132. Differential Revision: https://reviews.llvm.org/D66978 ------------------------------------------------------------------------ llvm-svn: 371053 --- .../SelectionDAG/SelectionDAGBuilder.cpp | 2 +- llvm/test/CodeGen/WebAssembly/multi-return.ll | 200 ++++++++++++++++++ 2 files changed, 201 insertions(+), 1 deletion(-) create mode 100644 llvm/test/CodeGen/WebAssembly/multi-return.ll diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index 3c02c36a7d26..4120a401b696 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -1810,7 +1810,7 @@ void SelectionDAGBuilder::visitRet(const ReturnInst &I) { // offsets to its parts don't wrap either. SDValue Ptr = DAG.getObjectPtrOffset(getCurSDLoc(), RetPtr, Offsets[i]); - SDValue Val = RetOp.getValue(i); + SDValue Val = RetOp.getValue(RetOp.getResNo() + i); if (MemVTs[i] != ValueVTs[i]) Val = DAG.getPtrExtOrTrunc(Val, getCurSDLoc(), MemVTs[i]); Chains[i] = DAG.getStore(Chain, getCurSDLoc(), Val, diff --git a/llvm/test/CodeGen/WebAssembly/multi-return.ll b/llvm/test/CodeGen/WebAssembly/multi-return.ll new file mode 100644 index 000000000000..d5db601b8f3a --- /dev/null +++ b/llvm/test/CodeGen/WebAssembly/multi-return.ll @@ -0,0 +1,200 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -asm-verbose=false -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck %s + +target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" +target triple = "wasm32-unknown-unknown" + +; Return multiple values, some of which will be legalized into multiple values. +declare { i64, i128, i192, i128, i64 } @return_multi_multi() + +; Test returning a single value from @return_multi_multi. + +define i64 @test0() { +; CHECK-LABEL: test0 +; CHECK: call return_multi_multi +; CHECK: i64.load $0=, 8($1) +; CHECK: local.copy $push8=, $0 + %t0 = call { i64, i128, i192, i128, i64 } @return_multi_multi() + %t1 = extractvalue { i64, i128, i192, i128, i64 } %t0, 0 + ret i64 %t1 +} + +define i128 @test1() { +; CHECK-LABEL: test1 +; CHECK: call return_multi_multi +; CHECK: i64.load $1=, 16($2) +; CHECK: i32.const $push0=, 24 +; CHECK: i32.add $push1=, $2, $pop0 +; CHECK: i64.load $push2=, 0($pop1) +; CHECK: i64.store 8($0), $pop2 +; CHECK: i64.store 0($0), $1 + %t0 = call { i64, i128, i192, i128, i64 } @return_multi_multi() + %t1 = extractvalue { i64, i128, i192, i128, i64 } %t0, 1 + ret i128 %t1 +} + +define i192 @test2() { +; CHECK-LABEL: test2 +; CHECK: call return_multi_multi +; CHECK: i32.const $push0=, 40 +; CHECK: i32.add $push1=, $3, $pop0 +; CHECK: i64.load $1=, 0($pop1) +; CHECK: i64.load $2=, 32($3) +; CHECK: i32.const $push2=, 48 +; CHECK: i32.add $push3=, $3, $pop2 +; CHECK: i64.load $push4=, 0($pop3) +; CHECK: i64.store 16($0), $pop4 +; CHECK: i64.store 0($0), $2 +; CHECK: i64.store 8($0), $1 + %t0 = call { i64, i128, i192, i128, i64 } @return_multi_multi() + %t1 = extractvalue { i64, i128, i192, i128, i64 } %t0, 2 + ret i192 %t1 +} + +define i128 @test3() { +; CHECK-LABEL: test3 +; CHECK: call return_multi_multi +; CHECK: i64.load $1=, 56($2) +; CHECK: i32.const $push0=, 64 +; CHECK: i32.add $push1=, $2, $pop0 +; CHECK: i64.load $push2=, 0($pop1) +; CHECK: i64.store 8($0), $pop2 +; CHECK: i64.store 0($0), $1 + %t0 = call { i64, i128, i192, i128, i64 } @return_multi_multi() + %t1 = extractvalue { i64, i128, i192, i128, i64 } %t0, 3 + ret i128 %t1 +} + +define i64 @test4() { +; CHECK-LABEL: test4 +; CHECK: call return_multi_multi +; CHECK: i64.load $0=, 72($1) +; CHECK: local.copy $push8=, $0 + %t0 = call { i64, i128, i192, i128, i64 } @return_multi_multi() + %t1 = extractvalue { i64, i128, i192, i128, i64 } %t0, 4 + ret i64 %t1 +} + +; Test returning multiple values from @return_multi_multi. + +define { i64, i128 } @test5() { +; CHECK-LABEL: test5 +; CHECK: call return_multi_multi +; CHECK: i32.const $push10=, 8 +; CHECK: i32.add $push11=, $3, $pop10 +; CHECK: i32.const $push0=, 16 +; CHECK: i32.add $push1=, $pop11, $pop0 +; CHECK: i64.load $1=, 0($pop1) +; CHECK: i64.load $2=, 8($3) +; CHECK: i64.load $push2=, 16($3) +; CHECK: i64.store 8($0), $pop2 +; CHECK: i32.const $push12=, 16 +; CHECK: i32.add $push3=, $0, $pop12 +; CHECK: i64.store 0($pop3), $1 +; CHECK: i64.store 0($0), $2 + %t0 = call { i64, i128, i192, i128, i64 } @return_multi_multi() + %r0 = extractvalue { i64, i128, i192, i128, i64 } %t0, 0 + %r1 = extractvalue { i64, i128, i192, i128, i64 } %t0, 1 + %s0 = insertvalue { i64, i128 } undef, i64 %r0, 0 + %s1 = insertvalue { i64, i128 } %s0, i128 %r1, 1 + ret { i64, i128 } %s1 +} + +define { i128, i128 } @test6() { +; CHECK-LABEL: test6 +; CHECK: call return_multi_multi +; CHECK: i32.const $push0=, 24 +; CHECK: i32.add $push1=, $4, $pop0 +; CHECK: i64.load $1=, 0($pop1) +; CHECK: i32.const $push2=, 64 +; CHECK: i32.add $push3=, $4, $pop2 +; CHECK: i64.load $2=, 0($pop3) +; CHECK: i64.load $3=, 16($4) +; CHECK: i64.load $push4=, 56($4) +; CHECK: i64.store 16($0), $pop4 +; CHECK: i32.const $push5=, 24 +; CHECK: i32.add $push6=, $0, $pop5 +; CHECK: i64.store 0($pop6), $2 +; CHECK: i64.store 0($0), $3 +; CHECK: i64.store 8($0), $1 + %t0 = call { i64, i128, i192, i128, i64 } @return_multi_multi() + %r1 = extractvalue { i64, i128, i192, i128, i64 } %t0, 1 + %r3 = extractvalue { i64, i128, i192, i128, i64 } %t0, 3 + %s0 = insertvalue { i128, i128 } undef, i128 %r1, 0 + %s1 = insertvalue { i128, i128 } %s0, i128 %r3, 1 + ret { i128, i128 } %s1 +} + +define { i64, i192 } @test7() { +; CHECK-LABEL: test7 +; CHECK: call return_multi_multi +; CHECK: i32.const $push2=, 40 +; CHECK: i32.add $push3=, $4, $pop2 +; CHECK: i64.load $1=, 0($pop3) +; CHECK: i64.load $2=, 8($4) +; CHECK: i64.load $3=, 32($4) +; CHECK: i32.const $push0=, 24 +; CHECK: i32.add $push1=, $0, $pop0 +; CHECK: i32.const $push4=, 48 +; CHECK: i32.add $push5=, $4, $pop4 +; CHECK: i64.load $push6=, 0($pop5) +; CHECK: i64.store 0($pop1), $pop6 +; CHECK: i64.store 8($0), $3 +; CHECK: i32.const $push7=, 16 +; CHECK: i32.add $push8=, $0, $pop7 +; CHECK: i64.store 0($pop8), $1 +; CHECK: i64.store 0($0), $2 + %t0 = call { i64, i128, i192, i128, i64 } @return_multi_multi() + %r0 = extractvalue { i64, i128, i192, i128, i64 } %t0, 0 + %r2 = extractvalue { i64, i128, i192, i128, i64 } %t0, 2 + %s0 = insertvalue { i64, i192 } undef, i64 %r0, 0 + %s1 = insertvalue { i64, i192 } %s0, i192 %r2, 1 + ret { i64, i192 } %s1 +} + +define { i128, i192, i128, i64 } @test8() { +; CHECK-LABEL: test8 +; CHECK: call return_multi_multi +; CHECK: i32.const $push0=, 64 +; CHECK: i32.add $push1=, $8, $pop0 +; CHECK: i64.load $1=, 0($pop1) +; CHECK: i32.const $push20=, 8 +; CHECK: i32.add $push21=, $8, $pop20 +; CHECK: i32.const $push2=, 32 +; CHECK: i32.add $push3=, $pop21, $pop2 +; CHECK: i64.load $2=, 0($pop3) +; CHECK: i32.const $push4=, 48 +; CHECK: i32.add $push5=, $8, $pop4 +; CHECK: i64.load $3=, 0($pop5) +; CHECK: i32.const $push6=, 24 +; CHECK: i32.add $push7=, $8, $pop6 +; CHECK: i64.load $4=, 0($pop7) +; CHECK: i64.load $5=, 8($8) +; CHECK: i64.load $6=, 56($8) +; CHECK: i64.load $7=, 32($8) +; CHECK: i64.load $push8=, 16($8) +; CHECK: i64.store 40($0), $pop8 +; CHECK: i32.const $push9=, 48 +; CHECK: i32.add $push10=, $0, $pop9 +; CHECK: i64.store 0($pop10), $4 +; CHECK: i32.const $push22=, 32 +; CHECK: i32.add $push11=, $0, $pop22 +; CHECK: i64.store 0($pop11), $3 +; CHECK: i64.store 16($0), $7 +; CHECK: i32.const $push12=, 24 +; CHECK: i32.add $push13=, $0, $pop12 +; CHECK: i64.store 0($pop13), $2 +; CHECK: i64.store 0($0), $6 +; CHECK: i64.store 8($0), $1 +; CHECK: i64.store 56($0), $5 + %t0 = call { i64, i128, i192, i128, i64 } @return_multi_multi() + %r0 = extractvalue { i64, i128, i192, i128, i64 } %t0, 0 + %r1 = extractvalue { i64, i128, i192, i128, i64 } %t0, 1 + %r2 = extractvalue { i64, i128, i192, i128, i64 } %t0, 2 + %r3 = extractvalue { i64, i128, i192, i128, i64 } %t0, 3 + %s0 = insertvalue { i128, i192, i128, i64 } undef, i128 %r3, 0 + %s1 = insertvalue { i128, i192, i128, i64 } %s0, i192 %r2, 1 + %s2 = insertvalue { i128, i192, i128, i64 } %s1, i128 %r1, 2 + %s3 = insertvalue { i128, i192, i128, i64 } %s2, i64 %r0, 3 + ret { i128, i192, i128, i64 } %s3 +} From ab62fa56a9dba7432cc3330dfa72c492153116dc Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Thu, 5 Sep 2019 11:33:27 +0000 Subject: [PATCH 204/289] Merging r371048: ------------------------------------------------------------------------ r371048 | jonpa | 2019-09-05 12:20:05 +0200 (Thu, 05 Sep 2019) | 7 lines [SystemZ] Recognize INLINEASM_BR in backend Handle the remaining cases also by handling asm goto in SystemZInstrInfo::getBranchInfo(). Review: Ulrich Weigand https://reviews.llvm.org/D67151 ------------------------------------------------------------------------ llvm-svn: 371057 --- llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp | 22 +++++++++++-------- llvm/lib/Target/SystemZ/SystemZInstrInfo.h | 22 ++++++++++++++----- llvm/lib/Target/SystemZ/SystemZLongBranch.cpp | 2 +- .../SystemZ/SystemZMachineScheduler.cpp | 4 ++-- llvm/test/CodeGen/SystemZ/asm-20.ll | 4 ++-- 5 files changed, 34 insertions(+), 20 deletions(-) diff --git a/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp b/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp index 5f7576894e54..8df19286965b 100644 --- a/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp +++ b/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp @@ -462,13 +462,13 @@ bool SystemZInstrInfo::analyzeBranch(MachineBasicBlock &MBB, break; // A terminator that isn't a branch can't easily be handled by this - // analysis. Asm goto is not understood / optimized. - if (!I->isBranch() || I->getOpcode() == SystemZ::INLINEASM_BR) + // analysis. + if (!I->isBranch()) return true; // Can't handle indirect branches. SystemZII::Branch Branch(getBranchInfo(*I)); - if (!Branch.Target->isMBB()) + if (!Branch.hasMBBTarget()) return true; // Punt on compound branches. @@ -478,7 +478,7 @@ bool SystemZInstrInfo::analyzeBranch(MachineBasicBlock &MBB, if (Branch.CCMask == SystemZ::CCMASK_ANY) { // Handle unconditional branches. if (!AllowModify) { - TBB = Branch.Target->getMBB(); + TBB = Branch.getMBBTarget(); continue; } @@ -490,7 +490,7 @@ bool SystemZInstrInfo::analyzeBranch(MachineBasicBlock &MBB, FBB = nullptr; // Delete the JMP if it's equivalent to a fall-through. - if (MBB.isLayoutSuccessor(Branch.Target->getMBB())) { + if (MBB.isLayoutSuccessor(Branch.getMBBTarget())) { TBB = nullptr; I->eraseFromParent(); I = MBB.end(); @@ -498,7 +498,7 @@ bool SystemZInstrInfo::analyzeBranch(MachineBasicBlock &MBB, } // TBB is used to indicate the unconditinal destination. - TBB = Branch.Target->getMBB(); + TBB = Branch.getMBBTarget(); continue; } @@ -506,7 +506,7 @@ bool SystemZInstrInfo::analyzeBranch(MachineBasicBlock &MBB, if (Cond.empty()) { // FIXME: add X86-style branch swap FBB = TBB; - TBB = Branch.Target->getMBB(); + TBB = Branch.getMBBTarget(); Cond.push_back(MachineOperand::CreateImm(Branch.CCValid)); Cond.push_back(MachineOperand::CreateImm(Branch.CCMask)); continue; @@ -517,7 +517,7 @@ bool SystemZInstrInfo::analyzeBranch(MachineBasicBlock &MBB, // Only handle the case where all conditional branches branch to the same // destination. - if (TBB != Branch.Target->getMBB()) + if (TBB != Branch.getMBBTarget()) return true; // If the conditions are the same, we can leave them alone. @@ -547,7 +547,7 @@ unsigned SystemZInstrInfo::removeBranch(MachineBasicBlock &MBB, continue; if (!I->isBranch()) break; - if (!getBranchInfo(*I).Target->isMBB()) + if (!getBranchInfo(*I).hasMBBTarget()) break; // Remove the branch. I->eraseFromParent(); @@ -1545,6 +1545,10 @@ SystemZInstrInfo::getBranchInfo(const MachineInstr &MI) const { return SystemZII::Branch(SystemZII::BranchCLG, SystemZ::CCMASK_ICMP, MI.getOperand(2).getImm(), &MI.getOperand(3)); + case SystemZ::INLINEASM_BR: + // Don't try to analyze asm goto, so pass nullptr as branch target argument. + return SystemZII::Branch(SystemZII::AsmGoto, 0, 0, nullptr); + default: llvm_unreachable("Unrecognized branch opcode"); } diff --git a/llvm/lib/Target/SystemZ/SystemZInstrInfo.h b/llvm/lib/Target/SystemZ/SystemZInstrInfo.h index 2edde175542e..134ed38a41aa 100644 --- a/llvm/lib/Target/SystemZ/SystemZInstrInfo.h +++ b/llvm/lib/Target/SystemZ/SystemZInstrInfo.h @@ -100,11 +100,18 @@ enum BranchType { // An instruction that decrements a 64-bit register and branches if // the result is nonzero. - BranchCTG + BranchCTG, + + // An instruction representing an asm goto statement. + AsmGoto }; // Information about a branch instruction. -struct Branch { +class Branch { + // The target of the branch. In case of INLINEASM_BR, this is nullptr. + const MachineOperand *Target; + +public: // The type of the branch. BranchType Type; @@ -114,12 +121,15 @@ struct Branch { // CCMASK_ is set if the branch should be taken when CC == N. unsigned CCMask; - // The target of the branch. - const MachineOperand *Target; - Branch(BranchType type, unsigned ccValid, unsigned ccMask, const MachineOperand *target) - : Type(type), CCValid(ccValid), CCMask(ccMask), Target(target) {} + : Target(target), Type(type), CCValid(ccValid), CCMask(ccMask) {} + + bool isIndirect() { return Target != nullptr && Target->isReg(); } + bool hasMBBTarget() { return Target != nullptr && Target->isMBB(); } + MachineBasicBlock *getMBBTarget() { + return hasMBBTarget() ? Target->getMBB() : nullptr; + } }; // Kinds of fused compares in compare-and-* instructions. Together with type diff --git a/llvm/lib/Target/SystemZ/SystemZLongBranch.cpp b/llvm/lib/Target/SystemZ/SystemZLongBranch.cpp index 95d7e22dec32..dcaf629d240a 100644 --- a/llvm/lib/Target/SystemZ/SystemZLongBranch.cpp +++ b/llvm/lib/Target/SystemZ/SystemZLongBranch.cpp @@ -257,7 +257,7 @@ TerminatorInfo SystemZLongBranch::describeTerminator(MachineInstr &MI) { } Terminator.Branch = &MI; Terminator.TargetBlock = - TII->getBranchInfo(MI).Target->getMBB()->getNumber(); + TII->getBranchInfo(MI).getMBBTarget()->getNumber(); } return Terminator; } diff --git a/llvm/lib/Target/SystemZ/SystemZMachineScheduler.cpp b/llvm/lib/Target/SystemZ/SystemZMachineScheduler.cpp index 0becfaa1d49c..eb9745f71b7d 100644 --- a/llvm/lib/Target/SystemZ/SystemZMachineScheduler.cpp +++ b/llvm/lib/Target/SystemZ/SystemZMachineScheduler.cpp @@ -108,8 +108,8 @@ void SystemZPostRASchedStrategy::enterMBB(MachineBasicBlock *NextMBB) { I != SinglePredMBB->end(); I++) { LLVM_DEBUG(dbgs() << "** Emitting incoming branch: "; I->dump();); bool TakenBranch = (I->isBranch() && - (TII->getBranchInfo(*I).Target->isReg() || // Relative branch - TII->getBranchInfo(*I).Target->getMBB() == MBB)); + (TII->getBranchInfo(*I).isIndirect() || + TII->getBranchInfo(*I).getMBBTarget() == MBB)); HazardRec->emitInstruction(&*I, TakenBranch); if (TakenBranch) break; diff --git a/llvm/test/CodeGen/SystemZ/asm-20.ll b/llvm/test/CodeGen/SystemZ/asm-20.ll index 402c038f022e..e80a0085bf9c 100644 --- a/llvm/test/CodeGen/SystemZ/asm-20.ll +++ b/llvm/test/CodeGen/SystemZ/asm-20.ll @@ -1,10 +1,10 @@ ; Test that asm goto can be compiled. ; -; RUN: llc < %s -mtriple=s390x-linux-gnu +; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z14 define i32 @c() { entry: - callbr void asm sideeffect "", "X"(i8* blockaddress(@c, %d)) + callbr void asm sideeffect "j d", "X"(i8* blockaddress(@c, %d)) to label %asm.fallthrough [label %d] asm.fallthrough: ; preds = %entry From 8d4ccfe3689e4e255efc24c2ea579f828824cdb3 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Thu, 5 Sep 2019 11:37:40 +0000 Subject: [PATCH 205/289] Merging r369760: ------------------------------------------------------------------------ r369760 | szelethus | 2019-08-23 16:21:13 +0200 (Fri, 23 Aug 2019) | 13 lines [analyzer] Avoid unnecessary enum range check on LValueToRValue casts Summary: EnumCastOutOfRangeChecker should not perform enum range checks on LValueToRValue casts, since this type of cast does not actually change the underlying type. Performing the unnecessary check actually triggered an assertion failure deeper in EnumCastOutOfRange for certain input (which is captured in the accompanying test code). Reviewers: #clang, Szelethus, gamesh411, NoQ Reviewed By: Szelethus, gamesh411, NoQ Subscribers: NoQ, gamesh411, xazax.hun, baloghadamsoftware, szepet, a.sidorin, mikhail.ramalho, donat.nagy, dkrupp, Charusso, bjope, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D66014 ------------------------------------------------------------------------ llvm-svn: 371058 --- .../Checkers/EnumCastOutOfRangeChecker.cpp | 16 +++++++++ clang/test/Analysis/enum-cast-out-of-range.c | 34 +++++++++++++++++++ .../test/Analysis/enum-cast-out-of-range.cpp | 10 +++++- 3 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 clang/test/Analysis/enum-cast-out-of-range.c diff --git a/clang/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp index 736d80ef9ec7..a6539098c89a 100644 --- a/clang/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/EnumCastOutOfRangeChecker.cpp @@ -91,6 +91,22 @@ void EnumCastOutOfRangeChecker::reportWarning(CheckerContext &C) const { void EnumCastOutOfRangeChecker::checkPreStmt(const CastExpr *CE, CheckerContext &C) const { + + // Only perform enum range check on casts where such checks are valid. For + // all other cast kinds (where enum range checks are unnecessary or invalid), + // just return immediately. TODO: The set of casts whitelisted for enum + // range checking may be incomplete. Better to add a missing cast kind to + // enable a missing check than to generate false negatives and have to remove + // those later. + switch (CE->getCastKind()) { + case CK_IntegralCast: + break; + + default: + return; + break; + } + // Get the value of the expression to cast. const llvm::Optional ValueToCast = C.getSVal(CE->getSubExpr()).getAs(); diff --git a/clang/test/Analysis/enum-cast-out-of-range.c b/clang/test/Analysis/enum-cast-out-of-range.c new file mode 100644 index 000000000000..03e1100c38f4 --- /dev/null +++ b/clang/test/Analysis/enum-cast-out-of-range.c @@ -0,0 +1,34 @@ +// RUN: %clang_analyze_cc1 \ +// RUN: -analyzer-checker=core,alpha.cplusplus.EnumCastOutOfRange \ +// RUN: -verify %s + +enum En_t { + En_0 = -4, + En_1, + En_2 = 1, + En_3, + En_4 = 4 +}; + +void unscopedUnspecifiedCStyle() { + enum En_t Below = (enum En_t)(-5); // expected-warning {{not in the valid range}} + enum En_t NegVal1 = (enum En_t)(-4); // OK. + enum En_t NegVal2 = (enum En_t)(-3); // OK. + enum En_t InRange1 = (enum En_t)(-2); // expected-warning {{not in the valid range}} + enum En_t InRange2 = (enum En_t)(-1); // expected-warning {{not in the valid range}} + enum En_t InRange3 = (enum En_t)(0); // expected-warning {{not in the valid range}} + enum En_t PosVal1 = (enum En_t)(1); // OK. + enum En_t PosVal2 = (enum En_t)(2); // OK. + enum En_t InRange4 = (enum En_t)(3); // expected-warning {{not in the valid range}} + enum En_t PosVal3 = (enum En_t)(4); // OK. + enum En_t Above = (enum En_t)(5); // expected-warning {{not in the valid range}} +} + +enum En_t unused; +void unusedExpr() { + // Following line is not something that EnumCastOutOfRangeChecker should + // evaluate. Checker should either ignore this line or process it without + // producing any warnings. However, compilation will (and should) still + // generate a warning having nothing to do with this checker. + unused; // expected-warning {{expression result unused}} +} diff --git a/clang/test/Analysis/enum-cast-out-of-range.cpp b/clang/test/Analysis/enum-cast-out-of-range.cpp index e77339b551e0..b600367f8c14 100644 --- a/clang/test/Analysis/enum-cast-out-of-range.cpp +++ b/clang/test/Analysis/enum-cast-out-of-range.cpp @@ -150,7 +150,15 @@ void scopedSpecifiedCStyle() { scoped_specified_t InvalidAfterRangeEnd = (scoped_specified_t)(5); // expected-warning {{The value provided to the cast expression is not in the valid range of values for the enum}} } -void rangeContstrained1(int input) { +unscoped_unspecified_t unused; +void unusedExpr() { + // following line is not something that EnumCastOutOfRangeChecker should evaluate. checker should either ignore this line + // or process it without producing any warnings. However, compilation will (and should) still generate a warning having + // nothing to do with this checker. + unused; // expected-warning {{expression result unused}} +} + +void rangeConstrained1(int input) { if (input > -5 && input < 5) auto value = static_cast(input); // OK. Being conservative, this is a possibly good value. } From ff382fe7ad0cdd2538a81d2bfc15d216846f875a Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Thu, 5 Sep 2019 11:43:42 +0000 Subject: [PATCH 206/289] Merging r370426: ------------------------------------------------------------------------ r370426 | maskray | 2019-08-30 04:20:49 +0200 (Fri, 30 Aug 2019) | 26 lines [PPC32] Emit R_PPC_GOT_TPREL16 instead R_PPC_GOT_TPREL16_LO Unlike ppc64, which has ADDISgotTprelHA+LDgotTprelL pairs, ppc32 just uses LDgotTprelL32, so it does not make lots of sense to use _LO without a paired _HA. Emit R_PPC_GOT_TPREL16 instead R_PPC_GOT_TPREL16_LO to match GCC, and get better linker relocation check. Note, R_PPC_GOT_TPREL16_{HA,LO} don't have good linker support: (a) lld does not support R_PPC_GOT_TPREL16_{HA,LO}. (b) Top of tree ld.bfd does not support R_PPC_GOT_REL16_HA Initial-Exec -> Local-Exec relaxation: // a.o addis 3, 3, tsd_tls@got@tprel@ha lwz 3, tsd_tls@got@tprel@l(3) add 3, 3, tsd_tls@tls // b.o .section .tdata,"awT"; .globl tsd_tls; tsd_tls: // ld/ld-new a.o b.o internal error, aborting at ../../bfd/elf32-ppc.c:7952 in ppc_elf_relocate_section Reviewed By: adalava Differential Revision: https://reviews.llvm.org/D66925 ------------------------------------------------------------------------ llvm-svn: 371059 --- llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp | 6 ++++-- llvm/test/CodeGen/PowerPC/tls.ll | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp index bd87ce06b4fb..269b84b4e8d8 100644 --- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp +++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -866,8 +866,10 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) { const GlobalValue *GValue = MO.getGlobal(); MCSymbol *MOSymbol = getSymbol(GValue); const MCExpr *Exp = - MCSymbolRefExpr::create(MOSymbol, MCSymbolRefExpr::VK_PPC_GOT_TPREL_LO, - OutContext); + MCSymbolRefExpr::create(MOSymbol, + isPPC64 ? MCSymbolRefExpr::VK_PPC_GOT_TPREL_LO + : MCSymbolRefExpr::VK_PPC_GOT_TPREL, + OutContext); TmpInst.getOperand(1) = MCOperand::createExpr(Exp); EmitToStreamer(*OutStreamer, TmpInst); return; diff --git a/llvm/test/CodeGen/PowerPC/tls.ll b/llvm/test/CodeGen/PowerPC/tls.ll index 6a0ab6956422..1d6b22e3f8f6 100644 --- a/llvm/test/CodeGen/PowerPC/tls.ll +++ b/llvm/test/CodeGen/PowerPC/tls.ll @@ -43,7 +43,7 @@ entry: ;OPT0-PPC32-LABEL: main2: ;OPT0-PPC32: li [[REG1:[0-9]+]], _GLOBAL_OFFSET_TABLE_@l ;OPT0-PPC32: addis [[REG1]], [[REG1]], _GLOBAL_OFFSET_TABLE_@ha -;OPT0-PPC32: lwz [[REG2:[0-9]+]], a2@got@tprel@l([[REG1]]) +;OPT0-PPC32: lwz [[REG2:[0-9]+]], a2@got@tprel([[REG1]]) ;OPT0-PPC32: add 3, [[REG2]], a2@tls ;OPT0-PPC32-PIC-LABEL: main2: @@ -51,4 +51,4 @@ entry: ;OPT0-PPC32-PIC-NOT: li {{[0-9]+}}, _GLOBAL_OFFSET_TABLE_@l ;OPT0-PPC32-PIC-NOT: addis {{[0-9]+}}, {{[0-9+]}}, _GLOBAL_OFFSET_TABLE_@ha ;OPT0-PPC32-PIC-NOT: bl __tls_get_addr(a2@tlsgd)@PLT -;OPT0-PPC32-PIC: lwz {{[0-9]+}}, a2@got@tprel@l({{[0-9]+}}) +;OPT0-PPC32-PIC: lwz {{[0-9]+}}, a2@got@tprel({{[0-9]+}}) From c2551012a43861017e20ed9d20b07d79d2711bdf Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Thu, 5 Sep 2019 11:55:39 +0000 Subject: [PATCH 207/289] Merging r371027: ------------------------------------------------------------------------ r371027 | hans | 2019-09-05 10:43:00 +0200 (Thu, 05 Sep 2019) | 20 lines Revert r361885 "[Driver] Fix -working-directory issues" This made clang unable to open files using relative paths on network shares on Windows (PR43204). On the bug it was pointed out that createPhysicalFileSystem() is not terribly mature, and using it is risky. Reverting for now until there's a clear way forward. > Currently the `-working-directory` option does not actually impact the working > directory for all of the clang driver, it only impacts how files are looked up > to make sure they exist. This means that that clang passes the wrong paths > to -fdebug-compilation-dir and -coverage-notes-file. > > This patch fixes that by changing all the places in the driver where we convert > to absolute paths to use the VFS, and then calling setCurrentWorkingDirectory on > the VFS. This also changes the default VFS for `Driver` to use a virtualized > working directory, instead of changing the process's working directory. > > Differential Revision: https://reviews.llvm.org/D62271 This also revertes the part of r369938 which checked that -working-directory works. ------------------------------------------------------------------------ llvm-svn: 371060 --- .../clang/Basic/DiagnosticDriverKinds.td | 2 -- clang/lib/Driver/Driver.cpp | 24 ++++++++++------- clang/lib/Driver/ToolChains/Clang.cpp | 26 ++++++++++++------- clang/test/Driver/working-directory.c | 10 +------ 4 files changed, 31 insertions(+), 31 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td index eab453ee20ec..12f1a7f6c488 100644 --- a/clang/include/clang/Basic/DiagnosticDriverKinds.td +++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -91,8 +91,6 @@ def err_no_external_assembler : Error< "there is no external assembler that can be used on this platform">; def err_drv_unable_to_remove_file : Error< "unable to remove file: %0">; -def err_drv_unable_to_set_working_directory : Error < - "unable to set working directory: %0">; def err_drv_command_failure : Error< "unable to execute command: %0">; def err_drv_invalid_darwin_version : Error< diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 396ddf4dd816..a9a273529b46 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -133,7 +133,7 @@ Driver::Driver(StringRef ClangExecutable, StringRef TargetTriple, // Provide a sane fallback if no VFS is specified. if (!this->VFS) - this->VFS = llvm::vfs::createPhysicalFileSystem().release(); + this->VFS = llvm::vfs::getRealFileSystem(); Name = llvm::sys::path::filename(ClangExecutable); Dir = llvm::sys::path::parent_path(ClangExecutable); @@ -1010,11 +1010,6 @@ Compilation *Driver::BuildCompilation(ArrayRef ArgList) { } } - // Check for working directory option before accessing any files - if (Arg *WD = Args.getLastArg(options::OPT_working_directory)) - if (VFS->setCurrentWorkingDirectory(WD->getValue())) - Diag(diag::err_drv_unable_to_set_working_directory) << WD->getValue(); - // FIXME: This stuff needs to go into the Compilation, not the driver. bool CCCPrintPhases; @@ -1995,11 +1990,20 @@ bool Driver::DiagnoseInputExistence(const DerivedArgList &Args, StringRef Value, if (Value == "-") return true; - if (getVFS().exists(Value)) + SmallString<64> Path(Value); + if (Arg *WorkDir = Args.getLastArg(options::OPT_working_directory)) { + if (!llvm::sys::path::is_absolute(Path)) { + SmallString<64> Directory(WorkDir->getValue()); + llvm::sys::path::append(Directory, Value); + Path.assign(Directory); + } + } + + if (getVFS().exists(Path)) return true; if (IsCLMode()) { - if (!llvm::sys::path::is_absolute(Twine(Value)) && + if (!llvm::sys::path::is_absolute(Twine(Path)) && llvm::sys::Process::FindInEnvPath("LIB", Value)) return true; @@ -2025,12 +2029,12 @@ bool Driver::DiagnoseInputExistence(const DerivedArgList &Args, StringRef Value, if (getOpts().findNearest(Value, Nearest, IncludedFlagsBitmask, ExcludedFlagsBitmask) <= 1) { Diag(clang::diag::err_drv_no_such_file_with_suggestion) - << Value << Nearest; + << Path << Nearest; return false; } } - Diag(clang::diag::err_drv_no_such_file) << Value; + Diag(clang::diag::err_drv_no_such_file) << Path; return false; } diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 2508178423bf..dd461a1976d9 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -603,15 +603,16 @@ static bool shouldUseLeafFramePointer(const ArgList &Args, } /// Add a CC1 option to specify the debug compilation directory. -static void addDebugCompDirArg(const ArgList &Args, ArgStringList &CmdArgs, - const llvm::vfs::FileSystem &VFS) { +static void addDebugCompDirArg(const ArgList &Args, ArgStringList &CmdArgs) { if (Arg *A = Args.getLastArg(options::OPT_fdebug_compilation_dir)) { CmdArgs.push_back("-fdebug-compilation-dir"); CmdArgs.push_back(A->getValue()); - } else if (llvm::ErrorOr CWD = - VFS.getCurrentWorkingDirectory()) { - CmdArgs.push_back("-fdebug-compilation-dir"); - CmdArgs.push_back(Args.MakeArgString(*CWD)); + } else { + SmallString<128> cwd; + if (!llvm::sys::fs::current_path(cwd)) { + CmdArgs.push_back("-fdebug-compilation-dir"); + CmdArgs.push_back(Args.MakeArgString(cwd)); + } } } @@ -877,8 +878,13 @@ static void addPGOAndCoverageFlags(const ToolChain &TC, Compilation &C, else OutputFilename = llvm::sys::path::filename(Output.getBaseInput()); SmallString<128> CoverageFilename = OutputFilename; - if (llvm::sys::path::is_relative(CoverageFilename)) - (void)D.getVFS().makeAbsolute(CoverageFilename); + if (llvm::sys::path::is_relative(CoverageFilename)) { + SmallString<128> Pwd; + if (!llvm::sys::fs::current_path(Pwd)) { + llvm::sys::path::append(Pwd, CoverageFilename); + CoverageFilename.swap(Pwd); + } + } llvm::sys::path::replace_extension(CoverageFilename, "gcno"); CmdArgs.push_back(Args.MakeArgString(CoverageFilename)); @@ -4365,7 +4371,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-fno-autolink"); // Add in -fdebug-compilation-dir if necessary. - addDebugCompDirArg(Args, CmdArgs, D.getVFS()); + addDebugCompDirArg(Args, CmdArgs); addDebugPrefixMapArg(D, Args, CmdArgs); @@ -6092,7 +6098,7 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA, DebugInfoKind = (WantDebug ? codegenoptions::LimitedDebugInfo : codegenoptions::NoDebugInfo); // Add the -fdebug-compilation-dir flag if needed. - addDebugCompDirArg(Args, CmdArgs, C.getDriver().getVFS()); + addDebugCompDirArg(Args, CmdArgs); addDebugPrefixMapArg(getToolChain().getDriver(), Args, CmdArgs); diff --git a/clang/test/Driver/working-directory.c b/clang/test/Driver/working-directory.c index fbd4ed4f9e10..15ba8f00bd12 100644 --- a/clang/test/Driver/working-directory.c +++ b/clang/test/Driver/working-directory.c @@ -1,11 +1,3 @@ // RUN: %clang -### -working-directory /no/such/dir/ input 2>&1 | FileCheck %s -// RUN: %clang -### -working-directory %p/Inputs no_such_file.cpp -c 2>&1 | FileCheck %s --check-prefix=CHECK_NO_FILE -// RUN: %clang -### -working-directory %p/Inputs pchfile.cpp -c 2>&1 | FileCheck %s --check-prefix=CHECK_WORKS -// CHECK: unable to set working directory: /no/such/dir/ - -// CHECK_NO_FILE: no such file or directory: 'no_such_file.cpp' - -// CHECK_WORKS: "-coverage-notes-file" "{{[^"]+}}test{{/|\\\\}}Driver{{/|\\\\}}Inputs{{/|\\\\}}pchfile.gcno" -// CHECK_WORKS: "-working-directory" "{{[^"]+}}test{{/|\\\\}}Driver{{/|\\\\}}Inputs" -// CHECK_WORKS: "-fdebug-compilation-dir" "{{[^"]+}}test{{/|\\\\}}Driver{{/|\\\\}}Inputs" +//CHECK: no such file or directory: '/no/such/dir/input' From 5fc03679c9d501da8db078a90d77c8a3e1d4e1e9 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Fri, 6 Sep 2019 08:17:47 +0000 Subject: [PATCH 208/289] Merging r371088 and r371095: ------------------------------------------------------------------------ r371088 | spatel | 2019-09-05 18:58:18 +0200 (Thu, 05 Sep 2019) | 1 line [x86] add test for horizontal math bug (PR43225); NFC ------------------------------------------------------------------------ ------------------------------------------------------------------------ r371095 | spatel | 2019-09-05 19:28:17 +0200 (Thu, 05 Sep 2019) | 3 lines [x86] fix horizontal math bug exposed by improved demanded elements analysis (PR43225) https://bugs.llvm.org/show_bug.cgi?id=43225 ------------------------------------------------------------------------ llvm-svn: 371178 --- llvm/lib/Target/X86/X86ISelLowering.cpp | 29 +++++++++++++++---- .../CodeGen/X86/haddsub-shuf-undef-operand.ll | 26 +++++++++++++++++ 2 files changed, 50 insertions(+), 5 deletions(-) create mode 100644 llvm/test/CodeGen/X86/haddsub-shuf-undef-operand.ll diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index eecf34902ddc..87ff5a719fca 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -33594,7 +33594,7 @@ static SDValue combineShuffleOfConcatUndef(SDNode *N, SelectionDAG &DAG, } /// Eliminate a redundant shuffle of a horizontal math op. -static SDValue foldShuffleOfHorizOp(SDNode *N) { +static SDValue foldShuffleOfHorizOp(SDNode *N, SelectionDAG &DAG) { unsigned Opcode = N->getOpcode(); if (Opcode != X86ISD::MOVDDUP && Opcode != X86ISD::VBROADCAST) if (Opcode != ISD::VECTOR_SHUFFLE || !N->getOperand(1).isUndef()) @@ -33625,6 +33625,25 @@ static SDValue foldShuffleOfHorizOp(SDNode *N) { HOp.getOperand(0) != HOp.getOperand(1)) return SDValue(); + // The shuffle that we are eliminating may have allowed the horizontal op to + // have an undemanded (undefined) operand. Duplicate the other (defined) + // operand to ensure that the results are defined across all lanes without the + // shuffle. + auto updateHOp = [](SDValue HorizOp, SelectionDAG &DAG) { + SDValue X; + if (HorizOp.getOperand(0).isUndef()) { + assert(!HorizOp.getOperand(1).isUndef() && "Not expecting foldable h-op"); + X = HorizOp.getOperand(1); + } else if (HorizOp.getOperand(1).isUndef()) { + assert(!HorizOp.getOperand(0).isUndef() && "Not expecting foldable h-op"); + X = HorizOp.getOperand(0); + } else { + return HorizOp; + } + return DAG.getNode(HorizOp.getOpcode(), SDLoc(HorizOp), + HorizOp.getValueType(), X, X); + }; + // When the operands of a horizontal math op are identical, the low half of // the result is the same as the high half. If a target shuffle is also // replicating low and high halves, we don't need the shuffle. @@ -33635,7 +33654,7 @@ static SDValue foldShuffleOfHorizOp(SDNode *N) { assert((HOp.getValueType() == MVT::v2f64 || HOp.getValueType() == MVT::v4f64) && HOp.getValueType() == VT && "Unexpected type for h-op"); - return HOp; + return updateHOp(HOp, DAG); } return SDValue(); } @@ -33649,14 +33668,14 @@ static SDValue foldShuffleOfHorizOp(SDNode *N) { (isTargetShuffleEquivalent(Mask, {0, 0}) || isTargetShuffleEquivalent(Mask, {0, 1, 0, 1}) || isTargetShuffleEquivalent(Mask, {0, 1, 2, 3, 0, 1, 2, 3}))) - return HOp; + return updateHOp(HOp, DAG); if (HOp.getValueSizeInBits() == 256 && (isTargetShuffleEquivalent(Mask, {0, 0, 2, 2}) || isTargetShuffleEquivalent(Mask, {0, 1, 0, 1, 4, 5, 4, 5}) || isTargetShuffleEquivalent( Mask, {0, 1, 2, 3, 0, 1, 2, 3, 8, 9, 10, 11, 8, 9, 10, 11}))) - return HOp; + return updateHOp(HOp, DAG); return SDValue(); } @@ -33710,7 +33729,7 @@ static SDValue combineShuffle(SDNode *N, SelectionDAG &DAG, if (SDValue AddSub = combineShuffleToAddSubOrFMAddSub(N, Subtarget, DAG)) return AddSub; - if (SDValue HAddSub = foldShuffleOfHorizOp(N)) + if (SDValue HAddSub = foldShuffleOfHorizOp(N, DAG)) return HAddSub; } diff --git a/llvm/test/CodeGen/X86/haddsub-shuf-undef-operand.ll b/llvm/test/CodeGen/X86/haddsub-shuf-undef-operand.ll new file mode 100644 index 000000000000..b56ff9a9ad0e --- /dev/null +++ b/llvm/test/CodeGen/X86/haddsub-shuf-undef-operand.ll @@ -0,0 +1,26 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc < %s -mtriple=x86_64-- -mattr=avx | FileCheck %s + +; Eliminating a shuffle means we have to replace an undef operand of a horizontal op. + +define void @PR43225(<4 x double>* %p0, <4 x double>* %p1, <4 x double> %x, <4 x double> %y, <4 x double> %z) nounwind { +; CHECK-LABEL: PR43225: +; CHECK: # %bb.0: +; CHECK-NEXT: vmovaps (%rdi), %ymm0 +; CHECK-NEXT: vmovaps (%rsi), %ymm0 +; CHECK-NEXT: vhsubpd %ymm2, %ymm2, %ymm0 +; CHECK-NEXT: vmovapd %ymm0, (%rdi) +; CHECK-NEXT: vzeroupper +; CHECK-NEXT: retq + %t39 = load volatile <4 x double>, <4 x double>* %p0, align 32 + %shuffle11 = shufflevector <4 x double> %t39, <4 x double> %x, <4 x i32> + %t40 = load volatile <4 x double>, <4 x double>* %p1, align 32 + %t41 = tail call <4 x double> @llvm.x86.avx.hadd.pd.256(<4 x double> %shuffle11, <4 x double> %t40) + %t42 = tail call <4 x double> @llvm.x86.avx.hsub.pd.256(<4 x double> %z, <4 x double> %t41) + %shuffle12 = shufflevector <4 x double> %t42, <4 x double> undef, <4 x i32> + store volatile <4 x double> %shuffle12, <4 x double>* %p0, align 32 + ret void +} + +declare <4 x double> @llvm.x86.avx.hadd.pd.256(<4 x double>, <4 x double>) +declare <4 x double> @llvm.x86.avx.hsub.pd.256(<4 x double>, <4 x double>) From 501ad1d7ba8f256e3f5a7d69fa0f5a0710c9d061 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Fri, 6 Sep 2019 11:18:45 +0000 Subject: [PATCH 209/289] Merging r369828: ------------------------------------------------------------------------ r369828 | maskray | 2019-08-24 02:41:15 +0200 (Sat, 24 Aug 2019) | 18 lines [ELF] Align the first section of a PT_LOAD even if its type is SHT_NOBITS Reported at https://reviews.llvm.org/D64930#1642223 If the only section of a PT_LOAD is a SHT_NOBITS section (e.g. .bss), we may not align its sh_offset. p_offset of the PT_LOAD will be set to sh_offset, and we will get p_offset!=p_vaddr (mod p_align). If such executable is mapped by the Linux kernel, it will segfault. After D64906, this may happen the non-linker script case. The linker script case has had this issue for a long time. This was fixed by rL321657 (but the test linkerscript/nobits-offset.s failed to test a SHT_NOBITS section), but broken by rL345154. Reviewed By: peter.smith Differential Revision: https://reviews.llvm.org/D66658 ------------------------------------------------------------------------ llvm-svn: 371196 --- lld/ELF/Writer.cpp | 23 ++++++++++--------- lld/test/ELF/basic-ppc64.s | 12 +++++----- lld/test/ELF/linkerscript/nobits-offset.s | 25 +++++++++++++-------- lld/test/ELF/nobits-offset.s | 21 +++++++++++++++++ lld/test/ELF/relocation-copy-align-common.s | 2 +- 5 files changed, 56 insertions(+), 27 deletions(-) create mode 100644 lld/test/ELF/nobits-offset.s diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index b8c8891648a4..b5b81e959085 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -2230,25 +2230,26 @@ template void Writer::fixSectionAlignments() { // same with its virtual address modulo the page size, so that the loader can // load executables without any address adjustment. static uint64_t computeFileOffset(OutputSection *os, uint64_t off) { - // File offsets are not significant for .bss sections. By convention, we keep - // section offsets monotonically increasing rather than setting to zero. - if (os->type == SHT_NOBITS) - return off; - - // If the section is not in a PT_LOAD, we just have to align it. - if (!os->ptLoad) - return alignTo(off, os->alignment); - // The first section in a PT_LOAD has to have congruent offset and address // module the page size. - OutputSection *first = os->ptLoad->firstSec; - if (os == first) { + if (os->ptLoad && os->ptLoad->firstSec == os) { uint64_t alignment = std::max(os->alignment, config->maxPageSize); return alignTo(off, alignment, os->addr); } + // File offsets are not significant for .bss sections other than the first one + // in a PT_LOAD. By convention, we keep section offsets monotonically + // increasing rather than setting to zero. + if (os->type == SHT_NOBITS) + return off; + + // If the section is not in a PT_LOAD, we just have to align it. + if (!os->ptLoad) + return alignTo(off, os->alignment); + // If two sections share the same PT_LOAD the file offset is calculated // using this formula: Off2 = Off1 + (VA2 - VA1). + OutputSection *first = os->ptLoad->firstSec; return first->offset + os->addr - first->addr; } diff --git a/lld/test/ELF/basic-ppc64.s b/lld/test/ELF/basic-ppc64.s index cab130212b0b..d1e47464a9de 100644 --- a/lld/test/ELF/basic-ppc64.s +++ b/lld/test/ELF/basic-ppc64.s @@ -35,7 +35,7 @@ // CHECK-NEXT: Version: 1 // CHECK-NEXT: Entry: 0x10000 // CHECK-NEXT: ProgramHeaderOffset: 0x40 -// CHECK-NEXT: SectionHeaderOffset: 0x200F8 +// CHECK-NEXT: SectionHeaderOffset: 0x30098 // CHECK-NEXT: Flags [ (0x2) // CHECK-NEXT: 0x2 // CHECK-NEXT: ] @@ -178,7 +178,7 @@ // CHECK-NEXT: SHF_WRITE (0x1) // CHECK-NEXT: ] // CHECK-NEXT: Address: 0x30000 -// CHECK-NEXT: Offset: 0x20060 +// CHECK-NEXT: Offset: 0x30000 // CHECK-NEXT: Size: 0 // CHECK-NEXT: Link: 0 // CHECK-NEXT: Info: 0 @@ -194,7 +194,7 @@ // CHECK-NEXT: SHF_STRINGS (0x20) // CHECK-NEXT: ] // CHECK-NEXT: Address: 0x0 -// CHECK-NEXT: Offset: 0x20060 +// CHECK-NEXT: Offset: 0x30000 // CHECK-NEXT: Size: 8 // CHECK-NEXT: Link: 0 // CHECK-NEXT: Info: 0 @@ -211,7 +211,7 @@ // CHECK-NEXT: Flags [ (0x0) // CHECK-NEXT: ] // CHECK-NEXT: Address: 0x0 -// CHECK-NEXT: Offset: 0x20068 +// CHECK-NEXT: Offset: 0x30008 // CHECK-NEXT: Size: 48 // CHECK-NEXT: Link: 10 // CHECK-NEXT: Info: 2 @@ -233,7 +233,7 @@ // CHECK-NEXT: Flags [ (0x0) // CHECK-NEXT: ] // CHECK-NEXT: Address: 0x0 -// CHECK-NEXT: Offset: 0x20098 +// CHECK-NEXT: Offset: 0x30038 // CHECK-NEXT: Size: 84 // CHECK-NEXT: Link: 0 // CHECK-NEXT: Info: 0 @@ -255,7 +255,7 @@ // CHECK-NEXT: Flags [ (0x0) // CHECK-NEXT: ] // CHECK-NEXT: Address: 0x0 -// CHECK-NEXT: Offset: 0x200EC +// CHECK-NEXT: Offset: 0x3008C // CHECK-NEXT: Size: 10 // CHECK-NEXT: Link: 0 // CHECK-NEXT: Info: 0 diff --git a/lld/test/ELF/linkerscript/nobits-offset.s b/lld/test/ELF/linkerscript/nobits-offset.s index c4141487630b..051f3f99da3b 100644 --- a/lld/test/ELF/linkerscript/nobits-offset.s +++ b/lld/test/ELF/linkerscript/nobits-offset.s @@ -2,17 +2,24 @@ # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o # RUN: echo "SECTIONS { \ # RUN: .sec1 (NOLOAD) : { . += 1; } \ -# RUN: .text : { *(.text) } \ +# RUN: .bss : { *(.bss) } \ # RUN: };" > %t.script # RUN: ld.lld %t.o -T %t.script -o %t -# RUN: llvm-readelf --sections %t | FileCheck %s +# RUN: llvm-readelf -S -l %t | FileCheck %s -# We used to misalign section offsets if the first section in a -# PT_LOAD was SHT_NOBITS. +## If a SHT_NOBITS section is the only section of a PT_LOAD segment, +## p_offset will be set to the sh_offset field of the section. Check we align +## sh_offset to sh_addr modulo max-page-size, so that p_vaddr=p_offset (mod +## p_align). -# CHECK: [ 2] .text PROGBITS 0000000000000010 001010 000010 00 AX 0 0 16 +# CHECK: Name Type Address Off Size ES Flg Lk Inf Al +# CHECK: .bss NOBITS 0000000000000400 001400 000001 00 WA 0 0 1024 -.global _start -_start: - nop -.p2align 4 +# CHECK: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align +# CHECK: LOAD 0x001400 0x0000000000000400 0x0000000000000400 0x000000 0x000001 RW 0x1000 + +# CHECK: 00 .bss + +.bss +.p2align 10 +.byte 0 diff --git a/lld/test/ELF/nobits-offset.s b/lld/test/ELF/nobits-offset.s new file mode 100644 index 000000000000..c01047329046 --- /dev/null +++ b/lld/test/ELF/nobits-offset.s @@ -0,0 +1,21 @@ +# REQUIRES: aarch64 +# RUN: llvm-mc -filetype=obj -triple=aarch64 %s -o %t.o +# RUN: ld.lld %t.o -o %t +# RUN: llvm-readelf -S -l %t | FileCheck %s + +## If a SHT_NOBITS section is the only section of a PT_LOAD segment, +## p_offset will be set to the sh_offset field of the section. Check we align +## sh_offset to sh_addr modulo max-page-size, so that p_vaddr=p_offset (mod +## p_align). + +# CHECK: Name Type Address Off Size ES Flg Lk Inf Al +# CHECK: .bss NOBITS 0000000000210000 010000 000001 00 WA 0 0 4096 + +# CHECK: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align +# CHECK: LOAD 0x010000 0x0000000000210000 0x0000000000210000 0x000000 0x000001 RW 0x10000 + +# CHECK: 02 .bss + +.bss +.p2align 12 +.byte 0 diff --git a/lld/test/ELF/relocation-copy-align-common.s b/lld/test/ELF/relocation-copy-align-common.s index 124064c71d14..748f84546b71 100644 --- a/lld/test/ELF/relocation-copy-align-common.s +++ b/lld/test/ELF/relocation-copy-align-common.s @@ -15,7 +15,7 @@ # CHECK-NEXT: SHF_WRITE # CHECK-NEXT: ] # CHECK-NEXT: Address: 0x203000 -# CHECK-NEXT: Offset: 0x20B0 +# CHECK-NEXT: Offset: 0x3000 # CHECK-NEXT: Size: 16 # CHECK-NEXT: Link: 0 # CHECK-NEXT: Info: 0 From de934bf689686688eb0d2266800ee06f1129ca44 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Fri, 6 Sep 2019 11:20:15 +0000 Subject: [PATCH 210/289] Merging r371013: ------------------------------------------------------------------------ r371013 | ruiu | 2019-09-05 07:30:24 +0200 (Thu, 05 Sep 2019) | 13 lines Align output segments correctly Previously, segments were aligned according to their first section's alignment requirements. That was not correct, but segments are also aligned to a page boundary, and a page boundary is usually much larger than a section alignment requirement, so no one noticed this bug before. Now, lld has --nmagic option which sets maxPageSize to 1 to effectively disable page alignment, which reveals the issue. Fixes https://bugs.llvm.org/show_bug.cgi?id=43212 Differential Revision: https://reviews.llvm.org/D67152 ------------------------------------------------------------------------ llvm-svn: 371197 --- lld/ELF/Writer.cpp | 3 ++- lld/test/ELF/nmagic.s | 23 +++++++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 lld/test/ELF/nmagic.s diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index b5b81e959085..10b171e8c0d7 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -2233,7 +2233,8 @@ static uint64_t computeFileOffset(OutputSection *os, uint64_t off) { // The first section in a PT_LOAD has to have congruent offset and address // module the page size. if (os->ptLoad && os->ptLoad->firstSec == os) { - uint64_t alignment = std::max(os->alignment, config->maxPageSize); + uint64_t alignment = + std::max(os->ptLoad->p_align, config->maxPageSize); return alignTo(off, alignment, os->addr); } diff --git a/lld/test/ELF/nmagic.s b/lld/test/ELF/nmagic.s new file mode 100644 index 000000000000..f2feacb1bab5 --- /dev/null +++ b/lld/test/ELF/nmagic.s @@ -0,0 +1,23 @@ +# REQUIRES: x86 +# Verify that .rodata is aligned to a 8 byte boundary. + +# RUN: llvm-mc -filetype=obj -triple=i386 %s -o %t.o +# RUN: ld.lld %t.o -o %t.exe -n -Ttext 0 +# RUN: llvm-readelf --section-headers %t.exe | FileCheck %s + +# CHECK: [ 0] NULL 00000000 000000 000000 00 0 0 0 +# CHECK: [ 1] .text PROGBITS 00000000 0000d4 000001 00 AX 0 0 4 +# CHECK: [ 2] .rodata PROGBITS 00000008 0000d8 000008 00 A 0 0 8 +# CHECK: [ 3] .comment PROGBITS 00000000 0000e0 000008 01 MS 0 0 1 +# CHECK: [ 4] .symtab SYMTAB 00000000 0000e8 000020 10 6 1 4 +# CHECK: [ 5] .shstrtab STRTAB 00000000 000108 000032 00 0 0 1 +# CHECK: [ 6] .strtab STRTAB 00000000 00013a 000008 00 0 0 1 + +.globl _start +.text +_start: + ret + +.rodata +.align 8 +.quad 42 From c168b4b2a96df6fb44bfafc6ee271df4e3d92927 Mon Sep 17 00:00:00 2001 From: Martin Storsjo Date: Sat, 7 Sep 2019 10:57:20 +0000 Subject: [PATCH 211/289] Fix release notes for the MinGW frontend No --wrap or --emit-relocs options have been added there (only in the ELF linker). llvm-svn: 371301 --- lld/docs/ReleaseNotes.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lld/docs/ReleaseNotes.rst b/lld/docs/ReleaseNotes.rst index 768c088203fa..df00e31bf971 100644 --- a/lld/docs/ReleaseNotes.rst +++ b/lld/docs/ReleaseNotes.rst @@ -228,4 +228,4 @@ MinGW Improvements MinGW frontend to be called by GCC. * The following options are added: ``--exclude-all-symbols``, - ``--appcontainer``, ``--emit-relocs``, ``--wrap``, ``--undefined`` + ``--appcontainer``, ``--undefined`` From 7b927f75f22688819d1e82e572b7524ccd31e4ab Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Mon, 9 Sep 2019 08:44:55 +0000 Subject: [PATCH 212/289] Merging r369705 and r369713 for PR43243: ------------------------------------------------------------------------ r369705 | nickdesaulniers | 2019-08-22 22:47:12 +0200 (Thu, 22 Aug 2019) | 23 lines [Clang][CodeGen] set alias linkage on QualType Summary: It seems that CodeGen was always using ExternalLinkage when emitting a GlobalDecl with __attribute__((alias)). This leads to symbol redefinitions (ODR) that cause failures at link time for static aliases. This is readily attempting to link an ARM (32b) allyesconfig Linux kernel built with Clang. Reported-by: nathanchance Suggested-by: ihalip Link: https://bugs.llvm.org/show_bug.cgi?id=42377 Link: https://github.com/ClangBuiltLinux/linux/issues/631 Reviewers: rsmith, aaron.ballman, erichkeane Reviewed By: aaron.ballman Subscribers: javed.absar, kristof.beyls, cfe-commits, srhines, ihalip, nathanchance Tags: #clang Differential Revision: https://reviews.llvm.org/D66492 ------------------------------------------------------------------------ ------------------------------------------------------------------------ r369713 | nickdesaulniers | 2019-08-23 01:18:46 +0200 (Fri, 23 Aug 2019) | 17 lines [Bugfix] fix r369705 unit test Summary: Aliases aren't supported on OSX. Add a GNU target triple. Reported-by: leonardchan Reported-by: erik.pilkington Reviewers: leonardchan, erik.pilkington Reviewed By: leonardchan, erik.pilkington Subscribers: dexonsmith, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D66622 ------------------------------------------------------------------------ llvm-svn: 371372 --- clang/lib/CodeGen/CodeGenModule.cpp | 13 +++++++++---- clang/test/CodeGen/alias.c | 11 +++++++++++ 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 6ff72ec045e6..1fd4e4cf8b8f 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -4355,17 +4355,22 @@ void CodeGenModule::EmitAliasDefinition(GlobalDecl GD) { // Create a reference to the named value. This ensures that it is emitted // if a deferred decl. llvm::Constant *Aliasee; - if (isa(DeclTy)) + llvm::GlobalValue::LinkageTypes LT; + if (isa(DeclTy)) { Aliasee = GetOrCreateLLVMFunction(AA->getAliasee(), DeclTy, GD, /*ForVTable=*/false); - else + LT = getFunctionLinkage(GD); + } else { Aliasee = GetOrCreateLLVMGlobal(AA->getAliasee(), llvm::PointerType::getUnqual(DeclTy), /*D=*/nullptr); + LT = getLLVMLinkageVarDefinition(cast(GD.getDecl()), + D->getType().isConstQualified()); + } // Create the new alias itself, but don't set a name yet. - auto *GA = llvm::GlobalAlias::create( - DeclTy, 0, llvm::Function::ExternalLinkage, "", Aliasee, &getModule()); + auto *GA = + llvm::GlobalAlias::create(DeclTy, 0, LT, "", Aliasee, &getModule()); if (Entry) { if (GA->getAliasee() == Entry) { diff --git a/clang/test/CodeGen/alias.c b/clang/test/CodeGen/alias.c index 78b020454a9f..46568ee900c1 100644 --- a/clang/test/CodeGen/alias.c +++ b/clang/test/CodeGen/alias.c @@ -2,6 +2,7 @@ // RUN: %clang_cc1 -triple i386-pc-linux-gnu -emit-llvm -o - %s | FileCheck -check-prefix=CHECKBASIC %s // RUN: %clang_cc1 -triple armv7a-eabi -mfloat-abi hard -emit-llvm -o - %s | FileCheck -check-prefix=CHECKCC %s // RUN: %clang_cc1 -triple armv7a-eabi -mfloat-abi hard -S -o - %s | FileCheck -check-prefix=CHECKASM %s +// RUN: %clang_cc1 -triple aarch64-linux-gnu -emit-llvm -o - %s | FileCheck -check-prefix=CHECKGLOBALS %s int g0; // CHECKBASIC-DAG: @g0 = common global i32 0 @@ -88,3 +89,13 @@ void test8_zed() __attribute__((alias("test8_foo"))); void test9_bar(void) { } void test9_zed(void) __attribute__((section("test"))); void test9_zed(void) __attribute__((alias("test9_bar"))); + +// Test that the alias gets its linkage from its declared qual type. +// CHECKGLOBALS: @test10_foo = internal +// CHECKGLOBALS-NOT: @test10_foo = dso_local +int test10; +static int test10_foo __attribute__((alias("test10"))); +// CHECKGLOBALS: @test11_foo = internal +// CHECKGLOBALS-NOT: @test11_foo = dso_local +void test11(void) {} +static void test11_foo(void) __attribute__((alias("test11"))); From 9523a1c62d086b58040bc762b327a15be0bf3b24 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Mon, 9 Sep 2019 08:59:27 +0000 Subject: [PATCH 213/289] Merging r371262: ------------------------------------------------------------------------ r371262 | nickdesaulniers | 2019-09-06 23:50:11 +0200 (Fri, 06 Sep 2019) | 45 lines [IR] CallBrInst: scan+update arg list when indirect dest list changes Summary: There's an unspoken invariant of callbr that the list of BlockAddress Constants in the "function args" list match the BasicBlocks in the "other labels" list. (This invariant is being added to the LangRef in https://reviews.llvm.org/D67196). When modifying the any of the indirect destinations of a callbr instruction (possible jump targets), we need to update the function arguments if the argument is a BlockAddress whose BasicBlock refers to the indirect destination BasicBlock being replaced. Otherwise, many transforms that modify successors will end up violating that invariant. A recent change to the arm64 Linux kernel exposed this bug, which prevents the kernel from booting. I considered maintaining a mapping from indirect destination BasicBlock to argument operand BlockAddress, but this ends up being a one to potentially many (though usually one) mapping. Also, the list of arguments to a function (or more typically inline assembly) ends up being less than 10. The implementation is significantly simpler to just rescan the full list of arguments. Because of the one to potentially many relationship, the full arg list must be scanned (we can't stop at the first instance). Thanks to the following folks that reported the issue and helped debug it: * Nathan Chancellor * Will Deacon * Andrew Murray * Craig Topper Link: https://bugs.llvm.org/show_bug.cgi?id=43222 Link: https://github.com/ClangBuiltLinux/linux/issues/649 Link: https://lists.infradead.org/pipermail/linux-arm-kernel/2019-September/678330.html Reviewers: craig.topper, chandlerc Reviewed By: craig.topper Subscribers: void, javed.absar, kristof.beyls, hiraditya, llvm-commits, nathanchance, srhines Tags: #llvm Differential Revision: https://reviews.llvm.org/D67252 ------------------------------------------------------------------------ llvm-svn: 371376 --- llvm/include/llvm/IR/Instructions.h | 13 ++++--- llvm/lib/IR/Instructions.cpp | 11 ++++++ llvm/unittests/IR/InstructionsTest.cpp | 51 ++++++++++++++++++++++++++ 3 files changed, 70 insertions(+), 5 deletions(-) diff --git a/llvm/include/llvm/IR/Instructions.h b/llvm/include/llvm/IR/Instructions.h index 215ce45c7b75..6773664104a3 100644 --- a/llvm/include/llvm/IR/Instructions.h +++ b/llvm/include/llvm/IR/Instructions.h @@ -3938,6 +3938,9 @@ class CallBrInst : public CallBase { ArrayRef IndirectDests, ArrayRef Args, ArrayRef Bundles, const Twine &NameStr); + /// Should the Indirect Destinations change, scan + update the Arg list. + void updateArgBlockAddresses(unsigned i, BasicBlock *B); + /// Compute the number of operands to allocate. static int ComputeNumOperands(int NumArgs, int NumIndirectDests, int NumBundleInputs = 0) { @@ -4075,7 +4078,7 @@ class CallBrInst : public CallBase { return cast(*(&Op<-1>() - getNumIndirectDests() - 1)); } BasicBlock *getIndirectDest(unsigned i) const { - return cast(*(&Op<-1>() - getNumIndirectDests() + i)); + return cast_or_null(*(&Op<-1>() - getNumIndirectDests() + i)); } SmallVector getIndirectDests() const { SmallVector IndirectDests; @@ -4087,6 +4090,7 @@ class CallBrInst : public CallBase { *(&Op<-1>() - getNumIndirectDests() - 1) = reinterpret_cast(B); } void setIndirectDest(unsigned i, BasicBlock *B) { + updateArgBlockAddresses(i, B); *(&Op<-1>() - getNumIndirectDests() + i) = reinterpret_cast(B); } @@ -4096,11 +4100,10 @@ class CallBrInst : public CallBase { return i == 0 ? getDefaultDest() : getIndirectDest(i - 1); } - void setSuccessor(unsigned idx, BasicBlock *NewSucc) { - assert(idx < getNumIndirectDests() + 1 && + void setSuccessor(unsigned i, BasicBlock *NewSucc) { + assert(i < getNumIndirectDests() + 1 && "Successor # out of range for callbr!"); - *(&Op<-1>() - getNumIndirectDests() -1 + idx) = - reinterpret_cast(NewSucc); + return i == 0 ? setDefaultDest(NewSucc) : setIndirectDest(i - 1, NewSucc); } unsigned getNumSuccessors() const { return getNumIndirectDests() + 1; } diff --git a/llvm/lib/IR/Instructions.cpp b/llvm/lib/IR/Instructions.cpp index 2e7cad103c12..90cb2c26e082 100644 --- a/llvm/lib/IR/Instructions.cpp +++ b/llvm/lib/IR/Instructions.cpp @@ -822,6 +822,17 @@ void CallBrInst::init(FunctionType *FTy, Value *Fn, BasicBlock *Fallthrough, setName(NameStr); } +void CallBrInst::updateArgBlockAddresses(unsigned i, BasicBlock *B) { + assert(getNumIndirectDests() > i && "IndirectDest # out of range for callbr"); + if (BasicBlock *OldBB = getIndirectDest(i)) { + BlockAddress *Old = BlockAddress::get(OldBB); + BlockAddress *New = BlockAddress::get(B); + for (unsigned ArgNo = 0, e = getNumArgOperands(); ArgNo != e; ++ArgNo) + if (dyn_cast(getArgOperand(ArgNo)) == Old) + setArgOperand(ArgNo, New); + } +} + CallBrInst::CallBrInst(const CallBrInst &CBI) : CallBase(CBI.Attrs, CBI.FTy, CBI.getType(), Instruction::CallBr, OperandTraits::op_end(this) - CBI.getNumOperands(), diff --git a/llvm/unittests/IR/InstructionsTest.cpp b/llvm/unittests/IR/InstructionsTest.cpp index 9b9efe33cfed..b2ea3844d335 100644 --- a/llvm/unittests/IR/InstructionsTest.cpp +++ b/llvm/unittests/IR/InstructionsTest.cpp @@ -1061,5 +1061,56 @@ TEST(InstructionsTest, FNegInstruction) { FNeg->deleteValue(); } +TEST(InstructionsTest, CallBrInstruction) { + LLVMContext Context; + std::unique_ptr M = parseIR(Context, R"( +define void @foo() { +entry: + callbr void asm sideeffect "// XXX: ${0:l}", "X"(i8* blockaddress(@foo, %branch_test.exit)) + to label %land.rhs.i [label %branch_test.exit] + +land.rhs.i: + br label %branch_test.exit + +branch_test.exit: + %0 = phi i1 [ true, %entry ], [ false, %land.rhs.i ] + br i1 %0, label %if.end, label %if.then + +if.then: + ret void + +if.end: + ret void +} +)"); + Function *Foo = M->getFunction("foo"); + auto BBs = Foo->getBasicBlockList().begin(); + CallBrInst &CBI = cast(BBs->front()); + ++BBs; + ++BBs; + BasicBlock &BranchTestExit = *BBs; + ++BBs; + BasicBlock &IfThen = *BBs; + + // Test that setting the first indirect destination of callbr updates the dest + EXPECT_EQ(&BranchTestExit, CBI.getIndirectDest(0)); + CBI.setIndirectDest(0, &IfThen); + EXPECT_EQ(&IfThen, CBI.getIndirectDest(0)); + + // Further, test that changing the indirect destination updates the arg + // operand to use the block address of the new indirect destination basic + // block. This is a critical invariant of CallBrInst. + BlockAddress *IndirectBA = BlockAddress::get(CBI.getIndirectDest(0)); + BlockAddress *ArgBA = cast(CBI.getArgOperand(0)); + EXPECT_EQ(IndirectBA, ArgBA) + << "After setting the indirect destination, callbr had an indirect " + "destination of '" + << CBI.getIndirectDest(0)->getName() << "', but a argument of '" + << ArgBA->getBasicBlock()->getName() << "'. These should always match:\n" + << CBI; + EXPECT_EQ(IndirectBA->getBasicBlock(), &IfThen); + EXPECT_EQ(ArgBA->getBasicBlock(), &IfThen); +} + } // end anonymous namespace } // end namespace llvm From 8cdf289f45f58d65a6fd44bd71b8fcaef71a0698 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Mon, 9 Sep 2019 09:08:44 +0000 Subject: [PATCH 214/289] Merging r371111: ------------------------------------------------------------------------ r371111 | efriedma | 2019-09-05 22:02:38 +0200 (Thu, 05 Sep 2019) | 17 lines [IfConversion] Fix diamond conversion with unanalyzable branches. The code was incorrectly counting the number of identical instructions, and therefore tried to predicate an instruction which should not have been predicated. This could have various effects: a compiler crash, an assembler failure, a miscompile, or just generating an extra, unnecessary instruction. Instead of depending on TargetInstrInfo::removeBranch, which only works on analyzable branches, just remove all branch instructions. Fixes https://bugs.llvm.org/show_bug.cgi?id=43121 and https://bugs.llvm.org/show_bug.cgi?id=41121 . Differential Revision: https://reviews.llvm.org/D67203 ------------------------------------------------------------------------ llvm-svn: 371377 --- llvm/lib/CodeGen/IfConversion.cpp | 10 +++- .../ARM/ifcvt-diamond-unanalyzable-common.mir | 58 +++++++++++++++++++ 2 files changed, 66 insertions(+), 2 deletions(-) create mode 100644 llvm/test/CodeGen/ARM/ifcvt-diamond-unanalyzable-common.mir diff --git a/llvm/lib/CodeGen/IfConversion.cpp b/llvm/lib/CodeGen/IfConversion.cpp index b17a253fe23f..fde3c152e9d9 100644 --- a/llvm/lib/CodeGen/IfConversion.cpp +++ b/llvm/lib/CodeGen/IfConversion.cpp @@ -1758,9 +1758,15 @@ bool IfConverter::IfConvertDiamondCommon( if (!BBI1->IsBrAnalyzable) verifySameBranchInstructions(&MBB1, &MBB2); #endif - BBI1->NonPredSize -= TII->removeBranch(*BBI1->BB); - // Remove duplicated instructions. + // Remove duplicated instructions from the tail of MBB1: any branch + // instructions, and the common instructions counted by NumDups2. DI1 = MBB1.end(); + while (DI1 != MBB1.begin()) { + MachineBasicBlock::iterator Prev = std::prev(DI1); + if (!Prev->isBranch() && !Prev->isDebugInstr()) + break; + DI1 = Prev; + } for (unsigned i = 0; i != NumDups2; ) { // NumDups2 only counted non-dbg_value instructions, so this won't // run off the head of the list. diff --git a/llvm/test/CodeGen/ARM/ifcvt-diamond-unanalyzable-common.mir b/llvm/test/CodeGen/ARM/ifcvt-diamond-unanalyzable-common.mir new file mode 100644 index 000000000000..576362184031 --- /dev/null +++ b/llvm/test/CodeGen/ARM/ifcvt-diamond-unanalyzable-common.mir @@ -0,0 +1,58 @@ +# RUN: llc %s -o - -run-pass=if-converter | FileCheck %s +# Make sure we correctly if-convert blocks containing an INLINEASM_BR. +# CHECK: t2CMPri killed renamable $r2, 34 +# CHECK-NEXT: $r0 = t2MOVi 2, 1, $cpsr, $noreg +# CHECK-NEXT: $r0 = t2MOVi 3, 0, killed $cpsr, $noreg, implicit killed $r0 +# CHECK-NEXT: tBL 14, $noreg, @fn2 +# CHECK-NEXT: INLINEASM_BR &"", 9, 13, 0, 13, blockaddress(@fn1, %ir-block.l_yes) +# CHECK-NEXT: t2B %bb.1, 14, $noreg +--- | + target triple = "thumbv7-unknown-linux-gnueabi" + + define dso_local void @fn1() { + l_yes: + ret void + } + + declare dso_local i32 @fn2(...) +... +--- +name: fn1 +alignment: 1 +tracksRegLiveness: true +body: | + bb.0: + successors: %bb.1(0x40000000), %bb.2(0x40000000) + liveins: $r0, $r1, $r2, $r4, $lr + + $sp = frame-setup t2STMDB_UPD $sp, 14, $noreg, killed $r4, killed $lr + t2CMPri killed renamable $r2, 34, 14, $noreg, implicit-def $cpsr + t2Bcc %bb.2, 1, killed $cpsr + + bb.1: + successors: %bb.3(0x40000000), %bb.4(0x40000000) + liveins: $r1 + + $r0 = t2MOVi 3, 14, $noreg, $noreg + tBL 14, $noreg, @fn2, csr_aapcs, implicit-def dead $lr, implicit $sp, implicit $r0, implicit $r1, implicit-def $sp, implicit-def dead $r0 + INLINEASM_BR &"", 9, 13, 0, 13, blockaddress(@fn1, %ir-block.l_yes) + t2B %bb.3, 14, $noreg + + bb.2: + successors: %bb.3(0x40000000), %bb.4(0x40000000) + liveins: $r1 + + $r0 = t2MOVi 2, 14, $noreg, $noreg + tBL 14, $noreg, @fn2, csr_aapcs, implicit-def dead $lr, implicit $sp, implicit $r0, implicit $r1, implicit-def $sp, implicit-def dead $r0 + INLINEASM_BR &"", 9, 13, 0, 13, blockaddress(@fn1, %ir-block.l_yes) + t2B %bb.3, 14, $noreg + + bb.3: + successors: %bb.4(0x80000000) + + INLINEASM &"", 1 + + bb.4.l_yes (address-taken): + $sp = t2LDMIA_RET $sp, 14, $noreg, def $r4, def $pc + +... From 1c21c1972f9201c1f7d2a8f3ae27568b36d71efa Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Mon, 9 Sep 2019 09:36:49 +0000 Subject: [PATCH 215/289] Merging r371305 and r371307: ------------------------------------------------------------------------ r371305 | nikic | 2019-09-07 14:03:48 +0200 (Sat, 07 Sep 2019) | 1 line [X86] Add test for PR43230; NFC ------------------------------------------------------------------------ ------------------------------------------------------------------------ r371307 | nikic | 2019-09-07 14:13:44 +0200 (Sat, 07 Sep 2019) | 9 lines [X86] Fix pshuflw formation from repeated shuffle mask (PR43230) Fix for https://bugs.llvm.org/show_bug.cgi?id=43230. When creating PSHUFLW from a repeated shuffle mask, we have to apply the checks to the repeated mask, not the original one. For the test case from PR43230 the inspected part of the original mask is all undef. Differential Revision: https://reviews.llvm.org/D67314 ------------------------------------------------------------------------ llvm-svn: 371378 --- llvm/lib/Target/X86/X86ISelLowering.cpp | 4 +- .../CodeGen/X86/vector-shuffle-256-v16.ll | 41 +++++++++++++++++++ 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index 87ff5a719fca..e67ad2332159 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -31664,8 +31664,8 @@ static bool matchUnaryPermuteShuffle(MVT MaskVT, ArrayRef Mask, if (!ContainsZeros && AllowIntDomain && MaskScalarSizeInBits == 16) { SmallVector RepeatedMask; if (is128BitLaneRepeatedShuffleMask(MaskEltVT, Mask, RepeatedMask)) { - ArrayRef LoMask(Mask.data() + 0, 4); - ArrayRef HiMask(Mask.data() + 4, 4); + ArrayRef LoMask(RepeatedMask.data() + 0, 4); + ArrayRef HiMask(RepeatedMask.data() + 4, 4); // PSHUFLW: permute lower 4 elements only. if (isUndefOrInRange(LoMask, 0, 4) && diff --git a/llvm/test/CodeGen/X86/vector-shuffle-256-v16.ll b/llvm/test/CodeGen/X86/vector-shuffle-256-v16.ll index 0be1fec5ecd2..001288f87d77 100644 --- a/llvm/test/CodeGen/X86/vector-shuffle-256-v16.ll +++ b/llvm/test/CodeGen/X86/vector-shuffle-256-v16.ll @@ -4754,3 +4754,44 @@ define <16 x i16> @unpckh_v16i16(<16 x i16> %x, <16 x i16> %y) { ret <16 x i16> %unpckh } +define <16 x i16> @pr43230(<16 x i16> %a, <16 x i16> %b) { +; AVX1-LABEL: pr43230: +; AVX1: # %bb.0: +; AVX1-NEXT: vextractf128 $1, %ymm1, %xmm1 +; AVX1-NEXT: vpsllw $12, %xmm1, %xmm2 +; AVX1-NEXT: vpsllw $4, %xmm1, %xmm1 +; AVX1-NEXT: vpor %xmm2, %xmm1, %xmm1 +; AVX1-NEXT: vpaddw %xmm1, %xmm1, %xmm2 +; AVX1-NEXT: vextractf128 $1, %ymm0, %xmm0 +; AVX1-NEXT: vpsrlw $8, %xmm0, %xmm3 +; AVX1-NEXT: vpblendvb %xmm1, %xmm3, %xmm0, %xmm0 +; AVX1-NEXT: vpsrlw $4, %xmm0, %xmm1 +; AVX1-NEXT: vpblendvb %xmm2, %xmm1, %xmm0, %xmm0 +; AVX1-NEXT: vpsrlw $2, %xmm0, %xmm1 +; AVX1-NEXT: vpaddw %xmm2, %xmm2, %xmm2 +; AVX1-NEXT: vpblendvb %xmm2, %xmm1, %xmm0, %xmm0 +; AVX1-NEXT: vpsrlw $1, %xmm0, %xmm1 +; AVX1-NEXT: vpaddw %xmm2, %xmm2, %xmm2 +; AVX1-NEXT: vpblendvb %xmm2, %xmm1, %xmm0, %xmm0 +; AVX1-NEXT: vinsertf128 $1, %xmm0, %ymm0, %ymm0 +; AVX1-NEXT: vandps {{.*}}(%rip), %ymm0, %ymm0 +; AVX1-NEXT: retq +; +; AVX2-LABEL: pr43230: +; AVX2: # %bb.0: +; AVX2-NEXT: vpxor %xmm2, %xmm2, %xmm2 +; AVX2-NEXT: vpunpckhwd {{.*#+}} ymm1 = ymm1[4],ymm2[4],ymm1[5],ymm2[5],ymm1[6],ymm2[6],ymm1[7],ymm2[7],ymm1[12],ymm2[12],ymm1[13],ymm2[13],ymm1[14],ymm2[14],ymm1[15],ymm2[15] +; AVX2-NEXT: vpunpckhwd {{.*#+}} ymm0 = ymm2[4],ymm0[4],ymm2[5],ymm0[5],ymm2[6],ymm0[6],ymm2[7],ymm0[7],ymm2[12],ymm0[12],ymm2[13],ymm0[13],ymm2[14],ymm0[14],ymm2[15],ymm0[15] +; AVX2-NEXT: vpsrlvd %ymm1, %ymm0, %ymm0 +; AVX2-NEXT: vpshufb {{.*#+}} ymm0 = zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,zero,ymm0[26,27],zero,zero +; AVX2-NEXT: retq +; +; AVX512VL-LABEL: pr43230: +; AVX512VL: # %bb.0: +; AVX512VL-NEXT: vpsrlvw %ymm1, %ymm0, %ymm0 +; AVX512VL-NEXT: vpand {{.*}}(%rip), %ymm0, %ymm0 +; AVX512VL-NEXT: retq + %shr = lshr <16 x i16> %a, %b + %shuf = shufflevector <16 x i16> zeroinitializer, <16 x i16> %shr, <16 x i32> + ret <16 x i16> %shuf +} From b508b4ba06795704af6f05d4159fdf656e0185df Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Mon, 9 Sep 2019 09:43:19 +0000 Subject: [PATCH 216/289] Merging r371221 and r371224: ------------------------------------------------------------------------ r371221 | spatel | 2019-09-06 18:10:18 +0200 (Fri, 06 Sep 2019) | 3 lines [SimplifyLibCalls] handle pow(x,-0.0) before it can assert (PR43233) https://bugs.llvm.org/show_bug.cgi?id=43233 ------------------------------------------------------------------------ ------------------------------------------------------------------------ r371224 | jfb | 2019-09-06 18:26:59 +0200 (Fri, 06 Sep 2019) | 39 lines [InstCombine] pow(x, +/- 0.0) -> 1.0 Summary: This isn't an important optimization at all... We're already doing: pow(x, 0.0) -> 1.0 My patch merely teaches instcombine that -0.0 does the same. However, doing this fixes an AMAZING bug! Compile this program: extern "C" double pow(double, double); double boom(double base) { return pow(base, -0.0); } With: clang++ ~/Desktop/fast-math.cpp -ffast-math -O2 -S And clang will crash with a signal. Wow, fast math is so fast it ICEs the compiler! Arguably, the generated math is infinitely fast. What's actually happening is that we recurse infinitely in getPow. In debug we hit its assertion: assert(Exp != 0 && "Incorrect exponent 0 not handled"); We avoid this entire mess if we instead recognize that an exponent of positive and negative zero yield 1.0. A separate commit, r371221, fixed the same problem. This only contains the added tests. Reviewers: scanon Subscribers: hiraditya, jkorous, dexonsmith, ributzka, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D67248 ------------------------------------------------------------------------ llvm-svn: 371381 --- .../lib/Transforms/Utils/SimplifyLibCalls.cpp | 4 +- llvm/test/Transforms/InstCombine/pow-0.ll | 60 +++++++++++++++++++ llvm/test/Transforms/InstCombine/pow-4.ll | 10 ++++ 3 files changed, 72 insertions(+), 2 deletions(-) create mode 100644 llvm/test/Transforms/InstCombine/pow-0.ll diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp index e0def81d5eee..e938ae6cb42f 100644 --- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp @@ -1480,8 +1480,8 @@ Value *LibCallSimplifier::optimizePow(CallInst *Pow, IRBuilder<> &B) { if (match(Expo, m_SpecificFP(-1.0))) return B.CreateFDiv(ConstantFP::get(Ty, 1.0), Base, "reciprocal"); - // pow(x, 0.0) -> 1.0 - if (match(Expo, m_SpecificFP(0.0))) + // pow(x, +/-0.0) -> 1.0 + if (match(Expo, m_AnyZeroFP())) return ConstantFP::get(Ty, 1.0); // pow(x, 1.0) -> x diff --git a/llvm/test/Transforms/InstCombine/pow-0.ll b/llvm/test/Transforms/InstCombine/pow-0.ll new file mode 100644 index 000000000000..8de8e12a2d10 --- /dev/null +++ b/llvm/test/Transforms/InstCombine/pow-0.ll @@ -0,0 +1,60 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s + +; CHECK-LABEL: @zero( +; CHECK-NEXT: ret double 1.000000e+00 +define double @zero(double %value) { + %res = call double @llvm.pow.f64(double %value, double 0.000000e+00) + ret double %res +} + +; CHECK-LABEL: @minus_zero( +; CHECK-NEXT: ret double 1.000000e+00 +define double @minus_zero(double %value) { + %res = call double @llvm.pow.f64(double %value, double -0.000000e+00) + ret double %res +} + +; CHECK-LABEL: @fast_zero( +; CHECK-NEXT: ret double 1.000000e+00 +define double @fast_zero(double %value) { + %res = call fast double @llvm.pow.f64(double %value, double 0.000000e+00) + ret double %res +} + +; CHECK-LABEL: @fast_minus_zero( +; CHECK-NEXT: ret double 1.000000e+00 +define double @fast_minus_zero(double %value) { + %res = call fast double @llvm.pow.f64(double %value, double -0.000000e+00) + ret double %res +} + +; CHECK-LABEL: @vec_zero( +; CHECK-NEXT: ret <2 x double> +define <2 x double> @vec_zero(<2 x double> %value) { + %res = call <2 x double> @llvm.pow.v2f64(<2 x double> %value, <2 x double> ) + ret <2 x double> %res +} + +; CHECK-LABEL: @vec_minus_zero( +; CHECK-NEXT: ret <2 x double> +define <2 x double> @vec_minus_zero(<2 x double> %value) { + %res = call <2 x double> @llvm.pow.v2f64(<2 x double> %value, <2 x double> ) + ret <2 x double> %res +} + +; CHECK-LABEL: @vec_fast_zero( +; CHECK-NEXT: ret <2 x double> +define <2 x double> @vec_fast_zero(<2 x double> %value) { + %res = call fast <2 x double> @llvm.pow.v2f64(<2 x double> %value, <2 x double> ) + ret <2 x double> %res +} + +; CHECK-LABEL: @vec_fast_minus_zero( +; CHECK-NEXT: ret <2 x double> +define <2 x double> @vec_fast_minus_zero(<2 x double> %value) { + %res = call fast <2 x double> @llvm.pow.v2f64(<2 x double> %value, <2 x double> ) + ret <2 x double> %res +} + +declare double @llvm.pow.f64(double, double) +declare <2 x double> @llvm.pow.v2f64(<2 x double>, <2 x double>) diff --git a/llvm/test/Transforms/InstCombine/pow-4.ll b/llvm/test/Transforms/InstCombine/pow-4.ll index e4352392e229..4aac27fe72f0 100644 --- a/llvm/test/Transforms/InstCombine/pow-4.ll +++ b/llvm/test/Transforms/InstCombine/pow-4.ll @@ -223,3 +223,13 @@ define <4 x float> @test_simplify_3_5(<4 x float> %x) { ret <4 x float> %1 } +; Make sure that -0.0 exponent is always simplified. + +define double @PR43233(double %x) { +; CHECK-LABEL: @PR43233( +; CHECK-NEXT: ret double 1.000000e+00 +; + %r = call fast double @llvm.pow.f64(double %x, double -0.0) + ret double %r +} + From 5cbaa56ac5ff406d65037d5fa43ad44e0191f9b0 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Mon, 9 Sep 2019 09:48:38 +0000 Subject: [PATCH 217/289] Merging r370592: ------------------------------------------------------------------------ r370592 | rksimon | 2019-08-31 18:21:31 +0200 (Sat, 31 Aug 2019) | 3 lines [X86] EltsFromConsecutiveLoads - Don't confuse elt count with vector element count (PR43170) EltsFromConsecutiveLoads was assuming that the number of input elts was the same as the number of elements in the output vector type when creating a zeroing shuffle, causing an assert when subvectors were being combined instead of just scalars. ------------------------------------------------------------------------ llvm-svn: 371382 --- llvm/lib/Target/X86/X86ISelLowering.cpp | 27 +++++++------ .../test/CodeGen/X86/vector-shuffle-avx512.ll | 38 +++++++++++++++++++ 2 files changed, 54 insertions(+), 11 deletions(-) diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index e67ad2332159..0c5b8a79dd62 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -7650,17 +7650,22 @@ static SDValue EltsFromConsecutiveLoads(EVT VT, ArrayRef Elts, // IsConsecutiveLoadWithZeros - we need to create a shuffle of the loaded // vector and a zero vector to clear out the zero elements. if (!isAfterLegalize && VT.isVector()) { - SmallVector ClearMask(NumElems, -1); - for (unsigned i = 0; i < NumElems; ++i) { - if (ZeroMask[i]) - ClearMask[i] = i + NumElems; - else if (LoadMask[i]) - ClearMask[i] = i; - } - SDValue V = CreateLoad(VT, LDBase); - SDValue Z = VT.isInteger() ? DAG.getConstant(0, DL, VT) - : DAG.getConstantFP(0.0, DL, VT); - return DAG.getVectorShuffle(VT, DL, V, Z, ClearMask); + unsigned NumMaskElts = VT.getVectorNumElements(); + if ((NumMaskElts % NumElems) == 0) { + unsigned Scale = NumMaskElts / NumElems; + SmallVector ClearMask(NumMaskElts, -1); + for (unsigned i = 0; i < NumElems; ++i) { + if (UndefMask[i]) + continue; + int Offset = ZeroMask[i] ? NumMaskElts : 0; + for (unsigned j = 0; j != Scale; ++j) + ClearMask[(i * Scale) + j] = (i * Scale) + j + Offset; + } + SDValue V = CreateLoad(VT, LDBase); + SDValue Z = VT.isInteger() ? DAG.getConstant(0, DL, VT) + : DAG.getConstantFP(0.0, DL, VT); + return DAG.getVectorShuffle(VT, DL, V, Z, ClearMask); + } } } diff --git a/llvm/test/CodeGen/X86/vector-shuffle-avx512.ll b/llvm/test/CodeGen/X86/vector-shuffle-avx512.ll index 2092b3bf4530..65472aaeea7e 100644 --- a/llvm/test/CodeGen/X86/vector-shuffle-avx512.ll +++ b/llvm/test/CodeGen/X86/vector-shuffle-avx512.ll @@ -936,3 +936,41 @@ define <16 x float> @test_masked_permps_v16f32(<16 x float>* %vp, <16 x float> % %res = select <16 x i1> , <16 x float> %shuf, <16 x float> %vec2 ret <16 x float> %res } + +%union1= type { <16 x float> } +@src1 = external dso_local local_unnamed_addr global %union1, align 64 + +define void @PR43170(<16 x float>* %a0) { +; SKX64-LABEL: PR43170: +; SKX64: # %bb.0: # %entry +; SKX64-NEXT: vmovaps {{.*}}(%rip), %ymm0 +; SKX64-NEXT: vmovaps %zmm0, (%rdi) +; SKX64-NEXT: vzeroupper +; SKX64-NEXT: retq +; +; KNL64-LABEL: PR43170: +; KNL64: # %bb.0: # %entry +; KNL64-NEXT: vmovaps {{.*}}(%rip), %ymm0 +; KNL64-NEXT: vmovaps %zmm0, (%rdi) +; KNL64-NEXT: retq +; +; SKX32-LABEL: PR43170: +; SKX32: # %bb.0: # %entry +; SKX32-NEXT: movl {{[0-9]+}}(%esp), %eax +; SKX32-NEXT: vmovaps src1, %ymm0 +; SKX32-NEXT: vmovaps %zmm0, (%eax) +; SKX32-NEXT: vzeroupper +; SKX32-NEXT: retl +; +; KNL32-LABEL: PR43170: +; KNL32: # %bb.0: # %entry +; KNL32-NEXT: movl {{[0-9]+}}(%esp), %eax +; KNL32-NEXT: vmovaps src1, %ymm0 +; KNL32-NEXT: vmovaps %zmm0, (%eax) +; KNL32-NEXT: retl +entry: + %0 = load <8 x float>, <8 x float>* bitcast (%union1* @src1 to <8 x float>*), align 64 + %1 = shufflevector <8 x float> %0, <8 x float> zeroinitializer, <16 x i32> + store <16 x float> %1, <16 x float>* %a0, align 64 + ret void +} From 127240acf1001b72c0c52863ffe3dc39b7c5fd6d Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Tue, 10 Sep 2019 07:31:55 +0000 Subject: [PATCH 218/289] Merging r371434: ------------------------------------------------------------------------ r371434 | efriedma | 2019-09-09 20:29:27 +0200 (Mon, 09 Sep 2019) | 15 lines [IfConversion] Correctly handle cases where analyzeBranch fails. If analyzeBranch fails, on some targets, the out parameters point to some blocks in the function. But we can't use that information, so make sure to clear it out. (In some places in IfConversion, we assume that any block with a TrueBB is analyzable.) The change to the testcase makes it trigger a bug on builds without this fix: IfConvertDiamond tries to perform a followup "merge" operation, which isn't legal, and we somehow end up with a branch to a deleted MBB. I'm not sure how this doesn't crash the compiler. Differential Revision: https://reviews.llvm.org/D67306 ------------------------------------------------------------------------ llvm-svn: 371490 --- llvm/lib/CodeGen/IfConversion.cpp | 6 ++++++ llvm/test/CodeGen/ARM/ifcvt-diamond-unanalyzable-common.mir | 5 ++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/llvm/lib/CodeGen/IfConversion.cpp b/llvm/lib/CodeGen/IfConversion.cpp index fde3c152e9d9..af556e2c856e 100644 --- a/llvm/lib/CodeGen/IfConversion.cpp +++ b/llvm/lib/CodeGen/IfConversion.cpp @@ -912,6 +912,12 @@ void IfConverter::AnalyzeBranches(BBInfo &BBI) { BBI.BrCond.clear(); BBI.IsBrAnalyzable = !TII->analyzeBranch(*BBI.BB, BBI.TrueBB, BBI.FalseBB, BBI.BrCond); + if (!BBI.IsBrAnalyzable) { + BBI.TrueBB = nullptr; + BBI.FalseBB = nullptr; + BBI.BrCond.clear(); + } + SmallVector RevCond(BBI.BrCond.begin(), BBI.BrCond.end()); BBI.IsBrReversible = (RevCond.size() == 0) || !TII->reverseBranchCondition(RevCond); diff --git a/llvm/test/CodeGen/ARM/ifcvt-diamond-unanalyzable-common.mir b/llvm/test/CodeGen/ARM/ifcvt-diamond-unanalyzable-common.mir index 576362184031..a2218b149f1b 100644 --- a/llvm/test/CodeGen/ARM/ifcvt-diamond-unanalyzable-common.mir +++ b/llvm/test/CodeGen/ARM/ifcvt-diamond-unanalyzable-common.mir @@ -1,4 +1,4 @@ -# RUN: llc %s -o - -run-pass=if-converter | FileCheck %s +# RUN: llc %s -o - -run-pass=if-converter -verify-machineinstrs | FileCheck %s # Make sure we correctly if-convert blocks containing an INLINEASM_BR. # CHECK: t2CMPri killed renamable $r2, 34 # CHECK-NEXT: $r0 = t2MOVi 2, 1, $cpsr, $noreg @@ -48,9 +48,8 @@ body: | t2B %bb.3, 14, $noreg bb.3: - successors: %bb.4(0x80000000) - INLINEASM &"", 1 + $sp = t2LDMIA_RET $sp, 14, $noreg, def $r4, def $pc bb.4.l_yes (address-taken): $sp = t2LDMIA_RET $sp, 14, $noreg, def $r4, def $pc From 02a0ef03e6d4b03c510040b152ec6da2898c534b Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Fri, 13 Sep 2019 08:10:33 +0000 Subject: [PATCH 219/289] Merging r371766: ------------------------------------------------------------------------ r371766 | nickdesaulniers | 2019-09-12 21:53:35 +0200 (Thu, 12 Sep 2019) | 29 lines [Clang][CodeGen] support alias attribute w/ gnu_inline Summary: r369705 did not consider the addition of gnu_inline on function declarations of alias attributed functions. This resulted in a reported regression in the clang-9-rc4 release from the Zig developers building glibc, which was observable as a failed assertion: llvm-project/clang/lib/AST/Decl.cpp:3336: bool clang::FunctionDecl::isInlineDefinitionExternallyVisible() const: Assertion `(doesThisDeclarationHaveABody() || willHaveBody()) && "Must be a function definition"' failed. Alias function declarations do not have bodies, so allow us to proceed if we have the alias function attribute but no body/definition, and add a test case. The emitted symbols and their linkage matches GCC for the added test case. Link: https://bugs.llvm.org/show_bug.cgi?id=43268 Reviewers: aaron.ballman, rsmith, erichkeane, andrewrk Reviewed By: andrewrk Subscribers: cfe-commits, andrewrk, hans, srhines Tags: #clang Differential Revision: https://reviews.llvm.org/D67455 ------------------------------------------------------------------------ llvm-svn: 371821 --- clang/lib/AST/Decl.cpp | 3 ++- clang/test/CodeGen/alias.c | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 21cf9da18a8b..aa74da006174 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -3332,7 +3332,8 @@ SourceRange FunctionDecl::getExceptionSpecSourceRange() const { /// an externally visible symbol, but "extern inline" will not create an /// externally visible symbol. bool FunctionDecl::isInlineDefinitionExternallyVisible() const { - assert((doesThisDeclarationHaveABody() || willHaveBody()) && + assert((doesThisDeclarationHaveABody() || willHaveBody() || + hasAttr()) && "Must be a function definition"); assert(isInlined() && "Function must be inline"); ASTContext &Context = getASTContext(); diff --git a/clang/test/CodeGen/alias.c b/clang/test/CodeGen/alias.c index 46568ee900c1..f5bdf3c0587e 100644 --- a/clang/test/CodeGen/alias.c +++ b/clang/test/CodeGen/alias.c @@ -99,3 +99,8 @@ static int test10_foo __attribute__((alias("test10"))); // CHECKGLOBALS-NOT: @test11_foo = dso_local void test11(void) {} static void test11_foo(void) __attribute__((alias("test11"))); + +// Test that gnu_inline+alias work. +// CHECKGLOBALS: @test12_alias = alias void (), void ()* @test12 +void test12(void) {} +inline void test12_alias(void) __attribute__((gnu_inline, alias("test12"))); From 8972a4776da42d708b4273c5fae40c107f5e6904 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Mon, 16 Sep 2019 09:11:39 +0000 Subject: [PATCH 220/289] ReleaseNotes: known issue: PR40547 llvm-svn: 371964 --- llvm/docs/ReleaseNotes.rst | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst index f7a99bd41cbb..75146ec238d9 100644 --- a/llvm/docs/ReleaseNotes.rst +++ b/llvm/docs/ReleaseNotes.rst @@ -21,6 +21,15 @@ have questions or comments, the `LLVM Developer's Mailing List them. +Known Issues +============ + +These are issues that couldn't be fixed before the release. See the bug reports +for the latest status. + +* `PR40547 `_ Clang gets miscompiled by GCC 9. + + Non-comprehensive list of changes in this release ================================================= From 12f174e98c3514755b21db2f040544c0b2ed5f67 Mon Sep 17 00:00:00 2001 From: Hans Wennborg Date: Tue, 17 Sep 2019 10:19:31 +0000 Subject: [PATCH 221/289] Merging r371969: ------------------------------------------------------------------------ r371969 | karka | 2019-09-16 11:52:23 +0200 (Mon, 16 Sep 2019) | 13 lines Change signature of __builtin_rotateright64 back to unsigned The signature of __builtin_rotateright64 was by misstake changed from unsigned to signed in r360863, this patch will change it back to unsigned as intended. This fixes pr43309 Reviewers: efriedma, hans Reviewed By: hans Differential Revision: https://reviews.llvm.org/D67606 ------------------------------------------------------------------------ llvm-svn: 372100 --- clang/include/clang/Basic/Builtins.def | 2 +- clang/test/CodeGen/avr-builtins.c | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/clang/include/clang/Basic/Builtins.def b/clang/include/clang/Basic/Builtins.def index 984e607a2fc4..08c999af1f10 100644 --- a/clang/include/clang/Basic/Builtins.def +++ b/clang/include/clang/Basic/Builtins.def @@ -440,7 +440,7 @@ BUILTIN(__builtin_rotateleft64, "UWiUWiUWi", "nc") BUILTIN(__builtin_rotateright8, "UcUcUc", "nc") BUILTIN(__builtin_rotateright16, "UsUsUs", "nc") BUILTIN(__builtin_rotateright32, "UZiUZiUZi", "nc") -BUILTIN(__builtin_rotateright64, "UWiUWiWi", "nc") +BUILTIN(__builtin_rotateright64, "UWiUWiUWi", "nc") // Random GCC builtins BUILTIN(__builtin_constant_p, "i.", "nctu") diff --git a/clang/test/CodeGen/avr-builtins.c b/clang/test/CodeGen/avr-builtins.c index cbba6b2f2a2e..8fa983a78239 100644 --- a/clang/test/CodeGen/avr-builtins.c +++ b/clang/test/CodeGen/avr-builtins.c @@ -1,5 +1,9 @@ // RUN: %clang_cc1 -triple avr-unknown-unknown -emit-llvm -o - %s | FileCheck %s +// Check that the parameter types match. This verifies pr43309. +// RUN: %clang_cc1 -triple avr-unknown-unknown -Wconversion -verify %s +// expected-no-diagnostics + unsigned char bitrev8(unsigned char data) { return __builtin_bitreverse8(data); } From 0399d5a9682b3cef71c653373e38890c63c4c365 Mon Sep 17 00:00:00 2001 From: Kai Nacke Date: Tue, 17 Sep 2019 19:16:16 +0000 Subject: [PATCH 222/289] Add external project LDC to release notes. LDC, the LLVM-based D compiler, is already ready for LLVM 9.0.0. llvm-svn: 372167 --- llvm/docs/ReleaseNotes.rst | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst index 75146ec238d9..6ef3ff90e836 100644 --- a/llvm/docs/ReleaseNotes.rst +++ b/llvm/docs/ReleaseNotes.rst @@ -349,6 +349,21 @@ LLD combined with lazily building compiler-rt to provide out-of-the-box cross-compiling for all supported targets. +LDC - the LLVM-based D compiler +------------------------------- + +`D `_ is a language with C-like syntax and static typing. It +pragmatically combines efficiency, control, and modeling power, with safety and +programmer productivity. D supports powerful concepts like Compile-Time Function +Execution (CTFE) and Template Meta-Programming, provides an innovative approach +to concurrency and offers many classical paradigms. + +`LDC `_ uses the frontend from the reference compiler +combined with LLVM as backend to produce efficient native code. LDC targets +x86/x86_64 systems like Linux, OS X, FreeBSD and Windows and also Linux on ARM +and PowerPC (32/64 bit). Ports to other architectures are underway. + + Additional Information ====================== From d0b8dd14570dc9efac09d3c5fd6e8512980fd7b7 Mon Sep 17 00:00:00 2001 From: Ushitora Anqou Date: Sat, 12 Oct 2019 12:19:07 +0900 Subject: [PATCH 223/289] [CAHP] Add skeleton backend for CAHP --- llvm/include/llvm/ADT/Triple.h | 1 + llvm/include/llvm/BinaryFormat/ELF.h | 7 +++ .../llvm/BinaryFormat/ELFRelocs/CAHP.def | 5 ++ llvm/include/llvm/Object/ELFObjectFile.h | 4 ++ llvm/include/llvm/module.modulemap | 1 + llvm/lib/Object/ELF.cpp | 7 +++ llvm/lib/ObjectYAML/ELFYAML.cpp | 4 ++ llvm/lib/Support/Triple.cpp | 11 ++++ llvm/lib/Target/CAHP/CAHPTargetMachine.cpp | 51 +++++++++++++++++++ llvm/lib/Target/CAHP/CAHPTargetMachine.h | 31 +++++++++++ llvm/lib/Target/CAHP/CMakeLists.txt | 4 ++ llvm/lib/Target/CAHP/LLVMBuild.txt | 18 +++++++ .../Target/CAHP/TargetInfo/CAHPTargetInfo.cpp | 22 ++++++++ .../lib/Target/CAHP/TargetInfo/CMakeLists.txt | 3 ++ llvm/lib/Target/CAHP/TargetInfo/LLVMBuild.txt | 6 +++ llvm/lib/Target/LLVMBuild.txt | 1 + llvm/tools/llvm-readobj/ELFDumper.cpp | 1 + llvm/unittests/ADT/TripleTest.cpp | 17 +++++++ 18 files changed, 194 insertions(+) create mode 100644 llvm/include/llvm/BinaryFormat/ELFRelocs/CAHP.def create mode 100644 llvm/lib/Target/CAHP/CAHPTargetMachine.cpp create mode 100644 llvm/lib/Target/CAHP/CAHPTargetMachine.h create mode 100644 llvm/lib/Target/CAHP/CMakeLists.txt create mode 100644 llvm/lib/Target/CAHP/LLVMBuild.txt create mode 100644 llvm/lib/Target/CAHP/TargetInfo/CAHPTargetInfo.cpp create mode 100644 llvm/lib/Target/CAHP/TargetInfo/CMakeLists.txt create mode 100644 llvm/lib/Target/CAHP/TargetInfo/LLVMBuild.txt diff --git a/llvm/include/llvm/ADT/Triple.h b/llvm/include/llvm/ADT/Triple.h index edeb31efab80..3777be27ac6a 100644 --- a/llvm/include/llvm/ADT/Triple.h +++ b/llvm/include/llvm/ADT/Triple.h @@ -54,6 +54,7 @@ class Triple { avr, // AVR: Atmel AVR microcontroller bpfel, // eBPF or extended BPF or 64-bit BPF (little endian) bpfeb, // eBPF or extended BPF or 64-bit BPF (big endian) + cahp, hexagon, // Hexagon: hexagon mips, // MIPS: mips, mipsallegrex, mipsr6 mipsel, // MIPSEL: mipsel, mipsallegrexe, mipsr6el diff --git a/llvm/include/llvm/BinaryFormat/ELF.h b/llvm/include/llvm/BinaryFormat/ELF.h index 2bd711137845..e1fa610d9d31 100644 --- a/llvm/include/llvm/BinaryFormat/ELF.h +++ b/llvm/include/llvm/BinaryFormat/ELF.h @@ -311,6 +311,8 @@ enum { EM_RISCV = 243, // RISC-V EM_LANAI = 244, // Lanai 32-bit processor EM_BPF = 247, // Linux kernel bpf virtual machine + + EM_CAHP = 246, }; // Object file classes. @@ -611,6 +613,11 @@ enum { #include "ELFRelocs/Hexagon.def" }; +// ELF Relocation type for CAHP. +enum { +#include "ELFRelocs/CAHP.def" +}; + // ELF Relocation type for Lanai. enum { #include "ELFRelocs/Lanai.def" diff --git a/llvm/include/llvm/BinaryFormat/ELFRelocs/CAHP.def b/llvm/include/llvm/BinaryFormat/ELFRelocs/CAHP.def new file mode 100644 index 000000000000..f319279b5528 --- /dev/null +++ b/llvm/include/llvm/BinaryFormat/ELFRelocs/CAHP.def @@ -0,0 +1,5 @@ +#ifndef ELF_RELOC +#error "ELF_RELOC must be defined" +#endif + +ELF_RELOC(R_CAHP_NONE, 0) diff --git a/llvm/include/llvm/Object/ELFObjectFile.h b/llvm/include/llvm/Object/ELFObjectFile.h index 86c015efd704..990982e90a29 100644 --- a/llvm/include/llvm/Object/ELFObjectFile.h +++ b/llvm/include/llvm/Object/ELFObjectFile.h @@ -1059,6 +1059,8 @@ StringRef ELFObjectFile::getFileFormatName() const { return (IsLittleEndian ? "ELF32-arm-little" : "ELF32-arm-big"); case ELF::EM_AVR: return "ELF32-avr"; + case ELF::EM_CAHP: + return "ELF32-cahp"; case ELF::EM_HEXAGON: return "ELF32-hexagon"; case ELF::EM_LANAI: @@ -1124,6 +1126,8 @@ template Triple::ArchType ELFObjectFile::getArch() const { return Triple::arm; case ELF::EM_AVR: return Triple::avr; + case ELF::EM_CAHP: + return Triple::cahp; case ELF::EM_HEXAGON: return Triple::hexagon; case ELF::EM_LANAI: diff --git a/llvm/include/llvm/module.modulemap b/llvm/include/llvm/module.modulemap index 9c4668e1473c..7138ef5a283e 100644 --- a/llvm/include/llvm/module.modulemap +++ b/llvm/include/llvm/module.modulemap @@ -61,6 +61,7 @@ module LLVM_BinaryFormat { textual header "BinaryFormat/ELFRelocs/ARC.def" textual header "BinaryFormat/ELFRelocs/AVR.def" textual header "BinaryFormat/ELFRelocs/BPF.def" + textual header "BinaryFormat/ELFRelocs/CAHP.def" textual header "BinaryFormat/ELFRelocs/Hexagon.def" textual header "BinaryFormat/ELFRelocs/i386.def" textual header "BinaryFormat/ELFRelocs/Lanai.def" diff --git a/llvm/lib/Object/ELF.cpp b/llvm/lib/Object/ELF.cpp index 8660b1a64bdd..0b9b03797f33 100644 --- a/llvm/lib/Object/ELF.cpp +++ b/llvm/lib/Object/ELF.cpp @@ -73,6 +73,13 @@ StringRef llvm::object::getELFRelocationTypeName(uint32_t Machine, break; } break; + case ELF::EM_CAHP: + switch (Type) { +#include "llvm/BinaryFormat/ELFRelocs/CAHP.def" + default: + break; + } + break; case ELF::EM_HEXAGON: switch (Type) { #include "llvm/BinaryFormat/ELFRelocs/Hexagon.def" diff --git a/llvm/lib/ObjectYAML/ELFYAML.cpp b/llvm/lib/ObjectYAML/ELFYAML.cpp index 7497154c757d..a80792fa1cd6 100644 --- a/llvm/lib/ObjectYAML/ELFYAML.cpp +++ b/llvm/lib/ObjectYAML/ELFYAML.cpp @@ -216,6 +216,7 @@ void ScalarEnumerationTraits::enumeration( ECase(EM_RISCV); ECase(EM_LANAI); ECase(EM_BPF); + ECase(EM_CAHP); #undef ECase } @@ -662,6 +663,9 @@ void ScalarEnumerationTraits::enumeration( case ELF::EM_RISCV: #include "llvm/BinaryFormat/ELFRelocs/RISCV.def" break; + case ELF::EM_CAHP: +#include "llvm/BinaryFormat/ELFRelocs/CAHP.def" + break; case ELF::EM_LANAI: #include "llvm/BinaryFormat/ELFRelocs/Lanai.def" break; diff --git a/llvm/lib/Support/Triple.cpp b/llvm/lib/Support/Triple.cpp index d419463e6a5e..1759f5eef0f4 100644 --- a/llvm/lib/Support/Triple.cpp +++ b/llvm/lib/Support/Triple.cpp @@ -29,6 +29,7 @@ StringRef Triple::getArchTypeName(ArchType Kind) { case avr: return "avr"; case bpfel: return "bpfel"; case bpfeb: return "bpfeb"; + case cahp: return "cahp"; case hexagon: return "hexagon"; case mips: return "mips"; case mipsel: return "mipsel"; @@ -144,6 +145,8 @@ StringRef Triple::getArchTypePrefix(ArchType Kind) { case riscv32: case riscv64: return "riscv"; + + case cahp: return "cahp"; } } @@ -315,6 +318,7 @@ Triple::ArchType Triple::getArchTypeForLLVMName(StringRef Name) { .Case("wasm64", wasm64) .Case("renderscript32", renderscript32) .Case("renderscript64", renderscript64) + .Case("cahp", cahp) .Default(UnknownArch); } @@ -443,6 +447,7 @@ static Triple::ArchType parseArch(StringRef ArchName) { .Case("wasm64", Triple::wasm64) .Case("renderscript32", Triple::renderscript32) .Case("renderscript64", Triple::renderscript64) + .Case("cahp", Triple::cahp) .Default(Triple::UnknownArch); // Some architectures require special parsing logic just to compute the @@ -670,6 +675,7 @@ static Triple::ObjectFormatType getDefaultFormat(const Triple &T) { case Triple::avr: case Triple::bpfeb: case Triple::bpfel: + case Triple::cahp: case Triple::hexagon: case Triple::lanai: case Triple::hsail: @@ -1231,6 +1237,7 @@ static unsigned getArchPointerBitWidth(llvm::Triple::ArchType Arch) { return 0; case llvm::Triple::avr: + case llvm::Triple::cahp: case llvm::Triple::msp430: return 16; @@ -1309,6 +1316,7 @@ Triple Triple::get32BitArchVariant() const { case Triple::avr: case Triple::bpfel: case Triple::bpfeb: + case Triple::cahp: case Triple::msp430: case Triple::systemz: case Triple::ppc64le: @@ -1371,6 +1379,7 @@ Triple Triple::get64BitArchVariant() const { case Triple::UnknownArch: case Triple::arc: case Triple::avr: + case Triple::cahp: case Triple::hexagon: case Triple::kalimba: case Triple::lanai: @@ -1440,6 +1449,7 @@ Triple Triple::getBigEndianArchVariant() const { case Triple::amdil64: case Triple::amdil: case Triple::avr: + case Triple::cahp: case Triple::hexagon: case Triple::hsail64: case Triple::hsail: @@ -1525,6 +1535,7 @@ bool Triple::isLittleEndian() const { case Triple::arm: case Triple::avr: case Triple::bpfel: + case Triple::cahp: case Triple::hexagon: case Triple::hsail64: case Triple::hsail: diff --git a/llvm/lib/Target/CAHP/CAHPTargetMachine.cpp b/llvm/lib/Target/CAHP/CAHPTargetMachine.cpp new file mode 100644 index 000000000000..355891a4cbe6 --- /dev/null +++ b/llvm/lib/Target/CAHP/CAHPTargetMachine.cpp @@ -0,0 +1,51 @@ +// This file is copied and modified from The LLVM Compiler Infrastructure, which +// is distributed under the Apache License v2.0 with LLVM Exceptions (see +// LICENSE.TXT for details). This file is licensed under the same license. + +#include "CAHPTargetMachine.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" +#include "llvm/CodeGen/TargetPassConfig.h" +#include "llvm/IR/LegacyPassManager.h" +#include "llvm/Support/FormattedStream.h" +#include "llvm/Support/TargetRegistry.h" +#include "llvm/Target/TargetOptions.h" +using namespace llvm; + +extern "C" void LLVMInitializeCAHPTarget() { + RegisterTargetMachine X(getTheCAHPTarget()); +} + +static std::string computeDataLayout(const Triple &TT) { + return "e" // Little endian + "-m:e" // ELF name manging + "-p:16:16" // 16-bit pointers, 16 bit aligned + "-i16:16" // 16 bit integers, 16 bit aligned + "-n16" // 16 bit native integer width + "-S16"; // 16 bit natural stack alignment +} + +static Reloc::Model getEffectiveRelocModel(const Triple &TT, + Optional RM) { + if (!RM.hasValue()) + return Reloc::Static; + return *RM; +} + +CAHPTargetMachine::CAHPTargetMachine(const Target &T, const Triple &TT, + StringRef CPU, StringRef FS, + const TargetOptions &Options, + Optional RM, + Optional CM, + CodeGenOpt::Level OL, bool JIT) + : LLVMTargetMachine(T, computeDataLayout(TT), TT, CPU, FS, Options, + getEffectiveRelocModel(TT, RM), + getEffectiveCodeModel(CM, CodeModel::Small), OL), + TLOF(make_unique()) { + initAsmInfo(); +} + +TargetPassConfig *CAHPTargetMachine::createPassConfig(PassManagerBase &PM) { + return new TargetPassConfig(*this, PM); +} diff --git a/llvm/lib/Target/CAHP/CAHPTargetMachine.h b/llvm/lib/Target/CAHP/CAHPTargetMachine.h new file mode 100644 index 000000000000..22963964bc7e --- /dev/null +++ b/llvm/lib/Target/CAHP/CAHPTargetMachine.h @@ -0,0 +1,31 @@ +// This file is copied and modified from The LLVM Compiler Infrastructure, which +// is distributed under the Apache License v2.0 with LLVM Exceptions (see +// LICENSE.TXT for details). This file is licensed under the same license. + +#ifndef LLVM_LIB_TARGET_CAHP_CAHPTARGETMACHINE_H +#define LLVM_LIB_TARGET_CAHP_CAHPTARGETMACHINE_H + +#include "llvm/CodeGen/SelectionDAGTargetInfo.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/Target/TargetMachine.h" + +namespace llvm { +class CAHPTargetMachine : public LLVMTargetMachine { + std::unique_ptr TLOF; + +public: + CAHPTargetMachine(const Target &T, const Triple &TT, StringRef CPU, + StringRef FS, const TargetOptions &Options, + Optional RM, Optional CM, + CodeGenOpt::Level OL, bool JIT); + + TargetPassConfig *createPassConfig(PassManagerBase &PM) override; + + TargetLoweringObjectFile *getObjFileLowering() const override { + return TLOF.get(); + } +}; +Target &getTheCAHPTarget(); +} // namespace llvm + +#endif diff --git a/llvm/lib/Target/CAHP/CMakeLists.txt b/llvm/lib/Target/CAHP/CMakeLists.txt new file mode 100644 index 000000000000..c71ef3fdbf60 --- /dev/null +++ b/llvm/lib/Target/CAHP/CMakeLists.txt @@ -0,0 +1,4 @@ +add_llvm_target(CAHPCodeGen + CAHPTargetMachine.cpp + ) +add_subdirectory(TargetInfo) diff --git a/llvm/lib/Target/CAHP/LLVMBuild.txt b/llvm/lib/Target/CAHP/LLVMBuild.txt new file mode 100644 index 000000000000..6b76cc43d326 --- /dev/null +++ b/llvm/lib/Target/CAHP/LLVMBuild.txt @@ -0,0 +1,18 @@ +; This file is copied and modified from The LLVM Compiler Infrastructure, which +; is distributed under the Apache License v2.0 with LLVM Exceptions (see +; LICENSE.TXT for details). This file is licensed under the same license. + +[common] +subdirectories = TargetInfo + +[component_0] +type = TargetGroup +name = CAHP +parent = Target + +[component_1] +type = Library +name = CAHPCodeGen +parent = CAHP +required_libraries = Core CodeGen CAHPInfo Support Target +add_to_library_groups = CAHP diff --git a/llvm/lib/Target/CAHP/TargetInfo/CAHPTargetInfo.cpp b/llvm/lib/Target/CAHP/TargetInfo/CAHPTargetInfo.cpp new file mode 100644 index 000000000000..f25ddb6a1972 --- /dev/null +++ b/llvm/lib/Target/CAHP/TargetInfo/CAHPTargetInfo.cpp @@ -0,0 +1,22 @@ +// This file is copied and modified from The LLVM Compiler Infrastructure, which +// is distributed under the Apache License v2.0 with LLVM Exceptions (see +// LICENSE.TXT for details). This file is licensed under the same license. + +#include "llvm/Support/TargetRegistry.h" +using namespace llvm; + +namespace llvm { +Target &getTheCAHPTarget() { + static Target TheCAHPTarget; + return TheCAHPTarget; +} +} // namespace llvm + +extern "C" void LLVMInitializeCAHPTargetInfo() { + RegisterTarget X(getTheCAHPTarget(), "cahp", "CAHP", "CAHP"); +} + +// FIXME: Temporary stub - this function must be defined for linking +// to succeed and will be called unconditionally by llc, so must be a no-op. +// Remove once this function is properly implemented. +extern "C" void LLVMInitializeCAHPTargetMC() {} diff --git a/llvm/lib/Target/CAHP/TargetInfo/CMakeLists.txt b/llvm/lib/Target/CAHP/TargetInfo/CMakeLists.txt new file mode 100644 index 000000000000..17afa06d7638 --- /dev/null +++ b/llvm/lib/Target/CAHP/TargetInfo/CMakeLists.txt @@ -0,0 +1,3 @@ +add_llvm_library(LLVMCAHPInfo + CAHPTargetInfo.cpp + ) diff --git a/llvm/lib/Target/CAHP/TargetInfo/LLVMBuild.txt b/llvm/lib/Target/CAHP/TargetInfo/LLVMBuild.txt new file mode 100644 index 000000000000..e0563e6528d3 --- /dev/null +++ b/llvm/lib/Target/CAHP/TargetInfo/LLVMBuild.txt @@ -0,0 +1,6 @@ +[component_0] +type = Library +name = CAHPInfo +parent = CAHP +required_libraries = Support +add_to_library_groups = CAHP diff --git a/llvm/lib/Target/LLVMBuild.txt b/llvm/lib/Target/LLVMBuild.txt index d6a95a3c6713..62d9db2a5fc7 100644 --- a/llvm/lib/Target/LLVMBuild.txt +++ b/llvm/lib/Target/LLVMBuild.txt @@ -24,6 +24,7 @@ subdirectories = AArch64 AVR BPF + CAHP Lanai Hexagon MSP430 diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp index 4e1cb7d544e7..cce77cd8ffcd 100644 --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -1032,6 +1032,7 @@ static const EnumEntry ElfMachineType[] = { ENUM_ENT(EM_RISCV, "RISC-V"), ENUM_ENT(EM_LANAI, "EM_LANAI"), ENUM_ENT(EM_BPF, "EM_BPF"), + ENUM_ENT(EM_CAHP, "CAHP"), }; static const EnumEntry ElfSymbolBindings[] = { diff --git a/llvm/unittests/ADT/TripleTest.cpp b/llvm/unittests/ADT/TripleTest.cpp index 37ebe5dbcb28..7a3ac70ef615 100644 --- a/llvm/unittests/ADT/TripleTest.cpp +++ b/llvm/unittests/ADT/TripleTest.cpp @@ -560,6 +560,18 @@ TEST(TripleTest, ParsedIDs) { EXPECT_EQ(Triple::UnknownEnvironment, T.getEnvironment()); EXPECT_TRUE(T.isArch32Bit()); + T = Triple("cahp-unknown-unknown"); + EXPECT_EQ(Triple::cahp, T.getArch()); + EXPECT_EQ(Triple::UnknownVendor, T.getVendor()); + EXPECT_EQ(Triple::UnknownOS, T.getOS()); + EXPECT_EQ(Triple::UnknownEnvironment, T.getEnvironment()); + + T = Triple("cahp"); + EXPECT_EQ(Triple::cahp, T.getArch()); + EXPECT_EQ(Triple::UnknownVendor, T.getVendor()); + EXPECT_EQ(Triple::UnknownOS, T.getOS()); + EXPECT_EQ(Triple::UnknownEnvironment, T.getEnvironment()); + T = Triple("huh"); EXPECT_EQ(Triple::UnknownArch, T.getArch()); } @@ -883,6 +895,11 @@ TEST(TripleTest, BitWidthPredicates) { EXPECT_FALSE(T.isArch32Bit()); EXPECT_TRUE(T.isArch64Bit()); EXPECT_TRUE(T.isRISCV()); + + T.setArch(Triple::cahp); + EXPECT_TRUE(T.isArch16Bit()); + EXPECT_FALSE(T.isArch32Bit()); + EXPECT_FALSE(T.isArch64Bit()); } TEST(TripleTest, BitWidthArchVariants) { From 2c31c0a80020cc50bba6df1c35da228905190d97 Mon Sep 17 00:00:00 2001 From: Ushitora Anqou Date: Sat, 12 Oct 2019 17:04:43 +0900 Subject: [PATCH 224/289] [CAHP] Add simple assembler --- .../Target/CAHP/AsmParser/CAHPAsmParser.cpp | 439 ++++++++++++++++++ llvm/lib/Target/CAHP/AsmParser/CMakeLists.txt | 3 + llvm/lib/Target/CAHP/AsmParser/LLVMBuild.txt | 10 + llvm/lib/Target/CAHP/CAHP.td | 34 ++ llvm/lib/Target/CAHP/CAHPInstrFormats.td | 168 +++++++ llvm/lib/Target/CAHP/CAHPInstrInfo.td | 228 +++++++++ llvm/lib/Target/CAHP/CAHPRegisterInfo.td | 41 ++ llvm/lib/Target/CAHP/CAHPTargetMachine.h | 2 +- llvm/lib/Target/CAHP/CMakeLists.txt | 13 + llvm/lib/Target/CAHP/LLVMBuild.txt | 3 +- .../CAHP/MCTargetDesc/CAHPAsmBackend.cpp | 91 ++++ .../CAHP/MCTargetDesc/CAHPELFObjectWriter.cpp | 42 ++ .../CAHP/MCTargetDesc/CAHPMCAsmInfo.cpp | 16 + .../Target/CAHP/MCTargetDesc/CAHPMCAsmInfo.h | 25 + .../CAHP/MCTargetDesc/CAHPMCCodeEmitter.cpp | 103 ++++ .../CAHP/MCTargetDesc/CAHPMCTargetDesc.cpp | 63 +++ .../CAHP/MCTargetDesc/CAHPMCTargetDesc.h | 48 ++ .../Target/CAHP/MCTargetDesc/CMakeLists.txt | 7 + .../Target/CAHP/MCTargetDesc/LLVMBuild.txt | 10 + .../Target/CAHP/TargetInfo/CAHPTargetInfo.cpp | 5 - 20 files changed, 1344 insertions(+), 7 deletions(-) create mode 100644 llvm/lib/Target/CAHP/AsmParser/CAHPAsmParser.cpp create mode 100644 llvm/lib/Target/CAHP/AsmParser/CMakeLists.txt create mode 100644 llvm/lib/Target/CAHP/AsmParser/LLVMBuild.txt create mode 100644 llvm/lib/Target/CAHP/CAHP.td create mode 100644 llvm/lib/Target/CAHP/CAHPInstrFormats.td create mode 100644 llvm/lib/Target/CAHP/CAHPInstrInfo.td create mode 100644 llvm/lib/Target/CAHP/CAHPRegisterInfo.td create mode 100644 llvm/lib/Target/CAHP/MCTargetDesc/CAHPAsmBackend.cpp create mode 100644 llvm/lib/Target/CAHP/MCTargetDesc/CAHPELFObjectWriter.cpp create mode 100644 llvm/lib/Target/CAHP/MCTargetDesc/CAHPMCAsmInfo.cpp create mode 100644 llvm/lib/Target/CAHP/MCTargetDesc/CAHPMCAsmInfo.h create mode 100644 llvm/lib/Target/CAHP/MCTargetDesc/CAHPMCCodeEmitter.cpp create mode 100644 llvm/lib/Target/CAHP/MCTargetDesc/CAHPMCTargetDesc.cpp create mode 100644 llvm/lib/Target/CAHP/MCTargetDesc/CAHPMCTargetDesc.h create mode 100644 llvm/lib/Target/CAHP/MCTargetDesc/CMakeLists.txt create mode 100644 llvm/lib/Target/CAHP/MCTargetDesc/LLVMBuild.txt diff --git a/llvm/lib/Target/CAHP/AsmParser/CAHPAsmParser.cpp b/llvm/lib/Target/CAHP/AsmParser/CAHPAsmParser.cpp new file mode 100644 index 000000000000..1ae5116d11c0 --- /dev/null +++ b/llvm/lib/Target/CAHP/AsmParser/CAHPAsmParser.cpp @@ -0,0 +1,439 @@ +// This file is copied and modified from The LLVM Compiler Infrastructure, which +// is distributed under the Apache License v2.0 with LLVM Exceptions (see +// LICENSE.TXT for details). This file is licensed under the same license. + +#include "MCTargetDesc/CAHPMCTargetDesc.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCParser/MCAsmLexer.h" +#include "llvm/MC/MCParser/MCParsedAsmOperand.h" +#include "llvm/MC/MCParser/MCTargetAsmParser.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/TargetRegistry.h" + +using namespace llvm; + +namespace { +struct CAHPOperand; + +class CAHPAsmParser : public MCTargetAsmParser { + SMLoc getLoc() const { return getParser().getTok().getLoc(); } + + bool generateImmOutOfRangeError(OperandVector &Operands, uint64_t ErrorInfo, + int64_t Lower, int64_t Upper, Twine Msg); + + bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, + OperandVector &Operands, MCStreamer &Out, + uint64_t &ErrorInfo, + bool MatchingInlineAsm) override; + + bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override; + + bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name, + SMLoc NameLoc, OperandVector &Operands) override; + + bool ParseDirective(AsmToken DirectiveID) override; + +// Auto-generated instruction matching functions +#define GET_ASSEMBLER_HEADER +#include "CAHPGenAsmMatcher.inc" + + OperandMatchResultTy parseImmediate(OperandVector &Operands); + OperandMatchResultTy parseRegister(OperandVector &Operands); + + bool parseOperand(OperandVector &Operands); + +public: + enum CAHPMatchResultTy { + Match_Dummy = FIRST_TARGET_MATCH_RESULT_TY, +#define GET_OPERAND_DIAGNOSTIC_TYPES +#include "CAHPGenAsmMatcher.inc" +#undef GET_OPERAND_DIAGNOSTIC_TYPES + }; + + CAHPAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser, + const MCInstrInfo &MII, const MCTargetOptions &Options) + : MCTargetAsmParser(Options, STI, MII) { + setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits())); + } +}; + +/// CAHPOperand - Instances of this class represent a parsed machine +/// instruction +struct CAHPOperand : public MCParsedAsmOperand { + + enum KindTy { + Token, + Register, + Immediate, + } Kind; + + struct RegOp { + unsigned RegNum; + }; + + struct ImmOp { + const MCExpr *Val; + }; + + SMLoc StartLoc, EndLoc; + union { + StringRef Tok; + RegOp Reg; + ImmOp Imm; + }; + + CAHPOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {} + +public: + CAHPOperand(const CAHPOperand &o) : MCParsedAsmOperand() { + Kind = o.Kind; + StartLoc = o.StartLoc; + EndLoc = o.EndLoc; + switch (Kind) { + case Register: + Reg = o.Reg; + break; + case Immediate: + Imm = o.Imm; + break; + case Token: + Tok = o.Tok; + break; + } + } + + bool isToken() const override { return Kind == Token; } + bool isReg() const override { return Kind == Register; } + bool isImm() const override { return Kind == Immediate; } + bool isMem() const override { return false; } + + bool isConstantImm() const { + return isImm() && dyn_cast(getImm()); + } + + int64_t getConstantImm() const { + const MCExpr *Val = getImm(); + return static_cast(Val)->getValue(); + } + + bool isUImm4() const { + return (isConstantImm() && isUInt<4>(getConstantImm())); + } + + bool isSImm6() const { + return (isConstantImm() && isInt<6>(getConstantImm())); + } + + bool isUImm6() const { + return (isConstantImm() && isUInt<6>(getConstantImm())); + } + + bool isSImm8() const { + return (isConstantImm() && isInt<8>(getConstantImm())); + } + + bool isUImm8() const { + return (isConstantImm() && isUInt<8>(getConstantImm())); + } + + bool isSImm10() const { + return (isConstantImm() && isInt<10>(getConstantImm())); + } + + bool isSImm11() const { + return (isConstantImm() && isInt<11>(getConstantImm())); + } + + bool isUImm7Lsb0() const { + return (isConstantImm() && isShiftedUInt<6, 1>(getConstantImm())); + } + + bool isSImm11Lsb0() const { + return (isConstantImm() && isShiftedInt<10, 1>(getConstantImm())); + } + + /// getStartLoc - Gets location of the first token of this operand + SMLoc getStartLoc() const override { return StartLoc; } + /// getEndLoc - Gets location of the last token of this operand + SMLoc getEndLoc() const override { return EndLoc; } + + unsigned getReg() const override { + assert(Kind == Register && "Invalid type access!"); + return Reg.RegNum; + } + + const MCExpr *getImm() const { + assert(Kind == Immediate && "Invalid type access!"); + return Imm.Val; + } + + StringRef getToken() const { + assert(Kind == Token && "Invalid type access!"); + return Tok; + } + + void print(raw_ostream &OS) const override { + switch (Kind) { + case Immediate: + OS << *getImm(); + break; + case Register: + OS << ""; + break; + case Token: + OS << "'" << getToken() << "'"; + break; + } + } + + static std::unique_ptr createToken(StringRef Str, SMLoc S) { + auto Op = make_unique(Token); + Op->Tok = Str; + Op->StartLoc = S; + Op->EndLoc = S; + return Op; + } + + static std::unique_ptr createReg(unsigned RegNo, SMLoc S, + SMLoc E) { + auto Op = make_unique(Register); + Op->Reg.RegNum = RegNo; + Op->StartLoc = S; + Op->EndLoc = E; + return Op; + } + + static std::unique_ptr createImm(const MCExpr *Val, SMLoc S, + SMLoc E) { + auto Op = make_unique(Immediate); + Op->Imm.Val = Val; + Op->StartLoc = S; + Op->EndLoc = E; + return Op; + } + + void addExpr(MCInst &Inst, const MCExpr *Expr) const { + assert(Expr && "Expr shouldn't be null!"); + if (auto *CE = dyn_cast(Expr)) + Inst.addOperand(MCOperand::createImm(CE->getValue())); + else + Inst.addOperand(MCOperand::createExpr(Expr)); + } + + // Used by the TableGen Code + void addRegOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + Inst.addOperand(MCOperand::createReg(getReg())); + } + + void addImmOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + addExpr(Inst, getImm()); + } +}; +} // end anonymous namespace. + +#define GET_REGISTER_MATCHER +#define GET_MATCHER_IMPLEMENTATION +#include "CAHPGenAsmMatcher.inc" + +bool CAHPAsmParser::generateImmOutOfRangeError( + OperandVector &Operands, uint64_t ErrorInfo, int64_t Lower, int64_t Upper, + Twine Msg = "immediate must be an integer in the range") { + SMLoc ErrorLoc = ((CAHPOperand &)*Operands[ErrorInfo]).getStartLoc(); + return Error(ErrorLoc, Msg + " [" + Twine(Lower) + ", " + Twine(Upper) + "]"); +} + +bool CAHPAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, + OperandVector &Operands, + MCStreamer &Out, + uint64_t &ErrorInfo, + bool MatchingInlineAsm) { + MCInst Inst; + + unsigned Res = + MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm); + switch (Res) { + default: + break; + case Match_Success: + Inst.setLoc(IDLoc); + Out.EmitInstruction(Inst, getSTI()); + return false; + case Match_MissingFeature: + return Error(IDLoc, "instruction use requires an option to be enabled"); + case Match_MnemonicFail: + return Error(IDLoc, "unrecognized instruction mnemonic"); + case Match_InvalidOperand: { + SMLoc ErrorLoc = IDLoc; + if (ErrorInfo != ~0U) { + if (ErrorInfo >= Operands.size()) + return Error(ErrorLoc, "too few operands for instruction"); + + ErrorLoc = ((CAHPOperand &)*Operands[ErrorInfo]).getStartLoc(); + if (ErrorLoc == SMLoc()) + ErrorLoc = IDLoc; + } + return Error(ErrorLoc, "invalid operand for instruction"); + } + } + + CAHPOperand &Operand = (CAHPOperand &)*Operands[ErrorInfo]; + if (!Operand.isImm()) + return Error(Operand.getStartLoc(), "invalid operand for instruction"); + + switch (Res) { +#define CASE_MATCH_INVALID_SIMM(nbits) \ + case Match_InvalidSImm##nbits: \ + return generateImmOutOfRangeError( \ + Operands, ErrorInfo, -(1 << (nbits - 1)), (1 << (nbits - 1)) - 1); +#define CASE_MATCH_INVALID_UIMM(nbits) \ + case Match_InvalidUImm##nbits: \ + return generateImmOutOfRangeError(Operands, ErrorInfo, 0, (1 << nbits) - 1); +#define CASE_MATCH_INVALID_SIMM_LSB0(nbits) \ + case Match_InvalidSImm##nbits##Lsb0: \ + return generateImmOutOfRangeError( \ + Operands, ErrorInfo, -(1 << (nbits - 1)), (1 << (nbits - 1)) - 2, \ + "immediate must be a multiple of 2 bytes in the range"); +#define CASE_MATCH_INVALID_UIMM_LSB0(nbits) \ + case Match_InvalidUImm##nbits##Lsb0: \ + return generateImmOutOfRangeError( \ + Operands, ErrorInfo, 0, (1 << nbits) - 2, \ + "immediate must be a multiple of 2 bytes in the range"); + + CASE_MATCH_INVALID_UIMM(4); + CASE_MATCH_INVALID_SIMM(6); + CASE_MATCH_INVALID_UIMM(6); + CASE_MATCH_INVALID_SIMM(8); + CASE_MATCH_INVALID_UIMM(8); + CASE_MATCH_INVALID_SIMM(10); + CASE_MATCH_INVALID_SIMM(11); + CASE_MATCH_INVALID_UIMM_LSB0(7); + CASE_MATCH_INVALID_SIMM_LSB0(11); + } + + llvm_unreachable("Unknown match type detected!"); +} + +bool CAHPAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, + SMLoc &EndLoc) { + const AsmToken &Tok = getParser().getTok(); + StartLoc = Tok.getLoc(); + EndLoc = Tok.getEndLoc(); + RegNo = 0; + StringRef Name = getLexer().getTok().getIdentifier(); + + if (!MatchRegisterName(Name) || !MatchRegisterAltName(Name)) { + getParser().Lex(); // Eat identifier token. + return false; + } + + return Error(StartLoc, "invalid register name"); +} + +OperandMatchResultTy CAHPAsmParser::parseRegister(OperandVector &Operands) { + SMLoc S = getLoc(); + SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1); + + switch (getLexer().getKind()) { + default: + return MatchOperand_NoMatch; + case AsmToken::Identifier: + StringRef Name = getLexer().getTok().getIdentifier(); + unsigned RegNo = MatchRegisterName(Name); + if (RegNo == 0) { + RegNo = MatchRegisterAltName(Name); + if (RegNo == 0) + return MatchOperand_NoMatch; + } + getLexer().Lex(); + Operands.push_back(CAHPOperand::createReg(RegNo, S, E)); + } + return MatchOperand_Success; +} + +OperandMatchResultTy CAHPAsmParser::parseImmediate(OperandVector &Operands) { + switch (getLexer().getKind()) { + default: + return MatchOperand_NoMatch; + case AsmToken::LParen: + case AsmToken::Minus: + case AsmToken::Plus: + case AsmToken::Integer: + case AsmToken::String: + break; + } + + const MCExpr *IdVal; + SMLoc S = getLoc(); + if (getParser().parseExpression(IdVal)) + return MatchOperand_ParseFail; + + SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1); + Operands.push_back(CAHPOperand::createImm(IdVal, S, E)); + return MatchOperand_Success; +} + +/// Looks at a token type and creates the relevant operand +/// from this information, adding to Operands. +/// If operand was parsed, returns false, else true. +bool CAHPAsmParser::parseOperand(OperandVector &Operands) { + // Attempt to parse token as register + if (parseRegister(Operands) == MatchOperand_Success) + return false; + + // Attempt to parse token as an immediate + if (parseImmediate(Operands) == MatchOperand_Success) + return false; + + // Finally we have exhausted all options and must declare defeat. + Error(getLoc(), "unknown operand"); + return true; +} + +bool CAHPAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, + SMLoc NameLoc, OperandVector &Operands) { + // First operand is token for instruction + Operands.push_back(CAHPOperand::createToken(Name, NameLoc)); + + // If there are no more operands, then finish + if (getLexer().is(AsmToken::EndOfStatement)) + return false; + + // Parse first operand + if (parseOperand(Operands)) + return true; + + // Parse until end of statement, consuming commas between operands + while (getLexer().is(AsmToken::Comma)) { + // Consume comma token + getLexer().Lex(); + + // Parse next operand + if (parseOperand(Operands)) + return true; + } + + if (getLexer().isNot(AsmToken::EndOfStatement)) { + SMLoc Loc = getLexer().getLoc(); + getParser().eatToEndOfStatement(); + return Error(Loc, "unexpected token"); + } + + getParser().Lex(); // Consume the EndOfStatement. + return false; +} + +bool CAHPAsmParser::ParseDirective(AsmToken DirectiveID) { return true; } + +extern "C" void LLVMInitializeCAHPAsmParser() { + RegisterMCAsmParser X(getTheCAHPTarget()); +} diff --git a/llvm/lib/Target/CAHP/AsmParser/CMakeLists.txt b/llvm/lib/Target/CAHP/AsmParser/CMakeLists.txt new file mode 100644 index 000000000000..3675ebe04bfb --- /dev/null +++ b/llvm/lib/Target/CAHP/AsmParser/CMakeLists.txt @@ -0,0 +1,3 @@ +add_llvm_library(LLVMCAHPAsmParser + CAHPAsmParser.cpp + ) diff --git a/llvm/lib/Target/CAHP/AsmParser/LLVMBuild.txt b/llvm/lib/Target/CAHP/AsmParser/LLVMBuild.txt new file mode 100644 index 000000000000..ffa9ef3e7e06 --- /dev/null +++ b/llvm/lib/Target/CAHP/AsmParser/LLVMBuild.txt @@ -0,0 +1,10 @@ +; This file is copied and modified from The LLVM Compiler Infrastructure, which +; is distributed under the Apache License v2.0 with LLVM Exceptions (see +; LICENSE.TXT for details). This file is licensed under the same license. + +[component_0] +type = Library +name = CAHPAsmParser +parent = CAHP +required_libraries = MC MCParser CAHPDesc CAHPInfo Support +add_to_library_groups = CAHP diff --git a/llvm/lib/Target/CAHP/CAHP.td b/llvm/lib/Target/CAHP/CAHP.td new file mode 100644 index 000000000000..34b212f9c493 --- /dev/null +++ b/llvm/lib/Target/CAHP/CAHP.td @@ -0,0 +1,34 @@ +// This file is copied and modified from The LLVM Compiler Infrastructure, which +// is distributed under the Apache License v2.0 with LLVM Exceptions (see +// LICENSE.TXT for details). This file is licensed under the same license. + +include "llvm/Target/Target.td" + +//===----------------------------------------------------------------------===// +// Register file, instruction descriptions. +//===----------------------------------------------------------------------===// + +include "CAHPRegisterInfo.td" +include "CAHPInstrInfo.td" + +//===----------------------------------------------------------------------===// +// CAHP processors supported. +//===----------------------------------------------------------------------===// + +def : ProcessorModel<"generic-cahp", NoSchedModel, []>; + +//===----------------------------------------------------------------------===// +// Define the CAHP target. +//===----------------------------------------------------------------------===// + +def CAHPInstrInfo : InstrInfo; + +def CAHPAsmParser : AsmParser { + // Use alternative names of registers when emitting. + let ShouldEmitMatchRegisterAltName = 1; +} + +def CAHP : Target { + let InstructionSet = CAHPInstrInfo; + let AssemblyParsers = [CAHPAsmParser]; +} diff --git a/llvm/lib/Target/CAHP/CAHPInstrFormats.td b/llvm/lib/Target/CAHP/CAHPInstrFormats.td new file mode 100644 index 000000000000..3c306682ea86 --- /dev/null +++ b/llvm/lib/Target/CAHP/CAHPInstrFormats.td @@ -0,0 +1,168 @@ +// This file is copied and modified from The LLVM Compiler Infrastructure, which +// is distributed under the Apache License v2.0 with LLVM Exceptions (see +// LICENSE.TXT for details). This file is licensed under the same license. + +class CAHPInst pattern = []> +: Instruction { + let Namespace = "CAHP"; + + dag OutOperandList = outs; + dag InOperandList = ins; + + let AsmString = opcodestr # "\t" # argstr; + + // Matching patterns used when converting SelectionDAG into MachineDAG. + let Pattern = pattern; +} + +// 16-bit instruction format. +class CAHPInst16 pattern = []> +: CAHPInst { + let Size = 2; + bits<16> Inst; +} + +// 24-bit instruction format. +class CAHPInst24 pattern = []> +: CAHPInst { + let Size = 3; + bits<24> Inst; +} + +// Pseudo instructions +class Pseudo pattern> +: CAHPInst { + let isPseudo = 1; + let isCodeGenOnly = 1; +} + +class Pseudo16 pattern> +: Pseudo { + let Size = 2; +} + +class Pseudo24 pattern> +: Pseudo { + let Size = 3; +} + +// 24-bit M-instruction format. +class CAHPInst24MLoad opcode, dag outs, dag ins, string opcodestr, string argstr> +: CAHPInst24 { + bits<4> rd; + bits<4> rs; + + let Inst{15-12} = rs; + let Inst{11-8} = rd; + let Inst{5-0} = opcode; +} + +class CAHPInst24MStore opcode, dag outs, dag ins, string opcodestr, string argstr> +: CAHPInst24 { + bits<4> rs; + bits<4> rd; + + let Inst{15-12} = rd; + let Inst{11-8} = rs; + let Inst{5-0} = opcode; +} + +// 24-bit R-instruction format. +class CAHPInst24R opcode, dag outs, dag ins, string opcodestr, string argstr> +: CAHPInst24 { + bits<4> rd; + bits<4> rs1; + bits<4> rs2; + + let Inst{23-20} = 0; + let Inst{19-16} = rs2; + let Inst{15-12} = rs1; + let Inst{11-8} = rd; + let Inst{7-0} = opcode; +} + +// 24-bit I-instruction format. +class CAHPInst24I opcode, dag outs, dag ins, string opcodestr, string argstr> +: CAHPInst24 { + bits<4> rd; + bits<4> rs1; + bits<8> imm; + + let Inst{23-16} = imm; + let Inst{15-12} = rs1; + let Inst{11-8} = rd; + let Inst{7-0} = opcode; +} + +// 24-bit J-instruction format. +class CAHPInst24J opcode, dag ins, string opcodestr, string argstr> +: CAHPInst24<(outs), ins, opcodestr, argstr> { + bits<4> rs1; + bits<4> rs2; + bits<10> imm; + + let Inst{23-16} = imm{7-0}; + let Inst{15-12} = rs1; + let Inst{11-8} = rs2; + let Inst{7-6} = imm{9-8}; + let Inst{5-0} = opcode; +} + +// 16-bit M-instruction format. +class CAHPInst16Load opcode, dag outs, dag ins, string opcodestr, string argstr> +: CAHPInst16 { + bits<4> rd; + + let Inst{11-8} = rd; + let Inst{5-0} = opcode; +} + +class CAHPInst16Store opcode, dag outs, dag ins, string opcodestr, string argstr> +: CAHPInst16 { + bits<4> rs; + + let Inst{11-8} = rs; + let Inst{5-0} = opcode; +} + +// 16-bit R-instruction format. +class CAHPInst16R opcode, dag outs, dag ins, string opcodestr, string argstr> +: CAHPInst16 { + bits<4> rd; + bits<4> rs; + + let Inst{15-12} = rs; + let Inst{11-8} = rd; + let Inst{7-0} = opcode; +} + +// 16-bit I-instruction format. +class CAHPInst16I opcode, dag outs, dag ins, string opcodestr, string argstr> +: CAHPInst16 { + bits<4> rd; + bits<6> imm; + + let Inst{15-12} = imm{3-0}; + let Inst{11-8} = rd; + let Inst{7-6} = imm{5-4}; + let Inst{5-0} = opcode; +} + +// 16-bit J-instruction format. +class CAHPInst16JR opcode, dag ins, string opcodestr, string argstr> +: CAHPInst16<(outs), ins, opcodestr, argstr> { + bits<4> rs; + + let Inst{15-12} = 0; + let Inst{11-8} = rs; + let Inst{7-5} = 0; + let Inst{4-0} = opcode; +} + +class CAHPInst16JI opcode, dag ins, string opcodestr, string argstr> +: CAHPInst16<(outs), ins, opcodestr, argstr> { + bits<11> imm; + + let Inst{15-5} = imm; + let Inst{4-0} = opcode; +} diff --git a/llvm/lib/Target/CAHP/CAHPInstrInfo.td b/llvm/lib/Target/CAHP/CAHPInstrInfo.td new file mode 100644 index 000000000000..6387fa55d6ea --- /dev/null +++ b/llvm/lib/Target/CAHP/CAHPInstrInfo.td @@ -0,0 +1,228 @@ +// This file is copied and modified from The LLVM Compiler Infrastructure, which +// is distributed under the Apache License v2.0 with LLVM Exceptions (see +// LICENSE.TXT for details). This file is licensed under the same license. + +include "CAHPInstrFormats.td" + +class ImmAsmOperand : AsmOperandClass { + let Name = prefix # "Imm" # width # suffix; + let RenderMethod = "addImmOperands"; + let DiagnosticType = "Invalid" # Name; +} + +class SImmAsmOperand + : ImmAsmOperand<"S", width, suffix> { +} + +class UImmAsmOperand + : ImmAsmOperand<"U", width, suffix> { +} + +def uimm4 : Operand { + let ParserMatchClass = UImmAsmOperand<4>; +} + +def simm6 : Operand { + let ParserMatchClass = SImmAsmOperand<6>; +} + +def uimm6 : Operand { + let ParserMatchClass = UImmAsmOperand<6>; +} + +def simm8 : Operand { + let ParserMatchClass = SImmAsmOperand<8>; +} + +def uimm8 : Operand { + let ParserMatchClass = UImmAsmOperand<8>; +} + +def simm10 : Operand { + let ParserMatchClass = SImmAsmOperand<10>; +} + +def simm11 : Operand { + let ParserMatchClass = SImmAsmOperand<11>; +} + +def uimm7_lsb0 : Operand { + let ParserMatchClass = UImmAsmOperand<7, "Lsb0">; +} + +def simm11_lsb0 : Operand { + let ParserMatchClass = SImmAsmOperand<11, "Lsb0">; +} + +// 24-bit M-instructions. + +/* +def LW : CAHPInst24MLoad <0b010101, (outs GPR:$rd), (ins GPR:$rs, simm11_lsb0:$imm), + "lw", "$rd, ${imm}(${rs})"> { + bits<11> imm; + let Inst{23-16} = imm{8-1}; + let Inst{7-6} = imm{10-9}; +} +def LB : CAHPInst24MLoad <0b100101, (outs GPR:$rd), (ins GPR:$rs, simm10:$imm), + "lb", "$rd, ${imm}(${rs})"> { + bits<10> imm; + let Inst{23-16} = imm{7-0}; + let Inst{7-6} = imm{9-8}; +} +def LBU : CAHPInst24MLoad <0b000101, (outs GPR:$rd), (ins GPR:$rs, simm10:$imm), + "lbu", "$rd, ${imm}(${rs})"> { + bits<10> imm; + let Inst{23-16} = imm{7-0}; + let Inst{7-6} = imm{9-8}; +} +def SW : CAHPInst24MStore<0b011101, (outs GPR:$rd), (ins GPR:$rs, simm11_lsb0:$imm), + "sw", "$rs, ${imm}(${rd})"> { + bits<11> imm; + let Inst{23-16} = imm{8-1}; + let Inst{7-6} = imm{10-9}; +} +def SB : CAHPInst24MStore<0b001101, (outs GPR:$rd), (ins GPR:$rs, simm10:$imm), + "sb", "$rs, ${imm}(${rd})"> { + bits<10> imm; + let Inst{23-16} = imm{7-0}; + let Inst{7-6} = imm{9-8}; +} +*/ +def LI : CAHPInst24MLoad <0b110101, (outs GPR:$rd), (ins simm10:$imm), + "li", "$rd, $imm"> { + bits<10> imm; + let Inst{23-16} = imm{7-0}; + let Inst{7-6} = imm{9-8}; +} + +// 24-bit R-instructions. + +def ADD : CAHPInst24R<0b00000001, (outs GPR:$rd), (ins GPR:$rs1, GPR:$rs2), + "add", "$rd, $rs1, $rs2">; +def SUB : CAHPInst24R<0b00001001, (outs GPR:$rd), (ins GPR:$rs1, GPR:$rs2), + "sub", "$rd, $rs1, $rs2">; +def AND : CAHPInst24R<0b00010001, (outs GPR:$rd), (ins GPR:$rs1, GPR:$rs2), + "and", "$rd, $rs1, $rs2">; +def XOR : CAHPInst24R<0b00011001, (outs GPR:$rd), (ins GPR:$rs1, GPR:$rs2), + "xor", "$rd, $rs1, $rs2">; +def OR : CAHPInst24R<0b00100001, (outs GPR:$rd), (ins GPR:$rs1, GPR:$rs2), + "or", "$rd, $rs1, $rs2">; +def LSL : CAHPInst24R<0b00101001, (outs GPR:$rd), (ins GPR:$rs1, GPR:$rs2), + "lsl", "$rd, $rs1, $rs2">; +def LSR : CAHPInst24R<0b00110001, (outs GPR:$rd), (ins GPR:$rs1, GPR:$rs2), + "lsr", "$rd, $rs1, $rs2">; +def ASR : CAHPInst24R<0b00111001, (outs GPR:$rd), (ins GPR:$rs1, GPR:$rs2), + "asr", "$rd, $rs1, $rs2">; + +// 24-bit I-instructions. + +def ADDI : CAHPInst24I<0b11000011, (outs GPR:$rd), (ins GPR:$rs1, simm8:$imm), + "addi", "$rd, $rs1, $imm">; +def ANDI : CAHPInst24I<0b01010011, (outs GPR:$rd), (ins GPR:$rs1, uimm8:$imm), + "andi", "$rd, $rs1, $imm">; +def XORI : CAHPInst24I<0b01011011, (outs GPR:$rd), (ins GPR:$rs1, uimm8:$imm), + "xori", "$rd, $rs1, $imm">; +def ORI : CAHPInst24I<0b01100011, (outs GPR:$rd), (ins GPR:$rs1, uimm8:$imm), + "ori", "$rd, $rs1, $imm">; +def LSLI : CAHPInst24I<0b00101011, (outs GPR:$rd), (ins GPR:$rs1, uimm4:$imm), + "lsli", "$rd, $rs1, $imm">; +def LSRI : CAHPInst24I<0b00110011, (outs GPR:$rd), (ins GPR:$rs1, uimm4:$imm), + "lsri", "$rd, $rs1, $imm">; +def ASRI : CAHPInst24I<0b00111011, (outs GPR:$rd), (ins GPR:$rs1, uimm4:$imm), + "asri", "$rd, $rs1, $imm">; + +// 24-bit J-instructions. + +def BEQ : CAHPInst24J<0b001111, (ins GPR:$rs1, GPR:$rs2, simm10:$imm), + "beq", "$rs1, $rs2, $imm">; +def BNE : CAHPInst24J<0b101111, (ins GPR:$rs1, GPR:$rs2, simm10:$imm), + "bne", "$rs1, $rs2, $imm">; +def BLT : CAHPInst24J<0b110111, (ins GPR:$rs1, GPR:$rs2, simm10:$imm), + "blt", "$rs1, $rs2, $imm">; +def BLTU : CAHPInst24J<0b010111, (ins GPR:$rs1, GPR:$rs2, simm10:$imm), + "bltu", "$rs1, $rs2, $imm">; +def BLE : CAHPInst24J<0b111111, (ins GPR:$rs1, GPR:$rs2, simm10:$imm), + "ble", "$rs1, $rs2, $imm">; +def BLEU : CAHPInst24J<0b011111, (ins GPR:$rs1, GPR:$rs2, simm10:$imm), + "bleu", "$rs1, $rs2, $imm">; + +// 16-bit M-instructions. + +/* +def LWSP : CAHPInst16Load <0b010100, (outs GPR:$rd), (ins uimm7_lsb0:$imm), + "lwsp", "$rd, ${imm}(sp)"> { + bits<7> imm; + let Inst{15-12} = imm{4-1}; + let Inst{7-6} = imm{6-5}; +} +def SWSP : CAHPInst16Store<0b011100, (outs), (ins GPR:$rs, uimm7_lsb0:$imm), + "swsp", "$rs, ${imm}(sp)"> { + bits<7> imm; + let Inst{15-12} = imm{4-1}; + let Inst{7-6} = imm{6-5}; +} +*/ +def LSI : CAHPInst16Load <0b110100, (outs GPR:$rd), (ins simm6:$imm), + "lsi", "$rd, $imm"> { + bits<6> imm; + let Inst{15-12} = imm{3-0}; + let Inst{7-6} = imm{5-4}; +} +def LUI : CAHPInst16Load <0b000100, (outs GPR:$rd), (ins uimm6:$imm), + "lui", "$rd, $imm"> { + bits<6> imm; + let Inst{15-12} = imm{3-0}; + let Inst{7-6} = imm{5-4}; +} + +// 16-bit R-instructions. + +def MOV : CAHPInst16R<0b11000000, (outs GPR:$rd), (ins GPR:$rs), + "mov", "$rd, $rs">; + +let Constraints = "$rd = $rd_w" in { + def ADD2 : CAHPInst16R<0b10000000, (outs GPR:$rd_w), (ins GPR:$rd, GPR:$rs), + "add2", "$rd, $rs">; + def SUB2 : CAHPInst16R<0b10001000, (outs GPR:$rd_w), (ins GPR:$rd, GPR:$rs), + "sub2", "$rd, $rs">; + def AND2 : CAHPInst16R<0b10010000, (outs GPR:$rd_w), (ins GPR:$rd, GPR:$rs), + "and2", "$rd, $rs">; + def XOR2 : CAHPInst16R<0b10011000, (outs GPR:$rd_w), (ins GPR:$rd, GPR:$rs), + "xor2", "$rd, $rs">; + def OR2 : CAHPInst16R<0b10100000, (outs GPR:$rd_w), (ins GPR:$rd, GPR:$rs), + "or2", "$rd, $rs">; + def LSL2 : CAHPInst16R<0b10101000, (outs GPR:$rd_w), (ins GPR:$rd, GPR:$rs), + "lsl2", "$rd, $rs">; + def LSR2 : CAHPInst16R<0b10110000, (outs GPR:$rd_w), (ins GPR:$rd, GPR:$rs), + "lsr2", "$rd, $rs">; + def ASR2 : CAHPInst16R<0b10111000, (outs GPR:$rd_w), (ins GPR:$rd, GPR:$rs), + "asr2", "$rd, $rs">; +} + +// 16-bit I-instructions. + +let Constraints = "$rd = $rd_w" in { + def LSLI2 : CAHPInst16I<0b101010, (outs GPR:$rd_w), (ins GPR:$rd, uimm4:$imm), + "lsli2", "$rd, $imm">; + def LSRI2 : CAHPInst16I<0b110010, (outs GPR:$rd_w), (ins GPR:$rd, uimm4:$imm), + "lsri2", "$rd, $imm">; + def ASRI2 : CAHPInst16I<0b111010, (outs GPR:$rd_w), (ins GPR:$rd, uimm4:$imm), + "asri2", "$rd, $imm">; + def ADDI2 : CAHPInst16I<0b000010, (outs GPR:$rd_w), (ins GPR:$rd, simm6:$imm), + "addi2", "$rd, $imm">; + def ANDI2 : CAHPInst16I<0b010010, (outs GPR:$rd_w), (ins GPR:$rd, uimm6:$imm), + "andi2", "$rd, $imm">; +} + +// 16-bit J-instructions. + +def JALR : CAHPInst16JR<0b10110, (ins GPR:$rs), "jalr", "$rs">; +def JR : CAHPInst16JR<0b00110, (ins GPR:$rs), "jr", "$rs">; +def JS : CAHPInst16JI<0b01110, (ins simm11:$imm), "js", "$imm">; +def JSAL : CAHPInst16JI<0b11110, (ins simm11:$imm), "jsal", "$imm">; + +// Others. + +def NOP : CAHPInst16<(outs), (ins), "nop", ""> { + let Inst = 0; +} diff --git a/llvm/lib/Target/CAHP/CAHPRegisterInfo.td b/llvm/lib/Target/CAHP/CAHPRegisterInfo.td new file mode 100644 index 000000000000..25d30c245f3e --- /dev/null +++ b/llvm/lib/Target/CAHP/CAHPRegisterInfo.td @@ -0,0 +1,41 @@ +// This file is copied and modified from The LLVM Compiler Infrastructure, which +// is distributed under the Apache License v2.0 with LLVM Exceptions (see +// LICENSE.TXT for details). This file is licensed under the same license. + +let Namespace = "CAHP" in { + def ABIRegAltName : RegAltNameIndex; + + class CAHPReg Enc, string n, list alt = []> : Register { + let HWEncoding{3-0} = Enc; + let AltNames = alt; + let RegAltNameIndices = [ABIRegAltName]; + } +} // Namespace = "CAHP" + +// Integer registers +def X0 : CAHPReg<0, "x0", ["ra"]>, DwarfRegNum<[0]>; +def X1 : CAHPReg<1, "x1", ["sp"]>, DwarfRegNum<[1]>; +def X2 : CAHPReg<2, "x2", ["fp"]>, DwarfRegNum<[2]>; +def X3 : CAHPReg<3, "x3", ["s0"]>, DwarfRegNum<[3]>; +def X4 : CAHPReg<4, "x4", ["s1"]>, DwarfRegNum<[4]>; +def X5 : CAHPReg<5, "x5", ["s2"]>, DwarfRegNum<[5]>; +def X6 : CAHPReg<6, "x6", ["s3"]>, DwarfRegNum<[6]>; +def X7 : CAHPReg<7, "x7", ["s4"]>, DwarfRegNum<[7]>; +def X8 : CAHPReg<8, "x8", ["a0"]>, DwarfRegNum<[8]>; +def X9 : CAHPReg<9, "x9", ["a1"]>, DwarfRegNum<[9]>; +def X10 : CAHPReg<10,"x10", ["a2"]>, DwarfRegNum<[10]>; +def X11 : CAHPReg<11,"x11", ["a3"]>, DwarfRegNum<[11]>; +def X12 : CAHPReg<12,"x12", ["a4"]>, DwarfRegNum<[12]>; +def X13 : CAHPReg<13,"x13", ["a5"]>, DwarfRegNum<[13]>; +def X14 : CAHPReg<14,"x14", ["t0"]>, DwarfRegNum<[14]>; +def X15 : CAHPReg<15,"x15", ["t1"]>, DwarfRegNum<[15]>; + +// General Purpose Registers. +// The order of registers represents the preferred allocation sequence. +// Registers are listed in the order caller-save, callee-save, specials. +def GPR : RegisterClass<"CAHP", [i16], 16, (add + X8, X9, X10, X11, X12, X13, X14, X15, X3, X4, X5, X6, X7, X0, X1, X2 + )>; + +// For instructions like lwsp and swsp, which accept only the stack pointer as operand. +def SP : RegisterClass<"CAHP", [i16], 16, (add X1)>; diff --git a/llvm/lib/Target/CAHP/CAHPTargetMachine.h b/llvm/lib/Target/CAHP/CAHPTargetMachine.h index 22963964bc7e..aeddc3ded028 100644 --- a/llvm/lib/Target/CAHP/CAHPTargetMachine.h +++ b/llvm/lib/Target/CAHP/CAHPTargetMachine.h @@ -5,6 +5,7 @@ #ifndef LLVM_LIB_TARGET_CAHP_CAHPTARGETMACHINE_H #define LLVM_LIB_TARGET_CAHP_CAHPTARGETMACHINE_H +#include "MCTargetDesc/CAHPMCTargetDesc.h" #include "llvm/CodeGen/SelectionDAGTargetInfo.h" #include "llvm/IR/DataLayout.h" #include "llvm/Target/TargetMachine.h" @@ -25,7 +26,6 @@ class CAHPTargetMachine : public LLVMTargetMachine { return TLOF.get(); } }; -Target &getTheCAHPTarget(); } // namespace llvm #endif diff --git a/llvm/lib/Target/CAHP/CMakeLists.txt b/llvm/lib/Target/CAHP/CMakeLists.txt index c71ef3fdbf60..c5e8b01fecbd 100644 --- a/llvm/lib/Target/CAHP/CMakeLists.txt +++ b/llvm/lib/Target/CAHP/CMakeLists.txt @@ -1,4 +1,17 @@ +set(LLVM_TARGET_DEFINITIONS CAHP.td) + +tablegen(LLVM CAHPGenRegisterInfo.inc -gen-register-info) +tablegen(LLVM CAHPGenInstrInfo.inc -gen-instr-info) +tablegen(LLVM CAHPGenMCCodeEmitter.inc -gen-emitter) +tablegen(LLVM CAHPGenSubtargetInfo.inc -gen-subtarget) +tablegen(LLVM CAHPGenAsmMatcher.inc -gen-asm-matcher) +tablegen(LLVM CAHPGenAsmWriter.inc -gen-asm-writer) + +add_public_tablegen_target(CAHPCommonTableGen) + add_llvm_target(CAHPCodeGen CAHPTargetMachine.cpp ) +add_subdirectory(AsmParser) add_subdirectory(TargetInfo) +add_subdirectory(MCTargetDesc) diff --git a/llvm/lib/Target/CAHP/LLVMBuild.txt b/llvm/lib/Target/CAHP/LLVMBuild.txt index 6b76cc43d326..bd21505c6994 100644 --- a/llvm/lib/Target/CAHP/LLVMBuild.txt +++ b/llvm/lib/Target/CAHP/LLVMBuild.txt @@ -3,12 +3,13 @@ ; LICENSE.TXT for details). This file is licensed under the same license. [common] -subdirectories = TargetInfo +subdirectories = AsmParser TargetInfo MCTargetDesc [component_0] type = TargetGroup name = CAHP parent = Target +has_asmparser = 1 [component_1] type = Library diff --git a/llvm/lib/Target/CAHP/MCTargetDesc/CAHPAsmBackend.cpp b/llvm/lib/Target/CAHP/MCTargetDesc/CAHPAsmBackend.cpp new file mode 100644 index 000000000000..2bd74b9cc782 --- /dev/null +++ b/llvm/lib/Target/CAHP/MCTargetDesc/CAHPAsmBackend.cpp @@ -0,0 +1,91 @@ +// This file is copied and modified from The LLVM Compiler Infrastructure, which +// is distributed under the Apache License v2.0 with LLVM Exceptions (see +// LICENSE.TXT for details). This file is licensed under the same license. + +#include "MCTargetDesc/CAHPMCTargetDesc.h" +#include "llvm/MC/MCAsmBackend.h" +#include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCDirectives.h" +#include "llvm/MC/MCELFObjectWriter.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCFixupKindInfo.h" +#include "llvm/MC/MCObjectWriter.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +namespace { +class CAHPAsmBackend : public MCAsmBackend { + uint8_t OSABI; + +public: + CAHPAsmBackend(uint8_t OSABI) : MCAsmBackend(support::little), OSABI(OSABI) {} + ~CAHPAsmBackend() override {} + + void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, + const MCValue &Target, MutableArrayRef Data, + uint64_t Value, bool IsResolved, + const MCSubtargetInfo *STI) const override; + + std::unique_ptr + createObjectTargetWriter() const override; + + bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value, + const MCRelaxableFragment *DF, + const MCAsmLayout &Layout) const override { + return false; + } + + unsigned getNumFixupKinds() const override { return 1; } + + bool mayNeedRelaxation(const MCInst &Inst, + const MCSubtargetInfo &STI) const override { + return false; + } + + void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI, + MCInst &Res) const override { + + report_fatal_error("CAHPAsmBackend::relaxInstruction() unimplemented"); + } + + bool writeNopData(raw_ostream &OS, uint64_t Count) const override; +}; + +bool CAHPAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count) const { + if ((Count % 2) != 0) + return false; + + Count /= 2; + for (uint64_t i = 0; i < Count; ++i) + OS.write("\0\0", 2); + + return true; +} + +void CAHPAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, + const MCValue &Target, + MutableArrayRef Data, uint64_t Value, + bool IsResolved, + const MCSubtargetInfo *STI) const { + return; +} + +std::unique_ptr +CAHPAsmBackend::createObjectTargetWriter() const { + return createCAHPELFObjectWriter(OSABI); +} + +} // end anonymous namespace + +MCAsmBackend *llvm::createCAHPAsmBackend(const Target &T, + const MCSubtargetInfo &STI, + const MCRegisterInfo &MRI, + const MCTargetOptions &Options) { + const Triple &TT = STI.getTargetTriple(); + uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TT.getOS()); + return new CAHPAsmBackend(OSABI); +} diff --git a/llvm/lib/Target/CAHP/MCTargetDesc/CAHPELFObjectWriter.cpp b/llvm/lib/Target/CAHP/MCTargetDesc/CAHPELFObjectWriter.cpp new file mode 100644 index 000000000000..e22b02f95f68 --- /dev/null +++ b/llvm/lib/Target/CAHP/MCTargetDesc/CAHPELFObjectWriter.cpp @@ -0,0 +1,42 @@ +// This file is copied and modified from The LLVM Compiler Infrastructure, which +// is distributed under the Apache License v2.0 with LLVM Exceptions (see +// LICENSE.TXT for details). This file is licensed under the same license. + +#include "MCTargetDesc/CAHPMCTargetDesc.h" +#include "llvm/MC/MCELFObjectWriter.h" +#include "llvm/MC/MCFixup.h" +#include "llvm/MC/MCObjectWriter.h" +#include "llvm/Support/ErrorHandling.h" + +using namespace llvm; + +namespace { +class CAHPELFObjectWriter : public MCELFObjectTargetWriter { +public: + CAHPELFObjectWriter(uint8_t OSABI); + + ~CAHPELFObjectWriter() override; + +protected: + unsigned getRelocType(MCContext &Ctx, const MCValue &Target, + const MCFixup &Fixup, bool IsPCRel) const override; +}; +} // namespace + +CAHPELFObjectWriter::CAHPELFObjectWriter(uint8_t OSABI) + : MCELFObjectTargetWriter(false, OSABI, ELF::EM_CAHP, + /*HasRelocationAddend*/ true) {} + +CAHPELFObjectWriter::~CAHPELFObjectWriter() {} + +unsigned CAHPELFObjectWriter::getRelocType(MCContext &Ctx, + const MCValue &Target, + const MCFixup &Fixup, + bool IsPCRel) const { + report_fatal_error("invalid fixup kind!"); +} + +std::unique_ptr +llvm::createCAHPELFObjectWriter(uint8_t OSABI) { + return llvm::make_unique(OSABI); +} diff --git a/llvm/lib/Target/CAHP/MCTargetDesc/CAHPMCAsmInfo.cpp b/llvm/lib/Target/CAHP/MCTargetDesc/CAHPMCAsmInfo.cpp new file mode 100644 index 000000000000..22d0ddd12b72 --- /dev/null +++ b/llvm/lib/Target/CAHP/MCTargetDesc/CAHPMCAsmInfo.cpp @@ -0,0 +1,16 @@ +// This file is copied and modified from The LLVM Compiler Infrastructure, which +// is distributed under the Apache License v2.0 with LLVM Exceptions (see +// LICENSE.TXT for details). This file is licensed under the same license. + +#include "CAHPMCAsmInfo.h" +#include "llvm/ADT/Triple.h" +using namespace llvm; + +void CAHPMCAsmInfo::anchor() {} + +CAHPMCAsmInfo::CAHPMCAsmInfo(const Triple &TT) { + CodePointerSize = 2; + CalleeSaveStackSlotSize = 2; + CommentString = "#"; + SupportsDebugInformation = true; +} diff --git a/llvm/lib/Target/CAHP/MCTargetDesc/CAHPMCAsmInfo.h b/llvm/lib/Target/CAHP/MCTargetDesc/CAHPMCAsmInfo.h new file mode 100644 index 000000000000..05336c067008 --- /dev/null +++ b/llvm/lib/Target/CAHP/MCTargetDesc/CAHPMCAsmInfo.h @@ -0,0 +1,25 @@ +// This file is copied and modified from The LLVM Compiler Infrastructure, which +// is distributed under the Apache License v2.0 with LLVM Exceptions (see +// LICENSE.TXT for details). This file is licensed under the same license. + +#ifndef LLVM_LIB_TARGET_CAHP_MCTARGETDESC_CAHPMCASMINFO_H +#define LLVM_LIB_TARGET_CAHP_MCTARGETDESC_CAHPMCASMINFO_H + +#include "llvm/MC/MCAsmInfoELF.h" + +namespace llvm { +class Triple; + +class CAHPMCAsmInfo : public MCAsmInfoELF { + // This function MUST BE placed here to reduce the size of object files. + // See also: + // https://stackoverflow.com/questions/16801222/out-of-line-virtual-method + void anchor() override; + +public: + explicit CAHPMCAsmInfo(const Triple &TargetTriple); +}; + +} // namespace llvm + +#endif diff --git a/llvm/lib/Target/CAHP/MCTargetDesc/CAHPMCCodeEmitter.cpp b/llvm/lib/Target/CAHP/MCTargetDesc/CAHPMCCodeEmitter.cpp new file mode 100644 index 000000000000..ea3e5d49acdf --- /dev/null +++ b/llvm/lib/Target/CAHP/MCTargetDesc/CAHPMCCodeEmitter.cpp @@ -0,0 +1,103 @@ +// This file is copied and modified from The LLVM Compiler Infrastructure, which +// is distributed under the Apache License v2.0 with LLVM Exceptions (see +// LICENSE.TXT for details). This file is licensed under the same license. + +#include "MCTargetDesc/CAHPMCTargetDesc.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCCodeEmitter.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCInstrDesc.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Support/EndianStream.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +#define DEBUG_TYPE "mccodeemitter" + +STATISTIC(MCNumEmitted, "Number of MC instructions emitted"); + +namespace { +class CAHPMCCodeEmitter : public MCCodeEmitter { + CAHPMCCodeEmitter(const CAHPMCCodeEmitter &) = delete; + void operator=(const CAHPMCCodeEmitter &) = delete; + MCContext &Ctx; + MCInstrInfo const &MCII; + +public: + CAHPMCCodeEmitter(MCContext &ctx, const MCInstrInfo &MCII) + : Ctx(ctx), MCII(MCII) {} + + ~CAHPMCCodeEmitter() override {} + + void encodeInstruction(const MCInst &MI, raw_ostream &OS, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const override; + + /// TableGen'erated function for getting the binary encoding for an + /// instruction. + uint64_t getBinaryCodeForInstr(const MCInst &MI, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + + /// Return binary encoding of operand. If the machine operand requires + /// relocation, record the relocation and return zero. + unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; +}; +} // end anonymous namespace + +MCCodeEmitter *llvm::createCAHPMCCodeEmitter(const MCInstrInfo &MCII, + const MCRegisterInfo &MRI, + MCContext &Ctx) { + return new CAHPMCCodeEmitter(Ctx, MCII); +} + +void CAHPMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + const MCInstrDesc &Desc = MCII.get(MI.getOpcode()); + // Get byte count of instruction. + unsigned Size = Desc.getSize(); + + switch (Size) { + default: + llvm_unreachable("Unhandled encodeInstruction length!"); + case 2: { + uint16_t Bits = getBinaryCodeForInstr(MI, Fixups, STI); + support::endian::write(OS, Bits, support::little); + break; + } + case 3: { + uint32_t Bits = getBinaryCodeForInstr(MI, Fixups, STI); + support::endian::write(OS, Bits & 0xffff, support::little); + OS.write((Bits >> 16) & 0xff); + break; + } + } + + ++MCNumEmitted; // Keep track of the # of mi's emitted. +} + +unsigned +CAHPMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + + if (MO.isReg()) + return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg()); + + if (MO.isImm()) + return static_cast(MO.getImm()); + + llvm_unreachable("Unhandled expression!"); + return 0; +} + +#include "CAHPGenMCCodeEmitter.inc" diff --git a/llvm/lib/Target/CAHP/MCTargetDesc/CAHPMCTargetDesc.cpp b/llvm/lib/Target/CAHP/MCTargetDesc/CAHPMCTargetDesc.cpp new file mode 100644 index 000000000000..86bb5d07103b --- /dev/null +++ b/llvm/lib/Target/CAHP/MCTargetDesc/CAHPMCTargetDesc.cpp @@ -0,0 +1,63 @@ +// This file is copied and modified from The LLVM Compiler Infrastructure, which +// is distributed under the Apache License v2.0 with LLVM Exceptions (see +// LICENSE.TXT for details). This file is licensed under the same license. + +#include "CAHPMCTargetDesc.h" +#include "CAHPMCAsmInfo.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/TargetRegistry.h" + +#define GET_INSTRINFO_MC_DESC +#include "CAHPGenInstrInfo.inc" + +#define GET_REGINFO_MC_DESC +#include "CAHPGenRegisterInfo.inc" + +#define GET_SUBTARGETINFO_MC_DESC +#include "CAHPGenSubtargetInfo.inc" + +using namespace llvm; + +static MCInstrInfo *createCAHPMCInstrInfo() { + MCInstrInfo *X = new MCInstrInfo(); + InitCAHPMCInstrInfo(X); + return X; +} + +static MCRegisterInfo *createCAHPMCRegisterInfo(const Triple &TT) { + MCRegisterInfo *X = new MCRegisterInfo(); + + // X0 is the return address register. + InitCAHPMCRegisterInfo(X, CAHP::X0); + + return X; +} + +static MCAsmInfo *createCAHPMCAsmInfo(const MCRegisterInfo &MRI, + const Triple &TT) { + return new CAHPMCAsmInfo(TT); +} + +static MCSubtargetInfo *createCAHPMCSubtargetInfo(const Triple &TT, + StringRef CPU, StringRef FS) { + std::string CPUName = CPU; + if (CPUName.empty()) + CPUName = "generic-cahp"; + return createCAHPMCSubtargetInfoImpl(TT, CPUName, FS); +} + +extern "C" void LLVMInitializeCAHPTargetMC() { + Target &T = getTheCAHPTarget(); + TargetRegistry::RegisterMCAsmInfo(T, createCAHPMCAsmInfo); + TargetRegistry::RegisterMCInstrInfo(T, createCAHPMCInstrInfo); + TargetRegistry::RegisterMCRegInfo(T, createCAHPMCRegisterInfo); + TargetRegistry::RegisterMCAsmBackend(T, createCAHPAsmBackend); + TargetRegistry::RegisterMCSubtargetInfo(T, createCAHPMCSubtargetInfo); + TargetRegistry::RegisterMCCodeEmitter(T, createCAHPMCCodeEmitter); +} diff --git a/llvm/lib/Target/CAHP/MCTargetDesc/CAHPMCTargetDesc.h b/llvm/lib/Target/CAHP/MCTargetDesc/CAHPMCTargetDesc.h new file mode 100644 index 000000000000..7cef4c7246fa --- /dev/null +++ b/llvm/lib/Target/CAHP/MCTargetDesc/CAHPMCTargetDesc.h @@ -0,0 +1,48 @@ +// This file is copied and modified from The LLVM Compiler Infrastructure, which +// is distributed under the Apache License v2.0 with LLVM Exceptions (see +// LICENSE.TXT for details). This file is licensed under the same license. + +#ifndef LLVM_LIB_TARGET_CAHP_MCTARGETDESC_CAHPMCTARGETDESC_H +#define LLVM_LIB_TARGET_CAHP_MCTARGETDESC_CAHPMCTARGETDESC_H + +#include "llvm/Config/config.h" +#include "llvm/MC/MCTargetOptions.h" +#include "llvm/Support/DataTypes.h" +#include + +namespace llvm { +class MCAsmBackend; +class MCCodeEmitter; +class MCContext; +class MCInstrInfo; +class MCObjectTargetWriter; +class MCRegisterInfo; +class MCSubtargetInfo; +class StringRef; +class Target; +class Triple; +class raw_ostream; +class raw_pwrite_stream; + +Target &getTheCAHPTarget(); + +MCCodeEmitter *createCAHPMCCodeEmitter(const MCInstrInfo &MCII, + const MCRegisterInfo &MRI, + MCContext &Ctx); + +MCAsmBackend *createCAHPAsmBackend(const Target &T, const MCSubtargetInfo &STI, + const MCRegisterInfo &MRI, + const MCTargetOptions &Options); + +std::unique_ptr createCAHPELFObjectWriter(uint8_t OSABI); +} // namespace llvm + +// Defines symbolic names for CAHP registers. +#define GET_REGINFO_ENUM +#include "CAHPGenRegisterInfo.inc" + +// Defines symbolic names for CAHP instructions. +#define GET_INSTRINFO_ENUM +#include "CAHPGenInstrInfo.inc" + +#endif diff --git a/llvm/lib/Target/CAHP/MCTargetDesc/CMakeLists.txt b/llvm/lib/Target/CAHP/MCTargetDesc/CMakeLists.txt new file mode 100644 index 000000000000..f720c192eee2 --- /dev/null +++ b/llvm/lib/Target/CAHP/MCTargetDesc/CMakeLists.txt @@ -0,0 +1,7 @@ +add_llvm_library(LLVMCAHPDesc + CAHPMCTargetDesc.cpp + CAHPMCAsmInfo.cpp + CAHPAsmBackend.cpp + CAHPELFObjectWriter.cpp + CAHPMCCodeEmitter.cpp +) diff --git a/llvm/lib/Target/CAHP/MCTargetDesc/LLVMBuild.txt b/llvm/lib/Target/CAHP/MCTargetDesc/LLVMBuild.txt new file mode 100644 index 000000000000..a50763d45762 --- /dev/null +++ b/llvm/lib/Target/CAHP/MCTargetDesc/LLVMBuild.txt @@ -0,0 +1,10 @@ +; This file is copied and modified from The LLVM Compiler Infrastructure, which +; is distributed under the Apache License v2.0 with LLVM Exceptions (see +; LICENSE.TXT for details). This file is licensed under the same license. + +[component_0] +type = Library +name = CAHPDesc +parent = CAHP +required_libraries = MC CAHPInfo Support +add_to_library_groups = CAHP diff --git a/llvm/lib/Target/CAHP/TargetInfo/CAHPTargetInfo.cpp b/llvm/lib/Target/CAHP/TargetInfo/CAHPTargetInfo.cpp index f25ddb6a1972..e1c960079ba6 100644 --- a/llvm/lib/Target/CAHP/TargetInfo/CAHPTargetInfo.cpp +++ b/llvm/lib/Target/CAHP/TargetInfo/CAHPTargetInfo.cpp @@ -15,8 +15,3 @@ Target &getTheCAHPTarget() { extern "C" void LLVMInitializeCAHPTargetInfo() { RegisterTarget X(getTheCAHPTarget(), "cahp", "CAHP", "CAHP"); } - -// FIXME: Temporary stub - this function must be defined for linking -// to succeed and will be called unconditionally by llc, so must be a no-op. -// Remove once this function is properly implemented. -extern "C" void LLVMInitializeCAHPTargetMC() {} From aa66568c3dfe1d80a83a96bd0437a26fdb96872a Mon Sep 17 00:00:00 2001 From: Ushitora Anqou Date: Sat, 12 Oct 2019 22:11:34 +0900 Subject: [PATCH 225/289] [CAHP] Add InstPrinter to enable -show-encoding option --- llvm/lib/Target/CAHP/CMakeLists.txt | 3 +- .../CAHP/InstPrinter/CAHPInstPrinter.cpp | 46 +++++++++++++++++++ .../Target/CAHP/InstPrinter/CAHPInstPrinter.h | 34 ++++++++++++++ .../Target/CAHP/InstPrinter/CMakeLists.txt | 3 ++ .../lib/Target/CAHP/InstPrinter/LLVMBuild.txt | 10 ++++ llvm/lib/Target/CAHP/LLVMBuild.txt | 4 +- .../CAHP/MCTargetDesc/CAHPMCTargetDesc.cpp | 10 ++++ .../Target/CAHP/MCTargetDesc/LLVMBuild.txt | 2 +- 8 files changed, 108 insertions(+), 4 deletions(-) create mode 100644 llvm/lib/Target/CAHP/InstPrinter/CAHPInstPrinter.cpp create mode 100644 llvm/lib/Target/CAHP/InstPrinter/CAHPInstPrinter.h create mode 100644 llvm/lib/Target/CAHP/InstPrinter/CMakeLists.txt create mode 100644 llvm/lib/Target/CAHP/InstPrinter/LLVMBuild.txt diff --git a/llvm/lib/Target/CAHP/CMakeLists.txt b/llvm/lib/Target/CAHP/CMakeLists.txt index c5e8b01fecbd..03fc3c0b28d3 100644 --- a/llvm/lib/Target/CAHP/CMakeLists.txt +++ b/llvm/lib/Target/CAHP/CMakeLists.txt @@ -13,5 +13,6 @@ add_llvm_target(CAHPCodeGen CAHPTargetMachine.cpp ) add_subdirectory(AsmParser) -add_subdirectory(TargetInfo) +add_subdirectory(InstPrinter) add_subdirectory(MCTargetDesc) +add_subdirectory(TargetInfo) diff --git a/llvm/lib/Target/CAHP/InstPrinter/CAHPInstPrinter.cpp b/llvm/lib/Target/CAHP/InstPrinter/CAHPInstPrinter.cpp new file mode 100644 index 000000000000..19262868765b --- /dev/null +++ b/llvm/lib/Target/CAHP/InstPrinter/CAHPInstPrinter.cpp @@ -0,0 +1,46 @@ +// This file is copied and modified from The LLVM Compiler Infrastructure, which +// is distributed under the Apache License v2.0 with LLVM Exceptions (see +// LICENSE.TXT for details). This file is licensed under the same license. + +#include "CAHPInstPrinter.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FormattedStream.h" +using namespace llvm; + +#define DEBUG_TYPE "asm-printer" + +// Include the auto-generated portion of the assembly writer. +#include "CAHPGenAsmWriter.inc" + +void CAHPInstPrinter::printInst(const MCInst *MI, raw_ostream &O, + StringRef Annot, const MCSubtargetInfo &STI) { + printInstruction(MI, O); + printAnnotation(O, Annot); +} + +void CAHPInstPrinter::printRegName(raw_ostream &O, unsigned RegNo) const { + O << getRegisterName(RegNo); +} + +void CAHPInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, + raw_ostream &O, const char *Modifier) { + assert((Modifier == 0 || Modifier[0] == 0) && "No modifiers supported"); + const MCOperand &MO = MI->getOperand(OpNo); + + if (MO.isReg()) { + printRegName(O, MO.getReg()); + return; + } + + if (MO.isImm()) { + O << MO.getImm(); + return; + } + + assert(MO.isExpr() && "Unknown operand kind in printOperand"); + MO.getExpr()->print(O, &MAI); +} diff --git a/llvm/lib/Target/CAHP/InstPrinter/CAHPInstPrinter.h b/llvm/lib/Target/CAHP/InstPrinter/CAHPInstPrinter.h new file mode 100644 index 000000000000..6260882ce5e2 --- /dev/null +++ b/llvm/lib/Target/CAHP/InstPrinter/CAHPInstPrinter.h @@ -0,0 +1,34 @@ +// This file is copied and modified from The LLVM Compiler Infrastructure, which +// is distributed under the Apache License v2.0 with LLVM Exceptions (see +// LICENSE.TXT for details). This file is licensed under the same license. + +#ifndef LLVM_LIB_TARGET_CAHP_INSTPRINTER_CAHPINSTPRINTER_H +#define LLVM_LIB_TARGET_CAHP_INSTPRINTER_CAHPINSTPRINTER_H + +#include "MCTargetDesc/CAHPMCTargetDesc.h" +#include "llvm/MC/MCInstPrinter.h" + +namespace llvm { +class MCOperand; + +class CAHPInstPrinter : public MCInstPrinter { +public: + CAHPInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII, + const MCRegisterInfo &MRI) + : MCInstPrinter(MAI, MII, MRI) {} + + void printInst(const MCInst *MI, raw_ostream &O, StringRef Annot, + const MCSubtargetInfo &STI) override; + void printRegName(raw_ostream &O, unsigned RegNo) const override; + + void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O, + const char *Modifier = nullptr); + + // Autogenerated by tblgen. + void printInstruction(const MCInst *MI, raw_ostream &O); + static const char *getRegisterName(unsigned RegNo, + unsigned AltIdx = CAHP::ABIRegAltName); +}; +} // namespace llvm + +#endif diff --git a/llvm/lib/Target/CAHP/InstPrinter/CMakeLists.txt b/llvm/lib/Target/CAHP/InstPrinter/CMakeLists.txt new file mode 100644 index 000000000000..c0f247788336 --- /dev/null +++ b/llvm/lib/Target/CAHP/InstPrinter/CMakeLists.txt @@ -0,0 +1,3 @@ +add_llvm_library(LLVMCAHPAsmPrinter + CAHPInstPrinter.cpp + ) diff --git a/llvm/lib/Target/CAHP/InstPrinter/LLVMBuild.txt b/llvm/lib/Target/CAHP/InstPrinter/LLVMBuild.txt new file mode 100644 index 000000000000..2031db0ba364 --- /dev/null +++ b/llvm/lib/Target/CAHP/InstPrinter/LLVMBuild.txt @@ -0,0 +1,10 @@ +; This file is copied and modified from The LLVM Compiler Infrastructure, which +; is distributed under the Apache License v2.0 with LLVM Exceptions (see +; LICENSE.TXT for details). This file is licensed under the same license. + +[component_0] +type = Library +name = CAHPAsmPrinter +parent = CAHP +required_libraries = MC Support +add_to_library_groups = CAHP diff --git a/llvm/lib/Target/CAHP/LLVMBuild.txt b/llvm/lib/Target/CAHP/LLVMBuild.txt index bd21505c6994..e823775e31a7 100644 --- a/llvm/lib/Target/CAHP/LLVMBuild.txt +++ b/llvm/lib/Target/CAHP/LLVMBuild.txt @@ -3,7 +3,7 @@ ; LICENSE.TXT for details). This file is licensed under the same license. [common] -subdirectories = AsmParser TargetInfo MCTargetDesc +subdirectories = AsmParser InstPrinter TargetInfo MCTargetDesc [component_0] type = TargetGroup @@ -15,5 +15,5 @@ has_asmparser = 1 type = Library name = CAHPCodeGen parent = CAHP -required_libraries = Core CodeGen CAHPInfo Support Target +required_libraries = AsmPrinter Core CodeGen MC CAHPAsmPrinter CAHPDesc CAHPInfo Support Target add_to_library_groups = CAHP diff --git a/llvm/lib/Target/CAHP/MCTargetDesc/CAHPMCTargetDesc.cpp b/llvm/lib/Target/CAHP/MCTargetDesc/CAHPMCTargetDesc.cpp index 86bb5d07103b..bdd45e74c3df 100644 --- a/llvm/lib/Target/CAHP/MCTargetDesc/CAHPMCTargetDesc.cpp +++ b/llvm/lib/Target/CAHP/MCTargetDesc/CAHPMCTargetDesc.cpp @@ -4,6 +4,7 @@ #include "CAHPMCTargetDesc.h" #include "CAHPMCAsmInfo.h" +#include "InstPrinter/CAHPInstPrinter.h" #include "llvm/ADT/STLExtras.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCInstrInfo.h" @@ -52,6 +53,14 @@ static MCSubtargetInfo *createCAHPMCSubtargetInfo(const Triple &TT, return createCAHPMCSubtargetInfoImpl(TT, CPUName, FS); } +static MCInstPrinter *createCAHPMCInstPrinter(const Triple &T, + unsigned SyntaxVariant, + const MCAsmInfo &MAI, + const MCInstrInfo &MII, + const MCRegisterInfo &MRI) { + return new CAHPInstPrinter(MAI, MII, MRI); +} + extern "C" void LLVMInitializeCAHPTargetMC() { Target &T = getTheCAHPTarget(); TargetRegistry::RegisterMCAsmInfo(T, createCAHPMCAsmInfo); @@ -60,4 +69,5 @@ extern "C" void LLVMInitializeCAHPTargetMC() { TargetRegistry::RegisterMCAsmBackend(T, createCAHPAsmBackend); TargetRegistry::RegisterMCSubtargetInfo(T, createCAHPMCSubtargetInfo); TargetRegistry::RegisterMCCodeEmitter(T, createCAHPMCCodeEmitter); + TargetRegistry::RegisterMCInstPrinter(T, createCAHPMCInstPrinter); } diff --git a/llvm/lib/Target/CAHP/MCTargetDesc/LLVMBuild.txt b/llvm/lib/Target/CAHP/MCTargetDesc/LLVMBuild.txt index a50763d45762..1538585a7e95 100644 --- a/llvm/lib/Target/CAHP/MCTargetDesc/LLVMBuild.txt +++ b/llvm/lib/Target/CAHP/MCTargetDesc/LLVMBuild.txt @@ -6,5 +6,5 @@ type = Library name = CAHPDesc parent = CAHP -required_libraries = MC CAHPInfo Support +required_libraries = MC CAHPAsmPrinter CAHPInfo Support add_to_library_groups = CAHP From c8bbf894c7ba046ddd3f55677f2d4512dd944aa0 Mon Sep 17 00:00:00 2001 From: Ushitora Anqou Date: Sat, 12 Oct 2019 23:17:54 +0900 Subject: [PATCH 226/289] [CAHP] Add tests for assembler --- llvm/test/MC/CAHP/cahp-invalid.s | 37 +++++++ llvm/test/MC/CAHP/cahp-valid.s | 168 +++++++++++++++++++++++++++++++ llvm/test/MC/CAHP/lit.local.cfg | 2 + 3 files changed, 207 insertions(+) create mode 100644 llvm/test/MC/CAHP/cahp-invalid.s create mode 100644 llvm/test/MC/CAHP/cahp-valid.s create mode 100644 llvm/test/MC/CAHP/lit.local.cfg diff --git a/llvm/test/MC/CAHP/cahp-invalid.s b/llvm/test/MC/CAHP/cahp-invalid.s new file mode 100644 index 000000000000..693cce8acb14 --- /dev/null +++ b/llvm/test/MC/CAHP/cahp-invalid.s @@ -0,0 +1,37 @@ +# RUN: not llvm-mc -triple cahp < %s 2>&1 | FileCheck %s + +# Out of range immediates +li t0, -513 # CHECK: :[[@LINE]]:8: error: immediate must be an integer in the range [-512, 511] +li s0, 512 # CHECK: :[[@LINE]]:8: error: immediate must be an integer in the range [-512, 511] +addi a0, a1, 128 # CHECK: :[[@LINE]]:14: error: immediate must be an integer in the range [-128, 127] +addi a0, a1, -129 # CHECK: :[[@LINE]]:14: error: immediate must be an integer in the range [-128, 127] +andi a0, a1, 256 # CHECK: :[[@LINE]]:14: error: immediate must be an integer in the range [0, 255] +andi a0, a1, -1 # CHECK: :[[@LINE]]:14: error: immediate must be an integer in the range [0, 255] +lsli a0, a1, 16 # CHECK: :[[@LINE]]:14: error: immediate must be an integer in the range [0, 15] +asri a0, a1, -1 # CHECK: :[[@LINE]]:14: error: immediate must be an integer in the range [0, 15] +lsi a5, 32 # CHECK: :[[@LINE]]:9: error: immediate must be an integer in the range [-32, 31] +lsi a5, -33 # CHECK: :[[@LINE]]:9: error: immediate must be an integer in the range [-32, 31] +lui a5, 65 # CHECK: :[[@LINE]]:9: error: immediate must be an integer in the range [0, 63] +lui a5, -1 # CHECK: :[[@LINE]]:9: error: immediate must be an integer in the range [0, 63] +js 1024 # CHECK: :[[@LINE]]:4: error: immediate must be an integer in the range [-1024, 1023] +js -1025 # CHECK: :[[@LINE]]:4: error: immediate must be an integer in the range [-1024, 1023] + +# Invalid mnemonics +subs x1, x2 # CHECK: :[[@LINE]]:1: error: unrecognized instruction mnemonic +nandi x14, x13 # CHECK: :[[@LINE]]:1: error: unrecognized instruction mnemonic + +# Invalid register names +add foo, x1, x3 # CHECK: :[[@LINE]]:5: error: unknown operand +sub x0, x16, x4 # CHECK: :[[@LINE]]:9: error: unknown operand +mov t2, x8 # CHECK: :[[@LINE]]:5: error: unknown operand + +# Invalid operand types +add x15, x1, 1 # CHECK: :[[@LINE]]:14: error: invalid operand for instruction + +# Too many operand +mov x8, x9, x10 # CHECK: :[[@LINE]]:13: error: invalid operand for instruction +li x11, x12, x13 # CHECK: :[[@LINE]]:9: error: invalid operand for instruction + +# Too few operands +li x8 # CHECK: :[[@LINE]]:1: error: too few operands for instruction +mov x13 # CHECK: :[[@LINE]]:1: error: too few operands for instruction diff --git a/llvm/test/MC/CAHP/cahp-valid.s b/llvm/test/MC/CAHP/cahp-valid.s new file mode 100644 index 000000000000..dc25df635290 --- /dev/null +++ b/llvm/test/MC/CAHP/cahp-valid.s @@ -0,0 +1,168 @@ +# RUN: llvm-mc %s -triple=cahp -show-encoding \ +# RUN: | FileCheck -check-prefixes=CHECK,CHECK-INST %s + +# CHECK-INST: li ra, -500 +# CHECK: encoding: [0xb5,0x00,0x0c] +li ra, -500 +# CHECK-INST: add ra, sp, fp +# CHECK: encoding: [0x01,0x10,0x02] +add ra, sp, fp +# CHECK-INST: sub ra, sp, fp +# CHECK: encoding: [0x09,0x10,0x02] +sub ra, sp, fp +# CHECK-INST: and ra, sp, fp +# CHECK: encoding: [0x11,0x10,0x02] +and ra, sp, fp +# CHECK-INST: xor ra, sp, fp +# CHECK: encoding: [0x19,0x10,0x02] +xor ra, sp, fp +# CHECK-INST: or ra, sp, fp +# CHECK: encoding: [0x21,0x10,0x02] +or ra, sp, fp +# CHECK-INST: lsl ra, sp, fp +# CHECK: encoding: [0x29,0x10,0x02] +lsl ra, sp, fp +# CHECK-INST: lsr ra, sp, fp +# CHECK: encoding: [0x31,0x10,0x02] +lsr ra, sp, fp +# CHECK-INST: asr ra, sp, fp +# CHECK: encoding: [0x39,0x10,0x02] +asr ra, sp, fp +# CHECK-INST: addi ra, sp, -10 +# CHECK: encoding: [0xc3,0x10,0xf6] +addi ra, sp, -10 +# CHECK-INST: addi ra, sp, 10 +# CHECK: encoding: [0xc3,0x10,0x0a] +addi ra, sp, 10 +# CHECK-INST: andi ra, sp, 10 +# CHECK: encoding: [0x53,0x10,0x0a] +andi ra, sp, 10 +# CHECK-INST: xori ra, sp, 10 +# CHECK: encoding: [0x5b,0x10,0x0a] +xori ra, sp, 10 +# CHECK-INST: ori ra, sp, 10 +# CHECK: encoding: [0x63,0x10,0x0a] +ori ra, sp, 10 +# CHECK-INST: lsli ra, sp, 3 +# CHECK: encoding: [0x2b,0x10,0x03] +lsli ra, sp, 3 +# CHECK-INST: lsri ra, sp, 3 +# CHECK: encoding: [0x33,0x10,0x03] +lsri ra, sp, 3 +# CHECK-INST: asri ra, sp, 4 +# CHECK: encoding: [0x3b,0x10,0x04] +asri ra, sp, 4 +# CHECK-INST: beq ra, sp, 16 +# CHECK: encoding: [0x0f,0x01,0x10] +beq ra, sp, 16 +# CHECK-INST: beq ra, sp, 16 +# CHECK: encoding: [0x0f,0x01,0x10] +beq ra, sp, 16 +# CHECK-INST: bne ra, sp, 16 +# CHECK: encoding: [0x2f,0x01,0x10] +bne ra, sp, 16 +# CHECK-INST: bne ra, sp, 16 +# CHECK: encoding: [0x2f,0x01,0x10] +bne ra, sp, 16 +# CHECK-INST: blt ra, sp, 16 +# CHECK: encoding: [0x37,0x01,0x10] +blt ra, sp, 16 +# CHECK-INST: blt ra, sp, 16 +# CHECK: encoding: [0x37,0x01,0x10] +blt ra, sp, 16 +# CHECK-INST: blt ra, sp, 16 +# CHECK: encoding: [0x37,0x01,0x10] +blt ra, sp, 16 +# CHECK-INST: bltu ra, sp, 16 +# CHECK: encoding: [0x17,0x01,0x10] +bltu ra, sp, 16 +# CHECK-INST: bltu ra, sp, 16 +# CHECK: encoding: [0x17,0x01,0x10] +bltu ra, sp, 16 +# CHECK-INST: bltu ra, sp, 16 +# CHECK: encoding: [0x17,0x01,0x10] +bltu ra, sp, 16 +# CHECK-INST: ble ra, sp, 16 +# CHECK: encoding: [0x3f,0x01,0x10] +ble ra, sp, 16 +# CHECK-INST: ble ra, sp, 16 +# CHECK: encoding: [0x3f,0x01,0x10] +ble ra, sp, 16 +# CHECK-INST: ble ra, sp, 16 +# CHECK: encoding: [0x3f,0x01,0x10] +ble ra, sp, 16 +# CHECK-INST: bleu ra, sp, 16 +# CHECK: encoding: [0x1f,0x01,0x10] +bleu ra, sp, 16 +# CHECK-INST: bleu ra, sp, 16 +# CHECK: encoding: [0x1f,0x01,0x10] +bleu ra, sp, 16 +# CHECK-INST: bleu ra, sp, 16 +# CHECK: encoding: [0x1f,0x01,0x10] +bleu ra, sp, 16 +# CHECK-INST: lsi ra, -32 +# CHECK: encoding: [0xb4,0x00] +lsi ra, -32 +# CHECK-INST: lui ra, 32 +# CHECK: encoding: [0x84,0x00] +lui ra, 32 +# CHECK-INST: mov ra, sp +# CHECK: encoding: [0xc0,0x10] +mov ra, sp +# CHECK-INST: add2 ra, sp +# CHECK: encoding: [0x80,0x10] +add2 ra, sp +# CHECK-INST: sub2 ra, sp +# CHECK: encoding: [0x88,0x10] +sub2 ra, sp +# CHECK-INST: and2 ra, sp +# CHECK: encoding: [0x90,0x10] +and2 ra, sp +# CHECK-INST: xor2 ra, sp +# CHECK: encoding: [0x98,0x10] +xor2 ra, sp +# CHECK-INST: or2 ra, sp +# CHECK: encoding: [0xa0,0x10] +or2 ra, sp +# CHECK-INST: or2 ra, sp +# CHECK: encoding: [0xa0,0x10] +or2 ra, sp +# CHECK-INST: lsl2 ra, sp +# CHECK: encoding: [0xa8,0x10] +lsl2 ra, sp +# CHECK-INST: lsr2 ra, sp +# CHECK: encoding: [0xb0,0x10] +lsr2 ra, sp +# CHECK-INST: asr2 ra, sp +# CHECK: encoding: [0xb8,0x10] +asr2 ra, sp +# CHECK-INST: lsli2 ra, 3 +# CHECK: encoding: [0x2a,0x30] +lsli2 ra, 3 +# CHECK-INST: lsri2 ra, 3 +# CHECK: encoding: [0x32,0x30] +lsri2 ra, 3 +# CHECK-INST: asri2 ra, 3 +# CHECK: encoding: [0x3a,0x30] +asri2 ra, 3 +# CHECK-INST: addi2 ra, -32 +# CHECK: encoding: [0x82,0x00] +addi2 ra, -32 +# CHECK-INST: andi2 ra, 26 +# CHECK: encoding: [0x52,0xa0] +andi2 ra, 26 +# CHECK-INST: jalr sp +# CHECK: encoding: [0x16,0x01] +jalr sp +# CHECK-INST: jr sp +# CHECK: encoding: [0x06,0x01] +jr sp +# CHECK-INST: js 8 +# CHECK: encoding: [0x0e,0x01] +js 8 +# CHECK-INST: jsal 8 +# CHECK: encoding: [0x1e,0x01] +jsal 8 +# CHECK-INST: nop +# CHECK: encoding: [0x00,0x00] +nop diff --git a/llvm/test/MC/CAHP/lit.local.cfg b/llvm/test/MC/CAHP/lit.local.cfg new file mode 100644 index 000000000000..519647fc4da4 --- /dev/null +++ b/llvm/test/MC/CAHP/lit.local.cfg @@ -0,0 +1,2 @@ +if not 'CAHP' in config.root.targets: + config.unsupported = True From 43145f861dc729756a8a85df13a7257248e98169 Mon Sep 17 00:00:00 2001 From: Ushitora Anqou Date: Sun, 13 Oct 2019 23:05:29 +0900 Subject: [PATCH 227/289] [CAHP] Add lw/lb/lbu/sw/sb/lwsp/swsp --- .../Target/CAHP/AsmParser/CAHPAsmParser.cpp | 32 ++++++++++++++++++- llvm/lib/Target/CAHP/CAHPInstrInfo.td | 14 ++++---- llvm/test/MC/CAHP/cahp-invalid.s | 7 ++++ llvm/test/MC/CAHP/cahp-valid.s | 21 ++++++++++++ 4 files changed, 65 insertions(+), 9 deletions(-) diff --git a/llvm/lib/Target/CAHP/AsmParser/CAHPAsmParser.cpp b/llvm/lib/Target/CAHP/AsmParser/CAHPAsmParser.cpp index 1ae5116d11c0..f2cb1af21126 100644 --- a/llvm/lib/Target/CAHP/AsmParser/CAHPAsmParser.cpp +++ b/llvm/lib/Target/CAHP/AsmParser/CAHPAsmParser.cpp @@ -46,6 +46,7 @@ class CAHPAsmParser : public MCTargetAsmParser { OperandMatchResultTy parseImmediate(OperandVector &Operands); OperandMatchResultTy parseRegister(OperandVector &Operands); + OperandMatchResultTy parseMemOpBaseReg(OperandVector &Operands); bool parseOperand(OperandVector &Operands); @@ -382,6 +383,31 @@ OperandMatchResultTy CAHPAsmParser::parseImmediate(OperandVector &Operands) { return MatchOperand_Success; } +OperandMatchResultTy CAHPAsmParser::parseMemOpBaseReg(OperandVector &Operands) { + if (getLexer().isNot(AsmToken::LParen)) { + Error(getLoc(), "expected '('"); + return MatchOperand_ParseFail; + } + + getParser().Lex(); // Eat '(' + Operands.push_back(CAHPOperand::createToken("(", getLoc())); + + if (parseRegister(Operands) != MatchOperand_Success) { + Error(getLoc(), "expected register"); + return MatchOperand_ParseFail; + } + + if (getLexer().isNot(AsmToken::RParen)) { + Error(getLoc(), "expected ')'"); + return MatchOperand_ParseFail; + } + + getParser().Lex(); // Eat ')' + Operands.push_back(CAHPOperand::createToken(")", getLoc())); + + return MatchOperand_Success; +} + /// Looks at a token type and creates the relevant operand /// from this information, adding to Operands. /// If operand was parsed, returns false, else true. @@ -391,8 +417,12 @@ bool CAHPAsmParser::parseOperand(OperandVector &Operands) { return false; // Attempt to parse token as an immediate - if (parseImmediate(Operands) == MatchOperand_Success) + if (parseImmediate(Operands) == MatchOperand_Success) { + // Parse memory base register if present + if (getLexer().is(AsmToken::LParen)) + return parseMemOpBaseReg(Operands) != MatchOperand_Success; return false; + } // Finally we have exhausted all options and must declare defeat. Error(getLoc(), "unknown operand"); diff --git a/llvm/lib/Target/CAHP/CAHPInstrInfo.td b/llvm/lib/Target/CAHP/CAHPInstrInfo.td index 6387fa55d6ea..a69161c89598 100644 --- a/llvm/lib/Target/CAHP/CAHPInstrInfo.td +++ b/llvm/lib/Target/CAHP/CAHPInstrInfo.td @@ -56,7 +56,6 @@ def simm11_lsb0 : Operand { // 24-bit M-instructions. -/* def LW : CAHPInst24MLoad <0b010101, (outs GPR:$rd), (ins GPR:$rs, simm11_lsb0:$imm), "lw", "$rd, ${imm}(${rs})"> { bits<11> imm; @@ -87,7 +86,7 @@ def SB : CAHPInst24MStore<0b001101, (outs GPR:$rd), (ins GPR:$rs, simm10:$imm), let Inst{23-16} = imm{7-0}; let Inst{7-6} = imm{9-8}; } -*/ + def LI : CAHPInst24MLoad <0b110101, (outs GPR:$rd), (ins simm10:$imm), "li", "$rd, $imm"> { bits<10> imm; @@ -148,20 +147,19 @@ def BLEU : CAHPInst24J<0b011111, (ins GPR:$rs1, GPR:$rs2, simm10:$imm), // 16-bit M-instructions. -/* -def LWSP : CAHPInst16Load <0b010100, (outs GPR:$rd), (ins uimm7_lsb0:$imm), - "lwsp", "$rd, ${imm}(sp)"> { +def LWSP : CAHPInst16Load <0b010100, (outs GPR:$rd), (ins SP:$rs, uimm7_lsb0:$imm), + "lwsp", "$rd, ${imm}(${rs})"> { bits<7> imm; let Inst{15-12} = imm{4-1}; let Inst{7-6} = imm{6-5}; } -def SWSP : CAHPInst16Store<0b011100, (outs), (ins GPR:$rs, uimm7_lsb0:$imm), - "swsp", "$rs, ${imm}(sp)"> { +def SWSP : CAHPInst16Store<0b011100, (outs), (ins GPR:$rs, SP:$rd, uimm7_lsb0:$imm), + "swsp", "$rs, ${imm}(${rd})"> { bits<7> imm; let Inst{15-12} = imm{4-1}; let Inst{7-6} = imm{6-5}; } -*/ + def LSI : CAHPInst16Load <0b110100, (outs GPR:$rd), (ins simm6:$imm), "lsi", "$rd, $imm"> { bits<6> imm; diff --git a/llvm/test/MC/CAHP/cahp-invalid.s b/llvm/test/MC/CAHP/cahp-invalid.s index 693cce8acb14..d7aac9a337c1 100644 --- a/llvm/test/MC/CAHP/cahp-invalid.s +++ b/llvm/test/MC/CAHP/cahp-invalid.s @@ -1,6 +1,11 @@ # RUN: not llvm-mc -triple cahp < %s 2>&1 | FileCheck %s # Out of range immediates +lw a4, 1024(a2) # CHECK: :[[@LINE]]:8: error: immediate must be a multiple of 2 bytes in the range [-1024, 1022] +lb a4, -513(a2) # CHECK: :[[@LINE]]:8: error: immediate must be an integer in the range [-512, 511] +lbu a4, -513(a2) # CHECK: :[[@LINE]]:9: error: immediate must be an integer in the range [-512, 511] +sw a4, -1025(a2) # CHECK: :[[@LINE]]:8: error: immediate must be a multiple of 2 bytes in the range [-1024, 1022] +sb a4, 512(a2) # CHECK: :[[@LINE]]:8: error: immediate must be an integer in the range [-512, 511] li t0, -513 # CHECK: :[[@LINE]]:8: error: immediate must be an integer in the range [-512, 511] li s0, 512 # CHECK: :[[@LINE]]:8: error: immediate must be an integer in the range [-512, 511] addi a0, a1, 128 # CHECK: :[[@LINE]]:14: error: immediate must be an integer in the range [-128, 127] @@ -9,6 +14,8 @@ andi a0, a1, 256 # CHECK: :[[@LINE]]:14: error: immediate must be an integer in andi a0, a1, -1 # CHECK: :[[@LINE]]:14: error: immediate must be an integer in the range [0, 255] lsli a0, a1, 16 # CHECK: :[[@LINE]]:14: error: immediate must be an integer in the range [0, 15] asri a0, a1, -1 # CHECK: :[[@LINE]]:14: error: immediate must be an integer in the range [0, 15] +lwsp a4, 128(sp) # CHECK: :[[@LINE]]:10: error: immediate must be a multiple of 2 bytes in the range [0, 126] +swsp a3, -2(sp) # CHECK: :[[@LINE]]:10: error: immediate must be a multiple of 2 bytes in the range [0, 126] lsi a5, 32 # CHECK: :[[@LINE]]:9: error: immediate must be an integer in the range [-32, 31] lsi a5, -33 # CHECK: :[[@LINE]]:9: error: immediate must be an integer in the range [-32, 31] lui a5, 65 # CHECK: :[[@LINE]]:9: error: immediate must be an integer in the range [0, 63] diff --git a/llvm/test/MC/CAHP/cahp-valid.s b/llvm/test/MC/CAHP/cahp-valid.s index dc25df635290..38c958090d94 100644 --- a/llvm/test/MC/CAHP/cahp-valid.s +++ b/llvm/test/MC/CAHP/cahp-valid.s @@ -1,6 +1,21 @@ # RUN: llvm-mc %s -triple=cahp -show-encoding \ # RUN: | FileCheck -check-prefixes=CHECK,CHECK-INST %s +# CHECK-INST: lw ra, -1000(sp) +# CHECK: encoding: [0x95,0x10,0x0c] +lw ra, -1000(sp) +# CHECK-INST: lb ra, -500(sp) +# CHECK: encoding: [0xa5,0x10,0x0c] +lb ra, -500(sp) +# CHECK-INST: lbu ra, -500(sp) +# CHECK: encoding: [0x85,0x10,0x0c] +lbu ra, -500(sp) +# CHECK-INST: sw ra, -1000(sp) +# CHECK: encoding: [0x9d,0x10,0x0c] +sw ra, -1000(sp) +# CHECK-INST: sb ra, -500(sp) +# CHECK: encoding: [0x8d,0x10,0x0c] +sb ra, -500(sp) # CHECK-INST: li ra, -500 # CHECK: encoding: [0xb5,0x00,0x0c] li ra, -500 @@ -100,6 +115,12 @@ bleu ra, sp, 16 # CHECK-INST: bleu ra, sp, 16 # CHECK: encoding: [0x1f,0x01,0x10] bleu ra, sp, 16 +# CHECK-INST: lwsp ra, 32(sp) +# CHECK: encoding: [0x54,0x00] +lwsp ra, 32(sp) +# CHECK-INST: swsp ra, 64(sp) +# CHECK: encoding: [0x9c,0x00] +swsp ra, 64(sp) # CHECK-INST: lsi ra, -32 # CHECK: encoding: [0xb4,0x00] lsi ra, -32 From 1963e0288a450c3785723861c7c5d5c7280186fc Mon Sep 17 00:00:00 2001 From: Ushitora Anqou Date: Sun, 13 Oct 2019 23:25:13 +0900 Subject: [PATCH 228/289] [CAHP] Add records to instruction --- llvm/lib/Target/CAHP/CAHPInstrInfo.td | 206 +++++++++++++++----------- 1 file changed, 122 insertions(+), 84 deletions(-) diff --git a/llvm/lib/Target/CAHP/CAHPInstrInfo.td b/llvm/lib/Target/CAHP/CAHPInstrInfo.td index a69161c89598..41fedbe63dd6 100644 --- a/llvm/lib/Target/CAHP/CAHPInstrInfo.td +++ b/llvm/lib/Target/CAHP/CAHPInstrInfo.td @@ -56,37 +56,43 @@ def simm11_lsb0 : Operand { // 24-bit M-instructions. -def LW : CAHPInst24MLoad <0b010101, (outs GPR:$rd), (ins GPR:$rs, simm11_lsb0:$imm), - "lw", "$rd, ${imm}(${rs})"> { - bits<11> imm; - let Inst{23-16} = imm{8-1}; - let Inst{7-6} = imm{10-9}; -} -def LB : CAHPInst24MLoad <0b100101, (outs GPR:$rd), (ins GPR:$rs, simm10:$imm), - "lb", "$rd, ${imm}(${rs})"> { - bits<10> imm; - let Inst{23-16} = imm{7-0}; - let Inst{7-6} = imm{9-8}; +let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in { + def LW : CAHPInst24MLoad <0b010101, (outs GPR:$rd), (ins GPR:$rs, simm11_lsb0:$imm), + "lw", "$rd, ${imm}(${rs})"> { + bits<11> imm; + let Inst{23-16} = imm{8-1}; + let Inst{7-6} = imm{10-9}; + } + def LB : CAHPInst24MLoad <0b100101, (outs GPR:$rd), (ins GPR:$rs, simm10:$imm), + "lb", "$rd, ${imm}(${rs})"> { + bits<10> imm; + let Inst{23-16} = imm{7-0}; + let Inst{7-6} = imm{9-8}; + } + def LBU : CAHPInst24MLoad <0b000101, (outs GPR:$rd), (ins GPR:$rs, simm10:$imm), + "lbu", "$rd, ${imm}(${rs})"> { + bits<10> imm; + let Inst{23-16} = imm{7-0}; + let Inst{7-6} = imm{9-8}; + } } -def LBU : CAHPInst24MLoad <0b000101, (outs GPR:$rd), (ins GPR:$rs, simm10:$imm), - "lbu", "$rd, ${imm}(${rs})"> { - bits<10> imm; - let Inst{23-16} = imm{7-0}; - let Inst{7-6} = imm{9-8}; -} -def SW : CAHPInst24MStore<0b011101, (outs GPR:$rd), (ins GPR:$rs, simm11_lsb0:$imm), - "sw", "$rs, ${imm}(${rd})"> { - bits<11> imm; - let Inst{23-16} = imm{8-1}; - let Inst{7-6} = imm{10-9}; -} -def SB : CAHPInst24MStore<0b001101, (outs GPR:$rd), (ins GPR:$rs, simm10:$imm), - "sb", "$rs, ${imm}(${rd})"> { - bits<10> imm; - let Inst{23-16} = imm{7-0}; - let Inst{7-6} = imm{9-8}; + +let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in { + def SW : CAHPInst24MStore<0b011101, (outs GPR:$rd), (ins GPR:$rs, simm11_lsb0:$imm), + "sw", "$rs, ${imm}(${rd})"> { + bits<11> imm; + let Inst{23-16} = imm{8-1}; + let Inst{7-6} = imm{10-9}; + } + def SB : CAHPInst24MStore<0b001101, (outs GPR:$rd), (ins GPR:$rs, simm10:$imm), + "sb", "$rs, ${imm}(${rd})"> { + bits<10> imm; + let Inst{23-16} = imm{7-0}; + let Inst{7-6} = imm{9-8}; + } } +let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isMoveImm = 1 in def LI : CAHPInst24MLoad <0b110101, (outs GPR:$rd), (ins simm10:$imm), "li", "$rd, $imm"> { bits<10> imm; @@ -96,63 +102,76 @@ def LI : CAHPInst24MLoad <0b110101, (outs GPR:$rd), (ins simm10:$imm), // 24-bit R-instructions. -def ADD : CAHPInst24R<0b00000001, (outs GPR:$rd), (ins GPR:$rs1, GPR:$rs2), - "add", "$rd, $rs1, $rs2">; -def SUB : CAHPInst24R<0b00001001, (outs GPR:$rd), (ins GPR:$rs1, GPR:$rs2), - "sub", "$rd, $rs1, $rs2">; -def AND : CAHPInst24R<0b00010001, (outs GPR:$rd), (ins GPR:$rs1, GPR:$rs2), - "and", "$rd, $rs1, $rs2">; -def XOR : CAHPInst24R<0b00011001, (outs GPR:$rd), (ins GPR:$rs1, GPR:$rs2), - "xor", "$rd, $rs1, $rs2">; -def OR : CAHPInst24R<0b00100001, (outs GPR:$rd), (ins GPR:$rs1, GPR:$rs2), - "or", "$rd, $rs1, $rs2">; -def LSL : CAHPInst24R<0b00101001, (outs GPR:$rd), (ins GPR:$rs1, GPR:$rs2), - "lsl", "$rd, $rs1, $rs2">; -def LSR : CAHPInst24R<0b00110001, (outs GPR:$rd), (ins GPR:$rs1, GPR:$rs2), - "lsr", "$rd, $rs1, $rs2">; -def ASR : CAHPInst24R<0b00111001, (outs GPR:$rd), (ins GPR:$rs1, GPR:$rs2), - "asr", "$rd, $rs1, $rs2">; +let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in { + let isCommutable = 1 in { + def ADD : CAHPInst24R<0b00000001, (outs GPR:$rd), (ins GPR:$rs1, GPR:$rs2), + "add", "$rd, $rs1, $rs2">; + def AND : CAHPInst24R<0b00010001, (outs GPR:$rd), (ins GPR:$rs1, GPR:$rs2), + "and", "$rd, $rs1, $rs2">; + def XOR : CAHPInst24R<0b00011001, (outs GPR:$rd), (ins GPR:$rs1, GPR:$rs2), + "xor", "$rd, $rs1, $rs2">; + def OR : CAHPInst24R<0b00100001, (outs GPR:$rd), (ins GPR:$rs1, GPR:$rs2), + "or", "$rd, $rs1, $rs2">; + } + + def SUB : CAHPInst24R<0b00001001, (outs GPR:$rd), (ins GPR:$rs1, GPR:$rs2), + "sub", "$rd, $rs1, $rs2">; + def LSL : CAHPInst24R<0b00101001, (outs GPR:$rd), (ins GPR:$rs1, GPR:$rs2), + "lsl", "$rd, $rs1, $rs2">; + def LSR : CAHPInst24R<0b00110001, (outs GPR:$rd), (ins GPR:$rs1, GPR:$rs2), + "lsr", "$rd, $rs1, $rs2">; + def ASR : CAHPInst24R<0b00111001, (outs GPR:$rd), (ins GPR:$rs1, GPR:$rs2), + "asr", "$rd, $rs1, $rs2">; +} // 24-bit I-instructions. -def ADDI : CAHPInst24I<0b11000011, (outs GPR:$rd), (ins GPR:$rs1, simm8:$imm), - "addi", "$rd, $rs1, $imm">; -def ANDI : CAHPInst24I<0b01010011, (outs GPR:$rd), (ins GPR:$rs1, uimm8:$imm), - "andi", "$rd, $rs1, $imm">; -def XORI : CAHPInst24I<0b01011011, (outs GPR:$rd), (ins GPR:$rs1, uimm8:$imm), - "xori", "$rd, $rs1, $imm">; -def ORI : CAHPInst24I<0b01100011, (outs GPR:$rd), (ins GPR:$rs1, uimm8:$imm), - "ori", "$rd, $rs1, $imm">; -def LSLI : CAHPInst24I<0b00101011, (outs GPR:$rd), (ins GPR:$rs1, uimm4:$imm), - "lsli", "$rd, $rs1, $imm">; -def LSRI : CAHPInst24I<0b00110011, (outs GPR:$rd), (ins GPR:$rs1, uimm4:$imm), - "lsri", "$rd, $rs1, $imm">; -def ASRI : CAHPInst24I<0b00111011, (outs GPR:$rd), (ins GPR:$rs1, uimm4:$imm), - "asri", "$rd, $rs1, $imm">; +let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in { + def ADDI : CAHPInst24I<0b11000011, (outs GPR:$rd), (ins GPR:$rs1, simm8:$imm), + "addi", "$rd, $rs1, $imm">; + def ANDI : CAHPInst24I<0b01010011, (outs GPR:$rd), (ins GPR:$rs1, uimm8:$imm), + "andi", "$rd, $rs1, $imm">; + def XORI : CAHPInst24I<0b01011011, (outs GPR:$rd), (ins GPR:$rs1, uimm8:$imm), + "xori", "$rd, $rs1, $imm">; + def ORI : CAHPInst24I<0b01100011, (outs GPR:$rd), (ins GPR:$rs1, uimm8:$imm), + "ori", "$rd, $rs1, $imm">; + def LSLI : CAHPInst24I<0b00101011, (outs GPR:$rd), (ins GPR:$rs1, uimm4:$imm), + "lsli", "$rd, $rs1, $imm">; + def LSRI : CAHPInst24I<0b00110011, (outs GPR:$rd), (ins GPR:$rs1, uimm4:$imm), + "lsri", "$rd, $rs1, $imm">; + def ASRI : CAHPInst24I<0b00111011, (outs GPR:$rd), (ins GPR:$rs1, uimm4:$imm), + "asri", "$rd, $rs1, $imm">; +} // 24-bit J-instructions. -def BEQ : CAHPInst24J<0b001111, (ins GPR:$rs1, GPR:$rs2, simm10:$imm), - "beq", "$rs1, $rs2, $imm">; -def BNE : CAHPInst24J<0b101111, (ins GPR:$rs1, GPR:$rs2, simm10:$imm), - "bne", "$rs1, $rs2, $imm">; -def BLT : CAHPInst24J<0b110111, (ins GPR:$rs1, GPR:$rs2, simm10:$imm), - "blt", "$rs1, $rs2, $imm">; -def BLTU : CAHPInst24J<0b010111, (ins GPR:$rs1, GPR:$rs2, simm10:$imm), - "bltu", "$rs1, $rs2, $imm">; -def BLE : CAHPInst24J<0b111111, (ins GPR:$rs1, GPR:$rs2, simm10:$imm), - "ble", "$rs1, $rs2, $imm">; -def BLEU : CAHPInst24J<0b011111, (ins GPR:$rs1, GPR:$rs2, simm10:$imm), - "bleu", "$rs1, $rs2, $imm">; +let hasSideEffects = 0, mayLoad = 0, mayStore = 0, + isBranch = 1, isTerminator = 1 in { + def BEQ : CAHPInst24J<0b001111, (ins GPR:$rs1, GPR:$rs2, simm10:$imm), + "beq", "$rs1, $rs2, $imm">; + def BNE : CAHPInst24J<0b101111, (ins GPR:$rs1, GPR:$rs2, simm10:$imm), + "bne", "$rs1, $rs2, $imm">; + def BLT : CAHPInst24J<0b110111, (ins GPR:$rs1, GPR:$rs2, simm10:$imm), + "blt", "$rs1, $rs2, $imm">; + def BLTU : CAHPInst24J<0b010111, (ins GPR:$rs1, GPR:$rs2, simm10:$imm), + "bltu", "$rs1, $rs2, $imm">; + def BLE : CAHPInst24J<0b111111, (ins GPR:$rs1, GPR:$rs2, simm10:$imm), + "ble", "$rs1, $rs2, $imm">; + def BLEU : CAHPInst24J<0b011111, (ins GPR:$rs1, GPR:$rs2, simm10:$imm), + "bleu", "$rs1, $rs2, $imm">; +} // 16-bit M-instructions. +let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in def LWSP : CAHPInst16Load <0b010100, (outs GPR:$rd), (ins SP:$rs, uimm7_lsb0:$imm), "lwsp", "$rd, ${imm}(${rs})"> { bits<7> imm; let Inst{15-12} = imm{4-1}; let Inst{7-6} = imm{6-5}; } + +let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in def SWSP : CAHPInst16Store<0b011100, (outs), (ins GPR:$rs, SP:$rd, uimm7_lsb0:$imm), "swsp", "$rs, ${imm}(${rd})"> { bits<7> imm; @@ -160,12 +179,15 @@ def SWSP : CAHPInst16Store<0b011100, (outs), (ins GPR:$rs, SP:$rd, uimm7_lsb0:$i let Inst{7-6} = imm{6-5}; } +let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isMoveImm = 1 in def LSI : CAHPInst16Load <0b110100, (outs GPR:$rd), (ins simm6:$imm), "lsi", "$rd, $imm"> { bits<6> imm; let Inst{15-12} = imm{3-0}; let Inst{7-6} = imm{5-4}; } + +let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isMoveImm = 1 in def LUI : CAHPInst16Load <0b000100, (outs GPR:$rd), (ins uimm6:$imm), "lui", "$rd, $imm"> { bits<6> imm; @@ -175,20 +197,25 @@ def LUI : CAHPInst16Load <0b000100, (outs GPR:$rd), (ins uimm6:$imm), // 16-bit R-instructions. +let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isMoveReg = 1 in def MOV : CAHPInst16R<0b11000000, (outs GPR:$rd), (ins GPR:$rs), "mov", "$rd, $rs">; -let Constraints = "$rd = $rd_w" in { - def ADD2 : CAHPInst16R<0b10000000, (outs GPR:$rd_w), (ins GPR:$rd, GPR:$rs), - "add2", "$rd, $rs">; +let hasSideEffects = 0, mayLoad = 0, mayStore = 0, + Constraints = "$rd = $rd_w" in { + let isCommutable = 1 in { + def ADD2 : CAHPInst16R<0b10000000, (outs GPR:$rd_w), (ins GPR:$rd, GPR:$rs), + "add2", "$rd, $rs">; + def AND2 : CAHPInst16R<0b10010000, (outs GPR:$rd_w), (ins GPR:$rd, GPR:$rs), + "and2", "$rd, $rs">; + def XOR2 : CAHPInst16R<0b10011000, (outs GPR:$rd_w), (ins GPR:$rd, GPR:$rs), + "xor2", "$rd, $rs">; + def OR2 : CAHPInst16R<0b10100000, (outs GPR:$rd_w), (ins GPR:$rd, GPR:$rs), + "or2", "$rd, $rs">; + } + def SUB2 : CAHPInst16R<0b10001000, (outs GPR:$rd_w), (ins GPR:$rd, GPR:$rs), "sub2", "$rd, $rs">; - def AND2 : CAHPInst16R<0b10010000, (outs GPR:$rd_w), (ins GPR:$rd, GPR:$rs), - "and2", "$rd, $rs">; - def XOR2 : CAHPInst16R<0b10011000, (outs GPR:$rd_w), (ins GPR:$rd, GPR:$rs), - "xor2", "$rd, $rs">; - def OR2 : CAHPInst16R<0b10100000, (outs GPR:$rd_w), (ins GPR:$rd, GPR:$rs), - "or2", "$rd, $rs">; def LSL2 : CAHPInst16R<0b10101000, (outs GPR:$rd_w), (ins GPR:$rd, GPR:$rs), "lsl2", "$rd, $rs">; def LSR2 : CAHPInst16R<0b10110000, (outs GPR:$rd_w), (ins GPR:$rd, GPR:$rs), @@ -199,7 +226,8 @@ let Constraints = "$rd = $rd_w" in { // 16-bit I-instructions. -let Constraints = "$rd = $rd_w" in { +let hasSideEffects = 0, mayLoad = 0, mayStore = 0, + Constraints = "$rd = $rd_w" in { def LSLI2 : CAHPInst16I<0b101010, (outs GPR:$rd_w), (ins GPR:$rd, uimm4:$imm), "lsli2", "$rd, $imm">; def LSRI2 : CAHPInst16I<0b110010, (outs GPR:$rd_w), (ins GPR:$rd, uimm4:$imm), @@ -214,13 +242,23 @@ let Constraints = "$rd = $rd_w" in { // 16-bit J-instructions. -def JALR : CAHPInst16JR<0b10110, (ins GPR:$rs), "jalr", "$rs">; -def JR : CAHPInst16JR<0b00110, (ins GPR:$rs), "jr", "$rs">; -def JS : CAHPInst16JI<0b01110, (ins simm11:$imm), "js", "$imm">; -def JSAL : CAHPInst16JI<0b11110, (ins simm11:$imm), "jsal", "$imm">; +let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in { + let isCall = 1, Defs = [X0] in + def JALR : CAHPInst16JR<0b10110, (ins GPR:$rs), "jalr", "$rs">; + + let isBranch = 1, isBarrier = 1, isTerminator = 1, isIndirectBranch = 1 in + def JR : CAHPInst16JR<0b00110, (ins GPR:$rs), "jr", "$rs">; + + let isBranch = 1, isTerminator = 1, isBarrier = 1 in + def JS : CAHPInst16JI<0b01110, (ins simm11:$imm), "js", "$imm">; + + let isCall = 1, Defs = [X0] in + def JSAL : CAHPInst16JI<0b11110, (ins simm11:$imm), "jsal", "$imm">; +} // Others. +let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in def NOP : CAHPInst16<(outs), (ins), "nop", ""> { let Inst = 0; } From 01fdfc0e1a5281527e339913ee08cb0da9d75f46 Mon Sep 17 00:00:00 2001 From: Ushitora Anqou Date: Mon, 14 Oct 2019 22:35:38 +0900 Subject: [PATCH 229/289] [CAHP] Add disassembler --- llvm/lib/Target/CAHP/CAHPInstrFormats.td | 6 + llvm/lib/Target/CAHP/CAHPInstrInfo.td | 9 ++ llvm/lib/Target/CAHP/CMakeLists.txt | 2 + .../CAHP/Disassembler/CAHPDisassembler.cpp | 126 ++++++++++++++++++ .../Target/CAHP/Disassembler/CMakeLists.txt | 3 + .../Target/CAHP/Disassembler/LLVMBuild.txt | 10 ++ llvm/lib/Target/CAHP/LLVMBuild.txt | 4 +- llvm/test/MC/CAHP/cahp-valid.s | 2 + 8 files changed, 161 insertions(+), 1 deletion(-) create mode 100644 llvm/lib/Target/CAHP/Disassembler/CAHPDisassembler.cpp create mode 100644 llvm/lib/Target/CAHP/Disassembler/CMakeLists.txt create mode 100644 llvm/lib/Target/CAHP/Disassembler/LLVMBuild.txt diff --git a/llvm/lib/Target/CAHP/CAHPInstrFormats.td b/llvm/lib/Target/CAHP/CAHPInstrFormats.td index 3c306682ea86..59de5ded4110 100644 --- a/llvm/lib/Target/CAHP/CAHPInstrFormats.td +++ b/llvm/lib/Target/CAHP/CAHPInstrFormats.td @@ -4,6 +4,12 @@ class CAHPInst pattern = []> : Instruction { + // SoftFail is a field the disassembler can use to provide a way for + // instructions to not match without killing the whole decode process. It is + // mainly used for ARM, but Tablegen expects this field to exist or it fails + // to build the decode table. + bits<32> SoftFail = 0; + let Namespace = "CAHP"; dag OutOperandList = outs; diff --git a/llvm/lib/Target/CAHP/CAHPInstrInfo.td b/llvm/lib/Target/CAHP/CAHPInstrInfo.td index 41fedbe63dd6..f77764daace9 100644 --- a/llvm/lib/Target/CAHP/CAHPInstrInfo.td +++ b/llvm/lib/Target/CAHP/CAHPInstrInfo.td @@ -20,38 +20,47 @@ class UImmAsmOperand def uimm4 : Operand { let ParserMatchClass = UImmAsmOperand<4>; + let DecoderMethod = "decodeUImmOperand<4>"; } def simm6 : Operand { let ParserMatchClass = SImmAsmOperand<6>; + let DecoderMethod = "decodeSImmOperand<6>"; } def uimm6 : Operand { let ParserMatchClass = UImmAsmOperand<6>; + let DecoderMethod = "decodeUImmOperand<6>"; } def simm8 : Operand { let ParserMatchClass = SImmAsmOperand<8>; + let DecoderMethod = "decodeSImmOperand<8>"; } def uimm8 : Operand { let ParserMatchClass = UImmAsmOperand<8>; + let DecoderMethod = "decodeUImmOperand<8>"; } def simm10 : Operand { let ParserMatchClass = SImmAsmOperand<10>; + let DecoderMethod = "decodeSImmOperand<10>"; } def simm11 : Operand { let ParserMatchClass = SImmAsmOperand<11>; + let DecoderMethod = "decodeSImmOperand<11>"; } def uimm7_lsb0 : Operand { let ParserMatchClass = UImmAsmOperand<7, "Lsb0">; + let DecoderMethod = "decodeUImmOperand<7>"; } def simm11_lsb0 : Operand { let ParserMatchClass = SImmAsmOperand<11, "Lsb0">; + let DecoderMethod = "decodeSImmOperand<11>"; } // 24-bit M-instructions. diff --git a/llvm/lib/Target/CAHP/CMakeLists.txt b/llvm/lib/Target/CAHP/CMakeLists.txt index 03fc3c0b28d3..78861912c1a3 100644 --- a/llvm/lib/Target/CAHP/CMakeLists.txt +++ b/llvm/lib/Target/CAHP/CMakeLists.txt @@ -6,6 +6,7 @@ tablegen(LLVM CAHPGenMCCodeEmitter.inc -gen-emitter) tablegen(LLVM CAHPGenSubtargetInfo.inc -gen-subtarget) tablegen(LLVM CAHPGenAsmMatcher.inc -gen-asm-matcher) tablegen(LLVM CAHPGenAsmWriter.inc -gen-asm-writer) +tablegen(LLVM CAHPGenDisassemblerTables.inc -gen-disassembler) add_public_tablegen_target(CAHPCommonTableGen) @@ -13,6 +14,7 @@ add_llvm_target(CAHPCodeGen CAHPTargetMachine.cpp ) add_subdirectory(AsmParser) +add_subdirectory(Disassembler) add_subdirectory(InstPrinter) add_subdirectory(MCTargetDesc) add_subdirectory(TargetInfo) diff --git a/llvm/lib/Target/CAHP/Disassembler/CAHPDisassembler.cpp b/llvm/lib/Target/CAHP/Disassembler/CAHPDisassembler.cpp new file mode 100644 index 000000000000..be300ece8244 --- /dev/null +++ b/llvm/lib/Target/CAHP/Disassembler/CAHPDisassembler.cpp @@ -0,0 +1,126 @@ +// This file is copied and modified from The LLVM Compiler Infrastructure, which +// is distributed under the Apache License v2.0 with LLVM Exceptions (see +// LICENSE.TXT for details). This file is licensed under the same license. + +#include "MCTargetDesc/CAHPMCTargetDesc.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCDisassembler/MCDisassembler.h" +#include "llvm/MC/MCFixedLenDisassembler.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCRegisterInfo.h" +#include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/FormatVariadic.h" +#include "llvm/Support/TargetRegistry.h" + +using namespace llvm; + +#define DEBUG_TYPE "cahp-disassembler" + +typedef MCDisassembler::DecodeStatus DecodeStatus; + +namespace { +class CAHPDisassembler : public MCDisassembler { + +public: + CAHPDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx) + : MCDisassembler(STI, Ctx) {} + + DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size, + ArrayRef Bytes, uint64_t Address, + raw_ostream &VStream, + raw_ostream &CStream) const override; +}; +} // end anonymous namespace + +static MCDisassembler *createCAHPDisassembler(const Target &T, + const MCSubtargetInfo &STI, + MCContext &Ctx) { + return new CAHPDisassembler(STI, Ctx); +} + +extern "C" void LLVMInitializeCAHPDisassembler() { + TargetRegistry::RegisterMCDisassembler(getTheCAHPTarget(), + createCAHPDisassembler); +} + +static const unsigned GPRDecoderTable[] = { + CAHP::X0, CAHP::X1, CAHP::X2, CAHP::X3, CAHP::X4, CAHP::X5, + CAHP::X6, CAHP::X7, CAHP::X8, CAHP::X9, CAHP::X10, CAHP::X11, + CAHP::X12, CAHP::X13, CAHP::X14, CAHP::X15}; + +static DecodeStatus DecodeGPRRegisterClass(MCInst &Inst, uint64_t RegNo, + uint64_t Address, + const void *Decoder) { + if (RegNo > sizeof(GPRDecoderTable)) + return MCDisassembler::Fail; + + unsigned Reg = GPRDecoderTable[RegNo]; + Inst.addOperand(MCOperand::createReg(Reg)); + return MCDisassembler::Success; +} + +// Add implied SP operand for instructions lwsp/swsp. The SP operand isn't +// explicitly encoded in the instruction. +static void addImplySP(MCInst &Inst, int64_t Address, const void *Decoder) { + if (Inst.getOpcode() == CAHP::LWSP || Inst.getOpcode() == CAHP::SWSP) + DecodeGPRRegisterClass(Inst, /* SP */ 1, Address, Decoder); +} + +template +static DecodeStatus decodeUImmOperand(MCInst &Inst, uint64_t Imm, + int64_t Address, const void *Decoder) { + assert(isUInt(Imm) && "Invalid immediate"); + addImplySP(Inst, Address, Decoder); + Inst.addOperand(MCOperand::createImm(Imm)); + return MCDisassembler::Success; +} + +template +static DecodeStatus decodeSImmOperand(MCInst &Inst, uint64_t Imm, + int64_t Address, const void *Decoder) { + assert(isUInt(Imm) && "Invalid immediate"); + // Sign-extend the number in the bottom N bits of Imm + Inst.addOperand(MCOperand::createImm(SignExtend64(Imm))); + return MCDisassembler::Success; +} + +#include "CAHPGenDisassemblerTables.inc" + +DecodeStatus CAHPDisassembler::getInstruction(MCInst &MI, uint64_t &Size, + ArrayRef Bytes, + uint64_t Address, raw_ostream &OS, + raw_ostream &CS) const { + if (Bytes.size() < 2) { + Size = 0; + return MCDisassembler::Fail; + } + + uint32_t Inst; + DecodeStatus Result; + + uint8_t is24bitInst = Bytes[0] & 1; + + if (is24bitInst) { + if (Bytes.size() < 3) { + Size = 0; + return MCDisassembler::Fail; + } + + Inst = Bytes[0] | (Bytes[1] << 8) | (Bytes[2] << 16); + LLVM_DEBUG(dbgs() << "Trying CAHP 24bit table :\n"); + Result = decodeInstruction(DecoderTable24, MI, Inst, Address, this, STI); + Size = 3; + } else { + if (Bytes.size() < 2) { + Size = 0; + return MCDisassembler::Fail; + } + Inst = support::endian::read16le(Bytes.data()); + LLVM_DEBUG(dbgs() << "Trying CAHP 16bit table :\n"); + Result = decodeInstruction(DecoderTable16, MI, Inst, Address, this, STI); + Size = 2; + } + + return Result; +} diff --git a/llvm/lib/Target/CAHP/Disassembler/CMakeLists.txt b/llvm/lib/Target/CAHP/Disassembler/CMakeLists.txt new file mode 100644 index 000000000000..da9b68775796 --- /dev/null +++ b/llvm/lib/Target/CAHP/Disassembler/CMakeLists.txt @@ -0,0 +1,3 @@ +add_llvm_library(LLVMCAHPDisassembler + CAHPDisassembler.cpp + ) diff --git a/llvm/lib/Target/CAHP/Disassembler/LLVMBuild.txt b/llvm/lib/Target/CAHP/Disassembler/LLVMBuild.txt new file mode 100644 index 000000000000..f155874d28d4 --- /dev/null +++ b/llvm/lib/Target/CAHP/Disassembler/LLVMBuild.txt @@ -0,0 +1,10 @@ +; This file is copied and modified from The LLVM Compiler Infrastructure, which +; is distributed under the Apache License v2.0 with LLVM Exceptions (see +; LICENSE.TXT for details). This file is licensed under the same license. + +[component_0] +type = Library +name = CAHPDisassembler +parent = CAHP +required_libraries = MCDisassembler CAHPInfo Support +add_to_library_groups = CAHP diff --git a/llvm/lib/Target/CAHP/LLVMBuild.txt b/llvm/lib/Target/CAHP/LLVMBuild.txt index e823775e31a7..836740c1c763 100644 --- a/llvm/lib/Target/CAHP/LLVMBuild.txt +++ b/llvm/lib/Target/CAHP/LLVMBuild.txt @@ -3,13 +3,15 @@ ; LICENSE.TXT for details). This file is licensed under the same license. [common] -subdirectories = AsmParser InstPrinter TargetInfo MCTargetDesc +subdirectories = AsmParser Disassembler InstPrinter TargetInfo MCTargetDesc [component_0] type = TargetGroup name = CAHP parent = Target has_asmparser = 1 +has_asmprinter = 1 +has_disassembler = 1 [component_1] type = Library diff --git a/llvm/test/MC/CAHP/cahp-valid.s b/llvm/test/MC/CAHP/cahp-valid.s index 38c958090d94..355fef508689 100644 --- a/llvm/test/MC/CAHP/cahp-valid.s +++ b/llvm/test/MC/CAHP/cahp-valid.s @@ -1,5 +1,7 @@ # RUN: llvm-mc %s -triple=cahp -show-encoding \ # RUN: | FileCheck -check-prefixes=CHECK,CHECK-INST %s +# RUN: llvm-mc -filetype=obj -triple=cahp < %s \ +# RUN: | llvm-objdump -d - | FileCheck -check-prefix=CHECK-INST %s # CHECK-INST: lw ra, -1000(sp) # CHECK: encoding: [0x95,0x10,0x0c] From a03e70e9157510937ca522f14ca0c64c61d47ca7 Mon Sep 17 00:00:00 2001 From: Ushitora Anqou Date: Wed, 16 Oct 2019 13:51:05 +0900 Subject: [PATCH 230/289] [CAHP] Add support for fixups for jump/branch --- .../Target/CAHP/AsmParser/CAHPAsmParser.cpp | 36 +++++-- llvm/lib/Target/CAHP/CAHPInstrInfo.td | 9 ++ .../CAHP/MCTargetDesc/CAHPAsmBackend.cpp | 94 ++++++++++++++++++- .../Target/CAHP/MCTargetDesc/CAHPFixupKinds.h | 32 +++++++ .../CAHP/MCTargetDesc/CAHPMCCodeEmitter.cpp | 52 ++++++++++ llvm/test/MC/CAHP/cahp-invalid.s | 6 +- llvm/test/MC/CAHP/fixups.s | 55 +++++++++++ 7 files changed, 271 insertions(+), 13 deletions(-) create mode 100644 llvm/lib/Target/CAHP/MCTargetDesc/CAHPFixupKinds.h create mode 100644 llvm/test/MC/CAHP/fixups.s diff --git a/llvm/lib/Target/CAHP/AsmParser/CAHPAsmParser.cpp b/llvm/lib/Target/CAHP/AsmParser/CAHPAsmParser.cpp index f2cb1af21126..0721811dbf8a 100644 --- a/llvm/lib/Target/CAHP/AsmParser/CAHPAsmParser.cpp +++ b/llvm/lib/Target/CAHP/AsmParser/CAHPAsmParser.cpp @@ -145,11 +145,19 @@ struct CAHPOperand : public MCParsedAsmOperand { } bool isSImm10() const { - return (isConstantImm() && isInt<10>(getConstantImm())); + if (!isImm()) + return false; + if (isConstantImm()) + return isInt<10>(getConstantImm()); + return isa(getImm()); } bool isSImm11() const { - return (isConstantImm() && isInt<11>(getConstantImm())); + if (!isImm()) + return false; + if (isConstantImm()) + return isInt<11>(getConstantImm()); + return isa(getImm()); } bool isUImm7Lsb0() const { @@ -362,24 +370,34 @@ OperandMatchResultTy CAHPAsmParser::parseRegister(OperandVector &Operands) { } OperandMatchResultTy CAHPAsmParser::parseImmediate(OperandVector &Operands) { + SMLoc S = getLoc(); + SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1); + const MCExpr *Res; + switch (getLexer().getKind()) { default: return MatchOperand_NoMatch; + case AsmToken::LParen: case AsmToken::Minus: case AsmToken::Plus: case AsmToken::Integer: case AsmToken::String: + if (getParser().parseExpression(Res)) + return MatchOperand_ParseFail; break; - } - const MCExpr *IdVal; - SMLoc S = getLoc(); - if (getParser().parseExpression(IdVal)) - return MatchOperand_ParseFail; + case AsmToken::Identifier: { + StringRef Identifier; + if (getParser().parseIdentifier(Identifier)) + return MatchOperand_ParseFail; + MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier); + Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext()); + break; + } + } - SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1); - Operands.push_back(CAHPOperand::createImm(IdVal, S, E)); + Operands.push_back(CAHPOperand::createImm(Res, S, E)); return MatchOperand_Success; } diff --git a/llvm/lib/Target/CAHP/CAHPInstrInfo.td b/llvm/lib/Target/CAHP/CAHPInstrInfo.td index f77764daace9..65d821161e03 100644 --- a/llvm/lib/Target/CAHP/CAHPInstrInfo.td +++ b/llvm/lib/Target/CAHP/CAHPInstrInfo.td @@ -21,46 +21,55 @@ class UImmAsmOperand def uimm4 : Operand { let ParserMatchClass = UImmAsmOperand<4>; let DecoderMethod = "decodeUImmOperand<4>"; + let EncoderMethod = "getImmOpValue"; } def simm6 : Operand { let ParserMatchClass = SImmAsmOperand<6>; let DecoderMethod = "decodeSImmOperand<6>"; + let EncoderMethod = "getImmOpValue"; } def uimm6 : Operand { let ParserMatchClass = UImmAsmOperand<6>; let DecoderMethod = "decodeUImmOperand<6>"; + let EncoderMethod = "getImmOpValue"; } def simm8 : Operand { let ParserMatchClass = SImmAsmOperand<8>; let DecoderMethod = "decodeSImmOperand<8>"; + let EncoderMethod = "getImmOpValue"; } def uimm8 : Operand { let ParserMatchClass = UImmAsmOperand<8>; let DecoderMethod = "decodeUImmOperand<8>"; + let EncoderMethod = "getImmOpValue"; } def simm10 : Operand { let ParserMatchClass = SImmAsmOperand<10>; let DecoderMethod = "decodeSImmOperand<10>"; + let EncoderMethod = "getImmOpValue"; } def simm11 : Operand { let ParserMatchClass = SImmAsmOperand<11>; let DecoderMethod = "decodeSImmOperand<11>"; + let EncoderMethod = "getImmOpValue"; } def uimm7_lsb0 : Operand { let ParserMatchClass = UImmAsmOperand<7, "Lsb0">; let DecoderMethod = "decodeUImmOperand<7>"; + let EncoderMethod = "getImmOpValue"; } def simm11_lsb0 : Operand { let ParserMatchClass = SImmAsmOperand<11, "Lsb0">; let DecoderMethod = "decodeSImmOperand<11>"; + let EncoderMethod = "getImmOpValue"; } // 24-bit M-instructions. diff --git a/llvm/lib/Target/CAHP/MCTargetDesc/CAHPAsmBackend.cpp b/llvm/lib/Target/CAHP/MCTargetDesc/CAHPAsmBackend.cpp index 2bd74b9cc782..670d8f570616 100644 --- a/llvm/lib/Target/CAHP/MCTargetDesc/CAHPAsmBackend.cpp +++ b/llvm/lib/Target/CAHP/MCTargetDesc/CAHPAsmBackend.cpp @@ -2,9 +2,11 @@ // is distributed under the Apache License v2.0 with LLVM Exceptions (see // LICENSE.TXT for details). This file is licensed under the same license. +#include "MCTargetDesc/CAHPFixupKinds.h" #include "MCTargetDesc/CAHPMCTargetDesc.h" #include "llvm/MC/MCAsmBackend.h" #include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCContext.h" #include "llvm/MC/MCDirectives.h" #include "llvm/MC/MCELFObjectWriter.h" #include "llvm/MC/MCExpr.h" @@ -39,7 +41,37 @@ class CAHPAsmBackend : public MCAsmBackend { return false; } - unsigned getNumFixupKinds() const override { return 1; } + unsigned getNumFixupKinds() const override { + return CAHP::NumTargetFixupKinds; + } + + const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override { + if (Kind < FirstTargetFixupKind) + return MCAsmBackend::getFixupKindInfo(Kind); + + // MCFixupKindInfo{name, offset, bits, flag} + switch ((unsigned)Kind) { + case CAHP::fixup_cahp_hi6: + llvm_unreachable("Not yet implemented (fixup_cahp_hi6)"); + case CAHP::fixup_cahp_lo10: + llvm_unreachable("Not yet implemented (fixup_cahp_lo10)"); + + case CAHP::fixup_cahp_pcrel_10: { + const static MCFixupKindInfo info{"fixup_cahp_pcrel_10", 0, 24, + MCFixupKindInfo::FKF_IsPCRel}; + return info; + } + + case CAHP::fixup_cahp_pcrel_11: { + const static MCFixupKindInfo info{"fixup_cahp_pcrel_11", 5, 11, + MCFixupKindInfo::FKF_IsPCRel}; + return info; + } + + default: + llvm_unreachable("Invalid kind!"); + } + } bool mayNeedRelaxation(const MCInst &Inst, const MCSubtargetInfo &STI) const override { @@ -66,11 +98,71 @@ bool CAHPAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count) const { return true; } +static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value, + MCContext &Ctx) { + unsigned Kind = Fixup.getKind(); + switch (Kind) { + default: + llvm_unreachable("Unknown fixup kind!"); + + case FK_Data_1: + case FK_Data_2: + case FK_Data_4: + case FK_Data_8: + return Value; + + /* + // TODO: need rearranging of bits + case CAHP::fixup_cahp_hi6: + // Add 1 if bit 9 is 1, to compensate for low 10 bits being negative. + return ((Value + 0x200) >> 10) & 0x3f; + + case CAHP::fixup_cahp_lo10: + return Value & 0x3ff; + */ + + case CAHP::fixup_cahp_pcrel_10: + if (!isInt<10>(Value)) + Ctx.reportError(Fixup.getLoc(), + "fixup value out of range (fixup_cahp_pcrel_10)"); + // Need to produce (imm[7:0] << 16)|(imm[9:8] << 6) from the 10-bit Value. + return ((Value & 0xff) << 16) | (((Value >> 8) & 0x3) << 6); + + case CAHP::fixup_cahp_pcrel_11: + if (!isInt<11>(Value)) + Ctx.reportError(Fixup.getLoc(), + "fixup value out of range (fixup_cahp_pcrel_11)"); + return Value; + } +} + void CAHPAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, const MCValue &Target, MutableArrayRef Data, uint64_t Value, bool IsResolved, const MCSubtargetInfo *STI) const { + if (!Value) + return; // Doesn't change encoding. + + MCContext &Ctx = Asm.getContext(); + MCFixupKindInfo Info = getFixupKindInfo(Fixup.getKind()); + // Apply any target-specific value adjustments. + Value = adjustFixupValue(Fixup, Value, Ctx); + + // Shift the value into position. + Value <<= Info.TargetOffset; + + unsigned Offset = Fixup.getOffset(); + unsigned NumBytes = alignTo(Info.TargetSize + Info.TargetOffset, 8) / 8; + + assert(Offset + NumBytes <= Data.size() && "Invalid fixup offset!"); + + // For each byte of the fragment that the fixup touches, mask in the + // bits from the fixup value. + for (unsigned i = 0; i != NumBytes; ++i) { + Data[Offset + i] |= static_cast((Value >> (i * 8)) & 0xff); + } + return; } diff --git a/llvm/lib/Target/CAHP/MCTargetDesc/CAHPFixupKinds.h b/llvm/lib/Target/CAHP/MCTargetDesc/CAHPFixupKinds.h new file mode 100644 index 000000000000..061ff71ab394 --- /dev/null +++ b/llvm/lib/Target/CAHP/MCTargetDesc/CAHPFixupKinds.h @@ -0,0 +1,32 @@ +// This file is copied and modified from The LLVM Compiler Infrastructure, which +// is distributed under the Apache License v2.0 with LLVM Exceptions (see +// LICENSE.TXT for details). This file is licensed under the same license. + +#ifndef LLVM_LIB_TARGET_CAHP_MCTARGETDESC_CAHPFIXUPKINDS_H +#define LLVM_LIB_TARGET_CAHP_MCTARGETDESC_CAHPFIXUPKINDS_H + +#include "llvm/MC/MCFixup.h" + +#undef CAHP + +namespace llvm { +namespace CAHP { +enum Fixups { + // Fixups for hi/lo + fixup_cahp_hi6 = FirstTargetFixupKind, + fixup_cahp_lo10, + + // 10-bit pc relative. e.g. bcc + fixup_cahp_pcrel_10, + + // 11-bit pc relative. e.g. js, jsal + fixup_cahp_pcrel_11, + + // fixup_rv16k_invalid - used as a sentinel and a marker, must be last fixup + fixup_cahp_invalid, + NumTargetFixupKinds = fixup_cahp_invalid - FirstTargetFixupKind +}; +} // end namespace CAHP +} // end namespace llvm + +#endif diff --git a/llvm/lib/Target/CAHP/MCTargetDesc/CAHPMCCodeEmitter.cpp b/llvm/lib/Target/CAHP/MCTargetDesc/CAHPMCCodeEmitter.cpp index ea3e5d49acdf..39f48a51178b 100644 --- a/llvm/lib/Target/CAHP/MCTargetDesc/CAHPMCCodeEmitter.cpp +++ b/llvm/lib/Target/CAHP/MCTargetDesc/CAHPMCCodeEmitter.cpp @@ -2,6 +2,7 @@ // is distributed under the Apache License v2.0 with LLVM Exceptions (see // LICENSE.TXT for details). This file is licensed under the same license. +#include "MCTargetDesc/CAHPFixupKinds.h" #include "MCTargetDesc/CAHPMCTargetDesc.h" #include "llvm/ADT/Statistic.h" #include "llvm/MC/MCAsmInfo.h" @@ -13,6 +14,7 @@ #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCSymbol.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/EndianStream.h" #include "llvm/Support/raw_ostream.h" @@ -21,6 +23,7 @@ using namespace llvm; #define DEBUG_TYPE "mccodeemitter" STATISTIC(MCNumEmitted, "Number of MC instructions emitted"); +STATISTIC(MCNumFixups, "Number of MC fixups created"); namespace { class CAHPMCCodeEmitter : public MCCodeEmitter { @@ -50,6 +53,10 @@ class CAHPMCCodeEmitter : public MCCodeEmitter { unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; + + unsigned getImmOpValue(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; }; } // end anonymous namespace @@ -100,4 +107,49 @@ CAHPMCCodeEmitter::getMachineOpValue(const MCInst &MI, const MCOperand &MO, return 0; } +unsigned CAHPMCCodeEmitter::getImmOpValue(const MCInst &MI, unsigned OpNo, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + const MCOperand &MO = MI.getOperand(OpNo); + + if (MO.isImm()) + return MO.getImm(); + + assert(MO.isExpr() && "getImmOpValue expects only expressions or immediates"); + + const MCExpr *Expr = MO.getExpr(); + MCExpr::ExprKind Kind = Expr->getKind(); + MCFixupKind FixupKind = static_cast(CAHP::fixup_cahp_invalid); + unsigned Offset = 0; + + if (Kind == MCExpr::SymbolRef && + cast(Expr)->getKind() == MCSymbolRefExpr::VK_None) { + switch (MI.getOpcode()) { + case CAHP::JS: + case CAHP::JSAL: + FixupKind = static_cast(CAHP::fixup_cahp_pcrel_11); + break; + + case CAHP::BEQ: + case CAHP::BNE: + case CAHP::BLT: + case CAHP::BLTU: + case CAHP::BLE: + case CAHP::BLEU: + FixupKind = static_cast(CAHP::fixup_cahp_pcrel_10); + break; + + // TODO: li and other instructions using %hi/%lo + } + } + + assert(FixupKind != static_cast(CAHP::fixup_cahp_invalid) && + "Unhandled expression!"); + + Fixups.push_back(MCFixup::create(Offset, Expr, FixupKind, MI.getLoc())); + ++MCNumFixups; + + return 0; +} + #include "CAHPGenMCCodeEmitter.inc" diff --git a/llvm/test/MC/CAHP/cahp-invalid.s b/llvm/test/MC/CAHP/cahp-invalid.s index d7aac9a337c1..e3ba6cf99198 100644 --- a/llvm/test/MC/CAHP/cahp-invalid.s +++ b/llvm/test/MC/CAHP/cahp-invalid.s @@ -28,9 +28,9 @@ subs x1, x2 # CHECK: :[[@LINE]]:1: error: unrecognized instruction mnemonic nandi x14, x13 # CHECK: :[[@LINE]]:1: error: unrecognized instruction mnemonic # Invalid register names -add foo, x1, x3 # CHECK: :[[@LINE]]:5: error: unknown operand -sub x0, x16, x4 # CHECK: :[[@LINE]]:9: error: unknown operand -mov t2, x8 # CHECK: :[[@LINE]]:5: error: unknown operand +add foo, x1, x3 # CHECK: :[[@LINE]]:5: error: invalid operand for instruction +sub x0, x16, x4 # CHECK: :[[@LINE]]:9: error: invalid operand for instruction +mov t2, x8 # CHECK: :[[@LINE]]:5: error: invalid operand for instruction # Invalid operand types add x15, x1, 1 # CHECK: :[[@LINE]]:14: error: invalid operand for instruction diff --git a/llvm/test/MC/CAHP/fixups.s b/llvm/test/MC/CAHP/fixups.s new file mode 100644 index 000000000000..109d9d73a918 --- /dev/null +++ b/llvm/test/MC/CAHP/fixups.s @@ -0,0 +1,55 @@ +# RUN: llvm-mc -triple cahp < %s -show-encoding \ +# RUN: | FileCheck -check-prefix=CHECK-FIXUP %s +# RUN: llvm-mc -filetype=obj -triple cahp < %s \ +# RUN: | llvm-objdump -d - | FileCheck -check-prefix=CHECK-INSTR %s + +# Checks that fixups that can be resolved within the same object file are +# applied correctly + +.LBB0: +.space 1024 +js .LBB0 +# CHECK-FIXUP: fixup A - offset: 0, value: .LBB0, kind: fixup_cahp_pcrel_11 +# CHECK-INSTR: js -1024 + +.LBB1: +.space 1024 +jsal .LBB1 +# CHECK-FIXUP: fixup A - offset: 0, value: .LBB1, kind: fixup_cahp_pcrel_11 +# CHECK-INSTR: jsal -1024 + +.LBB2: +.space 512 +beq a0, a1, .LBB2 +# CHECK-FIXUP: fixup A - offset: 0, value: .LBB2, kind: fixup_cahp_pcrel_10 +# CHECK-INSTR: beq a0, a1, -512 + +.LBB3: +.space 512 +bne a0, a1, .LBB3 +# CHECK-FIXUP: fixup A - offset: 0, value: .LBB3, kind: fixup_cahp_pcrel_10 +# CHECK-INSTR: bne a0, a1, -512 + +.LBB4: +.space 512 +blt a0, a1, .LBB4 +# CHECK-FIXUP: fixup A - offset: 0, value: .LBB4, kind: fixup_cahp_pcrel_10 +# CHECK-INSTR: blt a0, a1, -512 + +.LBB5: +.space 512 +bltu a0, a1, .LBB5 +# CHECK-FIXUP: fixup A - offset: 0, value: .LBB5, kind: fixup_cahp_pcrel_10 +# CHECK-INSTR: bltu a0, a1, -512 + +.LBB6: +.space 512 +ble a0, a1, .LBB6 +# CHECK-FIXUP: fixup A - offset: 0, value: .LBB6, kind: fixup_cahp_pcrel_10 +# CHECK-INSTR: ble a0, a1, -512 + +.LBB7: +.space 512 +bleu a0, a1, .LBB7 +# CHECK-FIXUP: fixup A - offset: 0, value: .LBB7, kind: fixup_cahp_pcrel_10 +# CHECK-INSTR: bleu a0, a1, -512 From 41a709244f6e5f3fdc21013487b4a3ffaa59b7b2 Mon Sep 17 00:00:00 2001 From: Ushitora Anqou Date: Wed, 16 Oct 2019 15:37:38 +0900 Subject: [PATCH 231/289] [CAHP] Follow changes in ISA --- .../Target/CAHP/AsmParser/CAHPAsmParser.cpp | 20 +++-- llvm/lib/Target/CAHP/CAHPInstrFormats.td | 15 +++- llvm/lib/Target/CAHP/CAHPInstrInfo.td | 78 +++++-------------- llvm/test/MC/CAHP/cahp-invalid.s | 12 +-- llvm/test/MC/CAHP/cahp-valid.s | 32 ++++---- 5 files changed, 63 insertions(+), 94 deletions(-) diff --git a/llvm/lib/Target/CAHP/AsmParser/CAHPAsmParser.cpp b/llvm/lib/Target/CAHP/AsmParser/CAHPAsmParser.cpp index 0721811dbf8a..e2de6b893f69 100644 --- a/llvm/lib/Target/CAHP/AsmParser/CAHPAsmParser.cpp +++ b/llvm/lib/Target/CAHP/AsmParser/CAHPAsmParser.cpp @@ -136,14 +136,6 @@ struct CAHPOperand : public MCParsedAsmOperand { return (isConstantImm() && isUInt<6>(getConstantImm())); } - bool isSImm8() const { - return (isConstantImm() && isInt<8>(getConstantImm())); - } - - bool isUImm8() const { - return (isConstantImm() && isUInt<8>(getConstantImm())); - } - bool isSImm10() const { if (!isImm()) return false; @@ -152,6 +144,14 @@ struct CAHPOperand : public MCParsedAsmOperand { return isa(getImm()); } + bool isUImm10() const { + if (!isImm()) + return false; + if (isConstantImm()) + return isUInt<10>(getConstantImm()); + return isa(getImm()); + } + bool isSImm11() const { if (!isImm()) return false; @@ -321,12 +321,10 @@ bool CAHPAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, CASE_MATCH_INVALID_UIMM(4); CASE_MATCH_INVALID_SIMM(6); CASE_MATCH_INVALID_UIMM(6); - CASE_MATCH_INVALID_SIMM(8); - CASE_MATCH_INVALID_UIMM(8); CASE_MATCH_INVALID_SIMM(10); + CASE_MATCH_INVALID_UIMM(10); CASE_MATCH_INVALID_SIMM(11); CASE_MATCH_INVALID_UIMM_LSB0(7); - CASE_MATCH_INVALID_SIMM_LSB0(11); } llvm_unreachable("Unknown match type detected!"); diff --git a/llvm/lib/Target/CAHP/CAHPInstrFormats.td b/llvm/lib/Target/CAHP/CAHPInstrFormats.td index 59de5ded4110..97af073d257b 100644 --- a/llvm/lib/Target/CAHP/CAHPInstrFormats.td +++ b/llvm/lib/Target/CAHP/CAHPInstrFormats.td @@ -57,9 +57,12 @@ class CAHPInst24MLoad opcode, dag outs, dag ins, string opcodestr, strin : CAHPInst24 { bits<4> rd; bits<4> rs; + bits<10> imm; + let Inst{23-16} = imm{7-0}; let Inst{15-12} = rs; let Inst{11-8} = rd; + let Inst{7-6} = imm{9-8}; let Inst{5-0} = opcode; } @@ -67,9 +70,12 @@ class CAHPInst24MStore opcode, dag outs, dag ins, string opcodestr, stri : CAHPInst24 { bits<4> rs; bits<4> rd; + bits<10> imm; + let Inst{23-16} = imm{7-0}; let Inst{15-12} = rd; let Inst{11-8} = rs; + let Inst{7-6} = imm{9-8}; let Inst{5-0} = opcode; } @@ -88,16 +94,17 @@ class CAHPInst24R opcode, dag outs, dag ins, string opcodestr, string ar } // 24-bit I-instruction format. -class CAHPInst24I opcode, dag outs, dag ins, string opcodestr, string argstr> +class CAHPInst24I opcode, dag outs, dag ins, string opcodestr, string argstr> : CAHPInst24 { bits<4> rd; bits<4> rs1; - bits<8> imm; + bits<10> imm; - let Inst{23-16} = imm; + let Inst{23-16} = imm{7-0}; let Inst{15-12} = rs1; let Inst{11-8} = rd; - let Inst{7-0} = opcode; + let Inst{7-6} = imm{9-8}; + let Inst{5-0} = opcode; } // 24-bit J-instruction format. diff --git a/llvm/lib/Target/CAHP/CAHPInstrInfo.td b/llvm/lib/Target/CAHP/CAHPInstrInfo.td index 65d821161e03..3f318f5cf43e 100644 --- a/llvm/lib/Target/CAHP/CAHPInstrInfo.td +++ b/llvm/lib/Target/CAHP/CAHPInstrInfo.td @@ -36,24 +36,18 @@ def uimm6 : Operand { let EncoderMethod = "getImmOpValue"; } -def simm8 : Operand { - let ParserMatchClass = SImmAsmOperand<8>; - let DecoderMethod = "decodeSImmOperand<8>"; - let EncoderMethod = "getImmOpValue"; -} - -def uimm8 : Operand { - let ParserMatchClass = UImmAsmOperand<8>; - let DecoderMethod = "decodeUImmOperand<8>"; - let EncoderMethod = "getImmOpValue"; -} - def simm10 : Operand { let ParserMatchClass = SImmAsmOperand<10>; let DecoderMethod = "decodeSImmOperand<10>"; let EncoderMethod = "getImmOpValue"; } +def uimm10 : Operand { + let ParserMatchClass = UImmAsmOperand<10>; + let DecoderMethod = "decodeUImmOperand<10>"; + let EncoderMethod = "getImmOpValue"; +} + def simm11 : Operand { let ParserMatchClass = SImmAsmOperand<11>; let DecoderMethod = "decodeSImmOperand<11>"; @@ -66,57 +60,27 @@ def uimm7_lsb0 : Operand { let EncoderMethod = "getImmOpValue"; } -def simm11_lsb0 : Operand { - let ParserMatchClass = SImmAsmOperand<11, "Lsb0">; - let DecoderMethod = "decodeSImmOperand<11>"; - let EncoderMethod = "getImmOpValue"; -} - // 24-bit M-instructions. let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in { - def LW : CAHPInst24MLoad <0b010101, (outs GPR:$rd), (ins GPR:$rs, simm11_lsb0:$imm), - "lw", "$rd, ${imm}(${rs})"> { - bits<11> imm; - let Inst{23-16} = imm{8-1}; - let Inst{7-6} = imm{10-9}; - } + def LW : CAHPInst24MLoad <0b010101, (outs GPR:$rd), (ins GPR:$rs, simm10:$imm), + "lw", "$rd, ${imm}(${rs})">; def LB : CAHPInst24MLoad <0b100101, (outs GPR:$rd), (ins GPR:$rs, simm10:$imm), - "lb", "$rd, ${imm}(${rs})"> { - bits<10> imm; - let Inst{23-16} = imm{7-0}; - let Inst{7-6} = imm{9-8}; - } + "lb", "$rd, ${imm}(${rs})">; def LBU : CAHPInst24MLoad <0b000101, (outs GPR:$rd), (ins GPR:$rs, simm10:$imm), - "lbu", "$rd, ${imm}(${rs})"> { - bits<10> imm; - let Inst{23-16} = imm{7-0}; - let Inst{7-6} = imm{9-8}; - } + "lbu", "$rd, ${imm}(${rs})">; } let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in { - def SW : CAHPInst24MStore<0b011101, (outs GPR:$rd), (ins GPR:$rs, simm11_lsb0:$imm), - "sw", "$rs, ${imm}(${rd})"> { - bits<11> imm; - let Inst{23-16} = imm{8-1}; - let Inst{7-6} = imm{10-9}; - } + def SW : CAHPInst24MStore<0b011101, (outs GPR:$rd), (ins GPR:$rs, simm10:$imm), + "sw", "$rs, ${imm}(${rd})">; def SB : CAHPInst24MStore<0b001101, (outs GPR:$rd), (ins GPR:$rs, simm10:$imm), - "sb", "$rs, ${imm}(${rd})"> { - bits<10> imm; - let Inst{23-16} = imm{7-0}; - let Inst{7-6} = imm{9-8}; - } + "sb", "$rs, ${imm}(${rd})">; } let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isMoveImm = 1 in def LI : CAHPInst24MLoad <0b110101, (outs GPR:$rd), (ins simm10:$imm), - "li", "$rd, $imm"> { - bits<10> imm; - let Inst{23-16} = imm{7-0}; - let Inst{7-6} = imm{9-8}; -} + "li", "$rd, $imm">; // 24-bit R-instructions. @@ -145,19 +109,19 @@ let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in { // 24-bit I-instructions. let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in { - def ADDI : CAHPInst24I<0b11000011, (outs GPR:$rd), (ins GPR:$rs1, simm8:$imm), + def ADDI : CAHPInst24I<0b000011, (outs GPR:$rd), (ins GPR:$rs1, simm10:$imm), "addi", "$rd, $rs1, $imm">; - def ANDI : CAHPInst24I<0b01010011, (outs GPR:$rd), (ins GPR:$rs1, uimm8:$imm), + def ANDI : CAHPInst24I<0b010011, (outs GPR:$rd), (ins GPR:$rs1, uimm10:$imm), "andi", "$rd, $rs1, $imm">; - def XORI : CAHPInst24I<0b01011011, (outs GPR:$rd), (ins GPR:$rs1, uimm8:$imm), + def XORI : CAHPInst24I<0b011011, (outs GPR:$rd), (ins GPR:$rs1, uimm10:$imm), "xori", "$rd, $rs1, $imm">; - def ORI : CAHPInst24I<0b01100011, (outs GPR:$rd), (ins GPR:$rs1, uimm8:$imm), + def ORI : CAHPInst24I<0b100011, (outs GPR:$rd), (ins GPR:$rs1, uimm10:$imm), "ori", "$rd, $rs1, $imm">; - def LSLI : CAHPInst24I<0b00101011, (outs GPR:$rd), (ins GPR:$rs1, uimm4:$imm), + def LSLI : CAHPInst24I<0b101011, (outs GPR:$rd), (ins GPR:$rs1, uimm4:$imm), "lsli", "$rd, $rs1, $imm">; - def LSRI : CAHPInst24I<0b00110011, (outs GPR:$rd), (ins GPR:$rs1, uimm4:$imm), + def LSRI : CAHPInst24I<0b110011, (outs GPR:$rd), (ins GPR:$rs1, uimm4:$imm), "lsri", "$rd, $rs1, $imm">; - def ASRI : CAHPInst24I<0b00111011, (outs GPR:$rd), (ins GPR:$rs1, uimm4:$imm), + def ASRI : CAHPInst24I<0b111011, (outs GPR:$rd), (ins GPR:$rs1, uimm4:$imm), "asri", "$rd, $rs1, $imm">; } diff --git a/llvm/test/MC/CAHP/cahp-invalid.s b/llvm/test/MC/CAHP/cahp-invalid.s index e3ba6cf99198..3982ba2a5dbc 100644 --- a/llvm/test/MC/CAHP/cahp-invalid.s +++ b/llvm/test/MC/CAHP/cahp-invalid.s @@ -1,17 +1,17 @@ # RUN: not llvm-mc -triple cahp < %s 2>&1 | FileCheck %s # Out of range immediates -lw a4, 1024(a2) # CHECK: :[[@LINE]]:8: error: immediate must be a multiple of 2 bytes in the range [-1024, 1022] +lw a4, 512(a2) # CHECK: :[[@LINE]]:8: error: immediate must be an integer in the range [-512, 511] lb a4, -513(a2) # CHECK: :[[@LINE]]:8: error: immediate must be an integer in the range [-512, 511] lbu a4, -513(a2) # CHECK: :[[@LINE]]:9: error: immediate must be an integer in the range [-512, 511] -sw a4, -1025(a2) # CHECK: :[[@LINE]]:8: error: immediate must be a multiple of 2 bytes in the range [-1024, 1022] +sw a4, -513(a2) # CHECK: :[[@LINE]]:8: error: immediate must be an integer in the range [-512, 511] sb a4, 512(a2) # CHECK: :[[@LINE]]:8: error: immediate must be an integer in the range [-512, 511] li t0, -513 # CHECK: :[[@LINE]]:8: error: immediate must be an integer in the range [-512, 511] li s0, 512 # CHECK: :[[@LINE]]:8: error: immediate must be an integer in the range [-512, 511] -addi a0, a1, 128 # CHECK: :[[@LINE]]:14: error: immediate must be an integer in the range [-128, 127] -addi a0, a1, -129 # CHECK: :[[@LINE]]:14: error: immediate must be an integer in the range [-128, 127] -andi a0, a1, 256 # CHECK: :[[@LINE]]:14: error: immediate must be an integer in the range [0, 255] -andi a0, a1, -1 # CHECK: :[[@LINE]]:14: error: immediate must be an integer in the range [0, 255] +addi a0, a1, 512 # CHECK: :[[@LINE]]:14: error: immediate must be an integer in the range [-512, 511] +addi a0, a1, -513 # CHECK: :[[@LINE]]:14: error: immediate must be an integer in the range [-512, 511] +andi a0, a1, 1024 # CHECK: :[[@LINE]]:14: error: immediate must be an integer in the range [0, 1023] +xori a0, a1, -1 # CHECK: :[[@LINE]]:14: error: immediate must be an integer in the range [0, 1023] lsli a0, a1, 16 # CHECK: :[[@LINE]]:14: error: immediate must be an integer in the range [0, 15] asri a0, a1, -1 # CHECK: :[[@LINE]]:14: error: immediate must be an integer in the range [0, 15] lwsp a4, 128(sp) # CHECK: :[[@LINE]]:10: error: immediate must be a multiple of 2 bytes in the range [0, 126] diff --git a/llvm/test/MC/CAHP/cahp-valid.s b/llvm/test/MC/CAHP/cahp-valid.s index 355fef508689..6834428a5687 100644 --- a/llvm/test/MC/CAHP/cahp-valid.s +++ b/llvm/test/MC/CAHP/cahp-valid.s @@ -3,18 +3,18 @@ # RUN: llvm-mc -filetype=obj -triple=cahp < %s \ # RUN: | llvm-objdump -d - | FileCheck -check-prefix=CHECK-INST %s -# CHECK-INST: lw ra, -1000(sp) +# CHECK-INST: lw ra, -500(sp) # CHECK: encoding: [0x95,0x10,0x0c] -lw ra, -1000(sp) +lw ra, -500(sp) # CHECK-INST: lb ra, -500(sp) # CHECK: encoding: [0xa5,0x10,0x0c] lb ra, -500(sp) # CHECK-INST: lbu ra, -500(sp) # CHECK: encoding: [0x85,0x10,0x0c] lbu ra, -500(sp) -# CHECK-INST: sw ra, -1000(sp) +# CHECK-INST: sw ra, -500(sp) # CHECK: encoding: [0x9d,0x10,0x0c] -sw ra, -1000(sp) +sw ra, -500(sp) # CHECK-INST: sb ra, -500(sp) # CHECK: encoding: [0x8d,0x10,0x0c] sb ra, -500(sp) @@ -45,21 +45,21 @@ lsr ra, sp, fp # CHECK-INST: asr ra, sp, fp # CHECK: encoding: [0x39,0x10,0x02] asr ra, sp, fp +# CHECK-INST: addi ra, sp, 10 +# CHECK: encoding: [0x03,0x10,0x0a] +addi ra, sp, 10 # CHECK-INST: addi ra, sp, -10 # CHECK: encoding: [0xc3,0x10,0xf6] addi ra, sp, -10 -# CHECK-INST: addi ra, sp, 10 -# CHECK: encoding: [0xc3,0x10,0x0a] -addi ra, sp, 10 -# CHECK-INST: andi ra, sp, 10 -# CHECK: encoding: [0x53,0x10,0x0a] -andi ra, sp, 10 -# CHECK-INST: xori ra, sp, 10 -# CHECK: encoding: [0x5b,0x10,0x0a] -xori ra, sp, 10 -# CHECK-INST: ori ra, sp, 10 -# CHECK: encoding: [0x63,0x10,0x0a] -ori ra, sp, 10 +# CHECK-INST: andi ra, sp, 778 +# CHECK: encoding: [0xd3,0x10,0x0a] +andi ra, sp, 778 +# CHECK-INST: xori ra, sp, 778 +# CHECK: encoding: [0xdb,0x10,0x0a] +xori ra, sp, 778 +# CHECK-INST: ori ra, sp, 778 +# CHECK: encoding: [0xe3,0x10,0x0a] +ori ra, sp, 778 # CHECK-INST: lsli ra, sp, 3 # CHECK: encoding: [0x2b,0x10,0x03] lsli ra, sp, 3 From 7199c151e0dcd8688a5d2c671c9bd774818d6330 Mon Sep 17 00:00:00 2001 From: Ushitora Anqou Date: Sun, 20 Oct 2019 22:37:11 +0900 Subject: [PATCH 232/289] [CAHP] Add support for %hi/%lo --- .../Target/CAHP/AsmParser/CAHPAsmParser.cpp | 213 +++++++++++++++--- llvm/lib/Target/CAHP/CAHPInstrInfo.td | 4 +- .../CAHP/MCTargetDesc/CAHPAsmBackend.cpp | 24 +- .../CAHP/MCTargetDesc/CAHPELFObjectWriter.cpp | 1 + .../CAHP/MCTargetDesc/CAHPMCCodeEmitter.cpp | 36 ++- .../Target/CAHP/MCTargetDesc/CAHPMCExpr.cpp | 83 +++++++ .../lib/Target/CAHP/MCTargetDesc/CAHPMCExpr.h | 59 +++++ .../Target/CAHP/MCTargetDesc/CMakeLists.txt | 1 + llvm/test/MC/CAHP/cahp-invalid.s | 7 + llvm/test/MC/CAHP/cahp-valid.s | 9 + llvm/test/MC/CAHP/fixups.s | 12 + llvm/test/MC/CAHP/hilo-constaddr.s | 39 ++++ 12 files changed, 438 insertions(+), 50 deletions(-) create mode 100644 llvm/lib/Target/CAHP/MCTargetDesc/CAHPMCExpr.cpp create mode 100644 llvm/lib/Target/CAHP/MCTargetDesc/CAHPMCExpr.h create mode 100644 llvm/test/MC/CAHP/hilo-constaddr.s diff --git a/llvm/lib/Target/CAHP/AsmParser/CAHPAsmParser.cpp b/llvm/lib/Target/CAHP/AsmParser/CAHPAsmParser.cpp index e2de6b893f69..22c58e3943a4 100644 --- a/llvm/lib/Target/CAHP/AsmParser/CAHPAsmParser.cpp +++ b/llvm/lib/Target/CAHP/AsmParser/CAHPAsmParser.cpp @@ -2,6 +2,7 @@ // is distributed under the Apache License v2.0 with LLVM Exceptions (see // LICENSE.TXT for details). This file is licensed under the same license. +#include "MCTargetDesc/CAHPMCExpr.h" #include "MCTargetDesc/CAHPMCTargetDesc.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringSwitch.h" @@ -47,6 +48,7 @@ class CAHPAsmParser : public MCTargetAsmParser { OperandMatchResultTy parseImmediate(OperandVector &Operands); OperandMatchResultTy parseRegister(OperandVector &Operands); OperandMatchResultTy parseMemOpBaseReg(OperandVector &Operands); + OperandMatchResultTy parseOperandWithModifier(OperandVector &Operands); bool parseOperand(OperandVector &Operands); @@ -58,6 +60,9 @@ class CAHPAsmParser : public MCTargetAsmParser { #undef GET_OPERAND_DIAGNOSTIC_TYPES }; + static bool classifySymbolRef(const MCExpr *Expr, + CAHPMCExpr::VariantKind &Kind, int64_t &Addend); + CAHPAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser, const MCInstrInfo &MII, const MCTargetOptions &Options) : MCTargetAsmParser(Options, STI, MII) { @@ -115,8 +120,37 @@ struct CAHPOperand : public MCParsedAsmOperand { bool isImm() const override { return Kind == Immediate; } bool isMem() const override { return false; } - bool isConstantImm() const { - return isImm() && dyn_cast(getImm()); + bool evaluateConstantImm(int64_t &Imm, CAHPMCExpr::VariantKind &VK) const { + const MCExpr *Val = getImm(); + bool Ret = false; + if (auto *RE = dyn_cast(Val)) { + Ret = RE->evaluateAsConstant(Imm); + VK = RE->getKind(); + } else if (auto CE = dyn_cast(Val)) { + Ret = true; + VK = CAHPMCExpr::VK_CAHP_None; + Imm = CE->getValue(); + } + return Ret; + } + + // True if operand is a symbol with no modifiers, or a constant with no + // modifiers and pred(Op) is true. + template bool isBareImm(Pred pred) const { + if (!isImm()) + return false; + + CAHPMCExpr::VariantKind VK; + int64_t Imm; + bool IsValid; + + bool IsConstantImm = evaluateConstantImm(Imm, VK); + if (IsConstantImm) + IsValid = pred(Imm); + else + IsValid = CAHPAsmParser::classifySymbolRef(getImm(), VK, Imm); + + return IsValid && VK == CAHPMCExpr::VK_CAHP_None; } int64_t getConstantImm() const { @@ -124,50 +158,70 @@ struct CAHPOperand : public MCParsedAsmOperand { return static_cast(Val)->getValue(); } - bool isUImm4() const { - return (isConstantImm() && isUInt<4>(getConstantImm())); - } + bool isUImm4() const { return isBareImm(isUInt<4>); } - bool isSImm6() const { - return (isConstantImm() && isInt<6>(getConstantImm())); - } + bool isSImm6() const { return isBareImm(isInt<6>); } bool isUImm6() const { - return (isConstantImm() && isUInt<6>(getConstantImm())); + if (!isImm()) + return false; + + CAHPMCExpr::VariantKind VK; + int64_t Imm; + bool IsValid; + + bool IsConstantImm = evaluateConstantImm(Imm, VK); + if (IsConstantImm) + IsValid = isUInt<6>(Imm); + else + IsValid = CAHPAsmParser::classifySymbolRef(getImm(), VK, Imm); + + return IsValid && + (VK == CAHPMCExpr::VK_CAHP_None || VK == CAHPMCExpr::VK_CAHP_HI); } bool isSImm10() const { if (!isImm()) return false; - if (isConstantImm()) - return isInt<10>(getConstantImm()); - return isa(getImm()); + + CAHPMCExpr::VariantKind VK; + int64_t Imm; + bool IsValid; + + bool IsConstantImm = evaluateConstantImm(Imm, VK); + if (IsConstantImm) + IsValid = isInt<10>(Imm); + else + IsValid = CAHPAsmParser::classifySymbolRef(getImm(), VK, Imm); + + return IsValid && + (VK == CAHPMCExpr::VK_CAHP_None || VK == CAHPMCExpr::VK_CAHP_LO); } bool isUImm10() const { if (!isImm()) return false; - if (isConstantImm()) - return isUInt<10>(getConstantImm()); - return isa(getImm()); - } - bool isSImm11() const { - if (!isImm()) - return false; - if (isConstantImm()) - return isInt<11>(getConstantImm()); - return isa(getImm()); - } + CAHPMCExpr::VariantKind VK; + int64_t Imm; + bool IsValid; - bool isUImm7Lsb0() const { - return (isConstantImm() && isShiftedUInt<6, 1>(getConstantImm())); - } + bool IsConstantImm = evaluateConstantImm(Imm, VK); + if (IsConstantImm) + IsValid = isUInt<10>(Imm); + else + IsValid = CAHPAsmParser::classifySymbolRef(getImm(), VK, Imm); - bool isSImm11Lsb0() const { - return (isConstantImm() && isShiftedInt<10, 1>(getConstantImm())); + return IsValid && + (VK == CAHPMCExpr::VK_CAHP_None || VK == CAHPMCExpr::VK_CAHP_LO); } + bool isSImm11() const { return isBareImm(isInt<11>); } + + bool isUImm7Lsb0() const { return isBareImm(&isShiftedUInt<6, 1>); } + + bool isSImm11Lsb0() const { return isBareImm(isShiftedInt<10, 1>); } + /// getStartLoc - Gets location of the first token of this operand SMLoc getStartLoc() const override { return StartLoc; } /// getEndLoc - Gets location of the last token of this operand @@ -231,8 +285,18 @@ struct CAHPOperand : public MCParsedAsmOperand { void addExpr(MCInst &Inst, const MCExpr *Expr) const { assert(Expr && "Expr shouldn't be null!"); - if (auto *CE = dyn_cast(Expr)) - Inst.addOperand(MCOperand::createImm(CE->getValue())); + + int64_t Imm = 0; + bool IsConstant = false; + if (auto *RE = dyn_cast(Expr)) { + IsConstant = RE->evaluateAsConstant(Imm); + } else if (auto *CE = dyn_cast(Expr)) { + IsConstant = true; + Imm = CE->getValue(); + } + + if (IsConstant) + Inst.addOperand(MCOperand::createImm(Imm)); else Inst.addOperand(MCOperand::createExpr(Expr)); } @@ -393,12 +457,56 @@ OperandMatchResultTy CAHPAsmParser::parseImmediate(OperandVector &Operands) { Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext()); break; } + + case AsmToken::Percent: { + return parseOperandWithModifier(Operands); + } } Operands.push_back(CAHPOperand::createImm(Res, S, E)); return MatchOperand_Success; } +OperandMatchResultTy +CAHPAsmParser::parseOperandWithModifier(OperandVector &Operands) { + SMLoc S = getLoc(); + SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1); + + if (getLexer().getKind() != AsmToken::Percent) { + Error(getLoc(), "expected '%' for operand modifier"); + return MatchOperand_ParseFail; + } + + getParser().Lex(); // Eat '%' + + if (getLexer().getKind() != AsmToken::Identifier) { + Error(getLoc(), "expected valid identifier for operand modifier"); + return MatchOperand_ParseFail; + } + StringRef Identifier = getParser().getTok().getIdentifier(); + CAHPMCExpr::VariantKind VK = CAHPMCExpr::getVariantKindForName(Identifier); + if (VK == CAHPMCExpr::VK_CAHP_Invalid) { + Error(getLoc(), "unrecognized operand modifier"); + return MatchOperand_ParseFail; + } + + getParser().Lex(); // Eat the identifier + if (getLexer().getKind() != AsmToken::LParen) { + Error(getLoc(), "expected '('"); + return MatchOperand_ParseFail; + } + getParser().Lex(); // Eat '(' + + const MCExpr *SubExpr; + if (getParser().parseParenExpression(SubExpr, E)) { + return MatchOperand_ParseFail; + } + + const MCExpr *ModExpr = CAHPMCExpr::create(SubExpr, VK, getContext()); + Operands.push_back(CAHPOperand::createImm(ModExpr, S, E)); + return MatchOperand_Success; +} + OperandMatchResultTy CAHPAsmParser::parseMemOpBaseReg(OperandVector &Operands) { if (getLexer().isNot(AsmToken::LParen)) { Error(getLoc(), "expected '('"); @@ -478,6 +586,51 @@ bool CAHPAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, return false; } +bool CAHPAsmParser::classifySymbolRef(const MCExpr *Expr, + CAHPMCExpr::VariantKind &Kind, + int64_t &Addend) { + Kind = CAHPMCExpr::VK_CAHP_None; + Addend = 0; + + if (const CAHPMCExpr *RE = dyn_cast(Expr)) { + Kind = RE->getKind(); + Expr = RE->getSubExpr(); + } + + // It's a simple symbol reference or constant with no addend. + if (isa(Expr) || isa(Expr)) + return true; + + const MCBinaryExpr *BE = dyn_cast(Expr); + if (!BE) + return false; + + if (!isa(BE->getLHS())) + return false; + + if (BE->getOpcode() != MCBinaryExpr::Add && + BE->getOpcode() != MCBinaryExpr::Sub) + return false; + + // We are able to support the subtraction of two symbol references + if (BE->getOpcode() == MCBinaryExpr::Sub && + isa(BE->getRHS())) + return true; + + // See if the addend is is a constant, otherwise there's more going + // on here than we can deal with. + auto AddendExpr = dyn_cast(BE->getRHS()); + if (!AddendExpr) + return false; + + Addend = AddendExpr->getValue(); + if (BE->getOpcode() == MCBinaryExpr::Sub) + Addend = -Addend; + + // It's some symbol reference + a constant addend + return Kind != CAHPMCExpr::VK_CAHP_Invalid; +} + bool CAHPAsmParser::ParseDirective(AsmToken DirectiveID) { return true; } extern "C" void LLVMInitializeCAHPAsmParser() { diff --git a/llvm/lib/Target/CAHP/CAHPInstrInfo.td b/llvm/lib/Target/CAHP/CAHPInstrInfo.td index 3f318f5cf43e..db86c52d8de4 100644 --- a/llvm/lib/Target/CAHP/CAHPInstrInfo.td +++ b/llvm/lib/Target/CAHP/CAHPInstrInfo.td @@ -80,7 +80,9 @@ let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in { let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isMoveImm = 1 in def LI : CAHPInst24MLoad <0b110101, (outs GPR:$rd), (ins simm10:$imm), - "li", "$rd, $imm">; + "li", "$rd, $imm"> { + let rs = 0; +} // 24-bit R-instructions. diff --git a/llvm/lib/Target/CAHP/MCTargetDesc/CAHPAsmBackend.cpp b/llvm/lib/Target/CAHP/MCTargetDesc/CAHPAsmBackend.cpp index 670d8f570616..fd697cee7c9b 100644 --- a/llvm/lib/Target/CAHP/MCTargetDesc/CAHPAsmBackend.cpp +++ b/llvm/lib/Target/CAHP/MCTargetDesc/CAHPAsmBackend.cpp @@ -51,10 +51,15 @@ class CAHPAsmBackend : public MCAsmBackend { // MCFixupKindInfo{name, offset, bits, flag} switch ((unsigned)Kind) { - case CAHP::fixup_cahp_hi6: - llvm_unreachable("Not yet implemented (fixup_cahp_hi6)"); - case CAHP::fixup_cahp_lo10: - llvm_unreachable("Not yet implemented (fixup_cahp_lo10)"); + case CAHP::fixup_cahp_hi6: { + const static MCFixupKindInfo info{"fixup_cahp_hi6", 0, 16, 0}; + return info; + } + + case CAHP::fixup_cahp_lo10: { + const static MCFixupKindInfo info{"fixup_cahp_lo10", 0, 24, 0}; + return info; + } case CAHP::fixup_cahp_pcrel_10: { const static MCFixupKindInfo info{"fixup_cahp_pcrel_10", 0, 24, @@ -111,15 +116,16 @@ static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value, case FK_Data_8: return Value; - /* - // TODO: need rearranging of bits case CAHP::fixup_cahp_hi6: // Add 1 if bit 9 is 1, to compensate for low 10 bits being negative. - return ((Value + 0x200) >> 10) & 0x3f; + Value = ((Value + 0x200) >> 10) & 0x3f; + // Need to produce (imm[3:0] << 12)|(imm[5:4] << 6) from the 6-bit Value. + return ((Value & 0xf) << 12) | (((Value >> 4) & 3) << 6); case CAHP::fixup_cahp_lo10: - return Value & 0x3ff; - */ + Value = Value & 0x3ff; + // Need to produce (imm[7:0] << 16)|(imm[9:8] << 6) + return ((Value & 0xff) << 16) | (((Value >> 8) & 3) << 6); case CAHP::fixup_cahp_pcrel_10: if (!isInt<10>(Value)) diff --git a/llvm/lib/Target/CAHP/MCTargetDesc/CAHPELFObjectWriter.cpp b/llvm/lib/Target/CAHP/MCTargetDesc/CAHPELFObjectWriter.cpp index e22b02f95f68..a3a8ef9598d4 100644 --- a/llvm/lib/Target/CAHP/MCTargetDesc/CAHPELFObjectWriter.cpp +++ b/llvm/lib/Target/CAHP/MCTargetDesc/CAHPELFObjectWriter.cpp @@ -33,6 +33,7 @@ unsigned CAHPELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target, const MCFixup &Fixup, bool IsPCRel) const { + // TODO: emit correct relocations. report_fatal_error("invalid fixup kind!"); } diff --git a/llvm/lib/Target/CAHP/MCTargetDesc/CAHPMCCodeEmitter.cpp b/llvm/lib/Target/CAHP/MCTargetDesc/CAHPMCCodeEmitter.cpp index 39f48a51178b..17859dd88761 100644 --- a/llvm/lib/Target/CAHP/MCTargetDesc/CAHPMCCodeEmitter.cpp +++ b/llvm/lib/Target/CAHP/MCTargetDesc/CAHPMCCodeEmitter.cpp @@ -3,6 +3,7 @@ // LICENSE.TXT for details). This file is licensed under the same license. #include "MCTargetDesc/CAHPFixupKinds.h" +#include "MCTargetDesc/CAHPMCExpr.h" #include "MCTargetDesc/CAHPMCTargetDesc.h" #include "llvm/ADT/Statistic.h" #include "llvm/MC/MCAsmInfo.h" @@ -119,15 +120,32 @@ unsigned CAHPMCCodeEmitter::getImmOpValue(const MCInst &MI, unsigned OpNo, const MCExpr *Expr = MO.getExpr(); MCExpr::ExprKind Kind = Expr->getKind(); - MCFixupKind FixupKind = static_cast(CAHP::fixup_cahp_invalid); + CAHP::Fixups FixupKind = CAHP::fixup_cahp_invalid; unsigned Offset = 0; - if (Kind == MCExpr::SymbolRef && - cast(Expr)->getKind() == MCSymbolRefExpr::VK_None) { + if (Kind == MCExpr::Target) { + const CAHPMCExpr *CAHPExpr = cast(Expr); + + switch (CAHPExpr->getKind()) { + case CAHPMCExpr::VK_CAHP_None: + case CAHPMCExpr::VK_CAHP_Invalid: + llvm_unreachable("Unhandled fixup kind!"); + + case CAHPMCExpr::VK_CAHP_LO: + FixupKind = CAHP::fixup_cahp_lo10; + break; + + case CAHPMCExpr::VK_CAHP_HI: + FixupKind = CAHP::fixup_cahp_hi6; + break; + } + } else if (Kind == MCExpr::SymbolRef && + cast(Expr)->getKind() == + MCSymbolRefExpr::VK_None) { switch (MI.getOpcode()) { case CAHP::JS: case CAHP::JSAL: - FixupKind = static_cast(CAHP::fixup_cahp_pcrel_11); + FixupKind = CAHP::fixup_cahp_pcrel_11; break; case CAHP::BEQ: @@ -136,17 +154,15 @@ unsigned CAHPMCCodeEmitter::getImmOpValue(const MCInst &MI, unsigned OpNo, case CAHP::BLTU: case CAHP::BLE: case CAHP::BLEU: - FixupKind = static_cast(CAHP::fixup_cahp_pcrel_10); + FixupKind = CAHP::fixup_cahp_pcrel_10; break; - - // TODO: li and other instructions using %hi/%lo } } - assert(FixupKind != static_cast(CAHP::fixup_cahp_invalid) && - "Unhandled expression!"); + assert(FixupKind != CAHP::fixup_cahp_invalid && "Unhandled expression!"); - Fixups.push_back(MCFixup::create(Offset, Expr, FixupKind, MI.getLoc())); + Fixups.push_back(MCFixup::create( + Offset, Expr, static_cast(FixupKind), MI.getLoc())); ++MCNumFixups; return 0; diff --git a/llvm/lib/Target/CAHP/MCTargetDesc/CAHPMCExpr.cpp b/llvm/lib/Target/CAHP/MCTargetDesc/CAHPMCExpr.cpp new file mode 100644 index 000000000000..650b7a2cabb9 --- /dev/null +++ b/llvm/lib/Target/CAHP/MCTargetDesc/CAHPMCExpr.cpp @@ -0,0 +1,83 @@ +// This file is copied and modified from The LLVM Compiler Infrastructure, which +// is distributed under the Apache License v2.0 with LLVM Exceptions (see +// LICENSE.TXT for details). This file is licensed under the same license. + +#include "CAHPMCExpr.h" +#include "llvm/MC/MCAssembler.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSymbolELF.h" +#include "llvm/MC/MCValue.h" +#include "llvm/Object/ELF.h" +#include "llvm/Support/ErrorHandling.h" + +using namespace llvm; + +#define DEBUG_TYPE "riscvmcexpr" + +const CAHPMCExpr *CAHPMCExpr::create(const MCExpr *Expr, VariantKind Kind, + MCContext &Ctx) { + return new (Ctx) CAHPMCExpr(Expr, Kind); +} + +void CAHPMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const { + bool HasVariant = getKind() != VK_CAHP_None; + if (HasVariant) + OS << '%' << getVariantKindName(getKind()) << '('; + Expr->print(OS, MAI); + if (HasVariant) + OS << ')'; +} + +bool CAHPMCExpr::evaluateAsRelocatableImpl(MCValue &Res, + const MCAsmLayout *Layout, + const MCFixup *Fixup) const { + return getSubExpr()->evaluateAsRelocatable(Res, Layout, Fixup); +} + +void CAHPMCExpr::visitUsedExpr(MCStreamer &Streamer) const { + Streamer.visitUsedExpr(*getSubExpr()); +} + +CAHPMCExpr::VariantKind CAHPMCExpr::getVariantKindForName(StringRef name) { + return StringSwitch(name) + .Case("lo", VK_CAHP_LO) + .Case("hi", VK_CAHP_HI) + .Default(VK_CAHP_Invalid); +} + +StringRef CAHPMCExpr::getVariantKindName(VariantKind Kind) { + switch (Kind) { + default: + llvm_unreachable("Invalid ELF symbol kind"); + case VK_CAHP_LO: + return "lo"; + case VK_CAHP_HI: + return "hi"; + } +} + +bool CAHPMCExpr::evaluateAsConstant(int64_t &Res) const { + MCValue Value; + + if (!getSubExpr()->evaluateAsRelocatable(Value, nullptr, nullptr)) + return false; + + if (!Value.isAbsolute()) + return false; + + Res = evaluateAsInt64(Value.getConstant()); + return true; +} + +int64_t CAHPMCExpr::evaluateAsInt64(int64_t Value) const { + switch (Kind) { + default: + llvm_unreachable("Invalid kind"); + case VK_CAHP_LO: + return SignExtend64<10>(Value); + case VK_CAHP_HI: + // Add 1 if bit 9 is 1, to compensate for low 10 bits being negative. + return ((Value + 0x200) >> 10) & 0x3f; + } +} diff --git a/llvm/lib/Target/CAHP/MCTargetDesc/CAHPMCExpr.h b/llvm/lib/Target/CAHP/MCTargetDesc/CAHPMCExpr.h new file mode 100644 index 000000000000..7b98e9b9630e --- /dev/null +++ b/llvm/lib/Target/CAHP/MCTargetDesc/CAHPMCExpr.h @@ -0,0 +1,59 @@ +// This file is copied and modified from The LLVM Compiler Infrastructure, which +// is distributed under the Apache License v2.0 with LLVM Exceptions (see +// LICENSE.TXT for details). This file is licensed under the same license. + +#ifndef LLVM_LIB_TARGET_CAHP_MCTARGETDESC_CAHPMCEXPR_H +#define LLVM_LIB_TARGET_CAHP_MCTARGETDESC_CAHPMCEXPR_H + +#include "llvm/MC/MCExpr.h" + +namespace llvm { + +class StringRef; +class CAHPMCExpr : public MCTargetExpr { +public: + enum VariantKind { VK_CAHP_None, VK_CAHP_LO, VK_CAHP_HI, VK_CAHP_Invalid }; + +private: + const MCExpr *Expr; + const VariantKind Kind; + + int64_t evaluateAsInt64(int64_t Value) const; + + explicit CAHPMCExpr(const MCExpr *Expr, VariantKind Kind) + : Expr(Expr), Kind(Kind) {} + +public: + static const CAHPMCExpr *create(const MCExpr *Expr, VariantKind Kind, + MCContext &Ctx); + + VariantKind getKind() const { return Kind; } + + const MCExpr *getSubExpr() const { return Expr; } + + void printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const override; + bool evaluateAsRelocatableImpl(MCValue &Res, const MCAsmLayout *Layout, + const MCFixup *Fixup) const override; + void visitUsedExpr(MCStreamer &Streamer) const override; + MCFragment *findAssociatedFragment() const override { + return getSubExpr()->findAssociatedFragment(); + } + + // There are no TLS CAHPMCExprs at the moment. + void fixELFSymbolsInTLSFixups(MCAssembler &Asm) const override {} + + bool evaluateAsConstant(int64_t &Res) const; + + static bool classof(const MCExpr *E) { + return E->getKind() == MCExpr::Target; + } + + static bool classof(const CAHPMCExpr *) { return true; } + + static VariantKind getVariantKindForName(StringRef name); + static StringRef getVariantKindName(VariantKind Kind); +}; + +} // end namespace llvm. + +#endif diff --git a/llvm/lib/Target/CAHP/MCTargetDesc/CMakeLists.txt b/llvm/lib/Target/CAHP/MCTargetDesc/CMakeLists.txt index f720c192eee2..fb967f57d2b4 100644 --- a/llvm/lib/Target/CAHP/MCTargetDesc/CMakeLists.txt +++ b/llvm/lib/Target/CAHP/MCTargetDesc/CMakeLists.txt @@ -4,4 +4,5 @@ add_llvm_library(LLVMCAHPDesc CAHPAsmBackend.cpp CAHPELFObjectWriter.cpp CAHPMCCodeEmitter.cpp + CAHPMCExpr.cpp ) diff --git a/llvm/test/MC/CAHP/cahp-invalid.s b/llvm/test/MC/CAHP/cahp-invalid.s index 3982ba2a5dbc..987cce0c1143 100644 --- a/llvm/test/MC/CAHP/cahp-invalid.s +++ b/llvm/test/MC/CAHP/cahp-invalid.s @@ -42,3 +42,10 @@ li x11, x12, x13 # CHECK: :[[@LINE]]:9: error: invalid operand for instruction # Too few operands li x8 # CHECK: :[[@LINE]]:1: error: too few operands for instruction mov x13 # CHECK: :[[@LINE]]:1: error: too few operands for instruction + +# Illegal operand modifier +lsli a0, a0, %lo(1) # CHECK: :[[@LINE]]:14: error: immediate must be an integer in the range [0, 15] +ori a0, a1, %hi(foo) # CHECK: :[[@LINE]]:13: error: immediate must be an integer in the range [0, 1023] +lui a0, %lo(1) # CHECK: :[[@LINE]]:9: error: immediate must be an integer in the range [0, 63] +addi t0, sp, %modifer(255) # CHECK: :[[@LINE]]:15: error: unrecognized operand modifier +addi t1, %lo(t2), 1 # CHECK: :[[@LINE]]:10: error: invalid operand for instruction diff --git a/llvm/test/MC/CAHP/cahp-valid.s b/llvm/test/MC/CAHP/cahp-valid.s index 6834428a5687..37b2e84cc1dd 100644 --- a/llvm/test/MC/CAHP/cahp-valid.s +++ b/llvm/test/MC/CAHP/cahp-valid.s @@ -21,6 +21,12 @@ sb ra, -500(sp) # CHECK-INST: li ra, -500 # CHECK: encoding: [0xb5,0x00,0x0c] li ra, -500 +# CHECK-INST: li a0, 391 +# CHECK: encoding: [0x75,0x08,0x87] +li a0, (0x187000 >> 12) +# CHECK-INST: li a0, 256 +# CHECK: encoding: [0x75,0x08,0x00] +li a0, %lo(0x8500) # CHECK-INST: add ra, sp, fp # CHECK: encoding: [0x01,0x10,0x02] add ra, sp, fp @@ -129,6 +135,9 @@ lsi ra, -32 # CHECK-INST: lui ra, 32 # CHECK: encoding: [0x84,0x00] lui ra, 32 +# CHECK-INST: lui a0, 0 +# CHECK: encoding: [0x04,0x08] +lui a0, %hi(2) # CHECK-INST: mov ra, sp # CHECK: encoding: [0xc0,0x10] mov ra, sp diff --git a/llvm/test/MC/CAHP/fixups.s b/llvm/test/MC/CAHP/fixups.s index 109d9d73a918..37f94eca19bb 100644 --- a/llvm/test/MC/CAHP/fixups.s +++ b/llvm/test/MC/CAHP/fixups.s @@ -53,3 +53,15 @@ ble a0, a1, .LBB6 bleu a0, a1, .LBB7 # CHECK-FIXUP: fixup A - offset: 0, value: .LBB7, kind: fixup_cahp_pcrel_10 # CHECK-INSTR: bleu a0, a1, -512 + +addi a0, a1, %lo(val) +# CHECK-FIXUP: fixup A - offset: 0, value: %lo(val), kind: fixup_cahp_lo10 +# CHECK-INSTR: addi a0, a1, -460 + +lui a0, %hi(val) +# CHECK-FIXUP: fixup A - offset: 0, value: %hi(val), kind: fixup_cahp_hi6 +# CHECK-INSTR: lui a0, 5 + +.set val, 0x1234 + +# CHECK-REL-NOT: R_CAHP diff --git a/llvm/test/MC/CAHP/hilo-constaddr.s b/llvm/test/MC/CAHP/hilo-constaddr.s new file mode 100644 index 000000000000..b745ae9e5456 --- /dev/null +++ b/llvm/test/MC/CAHP/hilo-constaddr.s @@ -0,0 +1,39 @@ +# RUN: llvm-mc -filetype=obj -triple=cahp %s \ +# RUN: | llvm-objdump -d - | FileCheck %s -check-prefix=CHECK-INSTR + +# RUN: llvm-mc -filetype=obj -triple=cahp %s \ +# RUN: | llvm-readobj -r | FileCheck %s -check-prefix=CHECK-REL + +# Check the assembler can handle hi and lo expressions with a constant +# address, and constant expressions involving labels. Test case derived from +# test/MC/Mips/hilo-addressing.s + +# Check that 1 is added to the high 6 bits if bit 9 of the low part is 1. +.equ addr, 0x1234 + lui t0, %hi(addr) + lw ra, %lo(addr)(t0) +# CHECK-INSTR: lui t0, 5 +# CHECK-INSTR: lw ra, -460(t0) + +# Check that assembler can handle %hi(label1 - label2) and %lo(label1 - label2) +# expressions. + +tmp1: + # Emit zeros so that difference between tmp1 and tmp3 is 0x1234+5 bytes. + .fill 0x1234 +tmp2: + lui t0, %hi(tmp3-tmp1) + lw ra, %lo(tmp3-tmp1)(t0) +# CHECK-INSTR: lui t0, 5 +# CHECK-INSTR: lw ra, -455(t0) + +tmp3: + lui t1, %hi(tmp2-tmp3) + lw sp, %lo(tmp2-tmp3)(t1) +# CHECK-INSTR: lui t1, 0 +# CHECK-INSTR: lw sp, -5(t1) + +# Check that a relocation isn't emitted for %hi(label1 - label2) and +# %lo(label1 - label2) expressions. + +# CHECK-REL-NOT: R_CAHP From a7d26497a4ce9af6a9bba17eedfa3d4c1ab24bb7 Mon Sep 17 00:00:00 2001 From: Ushitora Anqou Date: Sun, 20 Oct 2019 22:52:37 +0900 Subject: [PATCH 233/289] [CAHP] Follow changes in ISA --- .../Target/CAHP/AsmParser/CAHPAsmParser.cpp | 28 ++----------------- llvm/lib/Target/CAHP/CAHPInstrInfo.td | 22 ++++----------- llvm/test/MC/CAHP/cahp-invalid.s | 12 ++++---- llvm/test/MC/CAHP/cahp-valid.s | 19 +++++++------ 4 files changed, 25 insertions(+), 56 deletions(-) diff --git a/llvm/lib/Target/CAHP/AsmParser/CAHPAsmParser.cpp b/llvm/lib/Target/CAHP/AsmParser/CAHPAsmParser.cpp index 22c58e3943a4..52f76312c1b3 100644 --- a/llvm/lib/Target/CAHP/AsmParser/CAHPAsmParser.cpp +++ b/llvm/lib/Target/CAHP/AsmParser/CAHPAsmParser.cpp @@ -160,9 +160,7 @@ struct CAHPOperand : public MCParsedAsmOperand { bool isUImm4() const { return isBareImm(isUInt<4>); } - bool isSImm6() const { return isBareImm(isInt<6>); } - - bool isUImm6() const { + bool isSImm6() const { if (!isImm()) return false; @@ -172,7 +170,7 @@ struct CAHPOperand : public MCParsedAsmOperand { bool IsConstantImm = evaluateConstantImm(Imm, VK); if (IsConstantImm) - IsValid = isUInt<6>(Imm); + IsValid = isInt<6>(Imm); else IsValid = CAHPAsmParser::classifySymbolRef(getImm(), VK, Imm); @@ -198,27 +196,9 @@ struct CAHPOperand : public MCParsedAsmOperand { (VK == CAHPMCExpr::VK_CAHP_None || VK == CAHPMCExpr::VK_CAHP_LO); } - bool isUImm10() const { - if (!isImm()) - return false; - - CAHPMCExpr::VariantKind VK; - int64_t Imm; - bool IsValid; - - bool IsConstantImm = evaluateConstantImm(Imm, VK); - if (IsConstantImm) - IsValid = isUInt<10>(Imm); - else - IsValid = CAHPAsmParser::classifySymbolRef(getImm(), VK, Imm); - - return IsValid && - (VK == CAHPMCExpr::VK_CAHP_None || VK == CAHPMCExpr::VK_CAHP_LO); - } - bool isSImm11() const { return isBareImm(isInt<11>); } - bool isUImm7Lsb0() const { return isBareImm(&isShiftedUInt<6, 1>); } + bool isUImm7Lsb0() const { return isBareImm(isShiftedUInt<6, 1>); } bool isSImm11Lsb0() const { return isBareImm(isShiftedInt<10, 1>); } @@ -384,9 +364,7 @@ bool CAHPAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, CASE_MATCH_INVALID_UIMM(4); CASE_MATCH_INVALID_SIMM(6); - CASE_MATCH_INVALID_UIMM(6); CASE_MATCH_INVALID_SIMM(10); - CASE_MATCH_INVALID_UIMM(10); CASE_MATCH_INVALID_SIMM(11); CASE_MATCH_INVALID_UIMM_LSB0(7); } diff --git a/llvm/lib/Target/CAHP/CAHPInstrInfo.td b/llvm/lib/Target/CAHP/CAHPInstrInfo.td index db86c52d8de4..15adbf273a6a 100644 --- a/llvm/lib/Target/CAHP/CAHPInstrInfo.td +++ b/llvm/lib/Target/CAHP/CAHPInstrInfo.td @@ -30,24 +30,12 @@ def simm6 : Operand { let EncoderMethod = "getImmOpValue"; } -def uimm6 : Operand { - let ParserMatchClass = UImmAsmOperand<6>; - let DecoderMethod = "decodeUImmOperand<6>"; - let EncoderMethod = "getImmOpValue"; -} - def simm10 : Operand { let ParserMatchClass = SImmAsmOperand<10>; let DecoderMethod = "decodeSImmOperand<10>"; let EncoderMethod = "getImmOpValue"; } -def uimm10 : Operand { - let ParserMatchClass = UImmAsmOperand<10>; - let DecoderMethod = "decodeUImmOperand<10>"; - let EncoderMethod = "getImmOpValue"; -} - def simm11 : Operand { let ParserMatchClass = SImmAsmOperand<11>; let DecoderMethod = "decodeSImmOperand<11>"; @@ -113,11 +101,11 @@ let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in { let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in { def ADDI : CAHPInst24I<0b000011, (outs GPR:$rd), (ins GPR:$rs1, simm10:$imm), "addi", "$rd, $rs1, $imm">; - def ANDI : CAHPInst24I<0b010011, (outs GPR:$rd), (ins GPR:$rs1, uimm10:$imm), + def ANDI : CAHPInst24I<0b010011, (outs GPR:$rd), (ins GPR:$rs1, simm10:$imm), "andi", "$rd, $rs1, $imm">; - def XORI : CAHPInst24I<0b011011, (outs GPR:$rd), (ins GPR:$rs1, uimm10:$imm), + def XORI : CAHPInst24I<0b011011, (outs GPR:$rd), (ins GPR:$rs1, simm10:$imm), "xori", "$rd, $rs1, $imm">; - def ORI : CAHPInst24I<0b100011, (outs GPR:$rd), (ins GPR:$rs1, uimm10:$imm), + def ORI : CAHPInst24I<0b100011, (outs GPR:$rd), (ins GPR:$rs1, simm10:$imm), "ori", "$rd, $rs1, $imm">; def LSLI : CAHPInst24I<0b101011, (outs GPR:$rd), (ins GPR:$rs1, uimm4:$imm), "lsli", "$rd, $rs1, $imm">; @@ -172,7 +160,7 @@ def LSI : CAHPInst16Load <0b110100, (outs GPR:$rd), (ins simm6:$imm), } let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isMoveImm = 1 in -def LUI : CAHPInst16Load <0b000100, (outs GPR:$rd), (ins uimm6:$imm), +def LUI : CAHPInst16Load <0b000100, (outs GPR:$rd), (ins simm6:$imm), "lui", "$rd, $imm"> { bits<6> imm; let Inst{15-12} = imm{3-0}; @@ -220,7 +208,7 @@ let hasSideEffects = 0, mayLoad = 0, mayStore = 0, "asri2", "$rd, $imm">; def ADDI2 : CAHPInst16I<0b000010, (outs GPR:$rd_w), (ins GPR:$rd, simm6:$imm), "addi2", "$rd, $imm">; - def ANDI2 : CAHPInst16I<0b010010, (outs GPR:$rd_w), (ins GPR:$rd, uimm6:$imm), + def ANDI2 : CAHPInst16I<0b010010, (outs GPR:$rd_w), (ins GPR:$rd, simm6:$imm), "andi2", "$rd, $imm">; } diff --git a/llvm/test/MC/CAHP/cahp-invalid.s b/llvm/test/MC/CAHP/cahp-invalid.s index 987cce0c1143..ca0af3855372 100644 --- a/llvm/test/MC/CAHP/cahp-invalid.s +++ b/llvm/test/MC/CAHP/cahp-invalid.s @@ -10,16 +10,16 @@ li t0, -513 # CHECK: :[[@LINE]]:8: error: immediate must be an integer in the ra li s0, 512 # CHECK: :[[@LINE]]:8: error: immediate must be an integer in the range [-512, 511] addi a0, a1, 512 # CHECK: :[[@LINE]]:14: error: immediate must be an integer in the range [-512, 511] addi a0, a1, -513 # CHECK: :[[@LINE]]:14: error: immediate must be an integer in the range [-512, 511] -andi a0, a1, 1024 # CHECK: :[[@LINE]]:14: error: immediate must be an integer in the range [0, 1023] -xori a0, a1, -1 # CHECK: :[[@LINE]]:14: error: immediate must be an integer in the range [0, 1023] +andi a0, a1, 512 # CHECK: :[[@LINE]]:14: error: immediate must be an integer in the range [-512, 511] +xori a0, a1, -513 # CHECK: :[[@LINE]]:14: error: immediate must be an integer in the range [-512, 511] lsli a0, a1, 16 # CHECK: :[[@LINE]]:14: error: immediate must be an integer in the range [0, 15] asri a0, a1, -1 # CHECK: :[[@LINE]]:14: error: immediate must be an integer in the range [0, 15] lwsp a4, 128(sp) # CHECK: :[[@LINE]]:10: error: immediate must be a multiple of 2 bytes in the range [0, 126] swsp a3, -2(sp) # CHECK: :[[@LINE]]:10: error: immediate must be a multiple of 2 bytes in the range [0, 126] lsi a5, 32 # CHECK: :[[@LINE]]:9: error: immediate must be an integer in the range [-32, 31] lsi a5, -33 # CHECK: :[[@LINE]]:9: error: immediate must be an integer in the range [-32, 31] -lui a5, 65 # CHECK: :[[@LINE]]:9: error: immediate must be an integer in the range [0, 63] -lui a5, -1 # CHECK: :[[@LINE]]:9: error: immediate must be an integer in the range [0, 63] +lui a5, 32 # CHECK: :[[@LINE]]:9: error: immediate must be an integer in the range [-32, 31] +lui a5, -33 # CHECK: :[[@LINE]]:9: error: immediate must be an integer in the range [-32, 31] js 1024 # CHECK: :[[@LINE]]:4: error: immediate must be an integer in the range [-1024, 1023] js -1025 # CHECK: :[[@LINE]]:4: error: immediate must be an integer in the range [-1024, 1023] @@ -45,7 +45,7 @@ mov x13 # CHECK: :[[@LINE]]:1: error: too few operands for instruction # Illegal operand modifier lsli a0, a0, %lo(1) # CHECK: :[[@LINE]]:14: error: immediate must be an integer in the range [0, 15] -ori a0, a1, %hi(foo) # CHECK: :[[@LINE]]:13: error: immediate must be an integer in the range [0, 1023] -lui a0, %lo(1) # CHECK: :[[@LINE]]:9: error: immediate must be an integer in the range [0, 63] +ori a0, a1, %hi(foo) # CHECK: :[[@LINE]]:13: error: immediate must be an integer in the range [-512, 511] +lui a0, %lo(1) # CHECK: :[[@LINE]]:9: error: immediate must be an integer in the range [-32, 31] addi t0, sp, %modifer(255) # CHECK: :[[@LINE]]:15: error: unrecognized operand modifier addi t1, %lo(t2), 1 # CHECK: :[[@LINE]]:10: error: invalid operand for instruction diff --git a/llvm/test/MC/CAHP/cahp-valid.s b/llvm/test/MC/CAHP/cahp-valid.s index 37b2e84cc1dd..8a4ef7cb3049 100644 --- a/llvm/test/MC/CAHP/cahp-valid.s +++ b/llvm/test/MC/CAHP/cahp-valid.s @@ -57,15 +57,18 @@ addi ra, sp, 10 # CHECK-INST: addi ra, sp, -10 # CHECK: encoding: [0xc3,0x10,0xf6] addi ra, sp, -10 -# CHECK-INST: andi ra, sp, 778 +# CHECK-INST: andi ra, sp, -246 # CHECK: encoding: [0xd3,0x10,0x0a] -andi ra, sp, 778 -# CHECK-INST: xori ra, sp, 778 +andi ra, sp, -246 +# CHECK-INST: xori ra, sp, -246 # CHECK: encoding: [0xdb,0x10,0x0a] -xori ra, sp, 778 -# CHECK-INST: ori ra, sp, 778 +xori ra, sp, -246 +# CHECK-INST: ori ra, sp, -246 # CHECK: encoding: [0xe3,0x10,0x0a] -ori ra, sp, 778 +ori ra, sp, -246 +# CHECK-INST: ori ra, sp, -246 +# CHECK: encoding: [0xe3,0x10,0x0a] +ori ra, sp, %lo(0xA70A) # CHECK-INST: lsli ra, sp, 3 # CHECK: encoding: [0x2b,0x10,0x03] lsli ra, sp, 3 @@ -132,9 +135,9 @@ swsp ra, 64(sp) # CHECK-INST: lsi ra, -32 # CHECK: encoding: [0xb4,0x00] lsi ra, -32 -# CHECK-INST: lui ra, 32 +# CHECK-INST: lui ra, -32 # CHECK: encoding: [0x84,0x00] -lui ra, 32 +lui ra, -32 # CHECK-INST: lui a0, 0 # CHECK: encoding: [0x04,0x08] lui a0, %hi(2) From b653548e42fa9919010de623c0dac8457c4e6a77 Mon Sep 17 00:00:00 2001 From: Ushitora Anqou Date: Mon, 21 Oct 2019 16:35:53 +0900 Subject: [PATCH 234/289] [CAHP] Add support for update_llc_test_checks.py --- llvm/utils/UpdateTestChecks/asm.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/llvm/utils/UpdateTestChecks/asm.py b/llvm/utils/UpdateTestChecks/asm.py index 9c250cd9898a..1bb29b0a03d5 100644 --- a/llvm/utils/UpdateTestChecks/asm.py +++ b/llvm/utils/UpdateTestChecks/asm.py @@ -42,6 +42,12 @@ class string: r'^\s*(\.Lfunc_end[0-9]+:\n|\.section)', flags=(re.M | re.S)) +ASM_FUNCTION_CAHP_RE = re.compile( + r'^_?(?P[^:]+):[ \t]*#+[ \t]*@(?P=func)\n(?:\s*\.?Lfunc_begin[^:\n]*:\n)?[^:]*?' + r'(?P^##?[ \t]+[^:]+:.*?)\s*' + r'.Lfunc_end[0-9]+:\n', + flags=(re.M | re.S)) + ASM_FUNCTION_HEXAGON_RE = re.compile( r'^_?(?P[^:]+):[ \t]*//[ \t]*@(?P=func)\n[^:]*?' r'(?P.*?)\n' # (body of the function) @@ -281,6 +287,16 @@ def scrub_asm_wasm32(asm, args): asm = common.SCRUB_TRAILING_WHITESPACE_RE.sub(r'', asm) return asm +def scrub_asm_cahp(asm, args): + # Scrub runs of whitespace out of the assembly, but leave the leading + # whitespace in place. + asm = common.SCRUB_WHITESPACE_RE.sub(r' ', asm) + # Expand the tabs used for indentation. + asm = string.expandtabs(asm, 2) + # Strip trailing whitespace. + asm = common.SCRUB_TRAILING_WHITESPACE_RE.sub(r'', asm) + return asm + def get_triple_from_march(march): triples = { 'amdgcn': 'amdgcn', @@ -323,6 +339,7 @@ def build_function_body_dictionary_for_triple(args, raw_tool_output, triple, pre 'sparc': (scrub_asm_sparc, ASM_FUNCTION_SPARC_RE), 's390x': (scrub_asm_systemz, ASM_FUNCTION_SYSTEMZ_RE), 'wasm32': (scrub_asm_wasm32, ASM_FUNCTION_WASM32_RE), + 'cahp': (scrub_asm_cahp, ASM_FUNCTION_CAHP_RE), } handler = None best_prefix = '' From 93131c5f0f44c1cbe28a5f2c28ebce0cbca29108 Mon Sep 17 00:00:00 2001 From: Ushitora Anqou Date: Mon, 21 Oct 2019 17:34:05 +0900 Subject: [PATCH 235/289] [CAHP] Add skeleton for codegen --- llvm/lib/Target/CAHP/CAHP.h | 21 +++ llvm/lib/Target/CAHP/CAHP.td | 8 +- llvm/lib/Target/CAHP/CAHPAsmPrinter.cpp | 57 ++++++++ llvm/lib/Target/CAHP/CAHPCallingConv.td | 22 +++ llvm/lib/Target/CAHP/CAHPFrameLowering.cpp | 20 +++ llvm/lib/Target/CAHP/CAHPFrameLowering.h | 26 ++++ llvm/lib/Target/CAHP/CAHPISelDAGToDAG.cpp | 51 +++++++ llvm/lib/Target/CAHP/CAHPISelLowering.cpp | 156 +++++++++++++++++++++ llvm/lib/Target/CAHP/CAHPISelLowering.h | 47 +++++++ llvm/lib/Target/CAHP/CAHPInstrInfo.cpp | 22 +++ llvm/lib/Target/CAHP/CAHPInstrInfo.h | 23 +++ llvm/lib/Target/CAHP/CAHPInstrInfo.td | 7 + llvm/lib/Target/CAHP/CAHPMCInstLower.cpp | 39 ++++++ llvm/lib/Target/CAHP/CAHPRegisterInfo.cpp | 50 +++++++ llvm/lib/Target/CAHP/CAHPRegisterInfo.h | 31 ++++ llvm/lib/Target/CAHP/CAHPSubtarget.cpp | 34 +++++ llvm/lib/Target/CAHP/CAHPSubtarget.h | 57 ++++++++ llvm/lib/Target/CAHP/CAHPTargetMachine.cpp | 25 +++- llvm/lib/Target/CAHP/CAHPTargetMachine.h | 6 + llvm/lib/Target/CAHP/CMakeLists.txt | 19 ++- llvm/lib/Target/CAHP/LLVMBuild.txt | 3 +- 21 files changed, 715 insertions(+), 9 deletions(-) create mode 100644 llvm/lib/Target/CAHP/CAHP.h create mode 100644 llvm/lib/Target/CAHP/CAHPAsmPrinter.cpp create mode 100644 llvm/lib/Target/CAHP/CAHPCallingConv.td create mode 100644 llvm/lib/Target/CAHP/CAHPFrameLowering.cpp create mode 100644 llvm/lib/Target/CAHP/CAHPFrameLowering.h create mode 100644 llvm/lib/Target/CAHP/CAHPISelDAGToDAG.cpp create mode 100644 llvm/lib/Target/CAHP/CAHPISelLowering.cpp create mode 100644 llvm/lib/Target/CAHP/CAHPISelLowering.h create mode 100644 llvm/lib/Target/CAHP/CAHPInstrInfo.cpp create mode 100644 llvm/lib/Target/CAHP/CAHPInstrInfo.h create mode 100644 llvm/lib/Target/CAHP/CAHPMCInstLower.cpp create mode 100644 llvm/lib/Target/CAHP/CAHPRegisterInfo.cpp create mode 100644 llvm/lib/Target/CAHP/CAHPRegisterInfo.h create mode 100644 llvm/lib/Target/CAHP/CAHPSubtarget.cpp create mode 100644 llvm/lib/Target/CAHP/CAHPSubtarget.h diff --git a/llvm/lib/Target/CAHP/CAHP.h b/llvm/lib/Target/CAHP/CAHP.h new file mode 100644 index 000000000000..c9714bbfe034 --- /dev/null +++ b/llvm/lib/Target/CAHP/CAHP.h @@ -0,0 +1,21 @@ +// This file is copied and modified from The LLVM Compiler Infrastructure, which +// is distributed under the Apache License v2.0 with LLVM Exceptions (see +// LICENSE.TXT for details). This file is licensed under the same license. + +#ifndef LLVM_LIB_TARGET_CAHP_CAHP_H +#define LLVM_LIB_TARGET_CAHP_CAHP_H + +#include "MCTargetDesc/CAHPMCTargetDesc.h" +#include "llvm/Target/TargetMachine.h" + +namespace llvm { +class CAHPTargetMachine; +class MCInst; +class MachineInstr; + +void LowerCAHPMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI); + +FunctionPass *createCAHPISelDag(CAHPTargetMachine &TM); +} // namespace llvm + +#endif diff --git a/llvm/lib/Target/CAHP/CAHP.td b/llvm/lib/Target/CAHP/CAHP.td index 34b212f9c493..838a643b17da 100644 --- a/llvm/lib/Target/CAHP/CAHP.td +++ b/llvm/lib/Target/CAHP/CAHP.td @@ -5,10 +5,11 @@ include "llvm/Target/Target.td" //===----------------------------------------------------------------------===// -// Register file, instruction descriptions. +// Register file, calling conventions, instruction descriptions. //===----------------------------------------------------------------------===// include "CAHPRegisterInfo.td" +include "CAHPCallingConv.td" include "CAHPInstrInfo.td" //===----------------------------------------------------------------------===// @@ -21,7 +22,9 @@ def : ProcessorModel<"generic-cahp", NoSchedModel, []>; // Define the CAHP target. //===----------------------------------------------------------------------===// -def CAHPInstrInfo : InstrInfo; +def CAHPInstrInfo : InstrInfo { + let guessInstructionProperties = 0; +} def CAHPAsmParser : AsmParser { // Use alternative names of registers when emitting. @@ -31,4 +34,5 @@ def CAHPAsmParser : AsmParser { def CAHP : Target { let InstructionSet = CAHPInstrInfo; let AssemblyParsers = [CAHPAsmParser]; + let AllowRegisterRenaming = 1; } diff --git a/llvm/lib/Target/CAHP/CAHPAsmPrinter.cpp b/llvm/lib/Target/CAHP/CAHPAsmPrinter.cpp new file mode 100644 index 000000000000..2078ef77b24d --- /dev/null +++ b/llvm/lib/Target/CAHP/CAHPAsmPrinter.cpp @@ -0,0 +1,57 @@ +// This file is copied and modified from The LLVM Compiler Infrastructure, which +// is distributed under the Apache License v2.0 with LLVM Exceptions (see +// LICENSE.TXT for details). This file is licensed under the same license. + +#include "CAHP.h" +#include "CAHPTargetMachine.h" +#include "InstPrinter/CAHPInstPrinter.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Support/TargetRegistry.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +#define DEBUG_TYPE "asm-printer" + +namespace { +class CAHPAsmPrinter : public AsmPrinter { +public: + explicit CAHPAsmPrinter(TargetMachine &TM, + std::unique_ptr Streamer) + : AsmPrinter(TM, std::move(Streamer)) {} + + StringRef getPassName() const override { return "CAHP Assembly Printer"; } + + void EmitInstruction(const MachineInstr *MI) override; + + // TableGen'erated function. + bool emitPseudoExpansionLowering(MCStreamer &OutStreamer, + const MachineInstr *MI); +}; +} // namespace + +// Simple pseudo-instructions have their lowering (with expansion to real +// instructions) auto-generated. +#include "CAHPGenMCPseudoLowering.inc" + +void CAHPAsmPrinter::EmitInstruction(const MachineInstr *MI) { + // Do any auto-generated pseudo lowerings. + if (emitPseudoExpansionLowering(*OutStreamer, MI)) + return; + + MCInst TmpInst; + LowerCAHPMachineInstrToMCInst(MI, TmpInst); + EmitToStreamer(*OutStreamer, TmpInst); +} + +// Force static initialization. +extern "C" void LLVMInitializeCAHPAsmPrinter() { + RegisterAsmPrinter X(getTheCAHPTarget()); +} diff --git a/llvm/lib/Target/CAHP/CAHPCallingConv.td b/llvm/lib/Target/CAHP/CAHPCallingConv.td new file mode 100644 index 000000000000..c57a85fd7083 --- /dev/null +++ b/llvm/lib/Target/CAHP/CAHPCallingConv.td @@ -0,0 +1,22 @@ +// This file is copied and modified from The LLVM Compiler Infrastructure, which +// is distributed under the Apache License v2.0 with LLVM Exceptions (see +// LICENSE.TXT for details). This file is licensed under the same license. + +// CAHP 16-bit C return-value convention. +def RetCC_CAHP : CallingConv<[ + CCIfType<[i16], CCAssignToReg<[X8, X9]>> +]>; + +// CAHP 16-bit C Calling convention. +def CC_CAHP : CallingConv<[ + // Promote i8 args to i16 + CCIfType<[i8], CCPromoteToType>, + + // All arguments get passed in integer registers if there is space. + CCIfType<[i16], CCAssignToReg<[ X8, X9, X10, X11, X12, X13 ]>>, + + // Could be assigned to the stack in 8-byte aligned units, but unsupported + CCAssignToStack<2, 2> // The slot's size, the stack alignment +]>; + +def CSR : CalleeSavedRegs<(add X0, X2, X3, X4, X5, X6, X7)>; diff --git a/llvm/lib/Target/CAHP/CAHPFrameLowering.cpp b/llvm/lib/Target/CAHP/CAHPFrameLowering.cpp new file mode 100644 index 000000000000..492af423f173 --- /dev/null +++ b/llvm/lib/Target/CAHP/CAHPFrameLowering.cpp @@ -0,0 +1,20 @@ +// This file is copied and modified from The LLVM Compiler Infrastructure, which +// is distributed under the Apache License v2.0 with LLVM Exceptions (see +// LICENSE.TXT for details). This file is licensed under the same license. + +#include "CAHPFrameLowering.h" +#include "CAHPSubtarget.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" + +using namespace llvm; + +bool CAHPFrameLowering::hasFP(const MachineFunction &MF) const { return true; } + +void CAHPFrameLowering::emitPrologue(MachineFunction &MF, + MachineBasicBlock &MBB) const {} + +void CAHPFrameLowering::emitEpilogue(MachineFunction &MF, + MachineBasicBlock &MBB) const {} diff --git a/llvm/lib/Target/CAHP/CAHPFrameLowering.h b/llvm/lib/Target/CAHP/CAHPFrameLowering.h new file mode 100644 index 000000000000..af184338420b --- /dev/null +++ b/llvm/lib/Target/CAHP/CAHPFrameLowering.h @@ -0,0 +1,26 @@ +// This file is copied and modified from The LLVM Compiler Infrastructure, which +// is distributed under the Apache License v2.0 with LLVM Exceptions (see +// LICENSE.TXT for details). This file is licensed under the same license. + +#ifndef LLVM_LIB_TARGET_CAHP_CAHPFRAMELOWERING_H +#define LLVM_LIB_TARGET_CAHP_CAHPFRAMELOWERING_H + +#include "llvm/CodeGen/TargetFrameLowering.h" + +namespace llvm { +class CAHPSubtarget; + +class CAHPFrameLowering : public TargetFrameLowering { +public: + explicit CAHPFrameLowering(const CAHPSubtarget &STI) + : TargetFrameLowering(StackGrowsDown, + /*StackAlignment=*/2, + /*LocalAreaOffset=*/0) {} + + void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override; + void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override; + + bool hasFP(const MachineFunction &MF) const override; +}; +} // namespace llvm +#endif diff --git a/llvm/lib/Target/CAHP/CAHPISelDAGToDAG.cpp b/llvm/lib/Target/CAHP/CAHPISelDAGToDAG.cpp new file mode 100644 index 000000000000..5fc0c4f51ede --- /dev/null +++ b/llvm/lib/Target/CAHP/CAHPISelDAGToDAG.cpp @@ -0,0 +1,51 @@ +// This file is copied and modified from The LLVM Compiler Infrastructure, which +// is distributed under the Apache License v2.0 with LLVM Exceptions (see +// LICENSE.TXT for details). This file is licensed under the same license. + +#include "CAHP.h" +#include "CAHPTargetMachine.h" +#include "MCTargetDesc/CAHPMCTargetDesc.h" +#include "llvm/CodeGen/SelectionDAGISel.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/raw_ostream.h" +using namespace llvm; + +#define DEBUG_TYPE "cahp-isel" + +// CAHP-specific code to select CAHP machine instructions for +// SelectionDAG operations. +namespace { +class CAHPDAGToDAGISel final : public SelectionDAGISel { +public: + explicit CAHPDAGToDAGISel(CAHPTargetMachine &TargetMachine) + : SelectionDAGISel(TargetMachine) {} + + StringRef getPassName() const override { + return "CAHP DAG->DAG Pattern Instruction Selection"; + } + + void Select(SDNode *Node) override; + + // Include the pieces autogenerated from the target description. +#include "CAHPGenDAGISel.inc" +}; +} // namespace + +void CAHPDAGToDAGISel::Select(SDNode *Node) { + // If we have a custom node, we have already selected + if (Node->isMachineOpcode()) { + LLVM_DEBUG(dbgs() << "== "; Node->dump(CurDAG); dbgs() << "\n"); + Node->setNodeId(-1); + return; + } + + // Select the default instruction. + SelectCode(Node); +} + +// This pass converts a legalized DAG into a CAHP-specific DAG, ready +// for instruction scheduling. +FunctionPass *llvm::createCAHPISelDag(CAHPTargetMachine &TM) { + return new CAHPDAGToDAGISel(TM); +} diff --git a/llvm/lib/Target/CAHP/CAHPISelLowering.cpp b/llvm/lib/Target/CAHP/CAHPISelLowering.cpp new file mode 100644 index 000000000000..82d44f99de47 --- /dev/null +++ b/llvm/lib/Target/CAHP/CAHPISelLowering.cpp @@ -0,0 +1,156 @@ +// This file is copied and modified from The LLVM Compiler Infrastructure, which +// is distributed under the Apache License v2.0 with LLVM Exceptions (see +// LICENSE.TXT for details). This file is licensed under the same license. + +#include "CAHPISelLowering.h" +#include "CAHP.h" +#include "CAHPRegisterInfo.h" +#include "CAHPSubtarget.h" +#include "CAHPTargetMachine.h" +#include "llvm/CodeGen/CallingConvLower.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/SelectionDAGISel.h" +#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" +#include "llvm/CodeGen/ValueTypes.h" +#include "llvm/IR/DiagnosticInfo.h" +#include "llvm/IR/DiagnosticPrinter.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +#define DEBUG_TYPE "cahp-lower" + +CAHPTargetLowering::CAHPTargetLowering(const TargetMachine &TM, + const CAHPSubtarget &STI) + : TargetLowering(TM) { + + // Set up the register classes. + addRegisterClass(MVT::i16, &CAHP::GPRRegClass); + + // Compute derived properties from the register classes. + computeRegisterProperties(STI.getRegisterInfo()); + + setStackPointerRegisterToSaveRestore(CAHP::X1); + + // TODO: add all necessary setOperationAction calls. + + setBooleanContents(ZeroOrOneBooleanContent); + + // Function alignments (log2). + setMinFunctionAlignment(1); + setPrefFunctionAlignment(1); +} + +SDValue CAHPTargetLowering::LowerOperation(SDValue Op, + SelectionDAG &DAG) const { + switch (Op.getOpcode()) { + default: + report_fatal_error("unimplemented operand"); + } +} + +// Calling Convention Implementation. +#include "CAHPGenCallingConv.inc" + +// Transform physical registers into virtual registers. +SDValue CAHPTargetLowering::LowerFormalArguments( + SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, + const SmallVectorImpl &Ins, const SDLoc &DL, + SelectionDAG &DAG, SmallVectorImpl &InVals) const { + + switch (CallConv) { + default: + report_fatal_error("Unsupported calling convention"); + case CallingConv::C: + break; + } + + MachineFunction &MF = DAG.getMachineFunction(); + MachineRegisterInfo &RegInfo = MF.getRegInfo(); + + if (IsVarArg) + report_fatal_error("VarArg not supported"); + + // Assign locations to all of the incoming arguments. + SmallVector ArgLocs; + CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext()); + CCInfo.AnalyzeFormalArguments(Ins, CC_CAHP); + + for (auto &VA : ArgLocs) { + if (!VA.isRegLoc()) + report_fatal_error("Defined with too many args"); + + // Arguments passed in registers. + EVT RegVT = VA.getLocVT(); + if (RegVT != MVT::i16) { + LLVM_DEBUG(dbgs() << "LowerFormalArguments Unhandled argument type: " + << RegVT.getEVTString() << "\n"); + report_fatal_error("unhandled argument type"); + } + const unsigned VReg = RegInfo.createVirtualRegister(&CAHP::GPRRegClass); + RegInfo.addLiveIn(VA.getLocReg(), VReg); + SDValue ArgIn = DAG.getCopyFromReg(Chain, DL, VReg, RegVT); + + InVals.push_back(ArgIn); + } + return Chain; +} + +SDValue +CAHPTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv, + bool IsVarArg, + const SmallVectorImpl &Outs, + const SmallVectorImpl &OutVals, + const SDLoc &DL, SelectionDAG &DAG) const { + if (IsVarArg) { + report_fatal_error("VarArg not supported"); + } + + // Stores the assignment of the return value to a location. + SmallVector RVLocs; + + // Info about the registers and stack slot. + CCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), RVLocs, + *DAG.getContext()); + + CCInfo.AnalyzeReturn(Outs, RetCC_CAHP); + + SDValue Flag; + SmallVector RetOps(1, Chain); + + // Copy the result values into the output registers. + for (unsigned i = 0, e = RVLocs.size(); i < e; ++i) { + CCValAssign &VA = RVLocs[i]; + assert(VA.isRegLoc() && "Can only return in registers!"); + + Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), OutVals[i], Flag); + + // Guarantee that all emitted copies are stuck together. + Flag = Chain.getValue(1); + RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT())); + } + + RetOps[0] = Chain; // Update chain. + + // Add the flag if we have it. + if (Flag.getNode()) { + RetOps.push_back(Flag); + } + + return DAG.getNode(CAHPISD::RET_FLAG, DL, MVT::Other, RetOps); +} + +const char *CAHPTargetLowering::getTargetNodeName(unsigned Opcode) const { + switch ((CAHPISD::NodeType)Opcode) { + case CAHPISD::FIRST_NUMBER: + break; + case CAHPISD::RET_FLAG: + return "CAHPISD::RET_FLAG"; + } + return nullptr; +} diff --git a/llvm/lib/Target/CAHP/CAHPISelLowering.h b/llvm/lib/Target/CAHP/CAHPISelLowering.h new file mode 100644 index 000000000000..0e4166f9a267 --- /dev/null +++ b/llvm/lib/Target/CAHP/CAHPISelLowering.h @@ -0,0 +1,47 @@ +// This file is copied and modified from The LLVM Compiler Infrastructure, which +// is distributed under the Apache License v2.0 with LLVM Exceptions (see +// LICENSE.TXT for details). This file is licensed under the same license. + +#ifndef LLVM_LIB_TARGET_CAHP_CAHPISELLOWERING_H +#define LLVM_LIB_TARGET_CAHP_CAHPISELLOWERING_H + +#include "CAHP.h" +#include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/CodeGen/TargetLowering.h" + +namespace llvm { +class CAHPSubtarget; +namespace CAHPISD { +enum NodeType : unsigned { FIRST_NUMBER = ISD::BUILTIN_OP_END, RET_FLAG }; +} + +class CAHPTargetLowering : public TargetLowering { +public: + explicit CAHPTargetLowering(const TargetMachine &TM, + const CAHPSubtarget &STI); + + // Provide custom lowering hooks for some operations. + SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override; + + // This method returns the name of a target specific DAG node. + const char *getTargetNodeName(unsigned Opcode) const override; + +private: + // Lower incoming arguments, copy physregs into vregs + SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, + bool IsVarArg, + const SmallVectorImpl &Ins, + const SDLoc &DL, SelectionDAG &DAG, + SmallVectorImpl &InVals) const override; + SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, + const SmallVectorImpl &Outs, + const SmallVectorImpl &OutVals, const SDLoc &DL, + SelectionDAG &DAG) const override; + bool shouldConvertConstantLoadToIntImm(const APInt &Imm, + Type *Ty) const override { + return true; + } +}; +} // namespace llvm + +#endif diff --git a/llvm/lib/Target/CAHP/CAHPInstrInfo.cpp b/llvm/lib/Target/CAHP/CAHPInstrInfo.cpp new file mode 100644 index 000000000000..480139b97e7b --- /dev/null +++ b/llvm/lib/Target/CAHP/CAHPInstrInfo.cpp @@ -0,0 +1,22 @@ +// This file is copied and modified from The LLVM Compiler Infrastructure, which +// is distributed under the Apache License v2.0 with LLVM Exceptions (see +// LICENSE.TXT for details). This file is licensed under the same license. + +#include "CAHPInstrInfo.h" +#include "CAHP.h" +#include "CAHPSubtarget.h" +#include "CAHPTargetMachine.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/TargetRegistry.h" + +#define GET_INSTRINFO_CTOR_DTOR +#include "CAHPGenInstrInfo.inc" + +using namespace llvm; + +CAHPInstrInfo::CAHPInstrInfo() : CAHPGenInstrInfo() {} diff --git a/llvm/lib/Target/CAHP/CAHPInstrInfo.h b/llvm/lib/Target/CAHP/CAHPInstrInfo.h new file mode 100644 index 000000000000..a5002c9b2500 --- /dev/null +++ b/llvm/lib/Target/CAHP/CAHPInstrInfo.h @@ -0,0 +1,23 @@ +// This file is copied and modified from The LLVM Compiler Infrastructure, which +// is distributed under the Apache License v2.0 with LLVM Exceptions (see +// LICENSE.TXT for details). This file is licensed under the same license. + +#ifndef LLVM_LIB_TARGET_CAHP_CAHPINSTRINFO_H +#define LLVM_LIB_TARGET_CAHP_CAHPINSTRINFO_H + +#include "CAHPRegisterInfo.h" +#include "llvm/CodeGen/TargetInstrInfo.h" + +#define GET_INSTRINFO_HEADER +#include "CAHPGenInstrInfo.inc" + +namespace llvm { + +class CAHPInstrInfo : public CAHPGenInstrInfo { + +public: + CAHPInstrInfo(); +}; +} // namespace llvm + +#endif diff --git a/llvm/lib/Target/CAHP/CAHPInstrInfo.td b/llvm/lib/Target/CAHP/CAHPInstrInfo.td index 15adbf273a6a..b160740872b1 100644 --- a/llvm/lib/Target/CAHP/CAHPInstrInfo.td +++ b/llvm/lib/Target/CAHP/CAHPInstrInfo.td @@ -4,6 +4,9 @@ include "CAHPInstrFormats.td" +def RetFlag : SDNode<"CAHPISD::RET_FLAG", SDTNone, + [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; + class ImmAsmOperand : AsmOperandClass { let Name = prefix # "Imm" # width # suffix; let RenderMethod = "addImmOperands"; @@ -234,3 +237,7 @@ let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in def NOP : CAHPInst16<(outs), (ins), "nop", ""> { let Inst = 0; } + +let isBarrier = 1, isReturn = 1, isTerminator = 1 in +def PseudoRET : Pseudo<(outs), (ins), [(RetFlag)]>, + PseudoInstExpansion<(JR X0)>; diff --git a/llvm/lib/Target/CAHP/CAHPMCInstLower.cpp b/llvm/lib/Target/CAHP/CAHPMCInstLower.cpp new file mode 100644 index 000000000000..c8ae328090e0 --- /dev/null +++ b/llvm/lib/Target/CAHP/CAHPMCInstLower.cpp @@ -0,0 +1,39 @@ +// This file is copied and modified from The LLVM Compiler Infrastructure, which +// is distributed under the Apache License v2.0 with LLVM Exceptions (see +// LICENSE.TXT for details). This file is licensed under the same license. + +#include "CAHP.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCExpr.h" +#include "llvm/MC/MCInst.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +void llvm::LowerCAHPMachineInstrToMCInst(const MachineInstr *MI, + MCInst &OutMI) { + OutMI.setOpcode(MI->getOpcode()); + + for (const MachineOperand &MO : MI->operands()) { + MCOperand MCOp; + switch (MO.getType()) { + default: + report_fatal_error("LowerCAHPMachineInstrToMCInst: unknown operand type"); + case MachineOperand::MO_Register: + // Ignore all implicit register operands. + if (MO.isImplicit()) + continue; + MCOp = MCOperand::createReg(MO.getReg()); + break; + case MachineOperand::MO_Immediate: + MCOp = MCOperand::createImm(MO.getImm()); + break; + } + + OutMI.addOperand(MCOp); + } +} diff --git a/llvm/lib/Target/CAHP/CAHPRegisterInfo.cpp b/llvm/lib/Target/CAHP/CAHPRegisterInfo.cpp new file mode 100644 index 000000000000..6dae41a91464 --- /dev/null +++ b/llvm/lib/Target/CAHP/CAHPRegisterInfo.cpp @@ -0,0 +1,50 @@ +// This file is copied and modified from The LLVM Compiler Infrastructure, which +// is distributed under the Apache License v2.0 with LLVM Exceptions (see +// LICENSE.TXT for details). This file is licensed under the same license. + +#include "CAHPRegisterInfo.h" +#include "CAHP.h" +#include "CAHPSubtarget.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/RegisterScavenging.h" +#include "llvm/CodeGen/TargetFrameLowering.h" +#include "llvm/CodeGen/TargetInstrInfo.h" +#include "llvm/Support/ErrorHandling.h" + +#define GET_REGINFO_TARGET_DESC +#include "CAHPGenRegisterInfo.inc" + +using namespace llvm; + +CAHPRegisterInfo::CAHPRegisterInfo(unsigned HwMode) + : CAHPGenRegisterInfo(/* RA */ CAHP::X0, /*DwarfFlavour*/ 0, + /*EHFlavor*/ 0, + /*PC*/ 0, HwMode) {} + +const MCPhysReg * +CAHPRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { + return CSR_SaveList; +} + +BitVector CAHPRegisterInfo::getReservedRegs(const MachineFunction &MF) const { + BitVector Reserved(getNumRegs()); + + // Use markSuperRegs to ensure any register aliases are also reserved + markSuperRegs(Reserved, CAHP::X0); // ra + markSuperRegs(Reserved, CAHP::X1); // sp + markSuperRegs(Reserved, CAHP::X2); // fp + assert(checkAllSuperRegsMarked(Reserved)); + return Reserved; +} + +void CAHPRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, + int SPAdj, unsigned FIOperandNum, + RegScavenger *RS) const { + report_fatal_error("Subroutines not supported yet"); +} + +Register CAHPRegisterInfo::getFrameRegister(const MachineFunction &MF) const { + return CAHP::X2; +} diff --git a/llvm/lib/Target/CAHP/CAHPRegisterInfo.h b/llvm/lib/Target/CAHP/CAHPRegisterInfo.h new file mode 100644 index 000000000000..70c940c13e17 --- /dev/null +++ b/llvm/lib/Target/CAHP/CAHPRegisterInfo.h @@ -0,0 +1,31 @@ +// This file is copied and modified from The LLVM Compiler Infrastructure, which +// is distributed under the Apache License v2.0 with LLVM Exceptions (see +// LICENSE.TXT for details). This file is licensed under the same license. + +#ifndef LLVM_LIB_TARGET_CAHP_CAHPREGISTERINFO_H +#define LLVM_LIB_TARGET_CAHP_CAHPREGISTERINFO_H + +#include "llvm/CodeGen/TargetRegisterInfo.h" + +#define GET_REGINFO_HEADER +#include "CAHPGenRegisterInfo.inc" + +namespace llvm { + +struct CAHPRegisterInfo : public CAHPGenRegisterInfo { + + CAHPRegisterInfo(unsigned HwMode); + + const MCPhysReg *getCalleeSavedRegs(const MachineFunction *MF) const override; + + BitVector getReservedRegs(const MachineFunction &MF) const override; + + void eliminateFrameIndex(MachineBasicBlock::iterator MI, int SPAdj, + unsigned FIOperandNum, + RegScavenger *RS = nullptr) const override; + + Register getFrameRegister(const MachineFunction &MF) const override; +}; +} // namespace llvm + +#endif diff --git a/llvm/lib/Target/CAHP/CAHPSubtarget.cpp b/llvm/lib/Target/CAHP/CAHPSubtarget.cpp new file mode 100644 index 000000000000..7f26657b9a74 --- /dev/null +++ b/llvm/lib/Target/CAHP/CAHPSubtarget.cpp @@ -0,0 +1,34 @@ +// This file is copied and modified from The LLVM Compiler Infrastructure, which +// is distributed under the Apache License v2.0 with LLVM Exceptions (see +// LICENSE.TXT for details). This file is licensed under the same license. + +#include "CAHPSubtarget.h" +#include "CAHP.h" +#include "CAHPFrameLowering.h" +#include "llvm/Support/TargetRegistry.h" + +using namespace llvm; + +#define DEBUG_TYPE "cahp-subtarget" + +#define GET_SUBTARGETINFO_TARGET_DESC +#define GET_SUBTARGETINFO_CTOR +#include "CAHPGenSubtargetInfo.inc" + +void CAHPSubtarget::anchor() {} + +CAHPSubtarget &CAHPSubtarget::initializeSubtargetDependencies(StringRef CPU, + StringRef FS) { + // Determine default and user-specified characteristics + std::string CPUName = CPU; + if (CPUName.empty()) + CPUName = "generic-cahp"; + ParseSubtargetFeatures(CPUName, FS); + return *this; +} + +CAHPSubtarget::CAHPSubtarget(const Triple &TT, const std::string &CPU, + const std::string &FS, const TargetMachine &TM) + : CAHPGenSubtargetInfo(TT, CPU, FS), + FrameLowering(initializeSubtargetDependencies(CPU, FS)), InstrInfo(), + RegInfo(getHwMode()), TLInfo(TM, *this) {} diff --git a/llvm/lib/Target/CAHP/CAHPSubtarget.h b/llvm/lib/Target/CAHP/CAHPSubtarget.h new file mode 100644 index 000000000000..2592c29ded33 --- /dev/null +++ b/llvm/lib/Target/CAHP/CAHPSubtarget.h @@ -0,0 +1,57 @@ +// This file is copied and modified from The LLVM Compiler Infrastructure, which +// is distributed under the Apache License v2.0 with LLVM Exceptions (see +// LICENSE.TXT for details). This file is licensed under the same license. + +#ifndef LLVM_LIB_TARGET_CAHP_CAHPSUBTARGET_H +#define LLVM_LIB_TARGET_CAHP_CAHPSUBTARGET_H + +#include "CAHPFrameLowering.h" +#include "CAHPISelLowering.h" +#include "CAHPInstrInfo.h" +#include "llvm/CodeGen/SelectionDAGTargetInfo.h" +#include "llvm/CodeGen/TargetSubtargetInfo.h" +#include "llvm/IR/DataLayout.h" +#include "llvm/Target/TargetMachine.h" + +#define GET_SUBTARGETINFO_HEADER +#include "CAHPGenSubtargetInfo.inc" + +namespace llvm { +class StringRef; + +class CAHPSubtarget : public CAHPGenSubtargetInfo { + virtual void anchor(); + CAHPFrameLowering FrameLowering; + CAHPInstrInfo InstrInfo; + CAHPRegisterInfo RegInfo; + CAHPTargetLowering TLInfo; + SelectionDAGTargetInfo TSInfo; + + /// Initializes using the passed in CPU and feature strings so that we can + /// use initializer lists for subtarget initialization. + CAHPSubtarget &initializeSubtargetDependencies(StringRef CPU, StringRef FS); + +public: + // Initializes the data members to match that of the specified triple. + CAHPSubtarget(const Triple &TT, const std::string &CPU, const std::string &FS, + const TargetMachine &TM); + + // Parses features string setting specified subtarget options. The + // definition of this function is auto-generated by tblgen. + void ParseSubtargetFeatures(StringRef CPU, StringRef FS); + + const CAHPFrameLowering *getFrameLowering() const override { + return &FrameLowering; + } + const CAHPInstrInfo *getInstrInfo() const override { return &InstrInfo; } + const CAHPRegisterInfo *getRegisterInfo() const override { return &RegInfo; } + const CAHPTargetLowering *getTargetLowering() const override { + return &TLInfo; + } + const SelectionDAGTargetInfo *getSelectionDAGInfo() const override { + return &TSInfo; + } +}; +} // namespace llvm + +#endif diff --git a/llvm/lib/Target/CAHP/CAHPTargetMachine.cpp b/llvm/lib/Target/CAHP/CAHPTargetMachine.cpp index 355891a4cbe6..fc1c8f9a7a1b 100644 --- a/llvm/lib/Target/CAHP/CAHPTargetMachine.cpp +++ b/llvm/lib/Target/CAHP/CAHPTargetMachine.cpp @@ -42,10 +42,31 @@ CAHPTargetMachine::CAHPTargetMachine(const Target &T, const Triple &TT, : LLVMTargetMachine(T, computeDataLayout(TT), TT, CPU, FS, Options, getEffectiveRelocModel(TT, RM), getEffectiveCodeModel(CM, CodeModel::Small), OL), - TLOF(make_unique()) { + TLOF(make_unique()), + Subtarget(TT, CPU, FS, *this) { initAsmInfo(); } +namespace { +class CAHPPassConfig : public TargetPassConfig { +public: + CAHPPassConfig(CAHPTargetMachine &TM, PassManagerBase &PM) + : TargetPassConfig(TM, PM) {} + + CAHPTargetMachine &getCAHPTargetMachine() const { + return getTM(); + } + + bool addInstSelector() override; +}; +} // namespace + TargetPassConfig *CAHPTargetMachine::createPassConfig(PassManagerBase &PM) { - return new TargetPassConfig(*this, PM); + return new CAHPPassConfig(*this, PM); +} + +bool CAHPPassConfig::addInstSelector() { + addPass(createCAHPISelDag(getCAHPTargetMachine())); + + return false; } diff --git a/llvm/lib/Target/CAHP/CAHPTargetMachine.h b/llvm/lib/Target/CAHP/CAHPTargetMachine.h index aeddc3ded028..67ca7694f54c 100644 --- a/llvm/lib/Target/CAHP/CAHPTargetMachine.h +++ b/llvm/lib/Target/CAHP/CAHPTargetMachine.h @@ -5,6 +5,7 @@ #ifndef LLVM_LIB_TARGET_CAHP_CAHPTARGETMACHINE_H #define LLVM_LIB_TARGET_CAHP_CAHPTARGETMACHINE_H +#include "CAHPSubtarget.h" #include "MCTargetDesc/CAHPMCTargetDesc.h" #include "llvm/CodeGen/SelectionDAGTargetInfo.h" #include "llvm/IR/DataLayout.h" @@ -13,6 +14,7 @@ namespace llvm { class CAHPTargetMachine : public LLVMTargetMachine { std::unique_ptr TLOF; + CAHPSubtarget Subtarget; public: CAHPTargetMachine(const Target &T, const Triple &TT, StringRef CPU, @@ -20,6 +22,10 @@ class CAHPTargetMachine : public LLVMTargetMachine { Optional RM, Optional CM, CodeGenOpt::Level OL, bool JIT); + const CAHPSubtarget *getSubtargetImpl(const Function &) const override { + return &Subtarget; + } + TargetPassConfig *createPassConfig(PassManagerBase &PM) override; TargetLoweringObjectFile *getObjFileLowering() const override { diff --git a/llvm/lib/Target/CAHP/CMakeLists.txt b/llvm/lib/Target/CAHP/CMakeLists.txt index 78861912c1a3..ff433de1ad2c 100644 --- a/llvm/lib/Target/CAHP/CMakeLists.txt +++ b/llvm/lib/Target/CAHP/CMakeLists.txt @@ -1,16 +1,27 @@ set(LLVM_TARGET_DEFINITIONS CAHP.td) -tablegen(LLVM CAHPGenRegisterInfo.inc -gen-register-info) -tablegen(LLVM CAHPGenInstrInfo.inc -gen-instr-info) -tablegen(LLVM CAHPGenMCCodeEmitter.inc -gen-emitter) -tablegen(LLVM CAHPGenSubtargetInfo.inc -gen-subtarget) tablegen(LLVM CAHPGenAsmMatcher.inc -gen-asm-matcher) tablegen(LLVM CAHPGenAsmWriter.inc -gen-asm-writer) +tablegen(LLVM CAHPGenCallingConv.inc -gen-callingconv) +tablegen(LLVM CAHPGenDAGISel.inc -gen-dag-isel) tablegen(LLVM CAHPGenDisassemblerTables.inc -gen-disassembler) +tablegen(LLVM CAHPGenInstrInfo.inc -gen-instr-info) +tablegen(LLVM CAHPGenMCCodeEmitter.inc -gen-emitter) +tablegen(LLVM CAHPGenMCPseudoLowering.inc -gen-pseudo-lowering) +tablegen(LLVM CAHPGenRegisterInfo.inc -gen-register-info) +tablegen(LLVM CAHPGenSubtargetInfo.inc -gen-subtarget) add_public_tablegen_target(CAHPCommonTableGen) add_llvm_target(CAHPCodeGen + CAHPAsmPrinter.cpp + CAHPFrameLowering.cpp + CAHPISelDAGToDAG.cpp + CAHPISelLowering.cpp + CAHPInstrInfo.cpp + CAHPMCInstLower.cpp + CAHPRegisterInfo.cpp + CAHPSubtarget.cpp CAHPTargetMachine.cpp ) add_subdirectory(AsmParser) diff --git a/llvm/lib/Target/CAHP/LLVMBuild.txt b/llvm/lib/Target/CAHP/LLVMBuild.txt index 836740c1c763..3681c230dc6b 100644 --- a/llvm/lib/Target/CAHP/LLVMBuild.txt +++ b/llvm/lib/Target/CAHP/LLVMBuild.txt @@ -17,5 +17,6 @@ has_disassembler = 1 type = Library name = CAHPCodeGen parent = CAHP -required_libraries = AsmPrinter Core CodeGen MC CAHPAsmPrinter CAHPDesc CAHPInfo Support Target +required_libraries = AsmPrinter CAHPAsmPrinter CAHPDesc CAHPInfo + CodeGen Core MC SelectionDAG Support Target add_to_library_groups = CAHP From 4cc30950f2a09bdb5ccd2f4e48c38296b2c30ea9 Mon Sep 17 00:00:00 2001 From: Ushitora Anqou Date: Mon, 21 Oct 2019 17:59:30 +0900 Subject: [PATCH 236/289] [CAHP] Add codegen patterns for instrs using alu --- llvm/lib/Target/CAHP/CAHPInstrInfo.td | 23 ++++- llvm/test/CodeGen/CAHP/alu16.ll | 143 ++++++++++++++++++++++++++ llvm/test/CodeGen/CAHP/lit.local.cfg | 2 + 3 files changed, 166 insertions(+), 2 deletions(-) create mode 100644 llvm/test/CodeGen/CAHP/alu16.ll create mode 100644 llvm/test/CodeGen/CAHP/lit.local.cfg diff --git a/llvm/lib/Target/CAHP/CAHPInstrInfo.td b/llvm/lib/Target/CAHP/CAHPInstrInfo.td index b160740872b1..01751913337c 100644 --- a/llvm/lib/Target/CAHP/CAHPInstrInfo.td +++ b/llvm/lib/Target/CAHP/CAHPInstrInfo.td @@ -21,7 +21,7 @@ class UImmAsmOperand : ImmAsmOperand<"U", width, suffix> { } -def uimm4 : Operand { +def uimm4 : Operand, ImmLeaf(Imm);}]> { let ParserMatchClass = UImmAsmOperand<4>; let DecoderMethod = "decodeUImmOperand<4>"; let EncoderMethod = "getImmOpValue"; @@ -33,7 +33,7 @@ def simm6 : Operand { let EncoderMethod = "getImmOpValue"; } -def simm10 : Operand { +def simm10 : Operand, ImmLeaf(Imm);}]> { let ParserMatchClass = SImmAsmOperand<10>; let DecoderMethod = "decodeSImmOperand<10>"; let EncoderMethod = "getImmOpValue"; @@ -241,3 +241,22 @@ def NOP : CAHPInst16<(outs), (ins), "nop", ""> { let isBarrier = 1, isReturn = 1, isTerminator = 1 in def PseudoRET : Pseudo<(outs), (ins), [(RetFlag)]>, PseudoInstExpansion<(JR X0)>; + +// Codegen patterns. + +def : Pat<(add GPR:$rs1, GPR:$rs2), (ADD GPR:$rs1, GPR:$rs2)>; +def : Pat<(sub GPR:$rs1, GPR:$rs2), (SUB GPR:$rs1, GPR:$rs2)>; +def : Pat<(and GPR:$rs1, GPR:$rs2), (AND GPR:$rs1, GPR:$rs2)>; +def : Pat<(xor GPR:$rs1, GPR:$rs2), (XOR GPR:$rs1, GPR:$rs2)>; +def : Pat<(or GPR:$rs1, GPR:$rs2), (OR GPR:$rs1, GPR:$rs2)>; +def : Pat<(shl GPR:$rs1, GPR:$rs2), (LSL GPR:$rs1, GPR:$rs2)>; +def : Pat<(srl GPR:$rs1, GPR:$rs2), (LSR GPR:$rs1, GPR:$rs2)>; +def : Pat<(sra GPR:$rs1, GPR:$rs2), (ASR GPR:$rs1, GPR:$rs2)>; + +def : Pat<(add GPR:$rs1, simm10:$imm), (ADDI GPR:$rs1, simm10:$imm)>; +def : Pat<(and GPR:$rs1, simm10:$imm), (ANDI GPR:$rs1, simm10:$imm)>; +def : Pat<(xor GPR:$rs1, simm10:$imm), (XORI GPR:$rs1, simm10:$imm)>; +def : Pat<(or GPR:$rs1, simm10:$imm), (ORI GPR:$rs1, simm10:$imm)>; +def : Pat<(shl GPR:$rs1, uimm4:$imm), (LSLI GPR:$rs1, uimm4:$imm)>; +def : Pat<(srl GPR:$rs1, uimm4:$imm), (LSRI GPR:$rs1, uimm4:$imm)>; +def : Pat<(sra GPR:$rs1, uimm4:$imm), (ASRI GPR:$rs1, uimm4:$imm)>; diff --git a/llvm/test/CodeGen/CAHP/alu16.ll b/llvm/test/CodeGen/CAHP/alu16.ll new file mode 100644 index 000000000000..f122ea7e8e67 --- /dev/null +++ b/llvm/test/CodeGen/CAHP/alu16.ll @@ -0,0 +1,143 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=cahp -verify-machineinstrs < %s \ +; RUN: | FileCheck %s -check-prefix=CAHP + +; Register-immediate instructions + +define i16 @addi(i16 %a) nounwind { +; CAHP-LABEL: addi: +; CAHP: # %bb.0: +; CAHP-NEXT: addi a0, a0, 1 +; CAHP-NEXT: jr ra +; TODO: check support for materialising larger constants + %1 = add i16 %a, 1 + ret i16 %1 +} + +define i16 @xori(i16 %a) nounwind { +; CAHP-LABEL: xori: +; CAHP: # %bb.0: +; CAHP-NEXT: xori a0, a0, 4 +; CAHP-NEXT: jr ra + %1 = xor i16 %a, 4 + ret i16 %1 +} + +define i16 @ori(i16 %a) nounwind { +; CAHP-LABEL: ori: +; CAHP: # %bb.0: +; CAHP-NEXT: ori a0, a0, 5 +; CAHP-NEXT: jr ra + %1 = or i16 %a, 5 + ret i16 %1 +} + +define i16 @andi(i16 %a) nounwind { +; CAHP-LABEL: andi: +; CAHP: # %bb.0: +; CAHP-NEXT: andi a0, a0, 6 +; CAHP-NEXT: jr ra + %1 = and i16 %a, 6 + ret i16 %1 +} + +define i16 @lsli(i16 %a) nounwind { +; CAHP-LABEL: lsli: +; CAHP: # %bb.0: +; CAHP-NEXT: lsli a0, a0, 7 +; CAHP-NEXT: jr ra + %1 = shl i16 %a, 7 + ret i16 %1 +} + +define i16 @lsri(i16 %a) nounwind { +; CAHP-LABEL: lsri: +; CAHP: # %bb.0: +; CAHP-NEXT: lsri a0, a0, 8 +; CAHP-NEXT: jr ra + %1 = lshr i16 %a, 8 + ret i16 %1 +} + +define i16 @asri(i16 %a) nounwind { +; CAHP-LABEL: asri: +; CAHP: # %bb.0: +; CAHP-NEXT: asri a0, a0, 9 +; CAHP-NEXT: jr ra + %1 = ashr i16 %a, 9 + ret i16 %1 +} + +; Register-register instructions + +define i16 @add(i16 %a, i16 %b) nounwind { +; CAHP-LABEL: add: +; CAHP: # %bb.0: +; CAHP-NEXT: add a0, a0, a1 +; CAHP-NEXT: jr ra + %1 = add i16 %a, %b + ret i16 %1 +} + +define i16 @sub(i16 %a, i16 %b) nounwind { +; CAHP-LABEL: sub: +; CAHP: # %bb.0: +; CAHP-NEXT: sub a0, a0, a1 +; CAHP-NEXT: jr ra + %1 = sub i16 %a, %b + ret i16 %1 +} + +define i16 @lsl(i16 %a, i16 %b) nounwind { +; CAHP-LABEL: lsl: +; CAHP: # %bb.0: +; CAHP-NEXT: lsl a0, a0, a1 +; CAHP-NEXT: jr ra + %1 = shl i16 %a, %b + ret i16 %1 +} + +define i16 @xor(i16 %a, i16 %b) nounwind { +; CAHP-LABEL: xor: +; CAHP: # %bb.0: +; CAHP-NEXT: xor a0, a0, a1 +; CAHP-NEXT: jr ra + %1 = xor i16 %a, %b + ret i16 %1 +} + +define i16 @lsr(i16 %a, i16 %b) nounwind { +; CAHP-LABEL: lsr: +; CAHP: # %bb.0: +; CAHP-NEXT: lsr a0, a0, a1 +; CAHP-NEXT: jr ra + %1 = lshr i16 %a, %b + ret i16 %1 +} + +define i16 @asr(i16 %a, i16 %b) nounwind { +; CAHP-LABEL: asr: +; CAHP: # %bb.0: +; CAHP-NEXT: asr a0, a0, a1 +; CAHP-NEXT: jr ra + %1 = ashr i16 %a, %b + ret i16 %1 +} + +define i16 @or(i16 %a, i16 %b) nounwind { +; CAHP-LABEL: or: +; CAHP: # %bb.0: +; CAHP-NEXT: or a0, a0, a1 +; CAHP-NEXT: jr ra + %1 = or i16 %a, %b + ret i16 %1 +} + +define i16 @and(i16 %a, i16 %b) nounwind { +; CAHP-LABEL: and: +; CAHP: # %bb.0: +; CAHP-NEXT: and a0, a0, a1 +; CAHP-NEXT: jr ra + %1 = and i16 %a, %b + ret i16 %1 +} diff --git a/llvm/test/CodeGen/CAHP/lit.local.cfg b/llvm/test/CodeGen/CAHP/lit.local.cfg new file mode 100644 index 000000000000..519647fc4da4 --- /dev/null +++ b/llvm/test/CodeGen/CAHP/lit.local.cfg @@ -0,0 +1,2 @@ +if not 'CAHP' in config.root.targets: + config.unsupported = True From 01169e875f5a73405bf16d600b87b962a23aa6d1 Mon Sep 17 00:00:00 2001 From: Ushitora Anqou Date: Tue, 22 Oct 2019 10:20:57 +0900 Subject: [PATCH 237/289] [CAHP] Codegen support for materializing constants --- llvm/lib/Target/CAHP/CAHPInstrInfo.td | 28 +++++++++- llvm/test/CodeGen/CAHP/alu16.ll | 1 - llvm/test/CodeGen/CAHP/imm.ll | 79 +++++++++++++++++++++++++++ 3 files changed, 105 insertions(+), 3 deletions(-) create mode 100644 llvm/test/CodeGen/CAHP/imm.ll diff --git a/llvm/lib/Target/CAHP/CAHPInstrInfo.td b/llvm/lib/Target/CAHP/CAHPInstrInfo.td index 01751913337c..a8bf73d8f73f 100644 --- a/llvm/lib/Target/CAHP/CAHPInstrInfo.td +++ b/llvm/lib/Target/CAHP/CAHPInstrInfo.td @@ -27,13 +27,13 @@ def uimm4 : Operand, ImmLeaf(Imm);}]> { let EncoderMethod = "getImmOpValue"; } -def simm6 : Operand { +def simm6 : Operand, ImmLeaf(Imm);}]> { let ParserMatchClass = SImmAsmOperand<6>; let DecoderMethod = "decodeSImmOperand<6>"; let EncoderMethod = "getImmOpValue"; } -def simm10 : Operand, ImmLeaf(Imm);}]> { +def simm10 : Operand, ImmLeaf(Imm);}]> { let ParserMatchClass = SImmAsmOperand<10>; let DecoderMethod = "decodeSImmOperand<10>"; let EncoderMethod = "getImmOpValue"; @@ -51,6 +51,25 @@ def uimm7_lsb0 : Operand { let EncoderMethod = "getImmOpValue"; } +// Standalone (codegen-only) immleaf patterns. +def simm16 : ImmLeaf(Imm);}]>; +def simm16hi6 : ImmLeaf(Imm);}]>; + +// Extract least significant 10 bits from an immediate value and sign extend +// them. +def LO10Sext : SDNodeXFormgetTargetConstant(SignExtend64<10>(N->getZExtValue()), + SDLoc(N), N->getValueType(0)); +}]>; + +// Extract the most significant 6 bits from an immediate value. Add 1 if bit +// 9 is 1, to compensate for the low 10 bits in the matching immediate addi +// or ld/st being negative. +def HI6 : SDNodeXFormgetTargetConstant(((N->getZExtValue()+0x200) >> 10) & 0x3f, + SDLoc(N), N->getValueType(0)); +}]>; + // 24-bit M-instructions. let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in { @@ -244,6 +263,11 @@ def PseudoRET : Pseudo<(outs), (ins), [(RetFlag)]>, // Codegen patterns. +def : Pat<(simm6:$imm), (LSI simm6:$imm)>; +def : Pat<(simm10:$imm), (LI simm10:$imm)>; +def : Pat<(simm16hi6:$imm), (LUI (HI6 imm:$imm))>; +def : Pat<(simm16:$imm), (ADDI (LUI (HI6 imm:$imm)), (LO10Sext imm:$imm))>; + def : Pat<(add GPR:$rs1, GPR:$rs2), (ADD GPR:$rs1, GPR:$rs2)>; def : Pat<(sub GPR:$rs1, GPR:$rs2), (SUB GPR:$rs1, GPR:$rs2)>; def : Pat<(and GPR:$rs1, GPR:$rs2), (AND GPR:$rs1, GPR:$rs2)>; diff --git a/llvm/test/CodeGen/CAHP/alu16.ll b/llvm/test/CodeGen/CAHP/alu16.ll index f122ea7e8e67..3e3b5c9a8ebb 100644 --- a/llvm/test/CodeGen/CAHP/alu16.ll +++ b/llvm/test/CodeGen/CAHP/alu16.ll @@ -9,7 +9,6 @@ define i16 @addi(i16 %a) nounwind { ; CAHP: # %bb.0: ; CAHP-NEXT: addi a0, a0, 1 ; CAHP-NEXT: jr ra -; TODO: check support for materialising larger constants %1 = add i16 %a, 1 ret i16 %1 } diff --git a/llvm/test/CodeGen/CAHP/imm.ll b/llvm/test/CodeGen/CAHP/imm.ll new file mode 100644 index 000000000000..31304675a970 --- /dev/null +++ b/llvm/test/CodeGen/CAHP/imm.ll @@ -0,0 +1,79 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=cahp -verify-machineinstrs < %s \ +; RUN: | FileCheck %s -check-prefix=CAHP + +; Materializing constants + +define i16 @zero() nounwind { +; CAHP-LABEL: zero: +; CAHP: # %bb.0: +; CAHP-NEXT: lsi a0, 0 +; CAHP-NEXT: jr ra + ret i16 0 +} + +define i16 @pos_small1() nounwind { +; CAHP-LABEL: pos_small1: +; CAHP: # %bb.0: +; CAHP-NEXT: lsi a0, 31 +; CAHP-NEXT: jr ra + ret i16 31 +} + +define i16 @neg_small1() nounwind { +; CAHP-LABEL: neg_small1: +; CAHP: # %bb.0: +; CAHP-NEXT: lsi a0, -32 +; CAHP-NEXT: jr ra + ret i16 -32 +} + +define i16 @pos_small2() nounwind { +; CAHP-LABEL: pos_small2: +; CAHP: # %bb.0: +; CAHP-NEXT: li a0, 511 +; CAHP-NEXT: jr ra + ret i16 511 +} + +define i16 @neg_small2() nounwind { +; CAHP-LABEL: neg_small2: +; CAHP: # %bb.0: +; CAHP-NEXT: li a0, -512 +; CAHP-NEXT: jr ra + ret i16 -512 +} + +define i16 @pos_i16() nounwind { +; CAHP-LABEL: pos_i16: +; CAHP: # %bb.0: +; CAHP-NEXT: lui a0, 22 +; CAHP-NEXT: addi a0, a0, 457 +; CAHP-NEXT: jr ra + ret i16 22985 +} + +define i16 @neg_i16() nounwind { +; CAHP-LABEL: neg_i16: +; CAHP: # %bb.0: +; CAHP-NEXT: lui a0, 42 +; CAHP-NEXT: addi a0, a0, -457 +; CAHP-NEXT: jr ra + ret i16 -22985 +} + +define i16 @pos_i16_hi6_only() nounwind { +; CAHP-LABEL: pos_i16_hi6_only: +; CAHP: # %bb.0: +; CAHP-NEXT: lui a0, 16 +; CAHP-NEXT: jr ra + ret i16 16384 +} + +define i16 @neg_i16_hi6_only() nounwind { +; CAHP-LABEL: neg_i16_hi6_only: +; CAHP: # %bb.0: +; CAHP-NEXT: lui a0, 32 +; CAHP-NEXT: jr ra + ret i16 -32768 +} From 4ba83f5e91ab50465c4836f8f978003c72354120 Mon Sep 17 00:00:00 2001 From: Ushitora Anqou Date: Wed, 23 Oct 2019 14:24:54 +0900 Subject: [PATCH 238/289] [CAHP] Codegen support for memory operations --- llvm/lib/Target/CAHP/CAHPISelLowering.cpp | 3 + llvm/lib/Target/CAHP/CAHPInstrInfo.cpp | 10 ++ llvm/lib/Target/CAHP/CAHPInstrInfo.h | 4 + llvm/lib/Target/CAHP/CAHPInstrInfo.td | 22 ++++- llvm/test/CodeGen/CAHP/mem.ll | 113 ++++++++++++++++++++++ llvm/test/CodeGen/CAHP/wide-mem.ll | 16 +++ 6 files changed, 166 insertions(+), 2 deletions(-) create mode 100644 llvm/test/CodeGen/CAHP/mem.ll create mode 100644 llvm/test/CodeGen/CAHP/wide-mem.ll diff --git a/llvm/lib/Target/CAHP/CAHPISelLowering.cpp b/llvm/lib/Target/CAHP/CAHPISelLowering.cpp index 82d44f99de47..41b8ed9cbb7d 100644 --- a/llvm/lib/Target/CAHP/CAHPISelLowering.cpp +++ b/llvm/lib/Target/CAHP/CAHPISelLowering.cpp @@ -37,6 +37,9 @@ CAHPTargetLowering::CAHPTargetLowering(const TargetMachine &TM, setStackPointerRegisterToSaveRestore(CAHP::X1); + for (auto N : {ISD::EXTLOAD, ISD::SEXTLOAD, ISD::ZEXTLOAD}) + setLoadExtAction(N, MVT::i16, MVT::i1, Promote); + // TODO: add all necessary setOperationAction calls. setBooleanContents(ZeroOrOneBooleanContent); diff --git a/llvm/lib/Target/CAHP/CAHPInstrInfo.cpp b/llvm/lib/Target/CAHP/CAHPInstrInfo.cpp index 480139b97e7b..1321965b7a9a 100644 --- a/llvm/lib/Target/CAHP/CAHPInstrInfo.cpp +++ b/llvm/lib/Target/CAHP/CAHPInstrInfo.cpp @@ -20,3 +20,13 @@ using namespace llvm; CAHPInstrInfo::CAHPInstrInfo() : CAHPGenInstrInfo() {} + +void CAHPInstrInfo::copyPhysReg(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + const DebugLoc &DL, unsigned DstReg, + unsigned SrcReg, bool KillSrc) const { + assert(CAHP::GPRRegClass.contains(DstReg, SrcReg) && + "Impossible reg-to-reg copy"); + + BuildMI(MBB, MBBI, DL, get(CAHP::MOV), DstReg).addReg(SrcReg); +} diff --git a/llvm/lib/Target/CAHP/CAHPInstrInfo.h b/llvm/lib/Target/CAHP/CAHPInstrInfo.h index a5002c9b2500..c8bc8a7d039d 100644 --- a/llvm/lib/Target/CAHP/CAHPInstrInfo.h +++ b/llvm/lib/Target/CAHP/CAHPInstrInfo.h @@ -17,6 +17,10 @@ class CAHPInstrInfo : public CAHPGenInstrInfo { public: CAHPInstrInfo(); + + void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, + const DebugLoc &DL, unsigned DstReg, unsigned SrcReg, + bool KillSrc) const override; }; } // namespace llvm diff --git a/llvm/lib/Target/CAHP/CAHPInstrInfo.td b/llvm/lib/Target/CAHP/CAHPInstrInfo.td index a8bf73d8f73f..7f6d2f9aaffc 100644 --- a/llvm/lib/Target/CAHP/CAHPInstrInfo.td +++ b/llvm/lib/Target/CAHP/CAHPInstrInfo.td @@ -82,9 +82,9 @@ let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in { } let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in { - def SW : CAHPInst24MStore<0b011101, (outs GPR:$rd), (ins GPR:$rs, simm10:$imm), + def SW : CAHPInst24MStore<0b011101, (outs), (ins GPR:$rs, GPR:$rd, simm10:$imm), "sw", "$rs, ${imm}(${rd})">; - def SB : CAHPInst24MStore<0b001101, (outs GPR:$rd), (ins GPR:$rs, simm10:$imm), + def SB : CAHPInst24MStore<0b001101, (outs), (ins GPR:$rs, GPR:$rd, simm10:$imm), "sb", "$rs, ${imm}(${rd})">; } @@ -268,6 +268,24 @@ def : Pat<(simm10:$imm), (LI simm10:$imm)>; def : Pat<(simm16hi6:$imm), (LUI (HI6 imm:$imm))>; def : Pat<(simm16:$imm), (ADDI (LUI (HI6 imm:$imm)), (LO10Sext imm:$imm))>; +multiclass LdPat { + def : Pat<(LoadOp GPR:$rs1), (Inst GPR:$rs1, 0)>; + def : Pat<(LoadOp (add GPR:$rs1, simm10:$imm)), + (Inst GPR:$rs1, simm10:$imm)>; +} +defm : LdPat; +defm : LdPat; +defm : LdPat; +defm : LdPat; + +multiclass StPat { + def : Pat<(StoreOp GPR:$rs, GPR:$rd), (Inst GPR:$rs, GPR:$rd, 0)>; + def : Pat<(StoreOp GPR:$rs, (add GPR:$rd, simm10:$imm)), + (Inst GPR:$rs, GPR:$rd, simm10:$imm)>; +} +defm : StPat; +defm : StPat; + def : Pat<(add GPR:$rs1, GPR:$rs2), (ADD GPR:$rs1, GPR:$rs2)>; def : Pat<(sub GPR:$rs1, GPR:$rs2), (SUB GPR:$rs1, GPR:$rs2)>; def : Pat<(and GPR:$rs1, GPR:$rs2), (AND GPR:$rs1, GPR:$rs2)>; diff --git a/llvm/test/CodeGen/CAHP/mem.ll b/llvm/test/CodeGen/CAHP/mem.ll new file mode 100644 index 000000000000..77c9cad2c7b6 --- /dev/null +++ b/llvm/test/CodeGen/CAHP/mem.ll @@ -0,0 +1,113 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=cahp -verify-machineinstrs < %s \ +; RUN: | FileCheck %s -check-prefix=CAHP + +; Check indexed and unindexed, sext, zext and anyext loads + +define i16 @lb(i8 *%a) nounwind { +; CAHP-LABEL: lb: +; CAHP: # %bb.0: +; CAHP-NEXT: lb a1, 0(a0) +; CAHP-NEXT: lb a0, 1(a0) +; CAHP-NEXT: jr ra + %1 = getelementptr i8, i8* %a, i16 1 + %2 = load i8, i8* %1 + %3 = sext i8 %2 to i16 + ; the unused load will produce an anyext for selection + %4 = load volatile i8, i8* %a + ret i16 %3 +} + +define i16 @lw(i16 *%a) nounwind { +; CAHP-LABEL: lw: +; CAHP: # %bb.0: +; CAHP-NEXT: lw a1, 0(a0) +; CAHP-NEXT: lw a0, 6(a0) +; CAHP-NEXT: jr ra + %1 = getelementptr i16, i16* %a, i16 3 + %2 = load i16, i16* %1 + %3 = load volatile i16, i16* %a + ret i16 %2 +} + +define i16 @lbu(i8 *%a) nounwind { +; CAHP-LABEL: lbu: +; CAHP: # %bb.0: +; CAHP-NEXT: lbu a1, 0(a0) +; CAHP-NEXT: lbu a0, 4(a0) +; CAHP-NEXT: add a0, a0, a1 +; CAHP-NEXT: jr ra + %1 = getelementptr i8, i8* %a, i16 4 + %2 = load i8, i8* %1 + %3 = zext i8 %2 to i16 + %4 = load volatile i8, i8* %a + %5 = zext i8 %4 to i16 + %6 = add i16 %3, %5 + ret i16 %6 +} + +; Check indexed and unindexed stores + +define void @sb(i8 *%a, i8 %b) nounwind { +; CAHP-LABEL: sb: +; CAHP: # %bb.0: +; CAHP-NEXT: sb a1, 6(a0) +; CAHP-NEXT: sb a1, 0(a0) +; CAHP-NEXT: jr ra + store i8 %b, i8* %a + %1 = getelementptr i8, i8* %a, i16 6 + store i8 %b, i8* %1 + ret void +} + +define void @sw(i16 *%a, i16 %b) nounwind { +; CAHP-LABEL: sw: +; CAHP: # %bb.0: +; CAHP-NEXT: sw a1, 16(a0) +; CAHP-NEXT: sw a1, 0(a0) +; CAHP-NEXT: jr ra + store i16 %b, i16* %a + %1 = getelementptr i16, i16* %a, i16 8 + store i16 %b, i16* %1 + ret void +} + +; Check load and store to an i1 location +define i16 @load_sext_zext_anyext_i1(i1 *%a) nounwind { +; CAHP-LABEL: load_sext_zext_anyext_i1: +; CAHP: # %bb.0: +; CAHP-NEXT: lb a1, 0(a0) +; CAHP-NEXT: lbu a1, 1(a0) +; CAHP-NEXT: lbu a0, 2(a0) +; CAHP-NEXT: sub a0, a0, a1 +; CAHP-NEXT: jr ra + ; sextload i1 + %1 = getelementptr i1, i1* %a, i16 1 + %2 = load i1, i1* %1 + %3 = sext i1 %2 to i16 + ; zextload i1 + %4 = getelementptr i1, i1* %a, i16 2 + %5 = load i1, i1* %4 + %6 = zext i1 %5 to i16 + %7 = add i16 %3, %6 + ; extload i1 (anyext). Produced as the load is unused. + %8 = load volatile i1, i1* %a + ret i16 %7 +} + +; Ensure that 1 is added to the high 6 bits if bit 9 of the low part is 1 +define i16 @lw_sw_constant(i16 %a) nounwind { +; TODO: the addi should be folded in to the lw/sw +; CAHP-LABEL: lw_sw_constant: +; CAHP: # %bb.0: +; CAHP-NEXT: lui a1, 11 +; CAHP-NEXT: addi a2, a1, -139 +; CAHP-NEXT: lw a1, 0(a2) +; CAHP-NEXT: sw a0, 0(a2) +; CAHP-NEXT: mov a0, a1 +; CAHP-NEXT: jr ra + %1 = inttoptr i16 11125 to i16* + %2 = load volatile i16, i16* %1 + store i16 %a, i16* %1 + ret i16 %2 +} diff --git a/llvm/test/CodeGen/CAHP/wide-mem.ll b/llvm/test/CodeGen/CAHP/wide-mem.ll new file mode 100644 index 000000000000..c411fa967526 --- /dev/null +++ b/llvm/test/CodeGen/CAHP/wide-mem.ll @@ -0,0 +1,16 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=cahp -verify-machineinstrs < %s \ +; RUN: | FileCheck %s -check-prefix=CAHP + +; Check load/store operations on values wider than what is natively supported + +define i32 @load_i32(i32 *%a) nounwind { +; CAHP-LABEL: load_i32: +; CAHP: # %bb.0: +; CAHP-NEXT: lw a2, 0(a0) +; CAHP-NEXT: lw a1, 2(a0) +; CAHP-NEXT: mov a0, a2 +; CAHP-NEXT: jr ra + %1 = load i32, i32* %a + ret i32 %1 +} From ebd2dbc4fab0f8f63bd63ea146d5bd5b8f2a992a Mon Sep 17 00:00:00 2001 From: Ushitora Anqou Date: Wed, 23 Oct 2019 15:12:38 +0900 Subject: [PATCH 239/289] [CAHP] Codegen support for memory operations on global addresses --- llvm/lib/Target/CAHP/CAHP.h | 12 ++- llvm/lib/Target/CAHP/CAHPAsmPrinter.cpp | 2 +- llvm/lib/Target/CAHP/CAHPISelLowering.cpp | 27 +++++++ llvm/lib/Target/CAHP/CAHPISelLowering.h | 2 + llvm/lib/Target/CAHP/CAHPMCInstLower.cpp | 81 +++++++++++++++---- .../Target/CAHP/MCTargetDesc/CAHPBaseInfo.h | 20 +++++ llvm/test/CodeGen/CAHP/mem.ll | 25 ++++++ llvm/test/CodeGen/CAHP/wide-mem.ll | 19 +++++ 8 files changed, 167 insertions(+), 21 deletions(-) create mode 100644 llvm/lib/Target/CAHP/MCTargetDesc/CAHPBaseInfo.h diff --git a/llvm/lib/Target/CAHP/CAHP.h b/llvm/lib/Target/CAHP/CAHP.h index c9714bbfe034..2bec5865ee19 100644 --- a/llvm/lib/Target/CAHP/CAHP.h +++ b/llvm/lib/Target/CAHP/CAHP.h @@ -5,15 +5,21 @@ #ifndef LLVM_LIB_TARGET_CAHP_CAHP_H #define LLVM_LIB_TARGET_CAHP_CAHP_H -#include "MCTargetDesc/CAHPMCTargetDesc.h" -#include "llvm/Target/TargetMachine.h" +#include "MCTargetDesc/CAHPBaseInfo.h" namespace llvm { +class AsmPrinter; class CAHPTargetMachine; +class FunctionPass; class MCInst; +class MCOperand; class MachineInstr; +class MachineOperand; -void LowerCAHPMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI); +void LowerCAHPMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI, + const AsmPrinter &AP); +bool LowerCAHPMachineOperandToMCOperand(const MachineOperand &MO, + MCOperand &MCOp, const AsmPrinter &AP); FunctionPass *createCAHPISelDag(CAHPTargetMachine &TM); } // namespace llvm diff --git a/llvm/lib/Target/CAHP/CAHPAsmPrinter.cpp b/llvm/lib/Target/CAHP/CAHPAsmPrinter.cpp index 2078ef77b24d..1dadcbc89d07 100644 --- a/llvm/lib/Target/CAHP/CAHPAsmPrinter.cpp +++ b/llvm/lib/Target/CAHP/CAHPAsmPrinter.cpp @@ -47,7 +47,7 @@ void CAHPAsmPrinter::EmitInstruction(const MachineInstr *MI) { return; MCInst TmpInst; - LowerCAHPMachineInstrToMCInst(MI, TmpInst); + LowerCAHPMachineInstrToMCInst(MI, TmpInst, *this); EmitToStreamer(*OutStreamer, TmpInst); } diff --git a/llvm/lib/Target/CAHP/CAHPISelLowering.cpp b/llvm/lib/Target/CAHP/CAHPISelLowering.cpp index 41b8ed9cbb7d..8bb4d832e4be 100644 --- a/llvm/lib/Target/CAHP/CAHPISelLowering.cpp +++ b/llvm/lib/Target/CAHP/CAHPISelLowering.cpp @@ -7,6 +7,7 @@ #include "CAHPRegisterInfo.h" #include "CAHPSubtarget.h" #include "CAHPTargetMachine.h" +#include "MCTargetDesc/CAHPBaseInfo.h" #include "llvm/CodeGen/CallingConvLower.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" @@ -41,6 +42,7 @@ CAHPTargetLowering::CAHPTargetLowering(const TargetMachine &TM, setLoadExtAction(N, MVT::i16, MVT::i1, Promote); // TODO: add all necessary setOperationAction calls. + setOperationAction(ISD::GlobalAddress, MVT::i16, Custom); setBooleanContents(ZeroOrOneBooleanContent); @@ -54,6 +56,31 @@ SDValue CAHPTargetLowering::LowerOperation(SDValue Op, switch (Op.getOpcode()) { default: report_fatal_error("unimplemented operand"); + + case ISD::GlobalAddress: + return lowerGlobalAddress(Op, DAG); + } +} + +SDValue CAHPTargetLowering::lowerGlobalAddress(SDValue Op, + SelectionDAG &DAG) const { + SDLoc DL(Op); + EVT Ty = Op.getValueType(); + GlobalAddressSDNode *N = cast(Op); + const GlobalValue *GV = N->getGlobal(); + int64_t Offset = N->getOffset(); + + if (!isPositionIndependent()) { + SDValue GAHi = + DAG.getTargetGlobalAddress(GV, DL, Ty, Offset, CAHPII::MO_HI); + SDValue GALo = + DAG.getTargetGlobalAddress(GV, DL, Ty, Offset, CAHPII::MO_LO); + SDValue MNHi = SDValue(DAG.getMachineNode(CAHP::LUI, DL, Ty, GAHi), 0); + SDValue MNLo = + SDValue(DAG.getMachineNode(CAHP::ADDI, DL, Ty, MNHi, GALo), 0); + return MNLo; + } else { + report_fatal_error("Unable to lowerGlobalAddress"); } } diff --git a/llvm/lib/Target/CAHP/CAHPISelLowering.h b/llvm/lib/Target/CAHP/CAHPISelLowering.h index 0e4166f9a267..36443461e565 100644 --- a/llvm/lib/Target/CAHP/CAHPISelLowering.h +++ b/llvm/lib/Target/CAHP/CAHPISelLowering.h @@ -41,6 +41,8 @@ class CAHPTargetLowering : public TargetLowering { Type *Ty) const override { return true; } + + SDValue lowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const; }; } // namespace llvm diff --git a/llvm/lib/Target/CAHP/CAHPMCInstLower.cpp b/llvm/lib/Target/CAHP/CAHPMCInstLower.cpp index c8ae328090e0..0177acad1815 100644 --- a/llvm/lib/Target/CAHP/CAHPMCInstLower.cpp +++ b/llvm/lib/Target/CAHP/CAHPMCInstLower.cpp @@ -3,6 +3,9 @@ // LICENSE.TXT for details). This file is licensed under the same license. #include "CAHP.h" +#include "MCTargetDesc/CAHPBaseInfo.h" +#include "MCTargetDesc/CAHPMCExpr.h" +#include "llvm/CodeGen/AsmPrinter.h" #include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineInstr.h" #include "llvm/MC/MCAsmInfo.h" @@ -14,26 +17,70 @@ using namespace llvm; -void llvm::LowerCAHPMachineInstrToMCInst(const MachineInstr *MI, - MCInst &OutMI) { +static MCOperand lowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym, + const AsmPrinter &AP) { + MCContext &Ctx = AP.OutContext; + CAHPMCExpr::VariantKind Kind; + + switch (MO.getTargetFlags()) { + default: + llvm_unreachable("Unknown target flag on GV operand"); + case CAHPII::MO_None: + Kind = CAHPMCExpr::VK_CAHP_None; + break; + case CAHPII::MO_LO: + Kind = CAHPMCExpr::VK_CAHP_LO; + break; + case CAHPII::MO_HI: + Kind = CAHPMCExpr::VK_CAHP_HI; + break; + } + + const MCExpr *ME = + MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, Ctx); + + if (!MO.isJTI() && MO.getOffset()) + ME = MCBinaryExpr::createAdd( + ME, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx); + + ME = CAHPMCExpr::create(ME, Kind, Ctx); + return MCOperand::createExpr(ME); +} + +bool llvm::LowerCAHPMachineOperandToMCOperand(const MachineOperand &MO, + MCOperand &MCOp, + const AsmPrinter &AP) { + switch (MO.getType()) { + default: + report_fatal_error("LowerCAHPMachineInstrToMCInst: unknown operand type"); + + case MachineOperand::MO_Register: + // Ignore all implicit register operands. + if (MO.isImplicit()) + return false; + MCOp = MCOperand::createReg(MO.getReg()); + break; + + case MachineOperand::MO_Immediate: + MCOp = MCOperand::createImm(MO.getImm()); + break; + + case MachineOperand::MO_GlobalAddress: + MCOp = lowerSymbolOperand(MO, AP.getSymbol(MO.getGlobal()), AP); + break; + } + + return true; +} + +void llvm::LowerCAHPMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI, + const AsmPrinter &AP) { OutMI.setOpcode(MI->getOpcode()); for (const MachineOperand &MO : MI->operands()) { MCOperand MCOp; - switch (MO.getType()) { - default: - report_fatal_error("LowerCAHPMachineInstrToMCInst: unknown operand type"); - case MachineOperand::MO_Register: - // Ignore all implicit register operands. - if (MO.isImplicit()) - continue; - MCOp = MCOperand::createReg(MO.getReg()); - break; - case MachineOperand::MO_Immediate: - MCOp = MCOperand::createImm(MO.getImm()); - break; - } - - OutMI.addOperand(MCOp); + LowerCAHPMachineOperandToMCOperand(MO, MCOp, AP); + if (LowerCAHPMachineOperandToMCOperand(MO, MCOp, AP)) + OutMI.addOperand(MCOp); } } diff --git a/llvm/lib/Target/CAHP/MCTargetDesc/CAHPBaseInfo.h b/llvm/lib/Target/CAHP/MCTargetDesc/CAHPBaseInfo.h new file mode 100644 index 000000000000..13b205e5b6f6 --- /dev/null +++ b/llvm/lib/Target/CAHP/MCTargetDesc/CAHPBaseInfo.h @@ -0,0 +1,20 @@ +#ifndef LLVM_LIB_TARGET_CAHP_MCTARGETDESC_CAHPBASEINFO_H +#define LLVM_LIB_TARGET_CAHP_MCTARGETDESC_CAHPBASEINFO_H + +#include "CAHPMCTargetDesc.h" + +namespace llvm { + +// CAHPII - This namespace holds all of the target specific flags that +// instruction info tracks. All definitions must match CAHPInstrFormats.td. +namespace CAHPII { +enum { + MO_None, + MO_LO, + MO_HI, +}; +} // namespace CAHPII + +} // namespace llvm + +#endif diff --git a/llvm/test/CodeGen/CAHP/mem.ll b/llvm/test/CodeGen/CAHP/mem.ll index 77c9cad2c7b6..b07c9c6142ae 100644 --- a/llvm/test/CodeGen/CAHP/mem.ll +++ b/llvm/test/CodeGen/CAHP/mem.ll @@ -111,3 +111,28 @@ define i16 @lw_sw_constant(i16 %a) nounwind { store i16 %a, i16* %1 ret i16 %2 } + +; Check load and store to a global +@G = global i16 0 + +define i16 @lw_sw_global(i16 %a) nounwind { +; CAHP-LABEL: lw_sw_global: +; CAHP: # %bb.0: +; CAHP-NEXT: lui a1, %hi(G) +; CAHP-NEXT: addi a2, a1, %lo(G) +; CAHP-NEXT: lw a1, 0(a2) +; CAHP-NEXT: sw a0, 0(a2) +; CAHP-NEXT: lui a2, %hi(G+18) +; CAHP-NEXT: addi a2, a2, %lo(G+18) +; CAHP-NEXT: lw a3, 0(a2) +; CAHP-NEXT: sw a0, 0(a2) +; CAHP-NEXT: mov a0, a1 +; CAHP-NEXT: jr ra + + %1 = load volatile i16, i16* @G + store i16 %a, i16* @G + %2 = getelementptr i16, i16* @G, i16 9 + %3 = load volatile i16, i16* %2 + store i16 %a, i16* %2 + ret i16 %1 +} diff --git a/llvm/test/CodeGen/CAHP/wide-mem.ll b/llvm/test/CodeGen/CAHP/wide-mem.ll index c411fa967526..56304ef93ac6 100644 --- a/llvm/test/CodeGen/CAHP/wide-mem.ll +++ b/llvm/test/CodeGen/CAHP/wide-mem.ll @@ -14,3 +14,22 @@ define i32 @load_i32(i32 *%a) nounwind { %1 = load i32, i32* %a ret i32 %1 } + +@val32 = local_unnamed_addr global i32 2863311, align 8 + +; TODO: codegen on this should be improved. It shouldn't be necessary to +; generate two addi +define i32 @load_i32_global() nounwind { +; CAHP-LABEL: load_i32_global: +; CAHP: # %bb.0: +; CAHP-NEXT: lui a0, %hi(val32) +; CAHP-NEXT: addi a0, a0, %lo(val32) +; CAHP-NEXT: lw a0, 0(a0) +; CAHP-NEXT: lui a1, %hi(val32+2) +; CAHP-NEXT: addi a1, a1, %lo(val32+2) +; CAHP-NEXT: lw a1, 0(a1) +; CAHP-NEXT: jr ra + + %1 = load i32, i32* @val32 + ret i32 %1 +} From 392f40d9c4eb8c934c4a39155046d73e357ce717 Mon Sep 17 00:00:00 2001 From: Ushitora Anqou Date: Wed, 23 Oct 2019 15:53:30 +0900 Subject: [PATCH 240/289] [CAHP] Add support for relocations --- .../llvm/BinaryFormat/ELFRelocs/CAHP.def | 6 ++- .../CAHP/MCTargetDesc/CAHPELFObjectWriter.cpp | 16 +++++++- llvm/test/MC/CAHP/relocations.s | 37 +++++++++++++++++++ 3 files changed, 56 insertions(+), 3 deletions(-) create mode 100644 llvm/test/MC/CAHP/relocations.s diff --git a/llvm/include/llvm/BinaryFormat/ELFRelocs/CAHP.def b/llvm/include/llvm/BinaryFormat/ELFRelocs/CAHP.def index f319279b5528..61ad6d07d5aa 100644 --- a/llvm/include/llvm/BinaryFormat/ELFRelocs/CAHP.def +++ b/llvm/include/llvm/BinaryFormat/ELFRelocs/CAHP.def @@ -2,4 +2,8 @@ #error "ELF_RELOC must be defined" #endif -ELF_RELOC(R_CAHP_NONE, 0) +ELF_RELOC(R_CAHP_NONE, 0) +ELF_RELOC(R_CAHP_16, 1) +ELF_RELOC(R_CAHP_HI6, 2) +ELF_RELOC(R_CAHP_LO10, 3) +ELF_RELOC(R_CAHP_PCREL_11, 4) diff --git a/llvm/lib/Target/CAHP/MCTargetDesc/CAHPELFObjectWriter.cpp b/llvm/lib/Target/CAHP/MCTargetDesc/CAHPELFObjectWriter.cpp index a3a8ef9598d4..2c9c5a8078bf 100644 --- a/llvm/lib/Target/CAHP/MCTargetDesc/CAHPELFObjectWriter.cpp +++ b/llvm/lib/Target/CAHP/MCTargetDesc/CAHPELFObjectWriter.cpp @@ -2,6 +2,7 @@ // is distributed under the Apache License v2.0 with LLVM Exceptions (see // LICENSE.TXT for details). This file is licensed under the same license. +#include "MCTargetDesc/CAHPFixupKinds.h" #include "MCTargetDesc/CAHPMCTargetDesc.h" #include "llvm/MC/MCELFObjectWriter.h" #include "llvm/MC/MCFixup.h" @@ -33,8 +34,19 @@ unsigned CAHPELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target, const MCFixup &Fixup, bool IsPCRel) const { - // TODO: emit correct relocations. - report_fatal_error("invalid fixup kind!"); + // Determine the type of the relocation + switch ((unsigned)Fixup.getKind()) { + default: + llvm_unreachable("invalid fixup kind!"); + case FK_Data_2: + return ELF::R_CAHP_16; + case CAHP::fixup_cahp_hi6: + return ELF::R_CAHP_HI6; + case CAHP::fixup_cahp_lo10: + return ELF::R_CAHP_LO10; + case CAHP::fixup_cahp_pcrel_11: + return ELF::R_CAHP_PCREL_11; + } } std::unique_ptr diff --git a/llvm/test/MC/CAHP/relocations.s b/llvm/test/MC/CAHP/relocations.s new file mode 100644 index 000000000000..f7001be75841 --- /dev/null +++ b/llvm/test/MC/CAHP/relocations.s @@ -0,0 +1,37 @@ +# RUN: llvm-mc -triple cahp < %s -show-encoding \ +# RUN: | FileCheck -check-prefix=INSTR -check-prefix=FIXUP %s +# RUN: llvm-mc -filetype=obj -triple cahp < %s \ +# RUN: | llvm-readobj -r | FileCheck -check-prefix=RELOC %s + +# Check prefixes: +# RELOC - Check the relocation in the object. +# FIXUP - Check the fixup on the instruction. +# INSTR - Check the instruction is handled properly by the ASMPrinter + +.2byte foo +# RELOC: R_CAHP_16 foo + +lui t1, %hi(foo) +# RELOC: R_CAHP_HI6 foo 0x0 +# INSTR: lui t1, %hi(foo) +# FIXUP: fixup A - offset: 0, value: %hi(foo), kind: fixup_cahp_hi6 + +lui t1, %hi(foo+4) +# RELOC: R_CAHP_HI6 foo 0x4 +# INSTR: lui t1, %hi(foo+4) +# FIXUP: fixup A - offset: 0, value: %hi(foo+4), kind: fixup_cahp_hi6 + +addi t1, t1, %lo(foo) +# RELOC: R_CAHP_LO10 foo 0x0 +# INSTR: addi t1, t1, %lo(foo) +# FIXUP: fixup A - offset: 0, value: %lo(foo), kind: fixup_cahp_lo10 + +addi t1, t1, %lo(foo+4) +# RELOC: R_CAHP_LO10 foo 0x4 +# INSTR: addi t1, t1, %lo(foo+4) +# FIXUP: fixup A - offset: 0, value: %lo(foo+4), kind: fixup_cahp_lo10 + +jsal foo +# RELOC: R_CAHP_PCREL_11 +# INSTR: jsal foo +# FIXUP: fixup A - offset: 0, value: foo, kind: fixup_cahp_pcrel_11 From 4b6d6907a7a535ec5691d25837b09adabbe7ed3b Mon Sep 17 00:00:00 2001 From: Ushitora Anqou Date: Thu, 24 Oct 2019 20:00:37 +0900 Subject: [PATCH 241/289] [CAHP] Codegen for conditional branches --- llvm/lib/Target/CAHP/CAHPISelLowering.cpp | 1 + llvm/lib/Target/CAHP/CAHPInstrInfo.td | 48 +++++++-- llvm/lib/Target/CAHP/CAHPMCInstLower.cpp | 5 + llvm/test/CodeGen/CAHP/branch.ll | 116 ++++++++++++++++++++++ 4 files changed, 163 insertions(+), 7 deletions(-) create mode 100644 llvm/test/CodeGen/CAHP/branch.ll diff --git a/llvm/lib/Target/CAHP/CAHPISelLowering.cpp b/llvm/lib/Target/CAHP/CAHPISelLowering.cpp index 8bb4d832e4be..396e5a79ca9d 100644 --- a/llvm/lib/Target/CAHP/CAHPISelLowering.cpp +++ b/llvm/lib/Target/CAHP/CAHPISelLowering.cpp @@ -43,6 +43,7 @@ CAHPTargetLowering::CAHPTargetLowering(const TargetMachine &TM, // TODO: add all necessary setOperationAction calls. setOperationAction(ISD::GlobalAddress, MVT::i16, Custom); + setOperationAction(ISD::BR_CC, MVT::i16, Expand); setBooleanContents(ZeroOrOneBooleanContent); diff --git a/llvm/lib/Target/CAHP/CAHPInstrInfo.td b/llvm/lib/Target/CAHP/CAHPInstrInfo.td index 7f6d2f9aaffc..a6e30d752108 100644 --- a/llvm/lib/Target/CAHP/CAHPInstrInfo.td +++ b/llvm/lib/Target/CAHP/CAHPInstrInfo.td @@ -39,7 +39,13 @@ def simm10 : Operand, ImmLeaf(Imm);}]> { let EncoderMethod = "getImmOpValue"; } -def simm11 : Operand { +def simm10_branch : Operand { + let ParserMatchClass = SImmAsmOperand<10>; + let DecoderMethod = "decodeSImmOperand<10>"; + let EncoderMethod = "getImmOpValue"; +} + +def simm11 : Operand { let ParserMatchClass = SImmAsmOperand<11>; let DecoderMethod = "decodeSImmOperand<11>"; let EncoderMethod = "getImmOpValue"; @@ -141,17 +147,17 @@ let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in { let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isBranch = 1, isTerminator = 1 in { - def BEQ : CAHPInst24J<0b001111, (ins GPR:$rs1, GPR:$rs2, simm10:$imm), + def BEQ : CAHPInst24J<0b001111, (ins GPR:$rs1, GPR:$rs2, simm10_branch:$imm), "beq", "$rs1, $rs2, $imm">; - def BNE : CAHPInst24J<0b101111, (ins GPR:$rs1, GPR:$rs2, simm10:$imm), + def BNE : CAHPInst24J<0b101111, (ins GPR:$rs1, GPR:$rs2, simm10_branch:$imm), "bne", "$rs1, $rs2, $imm">; - def BLT : CAHPInst24J<0b110111, (ins GPR:$rs1, GPR:$rs2, simm10:$imm), + def BLT : CAHPInst24J<0b110111, (ins GPR:$rs1, GPR:$rs2, simm10_branch:$imm), "blt", "$rs1, $rs2, $imm">; - def BLTU : CAHPInst24J<0b010111, (ins GPR:$rs1, GPR:$rs2, simm10:$imm), + def BLTU : CAHPInst24J<0b010111, (ins GPR:$rs1, GPR:$rs2, simm10_branch:$imm), "bltu", "$rs1, $rs2, $imm">; - def BLE : CAHPInst24J<0b111111, (ins GPR:$rs1, GPR:$rs2, simm10:$imm), + def BLE : CAHPInst24J<0b111111, (ins GPR:$rs1, GPR:$rs2, simm10_branch:$imm), "ble", "$rs1, $rs2, $imm">; - def BLEU : CAHPInst24J<0b011111, (ins GPR:$rs1, GPR:$rs2, simm10:$imm), + def BLEU : CAHPInst24J<0b011111, (ins GPR:$rs1, GPR:$rs2, simm10_branch:$imm), "bleu", "$rs1, $rs2, $imm">; } @@ -302,3 +308,31 @@ def : Pat<(or GPR:$rs1, simm10:$imm), (ORI GPR:$rs1, simm10:$imm)>; def : Pat<(shl GPR:$rs1, uimm4:$imm), (LSLI GPR:$rs1, uimm4:$imm)>; def : Pat<(srl GPR:$rs1, uimm4:$imm), (LSRI GPR:$rs1, uimm4:$imm)>; def : Pat<(sra GPR:$rs1, uimm4:$imm), (ASRI GPR:$rs1, uimm4:$imm)>; + +// Match `(brcond (CondOp ..), ..)` and lower to the appropriate CAHP branch +// instruction. +class BccPat + : Pat<(brcond (CondOp GPR:$rs1, GPR:$rs2), bb:$imm), + (Inst GPR:$rs1, GPR:$rs2, simm10_branch:$imm)>; +def : BccPat; +def : BccPat; +def : BccPat; +def : BccPat; +def : BccPat; +def : BccPat; + +class BccSwapPat + : Pat<(brcond (CondOp GPR:$rs1, GPR:$rs2), bb:$imm), + (InstBcc GPR:$rs2, GPR:$rs1, bb:$imm)>; +// Condition codes that don't have matching CAHP branch instructions, but +// are trivially supported by swapping the two input operands +def : BccSwapPat; +def : BccSwapPat; +def : BccSwapPat; +def : BccSwapPat; + +// An extra pattern is needed for a brcond without a setcc (i.e. where the +// condition was calculated elsewhere). +def : Pat<(brcond GPR:$cond, bb:$imm), (BNE GPR:$cond, (LSI 0), bb:$imm)>; + +def : Pat<(br bb:$imm), (JS simm11:$imm)>; diff --git a/llvm/lib/Target/CAHP/CAHPMCInstLower.cpp b/llvm/lib/Target/CAHP/CAHPMCInstLower.cpp index 0177acad1815..edeb1c010ef9 100644 --- a/llvm/lib/Target/CAHP/CAHPMCInstLower.cpp +++ b/llvm/lib/Target/CAHP/CAHPMCInstLower.cpp @@ -65,6 +65,11 @@ bool llvm::LowerCAHPMachineOperandToMCOperand(const MachineOperand &MO, MCOp = MCOperand::createImm(MO.getImm()); break; + case MachineOperand::MO_MachineBasicBlock: + MCOp = MCOperand::createExpr( + MCSymbolRefExpr::create(MO.getMBB()->getSymbol(), AP.OutContext)); + break; + case MachineOperand::MO_GlobalAddress: MCOp = lowerSymbolOperand(MO, AP.getSymbol(MO.getGlobal()), AP); break; diff --git a/llvm/test/CodeGen/CAHP/branch.ll b/llvm/test/CodeGen/CAHP/branch.ll new file mode 100644 index 000000000000..d50d8a79a7f9 --- /dev/null +++ b/llvm/test/CodeGen/CAHP/branch.ll @@ -0,0 +1,116 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=cahp -verify-machineinstrs < %s \ +; RUN: | FileCheck -check-prefix=CAHP %s + +define void @foo(i16 %a, i16 *%b, i1 %c) { +; CAHP-LABEL: foo: +; CAHP: # %bb.0: +; CAHP-NEXT: lw a2, 0(a1) +; CAHP-NEXT: beq a2, a0, .LBB0_11 +; CAHP-NEXT: js .LBB0_1 +; CAHP-NEXT:.LBB0_1: +; CAHP-NEXT: lw a2, 0(a1) +; CAHP-NEXT: bne a2, a0, .LBB0_11 +; CAHP-NEXT: js .LBB0_2 +; CAHP-NEXT:.LBB0_2: +; CAHP-NEXT: lw a2, 0(a1) +; CAHP-NEXT: blt a2, a0, .LBB0_11 +; CAHP-NEXT: js .LBB0_3 +; CAHP-NEXT:.LBB0_3: +; CAHP-NEXT: lw a2, 0(a1) +; CAHP-NEXT: ble a2, a0, .LBB0_11 +; CAHP-NEXT: js .LBB0_4 +; CAHP-NEXT:.LBB0_4: +; CAHP-NEXT: lw a2, 0(a1) +; CAHP-NEXT: bltu a2, a0, .LBB0_11 +; CAHP-NEXT: js .LBB0_5 +; CAHP-NEXT:.LBB0_5: +; CAHP-NEXT: lw a2, 0(a1) +; CAHP-NEXT: bleu a2, a0, .LBB0_11 +; CAHP-NEXT: js .LBB0_6 +; CAHP-NEXT:.LBB0_6: +; CAHP-NEXT: lw a2, 0(a1) +; CAHP-NEXT: blt a0, a2, .LBB0_11 +; CAHP-NEXT: js .LBB0_7 +; CAHP-NEXT:.LBB0_7: +; CAHP-NEXT: lw a2, 0(a1) +; CAHP-NEXT: ble a0, a2, .LBB0_11 +; CAHP-NEXT: js .LBB0_8 +; CAHP-NEXT:.LBB0_8: +; CAHP-NEXT: lw a2, 0(a1) +; CAHP-NEXT: bltu a0, a2, .LBB0_11 +; CAHP-NEXT: js .LBB0_9 +; CAHP-NEXT:.LBB0_9: +; CAHP-NEXT: lw a2, 0(a1) +; CAHP-NEXT: bleu a0, a2, .LBB0_11 +; CAHP-NEXT: js .LBB0_10 +; CAHP-NEXT:.LBB0_10: +; CAHP-NEXT: lw a0, 0(a1) +; CAHP-NEXT:.LBB0_11: # %end +; CAHP-NEXT: jr ra + + %val1 = load volatile i16, i16* %b + %tst1 = icmp eq i16 %val1, %a + br i1 %tst1, label %end, label %test2 + +test2: + %val2 = load volatile i16, i16* %b + %tst2 = icmp ne i16 %val2, %a + br i1 %tst2, label %end, label %test3 + +test3: + %val3 = load volatile i16, i16* %b + %tst3 = icmp slt i16 %val3, %a + br i1 %tst3, label %end, label %test4 + +test4: + %val4 = load volatile i16, i16* %b + %tst4 = icmp sle i16 %val4, %a + br i1 %tst4, label %end, label %test5 + +test5: + %val5 = load volatile i16, i16* %b + %tst5 = icmp ult i16 %val5, %a + br i1 %tst5, label %end, label %test6 + +test6: + %val6 = load volatile i16, i16* %b + %tst6 = icmp ule i16 %val6, %a + br i1 %tst6, label %end, label %test7 + +; Check for condition codes that don't have a matching instruction + +test7: + %val7 = load volatile i16, i16* %b + %tst7 = icmp sgt i16 %val7, %a + br i1 %tst7, label %end, label %test8 + +test8: + %val8 = load volatile i16, i16* %b + %tst8 = icmp sge i16 %val8, %a + br i1 %tst8, label %end, label %test9 + +test9: + %val9 = load volatile i16, i16* %b + %tst9 = icmp ugt i16 %val9, %a + br i1 %tst9, label %end, label %test10 + +test10: + %val10 = load volatile i16, i16* %b + %tst10 = icmp uge i16 %val10, %a + br i1 %tst10, label %end, label %test12 + +;; Check the case of a branch where the condition was generated in another +;; function +; +;test11: +; %val11 = load volatile i16, i16* %b +; br i1 %c, label %end, label %test12 + +test12: + %val12 = load volatile i16, i16* %b + br label %end + +end: + ret void +} From 4202dc9041f40db43184012f19e17c87d1f9f2bd Mon Sep 17 00:00:00 2001 From: Ushitora Anqou Date: Sun, 27 Oct 2019 11:45:30 +0900 Subject: [PATCH 242/289] [CAHP] Add support for storing/loading register to stack --- llvm/lib/Target/CAHP/CAHPInstrInfo.cpp | 30 +++++++++++++++++++++++ llvm/lib/Target/CAHP/CAHPInstrInfo.h | 8 ++++++ llvm/lib/Target/CAHP/CAHPRegisterInfo.cpp | 26 +++++++++++++++++++- 3 files changed, 63 insertions(+), 1 deletion(-) diff --git a/llvm/lib/Target/CAHP/CAHPInstrInfo.cpp b/llvm/lib/Target/CAHP/CAHPInstrInfo.cpp index 1321965b7a9a..6c232e1beed1 100644 --- a/llvm/lib/Target/CAHP/CAHPInstrInfo.cpp +++ b/llvm/lib/Target/CAHP/CAHPInstrInfo.cpp @@ -30,3 +30,33 @@ void CAHPInstrInfo::copyPhysReg(MachineBasicBlock &MBB, BuildMI(MBB, MBBI, DL, get(CAHP::MOV), DstReg).addReg(SrcReg); } + +void CAHPInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, + unsigned SrcReg, bool IsKill, int FI, + const TargetRegisterClass *RC, + const TargetRegisterInfo *TRI) const { + DebugLoc DL; + if (I != MBB.end()) + DL = I->getDebugLoc(); + + if (!CAHP::GPRRegClass.hasSubClassEq(RC)) + llvm_unreachable("Can't store this register to stack slot"); + + BuildMI(MBB, I, DL, get(CAHP::SW)).addReg(SrcReg).addFrameIndex(FI).addImm(0); +} + +void CAHPInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, + unsigned DstReg, int FI, + const TargetRegisterClass *RC, + const TargetRegisterInfo *TRI) const { + DebugLoc DL; + if (I != MBB.end()) + DL = I->getDebugLoc(); + + if (!CAHP::GPRRegClass.hasSubClassEq(RC)) + llvm_unreachable("Can't load this register from stack slot"); + + BuildMI(MBB, I, DL, get(CAHP::LW), DstReg).addFrameIndex(FI).addImm(0); +} diff --git a/llvm/lib/Target/CAHP/CAHPInstrInfo.h b/llvm/lib/Target/CAHP/CAHPInstrInfo.h index c8bc8a7d039d..a0cf9922a017 100644 --- a/llvm/lib/Target/CAHP/CAHPInstrInfo.h +++ b/llvm/lib/Target/CAHP/CAHPInstrInfo.h @@ -21,6 +21,14 @@ class CAHPInstrInfo : public CAHPGenInstrInfo { void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, unsigned DstReg, unsigned SrcReg, bool KillSrc) const override; + void storeRegToStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, unsigned SrcReg, + bool IsKill, int FI, const TargetRegisterClass *RC, + const TargetRegisterInfo *TRI) const override; + void loadRegFromStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, unsigned DstReg, + int FI, const TargetRegisterClass *RC, + const TargetRegisterInfo *TRI) const override; }; } // namespace llvm diff --git a/llvm/lib/Target/CAHP/CAHPRegisterInfo.cpp b/llvm/lib/Target/CAHP/CAHPRegisterInfo.cpp index 6dae41a91464..ac8506399439 100644 --- a/llvm/lib/Target/CAHP/CAHPRegisterInfo.cpp +++ b/llvm/lib/Target/CAHP/CAHPRegisterInfo.cpp @@ -42,7 +42,31 @@ BitVector CAHPRegisterInfo::getReservedRegs(const MachineFunction &MF) const { void CAHPRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, unsigned FIOperandNum, RegScavenger *RS) const { - report_fatal_error("Subroutines not supported yet"); + // TODO: this implementation is a temporary placeholder which does just + // enough to allow other aspects of code generation to be tested + + assert(SPAdj == 0 && "Unexpected non-zero SPAdj value"); + + MachineInstr &MI = *II; + MachineFunction &MF = *MI.getParent()->getParent(); + const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering(); + DebugLoc DL = MI.getDebugLoc(); + + unsigned FrameReg = getFrameRegister(MF); + int FrameIndex = MI.getOperand(FIOperandNum).getIndex(); + int Offset = TFI->getFrameIndexReference(MF, FrameIndex, FrameReg); + Offset += MI.getOperand(FIOperandNum + 1).getImm(); + + assert(TFI->hasFP(MF) && "eliminateFrameIndex currently requires hasFP"); + + // Offsets must be directly encoded in a 10-bit immediate field + if (!isInt<10>(Offset)) { + report_fatal_error( + "Frame offsets outside of the signed 10-bit range not supported"); + } + + MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false); + MI.getOperand(FIOperandNum + 1).ChangeToImmediate(Offset); } Register CAHPRegisterInfo::getFrameRegister(const MachineFunction &MF) const { From 4f800abeb88b681bb2471a7b79f03272f9137373 Mon Sep 17 00:00:00 2001 From: Ushitora Anqou Date: Sun, 27 Oct 2019 13:44:02 +0900 Subject: [PATCH 243/289] [CAHP] Add support for function calls --- llvm/lib/Target/CAHP/CAHPFrameLowering.h | 6 + llvm/lib/Target/CAHP/CAHPISelLowering.cpp | 136 +++++++++++++++++++++- llvm/lib/Target/CAHP/CAHPISelLowering.h | 12 +- llvm/lib/Target/CAHP/CAHPInstrInfo.cpp | 3 +- llvm/lib/Target/CAHP/CAHPInstrInfo.td | 29 ++++- llvm/lib/Target/CAHP/CAHPMCInstLower.cpp | 4 + llvm/lib/Target/CAHP/CAHPRegisterInfo.cpp | 6 + llvm/lib/Target/CAHP/CAHPRegisterInfo.h | 3 + llvm/test/CodeGen/CAHP/calls.ll | 53 +++++++++ 9 files changed, 243 insertions(+), 9 deletions(-) create mode 100644 llvm/test/CodeGen/CAHP/calls.ll diff --git a/llvm/lib/Target/CAHP/CAHPFrameLowering.h b/llvm/lib/Target/CAHP/CAHPFrameLowering.h index af184338420b..bb7c66dfaa89 100644 --- a/llvm/lib/Target/CAHP/CAHPFrameLowering.h +++ b/llvm/lib/Target/CAHP/CAHPFrameLowering.h @@ -21,6 +21,12 @@ class CAHPFrameLowering : public TargetFrameLowering { void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override; bool hasFP(const MachineFunction &MF) const override; + + MachineBasicBlock::iterator + eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI) const override { + return MBB.erase(MI); + } }; } // namespace llvm #endif diff --git a/llvm/lib/Target/CAHP/CAHPISelLowering.cpp b/llvm/lib/Target/CAHP/CAHPISelLowering.cpp index 396e5a79ca9d..6bff1dab1f78 100644 --- a/llvm/lib/Target/CAHP/CAHPISelLowering.cpp +++ b/llvm/lib/Target/CAHP/CAHPISelLowering.cpp @@ -28,7 +28,7 @@ using namespace llvm; CAHPTargetLowering::CAHPTargetLowering(const TargetMachine &TM, const CAHPSubtarget &STI) - : TargetLowering(TM) { + : TargetLowering(TM), Subtarget(STI) { // Set up the register classes. addRegisterClass(MVT::i16, &CAHP::GPRRegClass); @@ -48,8 +48,8 @@ CAHPTargetLowering::CAHPTargetLowering(const TargetMachine &TM, setBooleanContents(ZeroOrOneBooleanContent); // Function alignments (log2). - setMinFunctionAlignment(1); - setPrefFunctionAlignment(1); + setMinFunctionAlignment(0); + setPrefFunctionAlignment(0); } SDValue CAHPTargetLowering::LowerOperation(SDValue Op, @@ -132,6 +132,134 @@ SDValue CAHPTargetLowering::LowerFormalArguments( return Chain; } +// Lower a call to a callseq_start + CALL + callseq_end chain, and add input +// and output parameter nodes. +SDValue CAHPTargetLowering::LowerCall(CallLoweringInfo &CLI, + SmallVectorImpl &InVals) const { + SelectionDAG &DAG = CLI.DAG; + SDLoc &DL = CLI.DL; + SmallVectorImpl &Outs = CLI.Outs; + SmallVectorImpl &OutVals = CLI.OutVals; + SmallVectorImpl &Ins = CLI.Ins; + SDValue Chain = CLI.Chain; + SDValue Callee = CLI.Callee; + CLI.IsTailCall = false; + CallingConv::ID CallConv = CLI.CallConv; + bool IsVarArg = CLI.IsVarArg; + EVT PtrVT = getPointerTy(DAG.getDataLayout()); + + if (IsVarArg) { + report_fatal_error("LowerCall with varargs not implemented"); + } + + MachineFunction &MF = DAG.getMachineFunction(); + + // Analyze the operands of the call, assigning locations to each operand. + SmallVector ArgLocs; + CCState ArgCCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext()); + ArgCCInfo.AnalyzeCallOperands(Outs, CC_CAHP); + + // Get a count of how many bytes are to be pushed on the stack. + unsigned NumBytes = ArgCCInfo.getNextStackOffset(); + + for (auto &Arg : Outs) { + if (!Arg.Flags.isByVal()) + continue; + report_fatal_error("Passing arguments byval not yet implemented"); + } + + Chain = DAG.getCALLSEQ_START(Chain, NumBytes, 0, CLI.DL); + + // Copy argument values to their designated locations. + SmallVector, 8> RegsToPass; + for (unsigned I = 0, E = ArgLocs.size(); I != E; ++I) { + CCValAssign &VA = ArgLocs[I]; + SDValue ArgValue = OutVals[I]; + + // Promote the value if needed. + // For now, only handle fully promoted arguments. + switch (VA.getLocInfo()) { + case CCValAssign::Full: + break; + default: + llvm_unreachable("Unknown loc info!"); + } + + if (VA.isRegLoc()) { + // Queue up the argument copies and emit them at the end. + RegsToPass.push_back(std::make_pair(VA.getLocReg(), ArgValue)); + } else { + assert(VA.isMemLoc() && "Argument not register or memory"); + report_fatal_error("Passing arguments via the stack not yet implemented"); + } + } + + SDValue Glue; + + // Build a sequence of copy-to-reg nodes, chained and glued together. + for (auto &Reg : RegsToPass) { + Chain = DAG.getCopyToReg(Chain, DL, Reg.first, Reg.second, Glue); + Glue = Chain.getValue(1); + } + + if (isa(Callee)) { + // GlobalAddressSDNode *S = dyn_cast(Callee); + // Callee = DAG.getTargetGlobalAddress(S->getGlobal(), DL, PtrVT, 0, 0); + Callee = lowerGlobalAddress(Callee, DAG); + } else if (isa(Callee)) { + report_fatal_error( + "lowerExternalSymbol, needed for lowerCall, not yet handled"); + } + + // The first call operand is the chain and the second is the target address. + SmallVector Ops; + Ops.push_back(Chain); + Ops.push_back(Callee); + + // Add argument registers to the end of the list so that they are + // known live into the call. + for (auto &Reg : RegsToPass) + Ops.push_back(DAG.getRegister(Reg.first, Reg.second.getValueType())); + + // Add a register mask operand representing the call-preserved registers. + const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo(); + const uint32_t *Mask = TRI->getCallPreservedMask(MF, CallConv); + assert(Mask && "Missing call preserved mask for calling convention"); + Ops.push_back(DAG.getRegisterMask(Mask)); + + // Glue the call to the argument copies, if any. + if (Glue.getNode()) + Ops.push_back(Glue); + + // Emit the call. + SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); + Chain = DAG.getNode(CAHPISD::CALL, DL, NodeTys, Ops); + Glue = Chain.getValue(1); + + // Mark the end of the call, which is glued to the call itself. + Chain = DAG.getCALLSEQ_END(Chain, DAG.getConstant(NumBytes, DL, PtrVT, true), + DAG.getConstant(0, DL, PtrVT, true), Glue, DL); + Glue = Chain.getValue(1); + + // Assign locations to each value returned by this call. + SmallVector RVLocs; + CCState RetCCInfo(CallConv, IsVarArg, MF, RVLocs, *DAG.getContext()); + RetCCInfo.AnalyzeCallResult(Ins, RetCC_CAHP); + + // Copy all of the result registers out of their specified physreg. + for (auto &VA : RVLocs) { + // Copy the value out, gluing the copy to the end of the call sequence. + SDValue RetValue = + DAG.getCopyFromReg(Chain, DL, VA.getLocReg(), VA.getLocVT(), Glue); + Chain = RetValue.getValue(1); + Glue = RetValue.getValue(2); + + InVals.push_back(Chain.getValue(0)); + } + + return Chain; +} + SDValue CAHPTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, @@ -180,6 +308,8 @@ const char *CAHPTargetLowering::getTargetNodeName(unsigned Opcode) const { switch ((CAHPISD::NodeType)Opcode) { case CAHPISD::FIRST_NUMBER: break; + case CAHPISD::CALL: + return "CAHPISD::CALL"; case CAHPISD::RET_FLAG: return "CAHPISD::RET_FLAG"; } diff --git a/llvm/lib/Target/CAHP/CAHPISelLowering.h b/llvm/lib/Target/CAHP/CAHPISelLowering.h index 36443461e565..6d60c3dc7c90 100644 --- a/llvm/lib/Target/CAHP/CAHPISelLowering.h +++ b/llvm/lib/Target/CAHP/CAHPISelLowering.h @@ -12,10 +12,18 @@ namespace llvm { class CAHPSubtarget; namespace CAHPISD { -enum NodeType : unsigned { FIRST_NUMBER = ISD::BUILTIN_OP_END, RET_FLAG }; +enum NodeType : unsigned { + FIRST_NUMBER = ISD::BUILTIN_OP_END, + + CALL, + RET_FLAG, +}; } class CAHPTargetLowering : public TargetLowering { +private: + const CAHPSubtarget &Subtarget; + public: explicit CAHPTargetLowering(const TargetMachine &TM, const CAHPSubtarget &STI); @@ -37,6 +45,8 @@ class CAHPTargetLowering : public TargetLowering { const SmallVectorImpl &Outs, const SmallVectorImpl &OutVals, const SDLoc &DL, SelectionDAG &DAG) const override; + SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI, + SmallVectorImpl &InVals) const override; bool shouldConvertConstantLoadToIntImm(const APInt &Imm, Type *Ty) const override { return true; diff --git a/llvm/lib/Target/CAHP/CAHPInstrInfo.cpp b/llvm/lib/Target/CAHP/CAHPInstrInfo.cpp index 6c232e1beed1..cf5e27a63916 100644 --- a/llvm/lib/Target/CAHP/CAHPInstrInfo.cpp +++ b/llvm/lib/Target/CAHP/CAHPInstrInfo.cpp @@ -19,7 +19,8 @@ using namespace llvm; -CAHPInstrInfo::CAHPInstrInfo() : CAHPGenInstrInfo() {} +CAHPInstrInfo::CAHPInstrInfo() + : CAHPGenInstrInfo(CAHP::ADJCALLSTACKDOWN, CAHP::ADJCALLSTACKUP) {} void CAHPInstrInfo::copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, diff --git a/llvm/lib/Target/CAHP/CAHPInstrInfo.td b/llvm/lib/Target/CAHP/CAHPInstrInfo.td index a6e30d752108..8feae795f661 100644 --- a/llvm/lib/Target/CAHP/CAHPInstrInfo.td +++ b/llvm/lib/Target/CAHP/CAHPInstrInfo.td @@ -4,8 +4,19 @@ include "CAHPInstrFormats.td" -def RetFlag : SDNode<"CAHPISD::RET_FLAG", SDTNone, - [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; +def SDT_CAHPCall : SDTypeProfile<0, -1, [SDTCisVT<0, i16>]>; +def SDT_CAHPCallSeqStart : SDCallSeqStart<[SDTCisVT<0, i16>, SDTCisVT<1, i16>]>; +def SDT_CAHPCallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i16>, SDTCisVT<1, i16>]>; + +def Call : SDNode<"CAHPISD::CALL", SDT_CAHPCall, + [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue, + SDNPVariadic]>; +def CallSeqStart : SDNode<"ISD::CALLSEQ_START", SDT_CAHPCallSeqStart, + [SDNPHasChain, SDNPOutGlue]>; +def CallSeqEnd : SDNode<"ISD::CALLSEQ_END", SDT_CAHPCallSeqEnd, + [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>; +def RetFlag : SDNode<"CAHPISD::RET_FLAG", SDTNone, + [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; class ImmAsmOperand : AsmOperandClass { let Name = prefix # "Imm" # width # suffix; @@ -243,7 +254,7 @@ let hasSideEffects = 0, mayLoad = 0, mayStore = 0, // 16-bit J-instructions. let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in { - let isCall = 1, Defs = [X0] in + let isCall = 1, Defs = [/* RA */ X0] in def JALR : CAHPInst16JR<0b10110, (ins GPR:$rs), "jalr", "$rs">; let isBranch = 1, isBarrier = 1, isTerminator = 1, isIndirectBranch = 1 in @@ -252,7 +263,7 @@ let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in { let isBranch = 1, isTerminator = 1, isBarrier = 1 in def JS : CAHPInst16JI<0b01110, (ins simm11:$imm), "js", "$imm">; - let isCall = 1, Defs = [X0] in + let isCall = 1, Defs = [/* RA */ X0] in def JSAL : CAHPInst16JI<0b11110, (ins simm11:$imm), "jsal", "$imm">; } @@ -267,6 +278,14 @@ let isBarrier = 1, isReturn = 1, isTerminator = 1 in def PseudoRET : Pseudo<(outs), (ins), [(RetFlag)]>, PseudoInstExpansion<(JR X0)>; +// Pessimistically assume the stack pointer will be clobbered +let Defs = [/* SP */ X1], Uses = [/* SP */ X1] in { +def ADJCALLSTACKDOWN : Pseudo<(outs), (ins i16imm:$amt1, i16imm:$amt2), + [(CallSeqStart timm:$amt1, timm:$amt2)]>; +def ADJCALLSTACKUP : Pseudo<(outs), (ins i16imm:$amt1, i16imm:$amt2), + [(CallSeqEnd timm:$amt1, timm:$amt2)]>; +} // Defs = [X1], Uses = [X1] + // Codegen patterns. def : Pat<(simm6:$imm), (LSI simm6:$imm)>; @@ -336,3 +355,5 @@ def : BccSwapPat; def : Pat<(brcond GPR:$cond, bb:$imm), (BNE GPR:$cond, (LSI 0), bb:$imm)>; def : Pat<(br bb:$imm), (JS simm11:$imm)>; +def : Pat<(Call GPR:$rs), (JALR GPR:$rs)>; +def : Pat<(Call tglobaladdr:$dst), (JSAL tglobaladdr:$dst)>; diff --git a/llvm/lib/Target/CAHP/CAHPMCInstLower.cpp b/llvm/lib/Target/CAHP/CAHPMCInstLower.cpp index edeb1c010ef9..c11cf647b7ba 100644 --- a/llvm/lib/Target/CAHP/CAHPMCInstLower.cpp +++ b/llvm/lib/Target/CAHP/CAHPMCInstLower.cpp @@ -61,6 +61,10 @@ bool llvm::LowerCAHPMachineOperandToMCOperand(const MachineOperand &MO, MCOp = MCOperand::createReg(MO.getReg()); break; + case MachineOperand::MO_RegisterMask: + // Regmasks are like implicit defs. + return false; + case MachineOperand::MO_Immediate: MCOp = MCOperand::createImm(MO.getImm()); break; diff --git a/llvm/lib/Target/CAHP/CAHPRegisterInfo.cpp b/llvm/lib/Target/CAHP/CAHPRegisterInfo.cpp index ac8506399439..feb755ce0804 100644 --- a/llvm/lib/Target/CAHP/CAHPRegisterInfo.cpp +++ b/llvm/lib/Target/CAHP/CAHPRegisterInfo.cpp @@ -72,3 +72,9 @@ void CAHPRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, Register CAHPRegisterInfo::getFrameRegister(const MachineFunction &MF) const { return CAHP::X2; } + +const uint32_t * +CAHPRegisterInfo::getCallPreservedMask(const MachineFunction & /*MF*/, + CallingConv::ID /*CC*/) const { + return CSR_RegMask; +} diff --git a/llvm/lib/Target/CAHP/CAHPRegisterInfo.h b/llvm/lib/Target/CAHP/CAHPRegisterInfo.h index 70c940c13e17..261efeb97a7f 100644 --- a/llvm/lib/Target/CAHP/CAHPRegisterInfo.h +++ b/llvm/lib/Target/CAHP/CAHPRegisterInfo.h @@ -16,6 +16,9 @@ struct CAHPRegisterInfo : public CAHPGenRegisterInfo { CAHPRegisterInfo(unsigned HwMode); + const uint32_t *getCallPreservedMask(const MachineFunction &MF, + CallingConv::ID) const override; + const MCPhysReg *getCalleeSavedRegs(const MachineFunction *MF) const override; BitVector getReservedRegs(const MachineFunction &MF) const override; diff --git a/llvm/test/CodeGen/CAHP/calls.ll b/llvm/test/CodeGen/CAHP/calls.ll new file mode 100644 index 000000000000..7bc538794fc6 --- /dev/null +++ b/llvm/test/CodeGen/CAHP/calls.ll @@ -0,0 +1,53 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=cahp -verify-machineinstrs < %s \ +; RUN: | FileCheck -check-prefix=CAHP %s + +declare i16 @external_function(i16) + +define i16 @test_call_external(i16 %a) nounwind { +; CAHP-LABEL: test_call_external: +; CAHP: # %bb.0: +; CAHP-NEXT: sw ra, 0(fp) +; CAHP-NEXT: lui a1, %hi(external_function) +; CAHP-NEXT: addi a1, a1, %lo(external_function) +; CAHP-NEXT: jalr a1 +; CAHP-NEXT: lw ra, 0(fp) +; CAHP-NEXT: jr ra + %1 = call i16 @external_function(i16 %a) + ret i16 %1 +} + +define i16 @defined_function(i16 %a) nounwind { +; CAHP-LABEL: defined_function: +; CAHP: # %bb.0: +; CAHP-NEXT: addi a0, a0, 1 +; CAHP-NEXT: jr ra + %1 = add i16 %a, 1 + ret i16 %1 +} + +define i16 @test_call_defined(i16 %a) nounwind { +; CAHP-LABEL: test_call_defined: +; CAHP: # %bb.0: +; CAHP-NEXT: sw ra, 0(fp) +; CAHP-NEXT: lui a1, %hi(defined_function) +; CAHP-NEXT: addi a1, a1, %lo(defined_function) +; CAHP-NEXT: jalr a1 +; CAHP-NEXT: lw ra, 0(fp) +; CAHP-NEXT: jr ra + %1 = call i16 @defined_function(i16 %a) nounwind + ret i16 %1 +} + +define i16 @test_call_indirect(i16 (i16)* %a, i16 %b) nounwind { +; CAHP-LABEL: test_call_indirect: +; CAHP: # %bb.0: +; CAHP-NEXT: sw ra, 0(fp) +; CAHP-NEXT: mov a2, a0 +; CAHP-NEXT: mov a0, a1 +; CAHP-NEXT: jalr a2 +; CAHP-NEXT: lw ra, 0(fp) +; CAHP-NEXT: jr ra + %1 = call i16 %a(i16 %b) + ret i16 %1 +} From f5bc466d5878334ca300f5e4d1f802109784292a Mon Sep 17 00:00:00 2001 From: Ushitora Anqou Date: Sun, 27 Oct 2019 13:54:34 +0900 Subject: [PATCH 244/289] [CAHP] Add CAHP-specific getFrameIndexReference --- llvm/lib/Target/CAHP/CAHPFrameLowering.cpp | 28 ++++++++++++++++++++++ llvm/lib/Target/CAHP/CAHPFrameLowering.h | 3 +++ llvm/lib/Target/CAHP/CAHPRegisterInfo.cpp | 15 +++++------- llvm/test/CodeGen/CAHP/calls.ll | 12 +++++----- 4 files changed, 43 insertions(+), 15 deletions(-) diff --git a/llvm/lib/Target/CAHP/CAHPFrameLowering.cpp b/llvm/lib/Target/CAHP/CAHPFrameLowering.cpp index 492af423f173..2b2b58a66356 100644 --- a/llvm/lib/Target/CAHP/CAHPFrameLowering.cpp +++ b/llvm/lib/Target/CAHP/CAHPFrameLowering.cpp @@ -18,3 +18,31 @@ void CAHPFrameLowering::emitPrologue(MachineFunction &MF, void CAHPFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const {} + +int CAHPFrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI, + unsigned &FrameReg) const { + const MachineFrameInfo &MFI = MF.getFrameInfo(); + const TargetRegisterInfo *RI = MF.getSubtarget().getRegisterInfo(); + + // Callee-saved registers should be referenced relative to the stack + // pointer (positive offset), otherwise use the frame pointer (negative + // offset). + const std::vector &CSI = MFI.getCalleeSavedInfo(); + int MinCSFI = 0; + int MaxCSFI = -1; + + int Offset = MFI.getObjectOffset(FI) - getOffsetOfLocalArea() + + MFI.getOffsetAdjustment(); + + if (CSI.size()) { + MinCSFI = CSI[0].getFrameIdx(); + MaxCSFI = CSI[CSI.size() - 1].getFrameIdx(); + } + + FrameReg = RI->getFrameRegister(MF); + if (FI >= MinCSFI && FI <= MaxCSFI) { // callee-saved register? + FrameReg = CAHP::X1; // sp + Offset += MF.getFrameInfo().getStackSize(); // turn the Offset positive + } + return Offset; +} diff --git a/llvm/lib/Target/CAHP/CAHPFrameLowering.h b/llvm/lib/Target/CAHP/CAHPFrameLowering.h index bb7c66dfaa89..fac4ad133e4f 100644 --- a/llvm/lib/Target/CAHP/CAHPFrameLowering.h +++ b/llvm/lib/Target/CAHP/CAHPFrameLowering.h @@ -20,6 +20,9 @@ class CAHPFrameLowering : public TargetFrameLowering { void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override; void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override; + int getFrameIndexReference(const MachineFunction &MF, int FI, + unsigned &FrameReg) const override; + bool hasFP(const MachineFunction &MF) const override; MachineBasicBlock::iterator diff --git a/llvm/lib/Target/CAHP/CAHPRegisterInfo.cpp b/llvm/lib/Target/CAHP/CAHPRegisterInfo.cpp index feb755ce0804..58a356208e6c 100644 --- a/llvm/lib/Target/CAHP/CAHPRegisterInfo.cpp +++ b/llvm/lib/Target/CAHP/CAHPRegisterInfo.cpp @@ -42,22 +42,19 @@ BitVector CAHPRegisterInfo::getReservedRegs(const MachineFunction &MF) const { void CAHPRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, unsigned FIOperandNum, RegScavenger *RS) const { - // TODO: this implementation is a temporary placeholder which does just - // enough to allow other aspects of code generation to be tested - assert(SPAdj == 0 && "Unexpected non-zero SPAdj value"); MachineInstr &MI = *II; MachineFunction &MF = *MI.getParent()->getParent(); - const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering(); DebugLoc DL = MI.getDebugLoc(); - unsigned FrameReg = getFrameRegister(MF); int FrameIndex = MI.getOperand(FIOperandNum).getIndex(); - int Offset = TFI->getFrameIndexReference(MF, FrameIndex, FrameReg); - Offset += MI.getOperand(FIOperandNum + 1).getImm(); - - assert(TFI->hasFP(MF) && "eliminateFrameIndex currently requires hasFP"); + unsigned FrameReg; + int Offset = + getFrameLowering(MF)->getFrameIndexReference(MF, FrameIndex, FrameReg) + + MI.getOperand(FIOperandNum + 1).getImm(); + assert(MF.getSubtarget().getFrameLowering()->hasFP(MF) && + "eliminateFrameIndex currently requires hasFP"); // Offsets must be directly encoded in a 10-bit immediate field if (!isInt<10>(Offset)) { diff --git a/llvm/test/CodeGen/CAHP/calls.ll b/llvm/test/CodeGen/CAHP/calls.ll index 7bc538794fc6..745c1e0a4384 100644 --- a/llvm/test/CodeGen/CAHP/calls.ll +++ b/llvm/test/CodeGen/CAHP/calls.ll @@ -7,11 +7,11 @@ declare i16 @external_function(i16) define i16 @test_call_external(i16 %a) nounwind { ; CAHP-LABEL: test_call_external: ; CAHP: # %bb.0: -; CAHP-NEXT: sw ra, 0(fp) +; CAHP-NEXT: sw ra, 0(sp) ; CAHP-NEXT: lui a1, %hi(external_function) ; CAHP-NEXT: addi a1, a1, %lo(external_function) ; CAHP-NEXT: jalr a1 -; CAHP-NEXT: lw ra, 0(fp) +; CAHP-NEXT: lw ra, 0(sp) ; CAHP-NEXT: jr ra %1 = call i16 @external_function(i16 %a) ret i16 %1 @@ -29,11 +29,11 @@ define i16 @defined_function(i16 %a) nounwind { define i16 @test_call_defined(i16 %a) nounwind { ; CAHP-LABEL: test_call_defined: ; CAHP: # %bb.0: -; CAHP-NEXT: sw ra, 0(fp) +; CAHP-NEXT: sw ra, 0(sp) ; CAHP-NEXT: lui a1, %hi(defined_function) ; CAHP-NEXT: addi a1, a1, %lo(defined_function) ; CAHP-NEXT: jalr a1 -; CAHP-NEXT: lw ra, 0(fp) +; CAHP-NEXT: lw ra, 0(sp) ; CAHP-NEXT: jr ra %1 = call i16 @defined_function(i16 %a) nounwind ret i16 %1 @@ -42,11 +42,11 @@ define i16 @test_call_defined(i16 %a) nounwind { define i16 @test_call_indirect(i16 (i16)* %a, i16 %b) nounwind { ; CAHP-LABEL: test_call_indirect: ; CAHP: # %bb.0: -; CAHP-NEXT: sw ra, 0(fp) +; CAHP-NEXT: sw ra, 0(sp) ; CAHP-NEXT: mov a2, a0 ; CAHP-NEXT: mov a0, a1 ; CAHP-NEXT: jalr a2 -; CAHP-NEXT: lw ra, 0(fp) +; CAHP-NEXT: lw ra, 0(sp) ; CAHP-NEXT: jr ra %1 = call i16 %a(i16 %b) ret i16 %1 From 36fef7423e636bd74552ba657e5162eee7a9dcef Mon Sep 17 00:00:00 2001 From: Ushitora Anqou Date: Sun, 27 Oct 2019 14:35:55 +0900 Subject: [PATCH 245/289] [CAHP] Add prologue/epilogue insertion --- llvm/lib/Target/CAHP/CAHPFrameLowering.cpp | 136 ++++++++++++++++++++- llvm/lib/Target/CAHP/CAHPFrameLowering.h | 14 ++- 2 files changed, 147 insertions(+), 3 deletions(-) diff --git a/llvm/lib/Target/CAHP/CAHPFrameLowering.cpp b/llvm/lib/Target/CAHP/CAHPFrameLowering.cpp index 2b2b58a66356..2fe99d99a713 100644 --- a/llvm/lib/Target/CAHP/CAHPFrameLowering.cpp +++ b/llvm/lib/Target/CAHP/CAHPFrameLowering.cpp @@ -13,11 +13,133 @@ using namespace llvm; bool CAHPFrameLowering::hasFP(const MachineFunction &MF) const { return true; } +// Determines the size of the frame and maximum call frame size. +void CAHPFrameLowering::determineFrameLayout(MachineFunction &MF) const { + MachineFrameInfo &MFI = MF.getFrameInfo(); + const CAHPRegisterInfo *RI = STI.getRegisterInfo(); + + // Get the number of bytes to allocate from the FrameInfo. + uint64_t FrameSize = MFI.getStackSize(); + + // Get the alignment. + uint64_t StackAlign = RI->needsStackRealignment(MF) ? MFI.getMaxAlignment() + : getStackAlignment(); + + // Make sure the frame is aligned. + FrameSize = alignTo(FrameSize, StackAlign); + + // Update frame info. + MFI.setStackSize(FrameSize); +} + +// Build a MI to compute "DestReg = SrcReg + Val" +void CAHPFrameLowering::adjustReg(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + const DebugLoc &DL, unsigned DestReg, + unsigned SrcReg, int64_t Val, + MachineInstr::MIFlag Flag) const { + if (DestReg == SrcReg && Val == 0) + return; + + const CAHPInstrInfo *TII = STI.getInstrInfo(); + + if (isInt<10>(Val)) { + BuildMI(MBB, MBBI, DL, TII->get(CAHP::ADDI), DestReg) + .addReg(SrcReg) + .addImm(Val) + .setMIFlag(Flag); + } else { + report_fatal_error("adjustReg cannot yet handle adjustments >10 bits"); + } +} + +// Returns the register used to hold the frame pointer. +static unsigned getFPReg() { return CAHP::X2; } + +// Returns the register used to hold the stack pointer. +static unsigned getSPReg() { return CAHP::X1; } + void CAHPFrameLowering::emitPrologue(MachineFunction &MF, - MachineBasicBlock &MBB) const {} + MachineBasicBlock &MBB) const { + assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported"); + + if (!hasFP(MF)) { + report_fatal_error( + "emitPrologue doesn't support framepointer-less functions"); + } + + MachineFrameInfo &MFI = MF.getFrameInfo(); + MachineBasicBlock::iterator MBBI = MBB.begin(); + + unsigned FPReg = getFPReg(); + unsigned SPReg = getSPReg(); + + // Debug location must be unknown since the first debug location is used + // to determine the end of the prologue. + DebugLoc DL; + + // Determine the correct frame layout + determineFrameLayout(MF); + + // FIXME (note copied from Lanai/RISCV): This appears to be overallocating. + // Needs investigation. Get the number of bytes to allocate from the + // FrameInfo. + uint64_t StackSize = MFI.getStackSize(); + + // Early exit if there is no need to allocate on the stack + if (StackSize == 0 && !MFI.adjustsStack()) + return; + + // Allocate space on the stack if necessary. + adjustReg(MBB, MBBI, DL, SPReg, SPReg, -StackSize, MachineInstr::FrameSetup); + + // The frame pointer is callee-saved, and code has been generated for us to + // save it to the stack. We need to skip over the storing of callee-saved + // registers as the frame pointer must be modified after it has been saved + // to the stack, not before. + // FIXME: assumes exactly one instruction is used to save each callee-saved + // register. + const std::vector &CSI = MFI.getCalleeSavedInfo(); + std::advance(MBBI, CSI.size()); + + // Generate new FP. + adjustReg(MBB, MBBI, DL, FPReg, SPReg, StackSize, MachineInstr::FrameSetup); +} void CAHPFrameLowering::emitEpilogue(MachineFunction &MF, - MachineBasicBlock &MBB) const {} + MachineBasicBlock &MBB) const { + + if (!hasFP(MF)) { + report_fatal_error( + "emitEpilogue doesn't support framepointer-less functions"); + } + + MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); + const CAHPRegisterInfo *RI = STI.getRegisterInfo(); + MachineFrameInfo &MFI = MF.getFrameInfo(); + DebugLoc DL = MBBI->getDebugLoc(); + unsigned FPReg = getFPReg(); + unsigned SPReg = getSPReg(); + + // Skip to before the restores of callee-saved registers + // FIXME: assumes exactly one instruction is used to restore each + // callee-saved register. + MachineBasicBlock::iterator LastFrameDestroy = MBBI; + std::advance(LastFrameDestroy, -MFI.getCalleeSavedInfo().size()); + + uint64_t StackSize = MFI.getStackSize(); + + // Restore the stack pointer using the value of the frame pointer. Only + // necessary if the stack pointer was modified, meaning the stack size is + // unknown. + if (RI->needsStackRealignment(MF) || MFI.hasVarSizedObjects()) { + adjustReg(MBB, LastFrameDestroy, DL, SPReg, FPReg, -StackSize, + MachineInstr::FrameDestroy); + } + + // Deallocate stack + adjustReg(MBB, MBBI, DL, SPReg, SPReg, StackSize, MachineInstr::FrameDestroy); +} int CAHPFrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI, unsigned &FrameReg) const { @@ -46,3 +168,13 @@ int CAHPFrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI, } return Offset; } + +void CAHPFrameLowering::determineCalleeSaves(MachineFunction &MF, + BitVector &SavedRegs, + RegScavenger *RS) const { + TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS); + // TODO: Once frame pointer elimination is implemented, don't + // unconditionally spill the frame pointer and return address. + SavedRegs.set(CAHP::X0); + SavedRegs.set(CAHP::X2); +} diff --git a/llvm/lib/Target/CAHP/CAHPFrameLowering.h b/llvm/lib/Target/CAHP/CAHPFrameLowering.h index fac4ad133e4f..886ac48eb962 100644 --- a/llvm/lib/Target/CAHP/CAHPFrameLowering.h +++ b/llvm/lib/Target/CAHP/CAHPFrameLowering.h @@ -11,11 +11,20 @@ namespace llvm { class CAHPSubtarget; class CAHPFrameLowering : public TargetFrameLowering { +private: + const CAHPSubtarget &STI; + + void determineFrameLayout(MachineFunction &MF) const; + void adjustReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, + const DebugLoc &DL, unsigned DestReg, unsigned SrcReg, + int64_t Val, MachineInstr::MIFlag Flag) const; + public: explicit CAHPFrameLowering(const CAHPSubtarget &STI) : TargetFrameLowering(StackGrowsDown, /*StackAlignment=*/2, - /*LocalAreaOffset=*/0) {} + /*LocalAreaOffset=*/0), + STI(STI) {} void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override; void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override; @@ -23,6 +32,9 @@ class CAHPFrameLowering : public TargetFrameLowering { int getFrameIndexReference(const MachineFunction &MF, int FI, unsigned &FrameReg) const override; + void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, + RegScavenger *RS) const override; + bool hasFP(const MachineFunction &MF) const override; MachineBasicBlock::iterator From 1f0859491649ac423191a190d38b1b7e9bc3ce63 Mon Sep 17 00:00:00 2001 From: Ushitora Anqou Date: Mon, 28 Oct 2019 13:40:15 +0900 Subject: [PATCH 246/289] [CAHP] Add support for frame pointer elimination --- llvm/lib/Target/CAHP/CAHPFrameLowering.cpp | 47 +++++++++++++--------- llvm/lib/Target/CAHP/CAHPRegisterInfo.cpp | 6 +-- llvm/test/CodeGen/CAHP/calls.ll | 6 +++ 3 files changed, 36 insertions(+), 23 deletions(-) diff --git a/llvm/lib/Target/CAHP/CAHPFrameLowering.cpp b/llvm/lib/Target/CAHP/CAHPFrameLowering.cpp index 2fe99d99a713..8570c4c5b2f3 100644 --- a/llvm/lib/Target/CAHP/CAHPFrameLowering.cpp +++ b/llvm/lib/Target/CAHP/CAHPFrameLowering.cpp @@ -11,7 +11,17 @@ using namespace llvm; -bool CAHPFrameLowering::hasFP(const MachineFunction &MF) const { return true; } +// hasFP - Return true if the specified function should have a dedicated frame +// pointer register. This is true if the function has variable sized allocas or +// if frame pointer elimination is disabled. +bool CAHPFrameLowering::hasFP(const MachineFunction &MF) const { + const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo(); + const MachineFrameInfo &MFI = MF.getFrameInfo(); + + return MF.getTarget().Options.DisableFramePointerElim(MF) || + RegInfo->needsStackRealignment(MF) || MFI.hasVarSizedObjects() || + MFI.isFrameAddressTaken(); +} // Determines the size of the frame and maximum call frame size. void CAHPFrameLowering::determineFrameLayout(MachineFunction &MF) const { @@ -63,11 +73,6 @@ void CAHPFrameLowering::emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const { assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported"); - if (!hasFP(MF)) { - report_fatal_error( - "emitPrologue doesn't support framepointer-less functions"); - } - MachineFrameInfo &MFI = MF.getFrameInfo(); MachineBasicBlock::iterator MBBI = MBB.begin(); @@ -103,17 +108,12 @@ void CAHPFrameLowering::emitPrologue(MachineFunction &MF, std::advance(MBBI, CSI.size()); // Generate new FP. - adjustReg(MBB, MBBI, DL, FPReg, SPReg, StackSize, MachineInstr::FrameSetup); + if (hasFP(MF)) + adjustReg(MBB, MBBI, DL, FPReg, SPReg, StackSize, MachineInstr::FrameSetup); } void CAHPFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const { - - if (!hasFP(MF)) { - report_fatal_error( - "emitEpilogue doesn't support framepointer-less functions"); - } - MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); const CAHPRegisterInfo *RI = STI.getRegisterInfo(); MachineFrameInfo &MFI = MF.getFrameInfo(); @@ -133,6 +133,7 @@ void CAHPFrameLowering::emitEpilogue(MachineFunction &MF, // necessary if the stack pointer was modified, meaning the stack size is // unknown. if (RI->needsStackRealignment(MF) || MFI.hasVarSizedObjects()) { + assert(hasFP(MF) && "frame pointer should not have been eliminated"); adjustReg(MBB, LastFrameDestroy, DL, SPReg, FPReg, -StackSize, MachineInstr::FrameDestroy); } @@ -162,9 +163,13 @@ int CAHPFrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI, } FrameReg = RI->getFrameRegister(MF); - if (FI >= MinCSFI && FI <= MaxCSFI) { // callee-saved register? - FrameReg = CAHP::X1; // sp - Offset += MF.getFrameInfo().getStackSize(); // turn the Offset positive + + // If the frame index points to a callee-saved register or no frame pointer is + // used in the MachineFunction, then make the Offset relative to the stack + // pointer. + if ((FI >= MinCSFI && FI <= MaxCSFI) || !hasFP(MF)) { + FrameReg = CAHP::X1; // X1 is SP. + Offset += MF.getFrameInfo().getStackSize(); } return Offset; } @@ -173,8 +178,10 @@ void CAHPFrameLowering::determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, RegScavenger *RS) const { TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS); - // TODO: Once frame pointer elimination is implemented, don't - // unconditionally spill the frame pointer and return address. - SavedRegs.set(CAHP::X0); - SavedRegs.set(CAHP::X2); + // Unconditionally spill RA and FP only if the function uses a frame + // pointer. + if (hasFP(MF)) { + SavedRegs.set(CAHP::X0); + SavedRegs.set(CAHP::X2); + } } diff --git a/llvm/lib/Target/CAHP/CAHPRegisterInfo.cpp b/llvm/lib/Target/CAHP/CAHPRegisterInfo.cpp index 58a356208e6c..869f0f2e1e5c 100644 --- a/llvm/lib/Target/CAHP/CAHPRegisterInfo.cpp +++ b/llvm/lib/Target/CAHP/CAHPRegisterInfo.cpp @@ -53,8 +53,6 @@ void CAHPRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, int Offset = getFrameLowering(MF)->getFrameIndexReference(MF, FrameIndex, FrameReg) + MI.getOperand(FIOperandNum + 1).getImm(); - assert(MF.getSubtarget().getFrameLowering()->hasFP(MF) && - "eliminateFrameIndex currently requires hasFP"); // Offsets must be directly encoded in a 10-bit immediate field if (!isInt<10>(Offset)) { @@ -67,7 +65,9 @@ void CAHPRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, } Register CAHPRegisterInfo::getFrameRegister(const MachineFunction &MF) const { - return CAHP::X2; + const TargetFrameLowering *TFI = getFrameLowering(MF); + // Return FP if any, SP otherwise. + return TFI->hasFP(MF) ? CAHP::X2 /* FP */ : CAHP::X1 /* SP */; } const uint32_t * diff --git a/llvm/test/CodeGen/CAHP/calls.ll b/llvm/test/CodeGen/CAHP/calls.ll index 745c1e0a4384..8bdb61ac9c37 100644 --- a/llvm/test/CodeGen/CAHP/calls.ll +++ b/llvm/test/CodeGen/CAHP/calls.ll @@ -7,11 +7,13 @@ declare i16 @external_function(i16) define i16 @test_call_external(i16 %a) nounwind { ; CAHP-LABEL: test_call_external: ; CAHP: # %bb.0: +; CAHP-NEXT: addi sp, sp, -2 ; CAHP-NEXT: sw ra, 0(sp) ; CAHP-NEXT: lui a1, %hi(external_function) ; CAHP-NEXT: addi a1, a1, %lo(external_function) ; CAHP-NEXT: jalr a1 ; CAHP-NEXT: lw ra, 0(sp) +; CAHP-NEXT: addi sp, sp, 2 ; CAHP-NEXT: jr ra %1 = call i16 @external_function(i16 %a) ret i16 %1 @@ -29,11 +31,13 @@ define i16 @defined_function(i16 %a) nounwind { define i16 @test_call_defined(i16 %a) nounwind { ; CAHP-LABEL: test_call_defined: ; CAHP: # %bb.0: +; CAHP-NEXT: addi sp, sp, -2 ; CAHP-NEXT: sw ra, 0(sp) ; CAHP-NEXT: lui a1, %hi(defined_function) ; CAHP-NEXT: addi a1, a1, %lo(defined_function) ; CAHP-NEXT: jalr a1 ; CAHP-NEXT: lw ra, 0(sp) +; CAHP-NEXT: addi sp, sp, 2 ; CAHP-NEXT: jr ra %1 = call i16 @defined_function(i16 %a) nounwind ret i16 %1 @@ -42,11 +46,13 @@ define i16 @test_call_defined(i16 %a) nounwind { define i16 @test_call_indirect(i16 (i16)* %a, i16 %b) nounwind { ; CAHP-LABEL: test_call_indirect: ; CAHP: # %bb.0: +; CAHP-NEXT: addi sp, sp, -2 ; CAHP-NEXT: sw ra, 0(sp) ; CAHP-NEXT: mov a2, a0 ; CAHP-NEXT: mov a0, a1 ; CAHP-NEXT: jalr a2 ; CAHP-NEXT: lw ra, 0(sp) +; CAHP-NEXT: addi sp, sp, 2 ; CAHP-NEXT: jr ra %1 = call i16 %a(i16 %b) ret i16 %1 From 9a6e8aed07dfc0ea31403a9643aa37a906edf600 Mon Sep 17 00:00:00 2001 From: Ushitora Anqou Date: Mon, 28 Oct 2019 14:24:48 +0900 Subject: [PATCH 247/289] [CAHP] Add support for SELECT/SELECT_CC --- llvm/lib/Target/CAHP/CAHPISelLowering.cpp | 144 ++++++++++++++++++++++ llvm/lib/Target/CAHP/CAHPISelLowering.h | 6 + llvm/lib/Target/CAHP/CAHPInstrInfo.td | 12 ++ llvm/test/CodeGen/CAHP/bare-select.ll | 18 +++ llvm/test/CodeGen/CAHP/select-cc.ll | 100 +++++++++++++++ 5 files changed, 280 insertions(+) create mode 100644 llvm/test/CodeGen/CAHP/bare-select.ll create mode 100644 llvm/test/CodeGen/CAHP/select-cc.ll diff --git a/llvm/lib/Target/CAHP/CAHPISelLowering.cpp b/llvm/lib/Target/CAHP/CAHPISelLowering.cpp index 6bff1dab1f78..5189b4660db6 100644 --- a/llvm/lib/Target/CAHP/CAHPISelLowering.cpp +++ b/llvm/lib/Target/CAHP/CAHPISelLowering.cpp @@ -44,6 +44,8 @@ CAHPTargetLowering::CAHPTargetLowering(const TargetMachine &TM, // TODO: add all necessary setOperationAction calls. setOperationAction(ISD::GlobalAddress, MVT::i16, Custom); setOperationAction(ISD::BR_CC, MVT::i16, Expand); + setOperationAction(ISD::SELECT, MVT::i16, Custom); + setOperationAction(ISD::SELECT_CC, MVT::i16, Expand); setBooleanContents(ZeroOrOneBooleanContent); @@ -52,6 +54,45 @@ CAHPTargetLowering::CAHPTargetLowering(const TargetMachine &TM, setPrefFunctionAlignment(0); } +// Changes the condition code and swaps operands if necessary, so the SetCC +// operation matches one of the comparisons supported directly in the CAHP +// ISA. +static void normaliseSetCC(SDValue &LHS, SDValue &RHS, ISD::CondCode &CC) { + switch (CC) { + default: + break; + case ISD::SETGT: + case ISD::SETGE: + case ISD::SETUGT: + case ISD::SETUGE: + CC = ISD::getSetCCSwappedOperands(CC); + std::swap(LHS, RHS); + break; + } +} + +// Return the CAHP branch opcode that matches the given DAG integer +// condition code. The CondCode must be one of those supported by the CAHP +// ISA (see normaliseSetCC). +static unsigned getBranchOpcodeForIntCondCode(ISD::CondCode CC) { + switch (CC) { + default: + llvm_unreachable("Unsupported CondCode"); + case ISD::SETEQ: + return CAHP::BEQ; + case ISD::SETNE: + return CAHP::BNE; + case ISD::SETLT: + return CAHP::BLT; + case ISD::SETLE: + return CAHP::BLE; + case ISD::SETULT: + return CAHP::BLTU; + case ISD::SETULE: + return CAHP::BLEU; + } +} + SDValue CAHPTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const { switch (Op.getOpcode()) { @@ -60,6 +101,9 @@ SDValue CAHPTargetLowering::LowerOperation(SDValue Op, case ISD::GlobalAddress: return lowerGlobalAddress(Op, DAG); + + case ISD::SELECT: + return LowerSELECT(Op, DAG); } } @@ -85,6 +129,104 @@ SDValue CAHPTargetLowering::lowerGlobalAddress(SDValue Op, } } +SDValue CAHPTargetLowering::LowerSELECT(SDValue Op, SelectionDAG &DAG) const { + SDValue CondV = Op.getOperand(0); + SDValue TrueV = Op.getOperand(1); + SDValue FalseV = Op.getOperand(2); + SDLoc DL(Op); + + // (select (setcc lhs, rhs, cc), truev, falsev) + // -> (cahpisd::select_cc lhs, rhs, cc, truev, falsev) + if (Op.getSimpleValueType() == MVT::i16 && CondV.getOpcode() == ISD::SETCC && + CondV.getOperand(0).getSimpleValueType() == MVT::i16) { + SDValue LHS = CondV.getOperand(0); + SDValue RHS = CondV.getOperand(1); + auto CC = cast(CondV.getOperand(2)); + ISD::CondCode CCVal = CC->get(); + + normaliseSetCC(LHS, RHS, CCVal); + + SDValue TargetCC = DAG.getConstant(CCVal, DL, MVT::i16); + SDVTList VTs = DAG.getVTList(Op.getValueType(), MVT::Glue); + SDValue Ops[] = {LHS, RHS, TargetCC, TrueV, FalseV}; + return DAG.getNode(CAHPISD::SELECT_CC, DL, VTs, Ops); + } + + // Otherwise: + // (select condv, truev, falsev) + // -> (cahpisd::select_cc condv, zero, setne, truev, falsev) + SDValue Zero = DAG.getConstant(0, DL, MVT::i16); + SDValue SetNE = DAG.getConstant(ISD::SETNE, DL, MVT::i16); + + SDVTList VTs = DAG.getVTList(Op.getValueType(), MVT::Glue); + SDValue Ops[] = {CondV, Zero, SetNE, TrueV, FalseV}; + + return DAG.getNode(CAHPISD::SELECT_CC, DL, VTs, Ops); +} + +MachineBasicBlock * +CAHPTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI, + MachineBasicBlock *BB) const { + const TargetInstrInfo &TII = *BB->getParent()->getSubtarget().getInstrInfo(); + DebugLoc DL = MI.getDebugLoc(); + + assert(MI.getOpcode() == CAHP::Select_GPR_Using_CC_GPR && + "Unexpected instr type to insert"); + + // To "insert" a SELECT instruction, we actually have to insert the triangle + // control-flow pattern. The incoming instruction knows the destination vreg + // to set, the condition code register to branch on, the true/false values to + // select between, and the condcode to use to select the appropriate branch. + // + // We produce the following control flow: + // HeadMBB + // | \ + // | IfFalseMBB + // | / + // TailMBB + const BasicBlock *LLVM_BB = BB->getBasicBlock(); + MachineFunction::iterator I = ++BB->getIterator(); + + MachineBasicBlock *HeadMBB = BB; + MachineFunction *F = BB->getParent(); + MachineBasicBlock *TailMBB = F->CreateMachineBasicBlock(LLVM_BB); + MachineBasicBlock *IfFalseMBB = F->CreateMachineBasicBlock(LLVM_BB); + + F->insert(I, IfFalseMBB); + F->insert(I, TailMBB); + // Move all remaining instructions to TailMBB. + TailMBB->splice(TailMBB->begin(), HeadMBB, + std::next(MachineBasicBlock::iterator(MI)), HeadMBB->end()); + // Update machine-CFG edges by transferring all successors of the current + // block to the new block which will contain the Phi node for the select. + TailMBB->transferSuccessorsAndUpdatePHIs(HeadMBB); + // Set the successors for HeadMBB. + HeadMBB->addSuccessor(IfFalseMBB); + HeadMBB->addSuccessor(TailMBB); + + // Insert appropriate branch. + unsigned LHS = MI.getOperand(1).getReg(); + unsigned RHS = MI.getOperand(2).getReg(); + auto CC = static_cast(MI.getOperand(3).getImm()); + unsigned Opcode = getBranchOpcodeForIntCondCode(CC); + + BuildMI(HeadMBB, DL, TII.get(Opcode)).addReg(LHS).addReg(RHS).addMBB(TailMBB); + + // IfFalseMBB just falls through to TailMBB. + IfFalseMBB->addSuccessor(TailMBB); + + // %Result = phi [ %TrueValue, HeadMBB ], [ %FalseValue, IfFalseMBB ] + BuildMI(*TailMBB, TailMBB->begin(), DL, TII.get(CAHP::PHI), + MI.getOperand(0).getReg()) + .addReg(MI.getOperand(4).getReg()) + .addMBB(HeadMBB) + .addReg(MI.getOperand(5).getReg()) + .addMBB(IfFalseMBB); + + MI.eraseFromParent(); // The pseudo instruction is gone now. + return TailMBB; +} + // Calling Convention Implementation. #include "CAHPGenCallingConv.inc" @@ -310,6 +452,8 @@ const char *CAHPTargetLowering::getTargetNodeName(unsigned Opcode) const { break; case CAHPISD::CALL: return "CAHPISD::CALL"; + case CAHPISD::SELECT_CC: + return "CAHPISD::SELECT_CC"; case CAHPISD::RET_FLAG: return "CAHPISD::RET_FLAG"; } diff --git a/llvm/lib/Target/CAHP/CAHPISelLowering.h b/llvm/lib/Target/CAHP/CAHPISelLowering.h index 6d60c3dc7c90..0aa252ff26c7 100644 --- a/llvm/lib/Target/CAHP/CAHPISelLowering.h +++ b/llvm/lib/Target/CAHP/CAHPISelLowering.h @@ -16,6 +16,7 @@ enum NodeType : unsigned { FIRST_NUMBER = ISD::BUILTIN_OP_END, CALL, + SELECT_CC, RET_FLAG, }; } @@ -34,6 +35,10 @@ class CAHPTargetLowering : public TargetLowering { // This method returns the name of a target specific DAG node. const char *getTargetNodeName(unsigned Opcode) const override; + MachineBasicBlock * + EmitInstrWithCustomInserter(MachineInstr &MI, + MachineBasicBlock *BB) const override; + private: // Lower incoming arguments, copy physregs into vregs SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, @@ -53,6 +58,7 @@ class CAHPTargetLowering : public TargetLowering { } SDValue lowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerSELECT(SDValue Op, SelectionDAG &DAG) const; }; } // namespace llvm diff --git a/llvm/lib/Target/CAHP/CAHPInstrInfo.td b/llvm/lib/Target/CAHP/CAHPInstrInfo.td index 8feae795f661..9634e328db7c 100644 --- a/llvm/lib/Target/CAHP/CAHPInstrInfo.td +++ b/llvm/lib/Target/CAHP/CAHPInstrInfo.td @@ -7,6 +7,9 @@ include "CAHPInstrFormats.td" def SDT_CAHPCall : SDTypeProfile<0, -1, [SDTCisVT<0, i16>]>; def SDT_CAHPCallSeqStart : SDCallSeqStart<[SDTCisVT<0, i16>, SDTCisVT<1, i16>]>; def SDT_CAHPCallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i16>, SDTCisVT<1, i16>]>; +def SDT_CAHPSelectCC : SDTypeProfile<1, 5, [SDTCisSameAs<1, 2>, + SDTCisSameAs<0, 4>, + SDTCisSameAs<4, 5>]>; def Call : SDNode<"CAHPISD::CALL", SDT_CAHPCall, [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue, @@ -17,6 +20,8 @@ def CallSeqEnd : SDNode<"ISD::CALLSEQ_END", SDT_CAHPCallSeqEnd, [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue]>; def RetFlag : SDNode<"CAHPISD::RET_FLAG", SDTNone, [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; +def SelectCC : SDNode<"CAHPISD::SELECT_CC", SDT_CAHPSelectCC, + [SDNPInGlue]>; class ImmAsmOperand : AsmOperandClass { let Name = prefix # "Imm" # width # suffix; @@ -286,6 +291,13 @@ def ADJCALLSTACKUP : Pseudo<(outs), (ins i16imm:$amt1, i16imm:$amt2), [(CallSeqEnd timm:$amt1, timm:$amt2)]>; } // Defs = [X1], Uses = [X1] +let usesCustomInserter = 1 in +def Select_GPR_Using_CC_GPR + : Pseudo<(outs GPR:$dst), + (ins GPR:$lhs, GPR:$rhs, i16imm:$imm, GPR:$src, GPR:$src2), + [(set i16:$dst, (SelectCC GPR:$lhs, GPR:$rhs, + (i16 imm:$imm), GPR:$src, GPR:$src2))]>; + // Codegen patterns. def : Pat<(simm6:$imm), (LSI simm6:$imm)>; diff --git a/llvm/test/CodeGen/CAHP/bare-select.ll b/llvm/test/CodeGen/CAHP/bare-select.ll new file mode 100644 index 000000000000..c908e3b7400b --- /dev/null +++ b/llvm/test/CodeGen/CAHP/bare-select.ll @@ -0,0 +1,18 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=cahp -verify-machineinstrs < %s \ +; RUN: | FileCheck %s -check-prefix=CAHP + +define i16 @bare_select(i1 %a, i16 %b, i16 %c) { +; CAHP-LABEL: bare_select: +; CAHP: # %bb.0: +; CAHP-NEXT: andi a0, a0, 1 +; CAHP-NEXT: lsi a3, 0 +; CAHP-NEXT: bne a0, a3, .LBB0_2 +; CAHP-NEXT:# %bb.1: +; CAHP-NEXT: mov a1, a2 +; CAHP-NEXT:.LBB0_2: +; CAHP-NEXT: mov a0, a1 +; CAHP-NEXT: jr ra + %1 = select i1 %a, i16 %b, i16 %c + ret i16 %1 +} diff --git a/llvm/test/CodeGen/CAHP/select-cc.ll b/llvm/test/CodeGen/CAHP/select-cc.ll new file mode 100644 index 000000000000..5e6a035fb8fd --- /dev/null +++ b/llvm/test/CodeGen/CAHP/select-cc.ll @@ -0,0 +1,100 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=cahp -verify-machineinstrs < %s \ +; RUN: | FileCheck %s -check-prefix=CAHP + +define i16 @foo(i16 %a, i16 *%b) { +; CAHP-LABEL: foo: +; CAHP: # %bb.0: +; CAHP-NEXT: lw a2, 0(a1) +; CAHP-NEXT: beq a0, a2, .LBB0_2 +; CAHP-NEXT:# %bb.1: +; CAHP-NEXT: mov a0, a2 +; CAHP-NEXT:.LBB0_2: +; CAHP-NEXT: lw a2, 0(a1) +; CAHP-NEXT: bne a0, a2, .LBB0_4 +; CAHP-NEXT:# %bb.3: +; CAHP-NEXT: mov a0, a2 +; CAHP-NEXT:.LBB0_4: +; CAHP-NEXT: lw a2, 0(a1) +; CAHP-NEXT: bltu a2, a0, .LBB0_6 +; CAHP-NEXT:# %bb.5: +; CAHP-NEXT: mov a0, a2 +; CAHP-NEXT:.LBB0_6: +; CAHP-NEXT: lw a2, 0(a1) +; CAHP-NEXT: bleu a2, a0, .LBB0_8 +; CAHP-NEXT:# %bb.7: +; CAHP-NEXT: mov a0, a2 +; CAHP-NEXT:.LBB0_8: +; CAHP-NEXT: lw a2, 0(a1) +; CAHP-NEXT: bltu a0, a2, .LBB0_10 +; CAHP-NEXT:# %bb.9: +; CAHP-NEXT: mov a0, a2 +; CAHP-NEXT:.LBB0_10: +; CAHP-NEXT: lw a2, 0(a1) +; CAHP-NEXT: bleu a0, a2, .LBB0_12 +; CAHP-NEXT:# %bb.11: +; CAHP-NEXT: mov a0, a2 +; CAHP-NEXT:.LBB0_12: +; CAHP-NEXT: lw a2, 0(a1) +; CAHP-NEXT: blt a2, a0, .LBB0_14 +; CAHP-NEXT:# %bb.13: +; CAHP-NEXT: mov a0, a2 +; CAHP-NEXT:.LBB0_14: +; CAHP-NEXT: lw a2, 0(a1) +; CAHP-NEXT: ble a2, a0, .LBB0_16 +; CAHP-NEXT:# %bb.15: +; CAHP-NEXT: mov a0, a2 +; CAHP-NEXT:.LBB0_16: +; CAHP-NEXT: lw a2, 0(a1) +; CAHP-NEXT: blt a0, a2, .LBB0_18 +; CAHP-NEXT:# %bb.17: +; CAHP-NEXT: mov a0, a2 +; CAHP-NEXT:.LBB0_18: +; CAHP-NEXT: lw a1, 0(a1) +; CAHP-NEXT: ble a0, a1, .LBB0_20 +; CAHP-NEXT:# %bb.19: +; CAHP-NEXT: mov a0, a1 +; CAHP-NEXT:.LBB0_20: +; CAHP-NEXT: jr ra + %val1 = load volatile i16, i16* %b + %tst1 = icmp eq i16 %a, %val1 + %val2 = select i1 %tst1, i16 %a, i16 %val1 + + %val3 = load volatile i16, i16* %b + %tst2 = icmp ne i16 %val2, %val3 + %val4 = select i1 %tst2, i16 %val2, i16 %val3 + + %val5 = load volatile i16, i16* %b + %tst3 = icmp ugt i16 %val4, %val5 + %val6 = select i1 %tst3, i16 %val4, i16 %val5 + + %val7 = load volatile i16, i16* %b + %tst4 = icmp uge i16 %val6, %val7 + %val8 = select i1 %tst4, i16 %val6, i16 %val7 + + %val9 = load volatile i16, i16* %b + %tst5 = icmp ult i16 %val8, %val9 + %val10 = select i1 %tst5, i16 %val8, i16 %val9 + + %val11 = load volatile i16, i16* %b + %tst6 = icmp ule i16 %val10, %val11 + %val12 = select i1 %tst6, i16 %val10, i16 %val11 + + %val13 = load volatile i16, i16* %b + %tst7 = icmp sgt i16 %val12, %val13 + %val14 = select i1 %tst7, i16 %val12, i16 %val13 + + %val15 = load volatile i16, i16* %b + %tst8 = icmp sge i16 %val14, %val15 + %val16 = select i1 %tst8, i16 %val14, i16 %val15 + + %val17 = load volatile i16, i16* %b + %tst9 = icmp slt i16 %val16, %val17 + %val18 = select i1 %tst9, i16 %val16, i16 %val17 + + %val19 = load volatile i16, i16* %b + %tst10 = icmp sle i16 %val18, %val19 + %val20 = select i1 %tst10, i16 %val18, i16 %val19 + + ret i16 %val20 +} From 7f4c27b1150ded91b4517991b36cbf23ddbf01b0 Mon Sep 17 00:00:00 2001 From: Ushitora Anqou Date: Mon, 28 Oct 2019 15:44:49 +0900 Subject: [PATCH 248/289] [CAHP] Add support for lowering FrameIndex --- llvm/lib/Target/CAHP/CAHPISelDAGToDAG.cpp | 20 ++++++++++++++++++ llvm/lib/Target/CAHP/CAHPInstrInfo.td | 24 ++++++++++++++++++++++ llvm/test/CodeGen/CAHP/frameindex.ll | 25 +++++++++++++++++++++++ 3 files changed, 69 insertions(+) create mode 100644 llvm/test/CodeGen/CAHP/frameindex.ll diff --git a/llvm/lib/Target/CAHP/CAHPISelDAGToDAG.cpp b/llvm/lib/Target/CAHP/CAHPISelDAGToDAG.cpp index 5fc0c4f51ede..7e9d8c3d3147 100644 --- a/llvm/lib/Target/CAHP/CAHPISelDAGToDAG.cpp +++ b/llvm/lib/Target/CAHP/CAHPISelDAGToDAG.cpp @@ -27,6 +27,8 @@ class CAHPDAGToDAGISel final : public SelectionDAGISel { void Select(SDNode *Node) override; + bool SelectAddrFI(SDValue Addr, SDValue &Base); + // Include the pieces autogenerated from the target description. #include "CAHPGenDAGISel.inc" }; @@ -40,10 +42,28 @@ void CAHPDAGToDAGISel::Select(SDNode *Node) { return; } + if (Node->getOpcode() == ISD::FrameIndex) { + SDLoc DL(Node); + SDValue Imm = CurDAG->getTargetConstant(0, DL, MVT::i16); + int FI = dyn_cast(Node)->getIndex(); + EVT VT = Node->getValueType(0); + SDValue TFI = CurDAG->getTargetFrameIndex(FI, VT); + ReplaceNode(Node, CurDAG->getMachineNode(CAHP::ADDI, DL, VT, TFI, Imm)); + return; + } + // Select the default instruction. SelectCode(Node); } +bool CAHPDAGToDAGISel::SelectAddrFI(SDValue Addr, SDValue &Base) { + if (auto FIN = dyn_cast(Addr)) { + Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i16); + return true; + } + return false; +} + // This pass converts a legalized DAG into a CAHP-specific DAG, ready // for instruction scheduling. FunctionPass *llvm::createCAHPISelDag(CAHPTargetMachine &TM) { diff --git a/llvm/lib/Target/CAHP/CAHPInstrInfo.td b/llvm/lib/Target/CAHP/CAHPInstrInfo.td index 9634e328db7c..8dce6d638f13 100644 --- a/llvm/lib/Target/CAHP/CAHPInstrInfo.td +++ b/llvm/lib/Target/CAHP/CAHPInstrInfo.td @@ -92,6 +92,14 @@ def HI6 : SDNodeXFormgetValueType(0)); }]>; +// Addressing modes. +// Necessary because a frameindex can't be matched directly in a pattern. +def AddrFI : ComplexPattern; + +def IsOrAdd: PatFrag<(ops node:$A, node:$B), (or node:$A, node:$B), [{ + return isOrEquivalentToAdd(N); +}]>; + // 24-bit M-instructions. let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in { @@ -300,6 +308,12 @@ def Select_GPR_Using_CC_GPR // Codegen patterns. +/// FrameIndex calculations +def : Pat<(add (i16 AddrFI:$Rs), simm10:$imm), + (ADDI (i16 AddrFI:$Rs), simm10:$imm)>; +def : Pat<(IsOrAdd (i16 AddrFI:$Rs), simm10:$imm), + (ADDI (i16 AddrFI:$Rs), simm10:$imm)>; + def : Pat<(simm6:$imm), (LSI simm6:$imm)>; def : Pat<(simm10:$imm), (LI simm10:$imm)>; def : Pat<(simm16hi6:$imm), (LUI (HI6 imm:$imm))>; @@ -307,8 +321,13 @@ def : Pat<(simm16:$imm), (ADDI (LUI (HI6 imm:$imm)), (LO10Sext imm:$imm))>; multiclass LdPat { def : Pat<(LoadOp GPR:$rs1), (Inst GPR:$rs1, 0)>; + def : Pat<(LoadOp AddrFI:$rs1), (LW AddrFI:$rs1, 0)>; def : Pat<(LoadOp (add GPR:$rs1, simm10:$imm)), (Inst GPR:$rs1, simm10:$imm)>; + def : Pat<(LoadOp (add AddrFI:$rs1, simm10:$imm)), + (Inst AddrFI:$rs1, simm10:$imm)>; + def : Pat<(LoadOp (IsOrAdd AddrFI:$rs1, simm10:$imm)), + (Inst AddrFI:$rs1, simm10:$imm)>; } defm : LdPat; defm : LdPat; @@ -317,8 +336,13 @@ defm : LdPat; multiclass StPat { def : Pat<(StoreOp GPR:$rs, GPR:$rd), (Inst GPR:$rs, GPR:$rd, 0)>; + def : Pat<(StoreOp GPR:$rs, AddrFI:$rd), (Inst GPR:$rs, AddrFI:$rd, 0)>; def : Pat<(StoreOp GPR:$rs, (add GPR:$rd, simm10:$imm)), (Inst GPR:$rs, GPR:$rd, simm10:$imm)>; + def : Pat<(StoreOp GPR:$rs, (add AddrFI:$rd, simm10:$imm)), + (Inst GPR:$rs, AddrFI:$rd, simm10:$imm)>; + def : Pat<(StoreOp GPR:$rs, (IsOrAdd AddrFI:$rd, simm10:$imm)), + (Inst GPR:$rs, AddrFI:$rd, simm10:$imm)>; } defm : StPat; defm : StPat; diff --git a/llvm/test/CodeGen/CAHP/frameindex.ll b/llvm/test/CodeGen/CAHP/frameindex.ll new file mode 100644 index 000000000000..6637e8890b8b --- /dev/null +++ b/llvm/test/CodeGen/CAHP/frameindex.ll @@ -0,0 +1,25 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=cahp -verify-machineinstrs < %s \ +; RUN: | FileCheck -check-prefix=CAHP %s + +declare i16 @bar(i16*) + +define i16 @foo() { +; CAHP-LABEL: foo: +; CAHP: # %bb.0: +; CAHP-NEXT: addi sp, sp, -4 +; CAHP-NEXT: sw ra, 2(sp) +; CAHP-NEXT: lui a0, %hi(bar) +; CAHP-NEXT: addi a1, a0, %lo(bar) +; CAHP-NEXT: addi a0, sp, 0 +; CAHP-NEXT: jalr a1 +; CAHP-NEXT: lw a0, 0(sp) +; CAHP-NEXT: lw ra, 2(sp) +; CAHP-NEXT: addi sp, sp, 4 +; CAHP-NEXT: jr ra + %1 = alloca i16 + %2 = call i16 @bar(i16* %1) + %3 = getelementptr inbounds i16, i16* %1, i16 0 + %4 = load i16, i16* %3 + ret i16 %4 +} From 8715fe9594e25cfa32ece4a3f48a87bf2bbff390 Mon Sep 17 00:00:00 2001 From: Ushitora Anqou Date: Mon, 28 Oct 2019 16:41:27 +0900 Subject: [PATCH 249/289] [CAHP] Add support for large stack frame --- llvm/lib/Target/CAHP/CAHPFrameLowering.cpp | 17 +++++++- llvm/lib/Target/CAHP/CAHPInstrInfo.cpp | 18 ++++++++ llvm/lib/Target/CAHP/CAHPInstrInfo.h | 5 +++ llvm/lib/Target/CAHP/CAHPRegisterInfo.cpp | 18 ++++++-- llvm/lib/Target/CAHP/CAHPRegisterInfo.h | 8 ++++ llvm/test/CodeGen/CAHP/large-stack.ll | 51 ++++++++++++++++++++++ 6 files changed, 113 insertions(+), 4 deletions(-) create mode 100644 llvm/test/CodeGen/CAHP/large-stack.ll diff --git a/llvm/lib/Target/CAHP/CAHPFrameLowering.cpp b/llvm/lib/Target/CAHP/CAHPFrameLowering.cpp index 8570c4c5b2f3..ea2adef56c2c 100644 --- a/llvm/lib/Target/CAHP/CAHPFrameLowering.cpp +++ b/llvm/lib/Target/CAHP/CAHPFrameLowering.cpp @@ -51,6 +51,7 @@ void CAHPFrameLowering::adjustReg(MachineBasicBlock &MBB, if (DestReg == SrcReg && Val == 0) return; + MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo(); const CAHPInstrInfo *TII = STI.getInstrInfo(); if (isInt<10>(Val)) { @@ -58,8 +59,22 @@ void CAHPFrameLowering::adjustReg(MachineBasicBlock &MBB, .addReg(SrcReg) .addImm(Val) .setMIFlag(Flag); + } else if (isInt<16>(Val)) { + unsigned Opc = CAHP::ADD; + bool isSub = Val < 0; + if (isSub) { + Val = -Val; + Opc = CAHP::SUB; + } + + unsigned ScratchReg = MRI.createVirtualRegister(&CAHP::GPRRegClass); + TII->movImm16(MBB, MBBI, DL, ScratchReg, Val, Flag); + BuildMI(MBB, MBBI, DL, TII->get(Opc), DestReg) + .addReg(SrcReg) + .addReg(ScratchReg) + .setMIFlag(Flag); } else { - report_fatal_error("adjustReg cannot yet handle adjustments >10 bits"); + report_fatal_error("adjustReg cannot yet handle adjustments >16 bits"); } } diff --git a/llvm/lib/Target/CAHP/CAHPInstrInfo.cpp b/llvm/lib/Target/CAHP/CAHPInstrInfo.cpp index cf5e27a63916..fd38d3d0b2d8 100644 --- a/llvm/lib/Target/CAHP/CAHPInstrInfo.cpp +++ b/llvm/lib/Target/CAHP/CAHPInstrInfo.cpp @@ -61,3 +61,21 @@ void CAHPInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, BuildMI(MBB, I, DL, get(CAHP::LW), DstReg).addFrameIndex(FI).addImm(0); } + +void CAHPInstrInfo::movImm16(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + const DebugLoc &DL, unsigned DstReg, uint64_t Val, + MachineInstr::MIFlag Flag) const { + assert(isInt<16>(Val) && "Can only materialize 16-bit constants"); + + // TODO: If the value can be materialized using only one instruction, only + // insert a single instruction. + + uint64_t Hi6 = ((Val + 0x200) >> 10) & 0x3f; + uint64_t Lo10 = SignExtend64<10>(Val); + BuildMI(MBB, MBBI, DL, get(CAHP::LUI), DstReg).addImm(Hi6).setMIFlag(Flag); + BuildMI(MBB, MBBI, DL, get(CAHP::ADDI), DstReg) + .addReg(DstReg) + .addImm(Lo10) + .setMIFlag(Flag); +} diff --git a/llvm/lib/Target/CAHP/CAHPInstrInfo.h b/llvm/lib/Target/CAHP/CAHPInstrInfo.h index a0cf9922a017..c8e9099ead8c 100644 --- a/llvm/lib/Target/CAHP/CAHPInstrInfo.h +++ b/llvm/lib/Target/CAHP/CAHPInstrInfo.h @@ -29,6 +29,11 @@ class CAHPInstrInfo : public CAHPGenInstrInfo { MachineBasicBlock::iterator I, unsigned DstReg, int FI, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI) const override; + + // Materializes the given int16 Val into DstReg. + void movImm16(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, + const DebugLoc &DL, unsigned DstReg, uint64_t Val, + MachineInstr::MIFlag Flag = MachineInstr::NoFlags) const; }; } // namespace llvm diff --git a/llvm/lib/Target/CAHP/CAHPRegisterInfo.cpp b/llvm/lib/Target/CAHP/CAHPRegisterInfo.cpp index 869f0f2e1e5c..492b55d7387c 100644 --- a/llvm/lib/Target/CAHP/CAHPRegisterInfo.cpp +++ b/llvm/lib/Target/CAHP/CAHPRegisterInfo.cpp @@ -46,6 +46,8 @@ void CAHPRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, MachineInstr &MI = *II; MachineFunction &MF = *MI.getParent()->getParent(); + MachineRegisterInfo &MRI = MF.getRegInfo(); + const CAHPInstrInfo *TII = MF.getSubtarget().getInstrInfo(); DebugLoc DL = MI.getDebugLoc(); int FrameIndex = MI.getOperand(FIOperandNum).getIndex(); @@ -54,10 +56,20 @@ void CAHPRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, getFrameLowering(MF)->getFrameIndexReference(MF, FrameIndex, FrameReg) + MI.getOperand(FIOperandNum + 1).getImm(); - // Offsets must be directly encoded in a 10-bit immediate field - if (!isInt<10>(Offset)) { + if (!isInt<16>(Offset)) report_fatal_error( - "Frame offsets outside of the signed 10-bit range not supported"); + "Frame offsets outside of the signed 16-bit range not supported"); + + MachineBasicBlock &MBB = *MI.getParent(); + + if (!isInt<10>(Offset)) { + unsigned ScratchReg = MRI.createVirtualRegister(&CAHP::GPRRegClass); + TII->movImm16(MBB, II, DL, ScratchReg, Offset); + BuildMI(MBB, II, DL, TII->get(CAHP::ADD), ScratchReg) + .addReg(ScratchReg) + .addReg(FrameReg); + Offset = 0; + FrameReg = ScratchReg; } MI.getOperand(FIOperandNum).ChangeToRegister(FrameReg, false); diff --git a/llvm/lib/Target/CAHP/CAHPRegisterInfo.h b/llvm/lib/Target/CAHP/CAHPRegisterInfo.h index 261efeb97a7f..37bea41c7d79 100644 --- a/llvm/lib/Target/CAHP/CAHPRegisterInfo.h +++ b/llvm/lib/Target/CAHP/CAHPRegisterInfo.h @@ -28,6 +28,14 @@ struct CAHPRegisterInfo : public CAHPGenRegisterInfo { RegScavenger *RS = nullptr) const override; Register getFrameRegister(const MachineFunction &MF) const override; + + bool requiresRegisterScavenging(const MachineFunction &MF) const override { + return true; + } + + bool requiresFrameIndexScavenging(const MachineFunction &MF) const override { + return true; + } }; } // namespace llvm diff --git a/llvm/test/CodeGen/CAHP/large-stack.ll b/llvm/test/CodeGen/CAHP/large-stack.ll new file mode 100644 index 000000000000..76e9e692c5f9 --- /dev/null +++ b/llvm/test/CodeGen/CAHP/large-stack.ll @@ -0,0 +1,51 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=cahp -verify-machineinstrs < %s \ +; RUN: | FileCheck -check-prefix=CAHP-FPELIM %s +; RUN: llc -mtriple=cahp -verify-machineinstrs -frame-pointer=all < %s \ +; RUN: | FileCheck -check-prefix=CAHP-WITHFP %s + +; TODO: the quality of the generated code is poor + +define void @test() nounwind { +; CAHP-WITHFP-LABEL: test: +; CAHP-WITHFP: # %bb.0: +; CAHP-WITHFP-NEXT: lui a0, 3 +; CAHP-WITHFP-NEXT: addi a0, a0, -68 +; CAHP-WITHFP-NEXT: sub sp, sp, a0 +; CAHP-WITHFP-NEXT: lui a0, 3 +; CAHP-WITHFP-NEXT: addi a0, a0, -70 +; CAHP-WITHFP-NEXT: add a0, a0, sp +; CAHP-WITHFP-NEXT: sw ra, 0(a0) +; CAHP-WITHFP-NEXT: lui a0, 3 +; CAHP-WITHFP-NEXT: addi a0, a0, -72 +; CAHP-WITHFP-NEXT: add a0, a0, sp +; CAHP-WITHFP-NEXT: sw fp, 0(a0) +; CAHP-WITHFP-NEXT: lui a0, 3 +; CAHP-WITHFP-NEXT: addi a0, a0, -68 +; CAHP-WITHFP-NEXT: add fp, sp, a0 +; CAHP-WITHFP-NEXT: lui a0, 3 +; CAHP-WITHFP-NEXT: addi a0, a0, -72 +; CAHP-WITHFP-NEXT: add a0, a0, sp +; CAHP-WITHFP-NEXT: lw fp, 0(a0) +; CAHP-WITHFP-NEXT: lui a0, 3 +; CAHP-WITHFP-NEXT: addi a0, a0, -70 +; CAHP-WITHFP-NEXT: add a0, a0, sp +; CAHP-WITHFP-NEXT: lw ra, 0(a0) +; CAHP-WITHFP-NEXT: lui a0, 3 +; CAHP-WITHFP-NEXT: addi a0, a0, -68 +; CAHP-WITHFP-NEXT: add sp, sp, a0 +; CAHP-WITHFP-NEXT: jr ra + +; CAHP-FPELIM-LABEL: test: +; CAHP-FPELIM: # %bb.0: +; CAHP-FPELIM-NEXT: lui a0, 3 +; CAHP-FPELIM-NEXT: addi a0, a0, -72 +; CAHP-FPELIM-NEXT: sub sp, sp, a0 +; CAHP-FPELIM-NEXT: lui a0, 3 +; CAHP-FPELIM-NEXT: addi a0, a0, -72 +; CAHP-FPELIM-NEXT: add sp, sp, a0 +; CAHP-FPELIM-NEXT: jr ra + + %tmp = alloca [ 3000 x i8 ] , align 2 + ret void +} From 67405d9f5bb021960473fb2f1c09e70d22642f19 Mon Sep 17 00:00:00 2001 From: Ushitora Anqou Date: Mon, 28 Oct 2019 22:34:43 +0900 Subject: [PATCH 250/289] [CAHP] Use BR_CC instead of BRCOND --- llvm/lib/Target/CAHP/CAHPISelLowering.cpp | 24 +++++++++- llvm/lib/Target/CAHP/CAHPISelLowering.h | 2 + llvm/lib/Target/CAHP/CAHPInstrInfo.td | 58 ++++++++++++++++------- 3 files changed, 67 insertions(+), 17 deletions(-) diff --git a/llvm/lib/Target/CAHP/CAHPISelLowering.cpp b/llvm/lib/Target/CAHP/CAHPISelLowering.cpp index 5189b4660db6..494c237dbf28 100644 --- a/llvm/lib/Target/CAHP/CAHPISelLowering.cpp +++ b/llvm/lib/Target/CAHP/CAHPISelLowering.cpp @@ -43,7 +43,8 @@ CAHPTargetLowering::CAHPTargetLowering(const TargetMachine &TM, // TODO: add all necessary setOperationAction calls. setOperationAction(ISD::GlobalAddress, MVT::i16, Custom); - setOperationAction(ISD::BR_CC, MVT::i16, Expand); + setOperationAction(ISD::BRCOND, MVT::Other, Expand); + setOperationAction(ISD::BR_CC, MVT::i16, Custom); setOperationAction(ISD::SELECT, MVT::i16, Custom); setOperationAction(ISD::SELECT_CC, MVT::i16, Expand); @@ -99,6 +100,9 @@ SDValue CAHPTargetLowering::LowerOperation(SDValue Op, default: report_fatal_error("unimplemented operand"); + case ISD::BR_CC: + return LowerBR_CC(Op, DAG); + case ISD::GlobalAddress: return lowerGlobalAddress(Op, DAG); @@ -227,6 +231,22 @@ CAHPTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI, return TailMBB; } +SDValue CAHPTargetLowering::LowerBR_CC(SDValue Op, SelectionDAG &DAG) const { + SDValue Chain = Op.getOperand(0); + SDValue Cond = Op.getOperand(1); + SDValue LHS = Op.getOperand(2); + SDValue RHS = Op.getOperand(3); + SDValue Dest = Op.getOperand(4); + SDLoc DL(Op); + + ISD::CondCode CC = cast(Cond)->get(); + normaliseSetCC(LHS, RHS, CC); + + // Create new SelectionDAG nodes + return DAG.getNode(CAHPISD::BR_CC, DL, Op.getValueType(), Chain, LHS, RHS, + DAG.getConstant(CC, DL, MVT::i16), Dest); +} + // Calling Convention Implementation. #include "CAHPGenCallingConv.inc" @@ -450,6 +470,8 @@ const char *CAHPTargetLowering::getTargetNodeName(unsigned Opcode) const { switch ((CAHPISD::NodeType)Opcode) { case CAHPISD::FIRST_NUMBER: break; + case CAHPISD::BR_CC: + return "CAHPISD::BR_CC"; case CAHPISD::CALL: return "CAHPISD::CALL"; case CAHPISD::SELECT_CC: diff --git a/llvm/lib/Target/CAHP/CAHPISelLowering.h b/llvm/lib/Target/CAHP/CAHPISelLowering.h index 0aa252ff26c7..54949c26f333 100644 --- a/llvm/lib/Target/CAHP/CAHPISelLowering.h +++ b/llvm/lib/Target/CAHP/CAHPISelLowering.h @@ -15,6 +15,7 @@ namespace CAHPISD { enum NodeType : unsigned { FIRST_NUMBER = ISD::BUILTIN_OP_END, + BR_CC, CALL, SELECT_CC, RET_FLAG, @@ -58,6 +59,7 @@ class CAHPTargetLowering : public TargetLowering { } SDValue lowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG) const; SDValue LowerSELECT(SDValue Op, SelectionDAG &DAG) const; }; } // namespace llvm diff --git a/llvm/lib/Target/CAHP/CAHPInstrInfo.td b/llvm/lib/Target/CAHP/CAHPInstrInfo.td index 8dce6d638f13..ca4848e564f8 100644 --- a/llvm/lib/Target/CAHP/CAHPInstrInfo.td +++ b/llvm/lib/Target/CAHP/CAHPInstrInfo.td @@ -10,7 +10,11 @@ def SDT_CAHPCallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i16>, SDTCisVT<1, i16>]>; def SDT_CAHPSelectCC : SDTypeProfile<1, 5, [SDTCisSameAs<1, 2>, SDTCisSameAs<0, 4>, SDTCisSameAs<4, 5>]>; +def SDT_CAHPBrCC : SDTypeProfile<0, 4, [SDTCisSameAs<0, 1>, + SDTCisVT<3, OtherVT>]>; +def BrCC : SDNode<"CAHPISD::BR_CC", SDT_CAHPBrCC, + [SDNPHasChain, SDNPOutGlue, SDNPInGlue]>; def Call : SDNode<"CAHPISD::CALL", SDT_CAHPCall, [SDNPHasChain, SDNPOptInGlue, SDNPOutGlue, SDNPVariadic]>; @@ -100,6 +104,28 @@ def IsOrAdd: PatFrag<(ops node:$A, node:$B), (or node:$A, node:$B), [{ return isOrEquivalentToAdd(N); }]>; +// Conditional code predicates - used for pattern matching for jump instructions +def CC_EQ : PatLeaf<(i16 imm), + [{return (N->getZExtValue() == ISD::SETEQ);}]>; +def CC_NE : PatLeaf<(i16 imm), + [{return (N->getZExtValue() == ISD::SETNE);}]>; +def CC_GE : PatLeaf<(i16 imm), + [{return (N->getZExtValue() == ISD::SETGE);}]>; +def CC_GT : PatLeaf<(i16 imm), + [{return (N->getZExtValue() == ISD::SETGT);}]>; +def CC_GTU : PatLeaf<(i16 imm), + [{return (N->getZExtValue() == ISD::SETUGT);}]>; +def CC_GEU : PatLeaf<(i16 imm), + [{return (N->getZExtValue() == ISD::SETUGE);}]>; +def CC_LE : PatLeaf<(i16 imm), + [{return (N->getZExtValue() == ISD::SETLE);}]>; +def CC_LT : PatLeaf<(i16 imm), + [{return (N->getZExtValue() == ISD::SETLT);}]>; +def CC_LTU : PatLeaf<(i16 imm), + [{return (N->getZExtValue() == ISD::SETULT);}]>; +def CC_LEU : PatLeaf<(i16 imm), + [{return (N->getZExtValue() == ISD::SETULE);}]>; + // 24-bit M-instructions. let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in { @@ -366,25 +392,25 @@ def : Pat<(sra GPR:$rs1, uimm4:$imm), (ASRI GPR:$rs1, uimm4:$imm)>; // Match `(brcond (CondOp ..), ..)` and lower to the appropriate CAHP branch // instruction. -class BccPat - : Pat<(brcond (CondOp GPR:$rs1, GPR:$rs2), bb:$imm), +class BccPat + : Pat<(BrCC GPR:$rs1, GPR:$rs2, Cond, bb:$imm), (Inst GPR:$rs1, GPR:$rs2, simm10_branch:$imm)>; -def : BccPat; -def : BccPat; -def : BccPat; -def : BccPat; -def : BccPat; -def : BccPat; - -class BccSwapPat - : Pat<(brcond (CondOp GPR:$rs1, GPR:$rs2), bb:$imm), - (InstBcc GPR:$rs2, GPR:$rs1, bb:$imm)>; +def : BccPat; +def : BccPat; +def : BccPat; +def : BccPat; +def : BccPat; +def : BccPat; + +class BccSwapPat + : Pat<(BrCC GPR:$rs1, GPR:$rs2, Cond, bb:$imm), + (Inst GPR:$rs2, GPR:$rs1, bb:$imm)>; // Condition codes that don't have matching CAHP branch instructions, but // are trivially supported by swapping the two input operands -def : BccSwapPat; -def : BccSwapPat; -def : BccSwapPat; -def : BccSwapPat; +def : BccSwapPat; +def : BccSwapPat; +def : BccSwapPat; +def : BccSwapPat; // An extra pattern is needed for a brcond without a setcc (i.e. where the // condition was calculated elsewhere). From 29d86647c84fc1cb95c6eb0e76479aa418756646 Mon Sep 17 00:00:00 2001 From: Ushitora Anqou Date: Mon, 28 Oct 2019 22:36:13 +0900 Subject: [PATCH 251/289] [CAHP] Expand SETCC into SELECT --- llvm/lib/Target/CAHP/CAHPISelLowering.cpp | 1 + llvm/test/CodeGen/CAHP/i16-icmp.ll | 167 ++++++++++++++++++++++ 2 files changed, 168 insertions(+) create mode 100644 llvm/test/CodeGen/CAHP/i16-icmp.ll diff --git a/llvm/lib/Target/CAHP/CAHPISelLowering.cpp b/llvm/lib/Target/CAHP/CAHPISelLowering.cpp index 494c237dbf28..e9730ef35798 100644 --- a/llvm/lib/Target/CAHP/CAHPISelLowering.cpp +++ b/llvm/lib/Target/CAHP/CAHPISelLowering.cpp @@ -47,6 +47,7 @@ CAHPTargetLowering::CAHPTargetLowering(const TargetMachine &TM, setOperationAction(ISD::BR_CC, MVT::i16, Custom); setOperationAction(ISD::SELECT, MVT::i16, Custom); setOperationAction(ISD::SELECT_CC, MVT::i16, Expand); + setOperationAction(ISD::SETCC, MVT::i16, Expand); setBooleanContents(ZeroOrOneBooleanContent); diff --git a/llvm/test/CodeGen/CAHP/i16-icmp.ll b/llvm/test/CodeGen/CAHP/i16-icmp.ll new file mode 100644 index 000000000000..912618a39b61 --- /dev/null +++ b/llvm/test/CodeGen/CAHP/i16-icmp.ll @@ -0,0 +1,167 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=cahp -verify-machineinstrs < %s \ +; RUN: | FileCheck %s -check-prefix=CAHP + +; TODO: check the generated instructions for the equivalent of seqz, snez, +; sltz, sgtz map to something simple + +define i16 @icmp_eq(i16 %a, i16 %b) nounwind { +; CAHP-LABEL: icmp_eq: +; CAHP: # %bb.0: +; CAHP-NEXT: mov a2, a0 +; CAHP-NEXT: lsi a0, 1 +; CAHP-NEXT: beq a2, a1, .LBB0_2 +; CAHP-NEXT:# %bb.1: +; CAHP-NEXT: lsi a0, 0 +; CAHP-NEXT:.LBB0_2: +; CAHP-NEXT: jr ra + + %1 = icmp eq i16 %a, %b + %2 = zext i1 %1 to i16 + ret i16 %2 +} + +define i16 @icmp_ne(i16 %a, i16 %b) nounwind { +; CAHP-LABEL: icmp_ne: +; CAHP: # %bb.0: +; CAHP-NEXT: mov a2, a0 +; CAHP-NEXT: lsi a0, 1 +; CAHP-NEXT: bne a2, a1, .LBB1_2 +; CAHP-NEXT:# %bb.1: +; CAHP-NEXT: lsi a0, 0 +; CAHP-NEXT:.LBB1_2: +; CAHP-NEXT: jr ra + + %1 = icmp ne i16 %a, %b + %2 = zext i1 %1 to i16 + ret i16 %2 +} + +define i16 @icmp_ugt(i16 %a, i16 %b) nounwind { +; CAHP-LABEL: icmp_ugt: +; CAHP: # %bb.0: +; CAHP-NEXT: mov a2, a0 +; CAHP-NEXT: lsi a0, 1 +; CAHP-NEXT: bltu a1, a2, .LBB2_2 +; CAHP-NEXT:# %bb.1: +; CAHP-NEXT: lsi a0, 0 +; CAHP-NEXT:.LBB2_2: +; CAHP-NEXT: jr ra + %1 = icmp ugt i16 %a, %b + %2 = zext i1 %1 to i16 + ret i16 %2 +} + +define i16 @icmp_uge(i16 %a, i16 %b) nounwind { +; CAHP-LABEL: icmp_uge: +; CAHP: # %bb.0: +; CAHP-NEXT: mov a2, a0 +; CAHP-NEXT: lsi a0, 1 +; CAHP-NEXT: bleu a1, a2, .LBB3_2 +; CAHP-NEXT:# %bb.1: +; CAHP-NEXT: lsi a0, 0 +; CAHP-NEXT:.LBB3_2: +; CAHP-NEXT: jr ra + + %1 = icmp uge i16 %a, %b + %2 = zext i1 %1 to i16 + ret i16 %2 +} + +define i16 @icmp_ult(i16 %a, i16 %b) nounwind { +; CAHP-LABEL: icmp_ult: +; CAHP: # %bb.0: +; CAHP-NEXT: mov a2, a0 +; CAHP-NEXT: lsi a0, 1 +; CAHP-NEXT: bltu a2, a1, .LBB4_2 +; CAHP-NEXT:# %bb.1: +; CAHP-NEXT: lsi a0, 0 +; CAHP-NEXT:.LBB4_2: +; CAHP-NEXT: jr ra + + %1 = icmp ult i16 %a, %b + %2 = zext i1 %1 to i16 + ret i16 %2 +} + +define i16 @icmp_ule(i16 %a, i16 %b) nounwind { +; CAHP-LABEL: icmp_ule: +; CAHP: # %bb.0: +; CAHP-NEXT: mov a2, a0 +; CAHP-NEXT: lsi a0, 1 +; CAHP-NEXT: bleu a2, a1, .LBB5_2 +; CAHP-NEXT:# %bb.1: +; CAHP-NEXT: lsi a0, 0 +; CAHP-NEXT:.LBB5_2: +; CAHP-NEXT: jr ra + + %1 = icmp ule i16 %a, %b + %2 = zext i1 %1 to i16 + ret i16 %2 +} + +define i16 @icmp_sgt(i16 %a, i16 %b) nounwind { +; CAHP-LABEL: icmp_sgt: +; CAHP: # %bb.0: +; CAHP-NEXT: mov a2, a0 +; CAHP-NEXT: lsi a0, 1 +; CAHP-NEXT: blt a1, a2, .LBB6_2 +; CAHP-NEXT:# %bb.1: +; CAHP-NEXT: lsi a0, 0 +; CAHP-NEXT:.LBB6_2: +; CAHP-NEXT: jr ra + + %1 = icmp sgt i16 %a, %b + %2 = zext i1 %1 to i16 + ret i16 %2 +} + +define i16 @icmp_sge(i16 %a, i16 %b) nounwind { +; CAHP-LABEL: icmp_sge: +; CAHP: # %bb.0: +; CAHP-NEXT: mov a2, a0 +; CAHP-NEXT: lsi a0, 1 +; CAHP-NEXT: ble a1, a2, .LBB7_2 +; CAHP-NEXT:# %bb.1: +; CAHP-NEXT: lsi a0, 0 +; CAHP-NEXT:.LBB7_2: +; CAHP-NEXT: jr ra + + %1 = icmp sge i16 %a, %b + %2 = zext i1 %1 to i16 + ret i16 %2 +} + +define i16 @icmp_slt(i16 %a, i16 %b) nounwind { +; CAHP-LABEL: icmp_slt: +; CAHP: # %bb.0: +; CAHP-NEXT: mov a2, a0 +; CAHP-NEXT: lsi a0, 1 +; CAHP-NEXT: blt a2, a1, .LBB8_2 +; CAHP-NEXT:# %bb.1: +; CAHP-NEXT: lsi a0, 0 +; CAHP-NEXT:.LBB8_2: +; CAHP-NEXT: jr ra + + %1 = icmp slt i16 %a, %b + %2 = zext i1 %1 to i16 + ret i16 %2 +} + +define i16 @icmp_sle(i16 %a, i16 %b) nounwind { +; CAHP-LABEL: icmp_sle: +; CAHP: # %bb.0: +; CAHP-NEXT: mov a2, a0 +; CAHP-NEXT: lsi a0, 1 +; CAHP-NEXT: ble a2, a1, .LBB9_2 +; CAHP-NEXT:# %bb.1: +; CAHP-NEXT: lsi a0, 0 +; CAHP-NEXT:.LBB9_2: +; CAHP-NEXT: jr ra + + %1 = icmp sle i16 %a, %b + %2 = zext i1 %1 to i16 + ret i16 %2 +} + +; TODO: check variants with an immediate? From 918a6a1c2567cb68e5940a8fd985b00fdcd539eb Mon Sep 17 00:00:00 2001 From: Ushitora Anqou Date: Mon, 28 Oct 2019 23:27:15 +0900 Subject: [PATCH 252/289] [CAHP] Add support for ExternalSymbol --- llvm/lib/Target/CAHP/CAHPISelLowering.cpp | 38 ++++++++++++------- llvm/lib/Target/CAHP/CAHPISelLowering.h | 1 + llvm/lib/Target/CAHP/CAHPMCInstLower.cpp | 5 +++ llvm/test/CodeGen/CAHP/frame.ll | 46 +++++++++++++++++++++++ 4 files changed, 77 insertions(+), 13 deletions(-) create mode 100644 llvm/test/CodeGen/CAHP/frame.ll diff --git a/llvm/lib/Target/CAHP/CAHPISelLowering.cpp b/llvm/lib/Target/CAHP/CAHPISelLowering.cpp index e9730ef35798..7a58383e1d7e 100644 --- a/llvm/lib/Target/CAHP/CAHPISelLowering.cpp +++ b/llvm/lib/Target/CAHP/CAHPISelLowering.cpp @@ -120,18 +120,31 @@ SDValue CAHPTargetLowering::lowerGlobalAddress(SDValue Op, const GlobalValue *GV = N->getGlobal(); int64_t Offset = N->getOffset(); - if (!isPositionIndependent()) { - SDValue GAHi = - DAG.getTargetGlobalAddress(GV, DL, Ty, Offset, CAHPII::MO_HI); - SDValue GALo = - DAG.getTargetGlobalAddress(GV, DL, Ty, Offset, CAHPII::MO_LO); - SDValue MNHi = SDValue(DAG.getMachineNode(CAHP::LUI, DL, Ty, GAHi), 0); - SDValue MNLo = - SDValue(DAG.getMachineNode(CAHP::ADDI, DL, Ty, MNHi, GALo), 0); - return MNLo; - } else { + if (isPositionIndependent()) report_fatal_error("Unable to lowerGlobalAddress"); - } + + SDValue GAHi = DAG.getTargetGlobalAddress(GV, DL, Ty, Offset, CAHPII::MO_HI); + SDValue GALo = DAG.getTargetGlobalAddress(GV, DL, Ty, Offset, CAHPII::MO_LO); + SDValue MNHi = SDValue(DAG.getMachineNode(CAHP::LUI, DL, Ty, GAHi), 0); + SDValue MNLo = SDValue(DAG.getMachineNode(CAHP::ADDI, DL, Ty, MNHi, GALo), 0); + return MNLo; +} + +SDValue CAHPTargetLowering::LowerExternalSymbol(SDValue Op, + SelectionDAG &DAG) const { + SDLoc DL(Op); + EVT Ty = Op.getValueType(); + ExternalSymbolSDNode *N = cast(Op); + const char *Sym = N->getSymbol(); + + if (isPositionIndependent()) + report_fatal_error("Unable to LowerExternalSymbol"); + + SDValue GAHi = DAG.getTargetExternalSymbol(Sym, Ty, CAHPII::MO_HI); + SDValue GALo = DAG.getTargetExternalSymbol(Sym, Ty, CAHPII::MO_LO); + SDValue MNHi = SDValue(DAG.getMachineNode(CAHP::LUI, DL, Ty, GAHi), 0); + SDValue MNLo = SDValue(DAG.getMachineNode(CAHP::ADDI, DL, Ty, MNHi, GALo), 0); + return MNLo; } SDValue CAHPTargetLowering::LowerSELECT(SDValue Op, SelectionDAG &DAG) const { @@ -370,8 +383,7 @@ SDValue CAHPTargetLowering::LowerCall(CallLoweringInfo &CLI, // Callee = DAG.getTargetGlobalAddress(S->getGlobal(), DL, PtrVT, 0, 0); Callee = lowerGlobalAddress(Callee, DAG); } else if (isa(Callee)) { - report_fatal_error( - "lowerExternalSymbol, needed for lowerCall, not yet handled"); + Callee = LowerExternalSymbol(Callee, DAG); } // The first call operand is the chain and the second is the target address. diff --git a/llvm/lib/Target/CAHP/CAHPISelLowering.h b/llvm/lib/Target/CAHP/CAHPISelLowering.h index 54949c26f333..838534e6fc4c 100644 --- a/llvm/lib/Target/CAHP/CAHPISelLowering.h +++ b/llvm/lib/Target/CAHP/CAHPISelLowering.h @@ -59,6 +59,7 @@ class CAHPTargetLowering : public TargetLowering { } SDValue lowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerExternalSymbol(SDValue Op, SelectionDAG &DAG) const; SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG) const; SDValue LowerSELECT(SDValue Op, SelectionDAG &DAG) const; }; diff --git a/llvm/lib/Target/CAHP/CAHPMCInstLower.cpp b/llvm/lib/Target/CAHP/CAHPMCInstLower.cpp index c11cf647b7ba..d6f9468a14cb 100644 --- a/llvm/lib/Target/CAHP/CAHPMCInstLower.cpp +++ b/llvm/lib/Target/CAHP/CAHPMCInstLower.cpp @@ -77,6 +77,11 @@ bool llvm::LowerCAHPMachineOperandToMCOperand(const MachineOperand &MO, case MachineOperand::MO_GlobalAddress: MCOp = lowerSymbolOperand(MO, AP.getSymbol(MO.getGlobal()), AP); break; + + case MachineOperand::MO_ExternalSymbol: + MCOp = lowerSymbolOperand( + MO, AP.GetExternalSymbolSymbol(MO.getSymbolName()), AP); + break; } return true; diff --git a/llvm/test/CodeGen/CAHP/frame.ll b/llvm/test/CodeGen/CAHP/frame.ll new file mode 100644 index 000000000000..760d8f3fe398 --- /dev/null +++ b/llvm/test/CodeGen/CAHP/frame.ll @@ -0,0 +1,46 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=cahp -verify-machineinstrs < %s \ +; RUN: | FileCheck -check-prefix=CAHP %s + +%struct.key_t = type { i16, [16 x i8] } + +; FIXME: prologue and epilogue insertion must be implemented to complete this +; test + +define i16 @test() nounwind { +; CAHP-LABEL: test: +; CAHP: # %bb.0: +; CAHP-NEXT: addi sp, sp, -24 +; CAHP-NEXT: sw ra, 22(sp) +; CAHP-NEXT: sw fp, 20(sp) +; CAHP-NEXT: sw s0, 18(sp) +; CAHP-NEXT: addi fp, sp, 24 +; CAHP-NEXT: lsi s0, 0 +; CAHP-NEXT: sw s0, -16(fp) +; CAHP-NEXT: sw s0, -18(fp) +; CAHP-NEXT: sw s0, -20(fp) +; CAHP-NEXT: sw s0, -22(fp) +; CAHP-NEXT: sw s0, -24(fp) +; CAHP-NEXT: lui a0, %hi(test1) +; CAHP-NEXT: addi a1, a0, %lo(test1) +; CAHP-NEXT: addi a0, fp, -22 +; CAHP-NEXT: jalr a1 +; CAHP-NEXT: mov a0, s0 +; CAHP-NEXT: addi sp, fp, -24 +; CAHP-NEXT: lw s0, 18(sp) +; CAHP-NEXT: lw fp, 20(sp) +; CAHP-NEXT: lw ra, 22(sp) +; CAHP-NEXT: addi sp, sp, 24 +; CAHP-NEXT: jr ra + + %key = alloca %struct.key_t, align 2 + %1 = bitcast %struct.key_t* %key to i8* + call void @llvm.memset.p0i8.i64(i8* %1, i8 0, i64 10, i32 2, i1 false) + %2 = getelementptr inbounds %struct.key_t, %struct.key_t* %key, i64 0, i32 1, i64 0 + call void @test1(i8* %2) + ret i16 0 +} + +declare void @llvm.memset.p0i8.i64(i8* nocapture, i8, i64, i32, i1) + +declare void @test1(i8*) From 994bb5231f613f2e4f4aae4a7f4032a27b466ae7 Mon Sep 17 00:00:00 2001 From: Ushitora Anqou Date: Mon, 28 Oct 2019 23:40:21 +0900 Subject: [PATCH 253/289] [CAHP] s/lowerSymbolOperand/LowerSymbolOperand/ NFC. --- llvm/lib/Target/CAHP/CAHPMCInstLower.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/llvm/lib/Target/CAHP/CAHPMCInstLower.cpp b/llvm/lib/Target/CAHP/CAHPMCInstLower.cpp index d6f9468a14cb..bb2bd7325de8 100644 --- a/llvm/lib/Target/CAHP/CAHPMCInstLower.cpp +++ b/llvm/lib/Target/CAHP/CAHPMCInstLower.cpp @@ -17,7 +17,7 @@ using namespace llvm; -static MCOperand lowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym, +static MCOperand LowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym, const AsmPrinter &AP) { MCContext &Ctx = AP.OutContext; CAHPMCExpr::VariantKind Kind; @@ -75,11 +75,11 @@ bool llvm::LowerCAHPMachineOperandToMCOperand(const MachineOperand &MO, break; case MachineOperand::MO_GlobalAddress: - MCOp = lowerSymbolOperand(MO, AP.getSymbol(MO.getGlobal()), AP); + MCOp = LowerSymbolOperand(MO, AP.getSymbol(MO.getGlobal()), AP); break; case MachineOperand::MO_ExternalSymbol: - MCOp = lowerSymbolOperand( + MCOp = LowerSymbolOperand( MO, AP.GetExternalSymbolSymbol(MO.getSymbolName()), AP); break; } From 70fa0c10f9a777fe74d4a02ac7af75c149a24c73 Mon Sep 17 00:00:00 2001 From: Ushitora Anqou Date: Mon, 28 Oct 2019 23:41:17 +0900 Subject: [PATCH 254/289] [CAHP] s/normaliseSetCC/normalizeSetCC/ NFC. --- llvm/lib/Target/CAHP/CAHPISelLowering.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/llvm/lib/Target/CAHP/CAHPISelLowering.cpp b/llvm/lib/Target/CAHP/CAHPISelLowering.cpp index 7a58383e1d7e..ed8a6b647123 100644 --- a/llvm/lib/Target/CAHP/CAHPISelLowering.cpp +++ b/llvm/lib/Target/CAHP/CAHPISelLowering.cpp @@ -59,7 +59,7 @@ CAHPTargetLowering::CAHPTargetLowering(const TargetMachine &TM, // Changes the condition code and swaps operands if necessary, so the SetCC // operation matches one of the comparisons supported directly in the CAHP // ISA. -static void normaliseSetCC(SDValue &LHS, SDValue &RHS, ISD::CondCode &CC) { +static void normalizeSetCC(SDValue &LHS, SDValue &RHS, ISD::CondCode &CC) { switch (CC) { default: break; @@ -75,7 +75,7 @@ static void normaliseSetCC(SDValue &LHS, SDValue &RHS, ISD::CondCode &CC) { // Return the CAHP branch opcode that matches the given DAG integer // condition code. The CondCode must be one of those supported by the CAHP -// ISA (see normaliseSetCC). +// ISA (see normalizeSetCC). static unsigned getBranchOpcodeForIntCondCode(ISD::CondCode CC) { switch (CC) { default: @@ -162,7 +162,7 @@ SDValue CAHPTargetLowering::LowerSELECT(SDValue Op, SelectionDAG &DAG) const { auto CC = cast(CondV.getOperand(2)); ISD::CondCode CCVal = CC->get(); - normaliseSetCC(LHS, RHS, CCVal); + normalizeSetCC(LHS, RHS, CCVal); SDValue TargetCC = DAG.getConstant(CCVal, DL, MVT::i16); SDVTList VTs = DAG.getVTList(Op.getValueType(), MVT::Glue); @@ -254,7 +254,7 @@ SDValue CAHPTargetLowering::LowerBR_CC(SDValue Op, SelectionDAG &DAG) const { SDLoc DL(Op); ISD::CondCode CC = cast(Cond)->get(); - normaliseSetCC(LHS, RHS, CC); + normalizeSetCC(LHS, RHS, CC); // Create new SelectionDAG nodes return DAG.getNode(CAHPISD::BR_CC, DL, Op.getValueType(), Chain, LHS, RHS, From e9c75fbefa6d4b31579b29deed7296e4d01ef141 Mon Sep 17 00:00:00 2001 From: Ushitora Anqou Date: Mon, 28 Oct 2019 23:53:09 +0900 Subject: [PATCH 255/289] [CAHP] s/lowerGlobalAddress/LowerGlobalAddress/ NFC. --- llvm/lib/Target/CAHP/CAHPISelLowering.cpp | 8 ++++---- llvm/lib/Target/CAHP/CAHPISelLowering.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/llvm/lib/Target/CAHP/CAHPISelLowering.cpp b/llvm/lib/Target/CAHP/CAHPISelLowering.cpp index ed8a6b647123..aadd5b5c9f8e 100644 --- a/llvm/lib/Target/CAHP/CAHPISelLowering.cpp +++ b/llvm/lib/Target/CAHP/CAHPISelLowering.cpp @@ -105,14 +105,14 @@ SDValue CAHPTargetLowering::LowerOperation(SDValue Op, return LowerBR_CC(Op, DAG); case ISD::GlobalAddress: - return lowerGlobalAddress(Op, DAG); + return LowerGlobalAddress(Op, DAG); case ISD::SELECT: return LowerSELECT(Op, DAG); } } -SDValue CAHPTargetLowering::lowerGlobalAddress(SDValue Op, +SDValue CAHPTargetLowering::LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const { SDLoc DL(Op); EVT Ty = Op.getValueType(); @@ -121,7 +121,7 @@ SDValue CAHPTargetLowering::lowerGlobalAddress(SDValue Op, int64_t Offset = N->getOffset(); if (isPositionIndependent()) - report_fatal_error("Unable to lowerGlobalAddress"); + report_fatal_error("Unable to LowerGlobalAddress"); SDValue GAHi = DAG.getTargetGlobalAddress(GV, DL, Ty, Offset, CAHPII::MO_HI); SDValue GALo = DAG.getTargetGlobalAddress(GV, DL, Ty, Offset, CAHPII::MO_LO); @@ -381,7 +381,7 @@ SDValue CAHPTargetLowering::LowerCall(CallLoweringInfo &CLI, if (isa(Callee)) { // GlobalAddressSDNode *S = dyn_cast(Callee); // Callee = DAG.getTargetGlobalAddress(S->getGlobal(), DL, PtrVT, 0, 0); - Callee = lowerGlobalAddress(Callee, DAG); + Callee = LowerGlobalAddress(Callee, DAG); } else if (isa(Callee)) { Callee = LowerExternalSymbol(Callee, DAG); } diff --git a/llvm/lib/Target/CAHP/CAHPISelLowering.h b/llvm/lib/Target/CAHP/CAHPISelLowering.h index 838534e6fc4c..101fa9f38372 100644 --- a/llvm/lib/Target/CAHP/CAHPISelLowering.h +++ b/llvm/lib/Target/CAHP/CAHPISelLowering.h @@ -58,7 +58,7 @@ class CAHPTargetLowering : public TargetLowering { return true; } - SDValue lowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const; SDValue LowerExternalSymbol(SDValue Op, SelectionDAG &DAG) const; SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG) const; SDValue LowerSELECT(SDValue Op, SelectionDAG &DAG) const; From a54da6e287358778474196de1978b9f0aaf21b8a Mon Sep 17 00:00:00 2001 From: Ushitora Anqou Date: Wed, 30 Oct 2019 14:12:23 +0900 Subject: [PATCH 256/289] [CAHP] Disable JumpTable and expand BR_JT --- llvm/lib/Target/CAHP/CAHPISelLowering.cpp | 4 ++ llvm/test/CodeGen/CAHP/jumptable.ll | 64 +++++++++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 llvm/test/CodeGen/CAHP/jumptable.ll diff --git a/llvm/lib/Target/CAHP/CAHPISelLowering.cpp b/llvm/lib/Target/CAHP/CAHPISelLowering.cpp index aadd5b5c9f8e..95a4d0cf6d5a 100644 --- a/llvm/lib/Target/CAHP/CAHPISelLowering.cpp +++ b/llvm/lib/Target/CAHP/CAHPISelLowering.cpp @@ -45,6 +45,7 @@ CAHPTargetLowering::CAHPTargetLowering(const TargetMachine &TM, setOperationAction(ISD::GlobalAddress, MVT::i16, Custom); setOperationAction(ISD::BRCOND, MVT::Other, Expand); setOperationAction(ISD::BR_CC, MVT::i16, Custom); + setOperationAction(ISD::BR_JT, MVT::Other, Expand); setOperationAction(ISD::SELECT, MVT::i16, Custom); setOperationAction(ISD::SELECT_CC, MVT::i16, Expand); setOperationAction(ISD::SETCC, MVT::i16, Expand); @@ -54,6 +55,9 @@ CAHPTargetLowering::CAHPTargetLowering(const TargetMachine &TM, // Function alignments (log2). setMinFunctionAlignment(0); setPrefFunctionAlignment(0); + + // Effectively disable jump table generation. + setMinimumJumpTableEntries(INT_MAX); } // Changes the condition code and swaps operands if necessary, so the SetCC diff --git a/llvm/test/CodeGen/CAHP/jumptable.ll b/llvm/test/CodeGen/CAHP/jumptable.ll new file mode 100644 index 000000000000..51bbe3892496 --- /dev/null +++ b/llvm/test/CodeGen/CAHP/jumptable.ll @@ -0,0 +1,64 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=cahp -verify-machineinstrs < %s \ +; RUN: | FileCheck %s -check-prefix=CAHP + +define void @jt(i16 %in, i16* %out) { +; CAHP-LABEL: jt: +; CAHP: # %bb.0: # %entry +; CAHP-NEXT: lsi a2, 2 +; CAHP-NEXT: blt a2, a0, .LBB0_3 +; CAHP-NEXT: js .LBB0_1 +; CAHP-NEXT:.LBB0_1: # %entry +; CAHP-NEXT: lsi a3, 1 +; CAHP-NEXT: beq a0, a3, .LBB0_5 +; CAHP-NEXT: js .LBB0_2 +; CAHP-NEXT:.LBB0_2: # %entry +; CAHP-NEXT: beq a0, a2, .LBB0_6 +; CAHP-NEXT: js .LBB0_9 +; CAHP-NEXT:.LBB0_6: # %bb2 +; CAHP-NEXT: lsi a0, 3 +; CAHP-NEXT: sw a0, 0(a1) +; CAHP-NEXT: js .LBB0_9 +; CAHP-NEXT:.LBB0_3: # %entry +; CAHP-NEXT: lsi a3, 3 +; CAHP-NEXT: beq a0, a3, .LBB0_7 +; CAHP-NEXT: js .LBB0_4 +; CAHP-NEXT:.LBB0_4: # %entry +; CAHP-NEXT: lsi a2, 4 +; CAHP-NEXT: beq a0, a2, .LBB0_8 +; CAHP-NEXT: js .LBB0_9 +; CAHP-NEXT:.LBB0_8: # %bb4 +; CAHP-NEXT: lsi a0, 1 +; CAHP-NEXT: sw a0, 0(a1) +; CAHP-NEXT:.LBB0_9: # %exit +; CAHP-NEXT: jr ra +; CAHP-NEXT:.LBB0_5: # %bb1 +; CAHP-NEXT: lsi a0, 4 +; CAHP-NEXT: sw a0, 0(a1) +; CAHP-NEXT: js .LBB0_9 +; CAHP-NEXT:.LBB0_7: # %bb3 +; CAHP-NEXT: sw a2, 0(a1) +; CAHP-NEXT: js .LBB0_9 + +entry: + switch i16 %in, label %exit [ + i16 1, label %bb1 + i16 2, label %bb2 + i16 3, label %bb3 + i16 4, label %bb4 + ] +bb1: + store i16 4, i16* %out + br label %exit +bb2: + store i16 3, i16* %out + br label %exit +bb3: + store i16 2, i16* %out + br label %exit +bb4: + store i16 1, i16* %out + br label %exit +exit: + ret void +} From f7c5aaae33091d5afe9be5f442e0966c75c44d97 Mon Sep 17 00:00:00 2001 From: Ushitora Anqou Date: Wed, 30 Oct 2019 16:34:50 +0900 Subject: [PATCH 257/289] [CAHP] Add CAHP target to LLD --- lld/ELF/Arch/CAHP.cpp | 92 ++++++++++++++++++++++++++++++++++++ lld/ELF/CMakeLists.txt | 1 + lld/ELF/Driver.cpp | 3 +- lld/ELF/Target.cpp | 2 + lld/ELF/Target.h | 1 + lld/test/ELF/cahp-hi6-lo10.s | 32 +++++++++++++ lld/test/lit.cfg.py | 1 + 7 files changed, 131 insertions(+), 1 deletion(-) create mode 100644 lld/ELF/Arch/CAHP.cpp create mode 100644 lld/test/ELF/cahp-hi6-lo10.s diff --git a/lld/ELF/Arch/CAHP.cpp b/lld/ELF/Arch/CAHP.cpp new file mode 100644 index 000000000000..167fb44cf389 --- /dev/null +++ b/lld/ELF/Arch/CAHP.cpp @@ -0,0 +1,92 @@ +// This file is copied and modified from The LLVM Compiler Infrastructure, which +// is distributed under the Apache License v2.0 with LLVM Exceptions (see +// LICENSE.TXT for details). This file is licensed under the same license. + +#include "InputFiles.h" +#include "SyntheticSections.h" +#include "Target.h" + +using namespace llvm; +using namespace llvm::object; +using namespace llvm::support::endian; +using namespace llvm::ELF; +using namespace lld; +using namespace lld::elf; + +namespace { + +class CAHP final : public TargetInfo { +public: + CAHP(); + RelExpr getRelExpr(RelType type, const Symbol &s, + const uint8_t *loc) const override; + void relocateOne(uint8_t *loc, RelType type, uint64_t val) const override; +}; + +} // end anonymous namespace + +CAHP::CAHP() { noneRel = R_CAHP_NONE; } + +RelExpr CAHP::getRelExpr(const RelType type, const Symbol &s, + const uint8_t *loc) const { + switch (type) { + case R_CAHP_PCREL_11: + return R_PC; + + default: + return R_ABS; + } +} + +void CAHP::relocateOne(uint8_t *loc, const RelType type, + const uint64_t val) const { + switch (type) { + case R_CAHP_NONE: + break; + + case R_CAHP_16: + write16le(loc, val); + break; + + case R_CAHP_PCREL_11: { + checkInt(loc, static_cast(val), 11, type); + uint32_t insn = read16le(loc) & 0x001F; + insn |= (val << 5); + write16le(loc, insn); + break; + } + + case R_CAHP_HI6: { + uint64_t hi = (val + 0x200) >> 10; + + uint32_t insn = read16le(loc) & 0x0F3F; + uint16_t imm3_0 = (hi & 0xF) << 12; + uint16_t imm5_4 = ((hi >> 4) & 3) << 6; + insn |= imm3_0 | imm5_4; + write16le(loc, insn); + break; + } + + case R_CAHP_LO10: { + uint64_t hi = (val + 0x200) >> 10; + uint64_t lo = val - (hi << 10); + + uint32_t insn = read32le(loc) & 0xFF00FF3F; + uint32_t imm7_0 = (lo & 0xFF) << 16; + uint32_t imm9_8 = ((lo >> 8) & 3) << 6; + insn |= imm7_0 | imm9_8; + write32le(loc, insn); + break; + } + + default: + error(getErrorLocation(loc) + + "unimplemented relocation: " + toString(type)); + return; + } +} + +TargetInfo *elf::getCAHPTargetInfo() { + static CAHP target; + return ⌖ +} diff --git a/lld/ELF/CMakeLists.txt b/lld/ELF/CMakeLists.txt index 70578746483d..b34a2ed846ca 100644 --- a/lld/ELF/CMakeLists.txt +++ b/lld/ELF/CMakeLists.txt @@ -12,6 +12,7 @@ add_lld_library(lldELF Arch/AMDGPU.cpp Arch/ARM.cpp Arch/AVR.cpp + Arch/CAHP.cpp Arch/Hexagon.cpp Arch/Mips.cpp Arch/MipsArchTree.cpp diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index fbfc71d22b7e..9c7aa4db2662 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -135,6 +135,7 @@ static std::tuple parseEmulation(StringRef emul) { .Cases("elf32btsmip", "elf32btsmipn32", {ELF32BEKind, EM_MIPS}) .Cases("elf32ltsmip", "elf32ltsmipn32", {ELF32LEKind, EM_MIPS}) .Case("elf32lriscv", {ELF32LEKind, EM_RISCV}) + .Case("elf32lcahp", {ELF32LEKind, EM_CAHP}) .Cases("elf32ppc", "elf32ppclinux", {ELF32BEKind, EM_PPC}) .Case("elf64btsmip", {ELF64BEKind, EM_MIPS}) .Case("elf64ltsmip", {ELF64LEKind, EM_MIPS}) @@ -1083,7 +1084,7 @@ static void setConfigs(opt::InputArgList &args) { // that. config->isRela = m == EM_AARCH64 || m == EM_AMDGPU || m == EM_HEXAGON || m == EM_PPC || m == EM_PPC64 || m == EM_RISCV || - m == EM_X86_64; + m == EM_X86_64 || m == EM_CAHP; // If the output uses REL relocations we must store the dynamic relocation // addends to the output sections. We also store addends for RELA relocations diff --git a/lld/ELF/Target.cpp b/lld/ELF/Target.cpp index d07478a5178c..a2ea90d1fa6d 100644 --- a/lld/ELF/Target.cpp +++ b/lld/ELF/Target.cpp @@ -59,6 +59,8 @@ TargetInfo *elf::getTarget() { return getARMTargetInfo(); case EM_AVR: return getAVRTargetInfo(); + case EM_CAHP: + return getCAHPTargetInfo(); case EM_HEXAGON: return getHexagonTargetInfo(); case EM_MIPS: diff --git a/lld/ELF/Target.h b/lld/ELF/Target.h index effa6001f6d9..705214d53b42 100644 --- a/lld/ELF/Target.h +++ b/lld/ELF/Target.h @@ -141,6 +141,7 @@ TargetInfo *getAArch64TargetInfo(); TargetInfo *getAMDGPUTargetInfo(); TargetInfo *getARMTargetInfo(); TargetInfo *getAVRTargetInfo(); +TargetInfo *getCAHPTargetInfo(); TargetInfo *getHexagonTargetInfo(); TargetInfo *getMSP430TargetInfo(); TargetInfo *getPPC64TargetInfo(); diff --git a/lld/test/ELF/cahp-hi6-lo10.s b/lld/test/ELF/cahp-hi6-lo10.s new file mode 100644 index 000000000000..1611c16f8132 --- /dev/null +++ b/lld/test/ELF/cahp-hi6-lo10.s @@ -0,0 +1,32 @@ +# REQUIRES: cahp + +# RUN: llvm-mc -filetype=obj -triple=cahp %s -o %t.o + +# RUN: ld.lld %t.o --defsym foo=0 --defsym bar=42 -o %t +# RUN: llvm-objdump -d %t | FileCheck %s +# CHECK: 04 08 lui a0, 0 +# CHECK-NEXT: 03 88 00 addi a0, a0, 0 +# CHECK-NEXT: 1d 88 00 sw a0, 0(a0) +# CHECK-NEXT: 04 09 lui a1, 0 +# CHECK-NEXT: 03 99 2a addi a1, a1, 42 +# CHECK-NEXT: 1d 99 2a sw a1, 42(a1) + +# RUN: ld.lld %t.o --defsym foo=0x7fff --defsym bar=0x7dff -o %t.limits +# RUN: llvm-objdump -d %t.limits | FileCheck --check-prefix=LIMITS %s +# LIMITS: 84 08 lui a0, -32 +# LIMITS-NEXT: c3 88 ff addi a0, a0, -1 +# LIMITS-NEXT: dd 88 ff sw a0, -1(a0) +# LIMITS-NEXT: 44 f9 lui a1, 31 +# LIMITS-NEXT: 43 99 ff addi a1, a1, 511 +# LIMITS-NEXT: 5d 99 ff sw a1, 511(a1) + +.global _start + +_start: + lui a0, %hi(foo) + addi a0, a0, %lo(foo) + sw a0, %lo(foo)(a0) + lui a1, %hi(bar) + addi a1, a1, %lo(bar) + sw a1, %lo(bar)(a1) + diff --git a/lld/test/lit.cfg.py b/lld/test/lit.cfg.py index 267f8c517858..52898a458e33 100644 --- a/lld/test/lit.cfg.py +++ b/lld/test/lit.cfg.py @@ -70,6 +70,7 @@ 'AMDGPU': 'amdgpu', 'ARM': 'arm', 'AVR': 'avr', + 'CAHP': 'cahp', 'Hexagon': 'hexagon', 'Mips': 'mips', 'MSP430': 'msp430', From 848b2974e63a04c6f8bdb81acaa623c306de225a Mon Sep 17 00:00:00 2001 From: Ushitora Anqou Date: Sun, 3 Nov 2019 11:08:14 +0900 Subject: [PATCH 258/289] [CAHP] Add CAHPAsmWriter --- llvm/lib/Target/CAHP/CAHP.td | 5 +++++ llvm/lib/Target/CAHP/InstPrinter/CAHPInstPrinter.cpp | 6 ++++-- llvm/lib/Target/CAHP/InstPrinter/CAHPInstPrinter.h | 7 ++++--- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/llvm/lib/Target/CAHP/CAHP.td b/llvm/lib/Target/CAHP/CAHP.td index 838a643b17da..39b8099d1496 100644 --- a/llvm/lib/Target/CAHP/CAHP.td +++ b/llvm/lib/Target/CAHP/CAHP.td @@ -31,8 +31,13 @@ def CAHPAsmParser : AsmParser { let ShouldEmitMatchRegisterAltName = 1; } +def CAHPAsmWriter : AsmWriter { + int PassSubtarget = 1; +} + def CAHP : Target { let InstructionSet = CAHPInstrInfo; let AssemblyParsers = [CAHPAsmParser]; + let AssemblyWriters = [CAHPAsmWriter]; let AllowRegisterRenaming = 1; } diff --git a/llvm/lib/Target/CAHP/InstPrinter/CAHPInstPrinter.cpp b/llvm/lib/Target/CAHP/InstPrinter/CAHPInstPrinter.cpp index 19262868765b..f8990b7c3c97 100644 --- a/llvm/lib/Target/CAHP/InstPrinter/CAHPInstPrinter.cpp +++ b/llvm/lib/Target/CAHP/InstPrinter/CAHPInstPrinter.cpp @@ -6,6 +6,7 @@ #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" +#include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/MCSymbol.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FormattedStream.h" @@ -18,7 +19,7 @@ using namespace llvm; void CAHPInstPrinter::printInst(const MCInst *MI, raw_ostream &O, StringRef Annot, const MCSubtargetInfo &STI) { - printInstruction(MI, O); + printInstruction(MI, STI, O); printAnnotation(O, Annot); } @@ -27,7 +28,8 @@ void CAHPInstPrinter::printRegName(raw_ostream &O, unsigned RegNo) const { } void CAHPInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, - raw_ostream &O, const char *Modifier) { + const MCSubtargetInfo &STI, raw_ostream &O, + const char *Modifier) { assert((Modifier == 0 || Modifier[0] == 0) && "No modifiers supported"); const MCOperand &MO = MI->getOperand(OpNo); diff --git a/llvm/lib/Target/CAHP/InstPrinter/CAHPInstPrinter.h b/llvm/lib/Target/CAHP/InstPrinter/CAHPInstPrinter.h index 6260882ce5e2..97cd75f177cc 100644 --- a/llvm/lib/Target/CAHP/InstPrinter/CAHPInstPrinter.h +++ b/llvm/lib/Target/CAHP/InstPrinter/CAHPInstPrinter.h @@ -21,11 +21,12 @@ class CAHPInstPrinter : public MCInstPrinter { const MCSubtargetInfo &STI) override; void printRegName(raw_ostream &O, unsigned RegNo) const override; - void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O, - const char *Modifier = nullptr); + void printOperand(const MCInst *MI, unsigned OpNo, const MCSubtargetInfo &STI, + raw_ostream &O, const char *Modifier = nullptr); // Autogenerated by tblgen. - void printInstruction(const MCInst *MI, raw_ostream &O); + void printInstruction(const MCInst *MI, const MCSubtargetInfo &STI, + raw_ostream &O); static const char *getRegisterName(unsigned RegNo, unsigned AltIdx = CAHP::ABIRegAltName); }; From 189d4063cd226c06f5ee57e72d119c00e975013c Mon Sep 17 00:00:00 2001 From: Ushitora Anqou Date: Sun, 3 Nov 2019 11:10:14 +0900 Subject: [PATCH 259/289] [CAHP] Use 16-bit instructions aggressively --- llvm/lib/Target/CAHP/CAHPAsmPrinter.cpp | 9 +- llvm/lib/Target/CAHP/CAHPInstrInfo.td | 63 ++ llvm/lib/Target/CAHP/CMakeLists.txt | 1 + llvm/test/CodeGen/CAHP/alu16.ll | 169 +++- llvm/test/CodeGen/CAHP/bare-select.ll | 2 +- llvm/test/CodeGen/CAHP/calls.ll | 26 +- llvm/test/CodeGen/CAHP/frame.ll | 16 +- llvm/test/CodeGen/CAHP/frameindex.ll | 10 +- llvm/test/CodeGen/CAHP/large-stack.ll | 16 +- llvm/test/CodeGen/CAHP/mem.ll | 4 +- .../TableGen/CAHPCompressInstEmitter.cpp | 760 ++++++++++++++++++ llvm/utils/TableGen/CMakeLists.txt | 1 + llvm/utils/TableGen/TableGen.cpp | 6 + llvm/utils/TableGen/TableGenBackends.h | 1 + 14 files changed, 1019 insertions(+), 65 deletions(-) create mode 100644 llvm/utils/TableGen/CAHPCompressInstEmitter.cpp diff --git a/llvm/lib/Target/CAHP/CAHPAsmPrinter.cpp b/llvm/lib/Target/CAHP/CAHPAsmPrinter.cpp index 1dadcbc89d07..220fc13dd9bc 100644 --- a/llvm/lib/Target/CAHP/CAHPAsmPrinter.cpp +++ b/llvm/lib/Target/CAHP/CAHPAsmPrinter.cpp @@ -41,14 +41,19 @@ class CAHPAsmPrinter : public AsmPrinter { // instructions) auto-generated. #include "CAHPGenMCPseudoLowering.inc" +#define GEN_COMPRESS_INSTR +#include "CAHPGenCompressInstEmitter.inc" + void CAHPAsmPrinter::EmitInstruction(const MachineInstr *MI) { // Do any auto-generated pseudo lowerings. if (emitPseudoExpansionLowering(*OutStreamer, MI)) return; - MCInst TmpInst; + MCInst TmpInst, CInst; LowerCAHPMachineInstrToMCInst(MI, TmpInst, *this); - EmitToStreamer(*OutStreamer, TmpInst); + bool Res = compressInst(CInst, TmpInst, *TM.getMCSubtargetInfo(), + OutStreamer->getContext()); + EmitToStreamer(*OutStreamer, Res ? CInst : TmpInst); } // Force static initialization. diff --git a/llvm/lib/Target/CAHP/CAHPInstrInfo.td b/llvm/lib/Target/CAHP/CAHPInstrInfo.td index ca4848e564f8..bc34b515153a 100644 --- a/llvm/lib/Target/CAHP/CAHPInstrInfo.td +++ b/llvm/lib/Target/CAHP/CAHPInstrInfo.td @@ -45,18 +45,36 @@ def uimm4 : Operand, ImmLeaf(Imm);}]> { let ParserMatchClass = UImmAsmOperand<4>; let DecoderMethod = "decodeUImmOperand<4>"; let EncoderMethod = "getImmOpValue"; + let MCOperandPredicate = [{ + int64_t Imm; + if (!MCOp.evaluateAsConstantImm(Imm)) + return false; + return isUInt<4>(Imm); + }]; } def simm6 : Operand, ImmLeaf(Imm);}]> { let ParserMatchClass = SImmAsmOperand<6>; let DecoderMethod = "decodeSImmOperand<6>"; let EncoderMethod = "getImmOpValue"; + let MCOperandPredicate = [{ + int64_t Imm; + if (!MCOp.evaluateAsConstantImm(Imm)) + return false; + return isInt<6>(Imm); + }]; } def simm10 : Operand, ImmLeaf(Imm);}]> { let ParserMatchClass = SImmAsmOperand<10>; let DecoderMethod = "decodeSImmOperand<10>"; let EncoderMethod = "getImmOpValue"; + let MCOperandPredicate = [{ + int64_t Imm; + if (!MCOp.evaluateAsConstantImm(Imm)) + return false; + return isInt<10>(Imm); + }]; } def simm10_branch : Operand { @@ -75,6 +93,12 @@ def uimm7_lsb0 : Operand { let ParserMatchClass = UImmAsmOperand<7, "Lsb0">; let DecoderMethod = "decodeUImmOperand<7>"; let EncoderMethod = "getImmOpValue"; + let MCOperandPredicate = [{ + int64_t Imm; + if (!MCOp.evaluateAsConstantImm(Imm)) + return false; + return isShiftedUInt<6, 1>(Imm); + }]; } // Standalone (codegen-only) immleaf patterns. @@ -419,3 +443,42 @@ def : Pat<(brcond GPR:$cond, bb:$imm), (BNE GPR:$cond, (LSI 0), bb:$imm)>; def : Pat<(br bb:$imm), (JS simm11:$imm)>; def : Pat<(Call GPR:$rs), (JALR GPR:$rs)>; def : Pat<(Call tglobaladdr:$dst), (JSAL tglobaladdr:$dst)>; + +// Compress patterns + +class CompressPat { + dag Input = input; + dag Output = output; + list Predicates = []; +} + +multiclass CompPatRRRComm { + def : CompressPat<(Inst24 GPR:$rs1, GPR:$rs1, GPR:$rs2), + (Inst16 GPR:$rs1, GPR:$rs2)>; + def : CompressPat<(Inst24 GPR:$rs1, GPR:$rs2, GPR:$rs1), + (Inst16 GPR:$rs1, GPR:$rs2)>; +} +defm : CompPatRRRComm; +defm : CompPatRRRComm; +defm : CompPatRRRComm; +defm : CompPatRRRComm; + +class CompPatRRRNonComm + : CompressPat<(Inst24 GPR:$rs1, GPR:$rs1, GPR:$rs2), + (Inst16 GPR:$rs1, GPR:$rs2)> { +} +def : CompPatRRRNonComm; +def : CompPatRRRNonComm; +def : CompPatRRRNonComm; +def : CompPatRRRNonComm; + +def : CompressPat<(LSLI GPR:$rs1, GPR:$rs1, uimm4:$imm), (LSLI2 GPR:$rs1, uimm4:$imm)>; +def : CompressPat<(LSRI GPR:$rs1, GPR:$rs1, uimm4:$imm), (LSRI2 GPR:$rs1, uimm4:$imm)>; +def : CompressPat<(ASRI GPR:$rs1, GPR:$rs1, uimm4:$imm), (ASRI2 GPR:$rs1, uimm4:$imm)>; +def : CompressPat<(ADDI GPR:$rs1, GPR:$rs1, simm6:$imm), (ADDI2 GPR:$rs1, simm6:$imm)>; +def : CompressPat<(ANDI GPR:$rs1, GPR:$rs1, simm6:$imm), (ANDI2 GPR:$rs1, simm6:$imm)>; + +def : CompressPat<(LW GPR:$rd, SP:$rs, uimm7_lsb0:$imm), + (LWSP GPR:$rd, SP:$rs, uimm7_lsb0:$imm)>; +def : CompressPat<(SW GPR:$rd, SP:$rs, uimm7_lsb0:$imm), + (SWSP GPR:$rd, SP:$rs, uimm7_lsb0:$imm)>; diff --git a/llvm/lib/Target/CAHP/CMakeLists.txt b/llvm/lib/Target/CAHP/CMakeLists.txt index ff433de1ad2c..d20b6916cbc0 100644 --- a/llvm/lib/Target/CAHP/CMakeLists.txt +++ b/llvm/lib/Target/CAHP/CMakeLists.txt @@ -2,6 +2,7 @@ set(LLVM_TARGET_DEFINITIONS CAHP.td) tablegen(LLVM CAHPGenAsmMatcher.inc -gen-asm-matcher) tablegen(LLVM CAHPGenAsmWriter.inc -gen-asm-writer) +tablegen(LLVM CAHPGenCompressInstEmitter.inc -gen-cahp-compress-inst-emitter) tablegen(LLVM CAHPGenCallingConv.inc -gen-callingconv) tablegen(LLVM CAHPGenDAGISel.inc -gen-dag-isel) tablegen(LLVM CAHPGenDisassemblerTables.inc -gen-disassembler) diff --git a/llvm/test/CodeGen/CAHP/alu16.ll b/llvm/test/CodeGen/CAHP/alu16.ll index 3e3b5c9a8ebb..6c987465873a 100644 --- a/llvm/test/CodeGen/CAHP/alu16.ll +++ b/llvm/test/CodeGen/CAHP/alu16.ll @@ -4,10 +4,19 @@ ; Register-immediate instructions -define i16 @addi(i16 %a) nounwind { +define i16 @addi(i16 %a, i16 %b) nounwind { ; CAHP-LABEL: addi: ; CAHP: # %bb.0: -; CAHP-NEXT: addi a0, a0, 1 +; CAHP-NEXT: addi a0, a1, 1 +; CAHP-NEXT: jr ra + %1 = add i16 %b, 1 + ret i16 %1 +} + +define i16 @addi2(i16 %a) nounwind { +; CAHP-LABEL: addi2: +; CAHP: # %bb.0: +; CAHP-NEXT: addi2 a0, 1 ; CAHP-NEXT: jr ra %1 = add i16 %a, 1 ret i16 %1 @@ -31,37 +40,73 @@ define i16 @ori(i16 %a) nounwind { ret i16 %1 } -define i16 @andi(i16 %a) nounwind { +define i16 @andi(i16 %a, i16 %b) nounwind { ; CAHP-LABEL: andi: ; CAHP: # %bb.0: -; CAHP-NEXT: andi a0, a0, 6 +; CAHP-NEXT: andi a0, a1, 6 +; CAHP-NEXT: jr ra + %1 = and i16 %b, 6 + ret i16 %1 +} + +define i16 @andi2(i16 %a) nounwind { +; CAHP-LABEL: andi2: +; CAHP: # %bb.0: +; CAHP-NEXT: andi2 a0, 6 ; CAHP-NEXT: jr ra %1 = and i16 %a, 6 ret i16 %1 } -define i16 @lsli(i16 %a) nounwind { +define i16 @lsli(i16 %a, i16 %b) nounwind { ; CAHP-LABEL: lsli: ; CAHP: # %bb.0: -; CAHP-NEXT: lsli a0, a0, 7 +; CAHP-NEXT: lsli a0, a1, 7 +; CAHP-NEXT: jr ra + %1 = shl i16 %b, 7 + ret i16 %1 +} + +define i16 @lsli2(i16 %a) nounwind { +; CAHP-LABEL: lsli2: +; CAHP: # %bb.0: +; CAHP-NEXT: lsli2 a0, 7 ; CAHP-NEXT: jr ra %1 = shl i16 %a, 7 ret i16 %1 } -define i16 @lsri(i16 %a) nounwind { +define i16 @lsri(i16 %a, i16 %b) nounwind { ; CAHP-LABEL: lsri: ; CAHP: # %bb.0: -; CAHP-NEXT: lsri a0, a0, 8 +; CAHP-NEXT: lsri a0, a1, 8 +; CAHP-NEXT: jr ra + %1 = lshr i16 %b, 8 + ret i16 %1 +} + +define i16 @lsri2(i16 %a) nounwind { +; CAHP-LABEL: lsri2: +; CAHP: # %bb.0: +; CAHP-NEXT: lsri2 a0, 8 ; CAHP-NEXT: jr ra %1 = lshr i16 %a, 8 ret i16 %1 } -define i16 @asri(i16 %a) nounwind { +define i16 @asri(i16 %a, i16 %b) nounwind { ; CAHP-LABEL: asri: ; CAHP: # %bb.0: -; CAHP-NEXT: asri a0, a0, 9 +; CAHP-NEXT: asri a0, a1, 9 +; CAHP-NEXT: jr ra + %1 = ashr i16 %b, 9 + ret i16 %1 +} + +define i16 @asri2(i16 %a) nounwind { +; CAHP-LABEL: asri2: +; CAHP: # %bb.0: +; CAHP-NEXT: asri2 a0, 9 ; CAHP-NEXT: jr ra %1 = ashr i16 %a, 9 ret i16 %1 @@ -69,73 +114,145 @@ define i16 @asri(i16 %a) nounwind { ; Register-register instructions -define i16 @add(i16 %a, i16 %b) nounwind { +define i16 @add(i16 %a, i16 %b, i16 %c) nounwind { ; CAHP-LABEL: add: ; CAHP: # %bb.0: -; CAHP-NEXT: add a0, a0, a1 +; CAHP-NEXT: add a0, a1, a2 +; CAHP-NEXT: jr ra + %1 = add i16 %b, %c + ret i16 %1 +} + +define i16 @add2(i16 %a, i16 %b) nounwind { +; CAHP-LABEL: add2: +; CAHP: # %bb.0: +; CAHP-NEXT: add2 a0, a1 ; CAHP-NEXT: jr ra %1 = add i16 %a, %b ret i16 %1 } -define i16 @sub(i16 %a, i16 %b) nounwind { +define i16 @sub(i16 %a, i16 %b, i16 %c) nounwind { ; CAHP-LABEL: sub: ; CAHP: # %bb.0: -; CAHP-NEXT: sub a0, a0, a1 +; CAHP-NEXT: sub a0, a1, a2 +; CAHP-NEXT: jr ra + %1 = sub i16 %b, %c + ret i16 %1 +} + +define i16 @sub2(i16 %a, i16 %b) nounwind { +; CAHP-LABEL: sub2: +; CAHP: # %bb.0: +; CAHP-NEXT: sub2 a0, a1 ; CAHP-NEXT: jr ra %1 = sub i16 %a, %b ret i16 %1 } -define i16 @lsl(i16 %a, i16 %b) nounwind { +define i16 @lsl(i16 %a, i16 %b, i16 %c) nounwind { ; CAHP-LABEL: lsl: ; CAHP: # %bb.0: -; CAHP-NEXT: lsl a0, a0, a1 +; CAHP-NEXT: lsl a0, a1, a2 +; CAHP-NEXT: jr ra + %1 = shl i16 %b, %c + ret i16 %1 +} + +define i16 @lsl2(i16 %a, i16 %b) nounwind { +; CAHP-LABEL: lsl2: +; CAHP: # %bb.0: +; CAHP-NEXT: lsl2 a0, a1 ; CAHP-NEXT: jr ra %1 = shl i16 %a, %b ret i16 %1 } -define i16 @xor(i16 %a, i16 %b) nounwind { +define i16 @xor(i16 %a, i16 %b, i16 %c) nounwind { ; CAHP-LABEL: xor: ; CAHP: # %bb.0: -; CAHP-NEXT: xor a0, a0, a1 +; CAHP-NEXT: xor a0, a1, a2 +; CAHP-NEXT: jr ra + %1 = xor i16 %b, %c + ret i16 %1 +} + +define i16 @xor2(i16 %a, i16 %b) nounwind { +; CAHP-LABEL: xor2: +; CAHP: # %bb.0: +; CAHP-NEXT: xor2 a0, a1 ; CAHP-NEXT: jr ra %1 = xor i16 %a, %b ret i16 %1 } -define i16 @lsr(i16 %a, i16 %b) nounwind { +define i16 @lsr(i16 %a, i16 %b, i16 %c) nounwind { ; CAHP-LABEL: lsr: ; CAHP: # %bb.0: -; CAHP-NEXT: lsr a0, a0, a1 +; CAHP-NEXT: lsr a0, a1, a2 +; CAHP-NEXT: jr ra + %1 = lshr i16 %b, %c + ret i16 %1 +} + +define i16 @lsr2(i16 %a, i16 %b) nounwind { +; CAHP-LABEL: lsr2: +; CAHP: # %bb.0: +; CAHP-NEXT: lsr2 a0, a1 ; CAHP-NEXT: jr ra %1 = lshr i16 %a, %b ret i16 %1 } -define i16 @asr(i16 %a, i16 %b) nounwind { +define i16 @asr(i16 %a, i16 %b, i16 %c) nounwind { ; CAHP-LABEL: asr: ; CAHP: # %bb.0: -; CAHP-NEXT: asr a0, a0, a1 +; CAHP-NEXT: asr a0, a1, a2 +; CAHP-NEXT: jr ra + %1 = ashr i16 %b, %c + ret i16 %1 +} + +define i16 @asr2(i16 %a, i16 %b) nounwind { +; CAHP-LABEL: asr2: +; CAHP: # %bb.0: +; CAHP-NEXT: asr2 a0, a1 ; CAHP-NEXT: jr ra %1 = ashr i16 %a, %b ret i16 %1 } -define i16 @or(i16 %a, i16 %b) nounwind { +define i16 @or(i16 %a, i16 %b, i16 %c) nounwind { ; CAHP-LABEL: or: ; CAHP: # %bb.0: -; CAHP-NEXT: or a0, a0, a1 +; CAHP-NEXT: or a0, a1, a2 +; CAHP-NEXT: jr ra + %1 = or i16 %b, %c + ret i16 %1 +} + +define i16 @or2(i16 %a, i16 %b) nounwind { +; CAHP-LABEL: or2: +; CAHP: # %bb.0: +; CAHP-NEXT: or2 a0, a1 ; CAHP-NEXT: jr ra %1 = or i16 %a, %b ret i16 %1 } -define i16 @and(i16 %a, i16 %b) nounwind { +define i16 @and(i16 %a, i16 %b, i16 %c) nounwind { ; CAHP-LABEL: and: ; CAHP: # %bb.0: -; CAHP-NEXT: and a0, a0, a1 +; CAHP-NEXT: and a0, a1, a2 +; CAHP-NEXT: jr ra + %1 = and i16 %b, %c + ret i16 %1 +} + +define i16 @and2(i16 %a, i16 %b) nounwind { +; CAHP-LABEL: and2: +; CAHP: # %bb.0: +; CAHP-NEXT: and2 a0, a1 ; CAHP-NEXT: jr ra %1 = and i16 %a, %b ret i16 %1 diff --git a/llvm/test/CodeGen/CAHP/bare-select.ll b/llvm/test/CodeGen/CAHP/bare-select.ll index c908e3b7400b..e97fe05a4739 100644 --- a/llvm/test/CodeGen/CAHP/bare-select.ll +++ b/llvm/test/CodeGen/CAHP/bare-select.ll @@ -5,7 +5,7 @@ define i16 @bare_select(i1 %a, i16 %b, i16 %c) { ; CAHP-LABEL: bare_select: ; CAHP: # %bb.0: -; CAHP-NEXT: andi a0, a0, 1 +; CAHP-NEXT: andi2 a0, 1 ; CAHP-NEXT: lsi a3, 0 ; CAHP-NEXT: bne a0, a3, .LBB0_2 ; CAHP-NEXT:# %bb.1: diff --git a/llvm/test/CodeGen/CAHP/calls.ll b/llvm/test/CodeGen/CAHP/calls.ll index 8bdb61ac9c37..83f822da64a8 100644 --- a/llvm/test/CodeGen/CAHP/calls.ll +++ b/llvm/test/CodeGen/CAHP/calls.ll @@ -7,13 +7,13 @@ declare i16 @external_function(i16) define i16 @test_call_external(i16 %a) nounwind { ; CAHP-LABEL: test_call_external: ; CAHP: # %bb.0: -; CAHP-NEXT: addi sp, sp, -2 -; CAHP-NEXT: sw ra, 0(sp) +; CAHP-NEXT: addi2 sp, -2 +; CAHP-NEXT: swsp ra, 0(sp) ; CAHP-NEXT: lui a1, %hi(external_function) ; CAHP-NEXT: addi a1, a1, %lo(external_function) ; CAHP-NEXT: jalr a1 -; CAHP-NEXT: lw ra, 0(sp) -; CAHP-NEXT: addi sp, sp, 2 +; CAHP-NEXT: lwsp ra, 0(sp) +; CAHP-NEXT: addi2 sp, 2 ; CAHP-NEXT: jr ra %1 = call i16 @external_function(i16 %a) ret i16 %1 @@ -22,7 +22,7 @@ define i16 @test_call_external(i16 %a) nounwind { define i16 @defined_function(i16 %a) nounwind { ; CAHP-LABEL: defined_function: ; CAHP: # %bb.0: -; CAHP-NEXT: addi a0, a0, 1 +; CAHP-NEXT: addi2 a0, 1 ; CAHP-NEXT: jr ra %1 = add i16 %a, 1 ret i16 %1 @@ -31,13 +31,13 @@ define i16 @defined_function(i16 %a) nounwind { define i16 @test_call_defined(i16 %a) nounwind { ; CAHP-LABEL: test_call_defined: ; CAHP: # %bb.0: -; CAHP-NEXT: addi sp, sp, -2 -; CAHP-NEXT: sw ra, 0(sp) +; CAHP-NEXT: addi2 sp, -2 +; CAHP-NEXT: swsp ra, 0(sp) ; CAHP-NEXT: lui a1, %hi(defined_function) ; CAHP-NEXT: addi a1, a1, %lo(defined_function) ; CAHP-NEXT: jalr a1 -; CAHP-NEXT: lw ra, 0(sp) -; CAHP-NEXT: addi sp, sp, 2 +; CAHP-NEXT: lwsp ra, 0(sp) +; CAHP-NEXT: addi2 sp, 2 ; CAHP-NEXT: jr ra %1 = call i16 @defined_function(i16 %a) nounwind ret i16 %1 @@ -46,13 +46,13 @@ define i16 @test_call_defined(i16 %a) nounwind { define i16 @test_call_indirect(i16 (i16)* %a, i16 %b) nounwind { ; CAHP-LABEL: test_call_indirect: ; CAHP: # %bb.0: -; CAHP-NEXT: addi sp, sp, -2 -; CAHP-NEXT: sw ra, 0(sp) +; CAHP-NEXT: addi2 sp, -2 +; CAHP-NEXT: swsp ra, 0(sp) ; CAHP-NEXT: mov a2, a0 ; CAHP-NEXT: mov a0, a1 ; CAHP-NEXT: jalr a2 -; CAHP-NEXT: lw ra, 0(sp) -; CAHP-NEXT: addi sp, sp, 2 +; CAHP-NEXT: lwsp ra, 0(sp) +; CAHP-NEXT: addi2 sp, 2 ; CAHP-NEXT: jr ra %1 = call i16 %a(i16 %b) ret i16 %1 diff --git a/llvm/test/CodeGen/CAHP/frame.ll b/llvm/test/CodeGen/CAHP/frame.ll index 760d8f3fe398..f587920ebe79 100644 --- a/llvm/test/CodeGen/CAHP/frame.ll +++ b/llvm/test/CodeGen/CAHP/frame.ll @@ -10,10 +10,10 @@ define i16 @test() nounwind { ; CAHP-LABEL: test: ; CAHP: # %bb.0: -; CAHP-NEXT: addi sp, sp, -24 -; CAHP-NEXT: sw ra, 22(sp) -; CAHP-NEXT: sw fp, 20(sp) -; CAHP-NEXT: sw s0, 18(sp) +; CAHP-NEXT: addi2 sp, -24 +; CAHP-NEXT: swsp ra, 22(sp) +; CAHP-NEXT: swsp fp, 20(sp) +; CAHP-NEXT: swsp s0, 18(sp) ; CAHP-NEXT: addi fp, sp, 24 ; CAHP-NEXT: lsi s0, 0 ; CAHP-NEXT: sw s0, -16(fp) @@ -27,10 +27,10 @@ define i16 @test() nounwind { ; CAHP-NEXT: jalr a1 ; CAHP-NEXT: mov a0, s0 ; CAHP-NEXT: addi sp, fp, -24 -; CAHP-NEXT: lw s0, 18(sp) -; CAHP-NEXT: lw fp, 20(sp) -; CAHP-NEXT: lw ra, 22(sp) -; CAHP-NEXT: addi sp, sp, 24 +; CAHP-NEXT: lwsp s0, 18(sp) +; CAHP-NEXT: lwsp fp, 20(sp) +; CAHP-NEXT: lwsp ra, 22(sp) +; CAHP-NEXT: addi2 sp, 24 ; CAHP-NEXT: jr ra %key = alloca %struct.key_t, align 2 diff --git a/llvm/test/CodeGen/CAHP/frameindex.ll b/llvm/test/CodeGen/CAHP/frameindex.ll index 6637e8890b8b..fcddb9c3e98a 100644 --- a/llvm/test/CodeGen/CAHP/frameindex.ll +++ b/llvm/test/CodeGen/CAHP/frameindex.ll @@ -7,15 +7,15 @@ declare i16 @bar(i16*) define i16 @foo() { ; CAHP-LABEL: foo: ; CAHP: # %bb.0: -; CAHP-NEXT: addi sp, sp, -4 -; CAHP-NEXT: sw ra, 2(sp) +; CAHP-NEXT: addi2 sp, -4 +; CAHP-NEXT: swsp ra, 2(sp) ; CAHP-NEXT: lui a0, %hi(bar) ; CAHP-NEXT: addi a1, a0, %lo(bar) ; CAHP-NEXT: addi a0, sp, 0 ; CAHP-NEXT: jalr a1 -; CAHP-NEXT: lw a0, 0(sp) -; CAHP-NEXT: lw ra, 2(sp) -; CAHP-NEXT: addi sp, sp, 4 +; CAHP-NEXT: lwsp a0, 0(sp) +; CAHP-NEXT: lwsp ra, 2(sp) +; CAHP-NEXT: addi2 sp, 4 ; CAHP-NEXT: jr ra %1 = alloca i16 %2 = call i16 @bar(i16* %1) diff --git a/llvm/test/CodeGen/CAHP/large-stack.ll b/llvm/test/CodeGen/CAHP/large-stack.ll index 76e9e692c5f9..5ca3da2f856e 100644 --- a/llvm/test/CodeGen/CAHP/large-stack.ll +++ b/llvm/test/CodeGen/CAHP/large-stack.ll @@ -11,39 +11,39 @@ define void @test() nounwind { ; CAHP-WITHFP: # %bb.0: ; CAHP-WITHFP-NEXT: lui a0, 3 ; CAHP-WITHFP-NEXT: addi a0, a0, -68 -; CAHP-WITHFP-NEXT: sub sp, sp, a0 +; CAHP-WITHFP-NEXT: sub2 sp, a0 ; CAHP-WITHFP-NEXT: lui a0, 3 ; CAHP-WITHFP-NEXT: addi a0, a0, -70 -; CAHP-WITHFP-NEXT: add a0, a0, sp +; CAHP-WITHFP-NEXT: add2 a0, sp ; CAHP-WITHFP-NEXT: sw ra, 0(a0) ; CAHP-WITHFP-NEXT: lui a0, 3 ; CAHP-WITHFP-NEXT: addi a0, a0, -72 -; CAHP-WITHFP-NEXT: add a0, a0, sp +; CAHP-WITHFP-NEXT: add2 a0, sp ; CAHP-WITHFP-NEXT: sw fp, 0(a0) ; CAHP-WITHFP-NEXT: lui a0, 3 ; CAHP-WITHFP-NEXT: addi a0, a0, -68 ; CAHP-WITHFP-NEXT: add fp, sp, a0 ; CAHP-WITHFP-NEXT: lui a0, 3 ; CAHP-WITHFP-NEXT: addi a0, a0, -72 -; CAHP-WITHFP-NEXT: add a0, a0, sp +; CAHP-WITHFP-NEXT: add2 a0, sp ; CAHP-WITHFP-NEXT: lw fp, 0(a0) ; CAHP-WITHFP-NEXT: lui a0, 3 ; CAHP-WITHFP-NEXT: addi a0, a0, -70 -; CAHP-WITHFP-NEXT: add a0, a0, sp +; CAHP-WITHFP-NEXT: add2 a0, sp ; CAHP-WITHFP-NEXT: lw ra, 0(a0) ; CAHP-WITHFP-NEXT: lui a0, 3 ; CAHP-WITHFP-NEXT: addi a0, a0, -68 -; CAHP-WITHFP-NEXT: add sp, sp, a0 +; CAHP-WITHFP-NEXT: add2 sp, a0 ; CAHP-WITHFP-NEXT: jr ra ; CAHP-FPELIM-LABEL: test: ; CAHP-FPELIM: # %bb.0: ; CAHP-FPELIM-NEXT: lui a0, 3 ; CAHP-FPELIM-NEXT: addi a0, a0, -72 -; CAHP-FPELIM-NEXT: sub sp, sp, a0 +; CAHP-FPELIM-NEXT: sub2 sp, a0 ; CAHP-FPELIM-NEXT: lui a0, 3 ; CAHP-FPELIM-NEXT: addi a0, a0, -72 -; CAHP-FPELIM-NEXT: add sp, sp, a0 +; CAHP-FPELIM-NEXT: add2 sp, a0 ; CAHP-FPELIM-NEXT: jr ra %tmp = alloca [ 3000 x i8 ] , align 2 diff --git a/llvm/test/CodeGen/CAHP/mem.ll b/llvm/test/CodeGen/CAHP/mem.ll index b07c9c6142ae..91c3d5b9c8d0 100644 --- a/llvm/test/CodeGen/CAHP/mem.ll +++ b/llvm/test/CodeGen/CAHP/mem.ll @@ -35,7 +35,7 @@ define i16 @lbu(i8 *%a) nounwind { ; CAHP: # %bb.0: ; CAHP-NEXT: lbu a1, 0(a0) ; CAHP-NEXT: lbu a0, 4(a0) -; CAHP-NEXT: add a0, a0, a1 +; CAHP-NEXT: add2 a0, a1 ; CAHP-NEXT: jr ra %1 = getelementptr i8, i8* %a, i16 4 %2 = load i8, i8* %1 @@ -79,7 +79,7 @@ define i16 @load_sext_zext_anyext_i1(i1 *%a) nounwind { ; CAHP-NEXT: lb a1, 0(a0) ; CAHP-NEXT: lbu a1, 1(a0) ; CAHP-NEXT: lbu a0, 2(a0) -; CAHP-NEXT: sub a0, a0, a1 +; CAHP-NEXT: sub2 a0, a1 ; CAHP-NEXT: jr ra ; sextload i1 %1 = getelementptr i1, i1* %a, i16 1 diff --git a/llvm/utils/TableGen/CAHPCompressInstEmitter.cpp b/llvm/utils/TableGen/CAHPCompressInstEmitter.cpp new file mode 100644 index 000000000000..4120d3e44c56 --- /dev/null +++ b/llvm/utils/TableGen/CAHPCompressInstEmitter.cpp @@ -0,0 +1,760 @@ +// This file is copied and modified from The LLVM Compiler Infrastructure, which +// is distributed under the Apache License v2.0 with LLVM Exceptions (see +// LICENSE.TXT for details). This file is licensed under the same license. + +#include "CodeGenInstruction.h" +#include "CodeGenTarget.h" +#include "llvm/ADT/IndexedMap.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/TableGen/Error.h" +#include "llvm/TableGen/Record.h" +#include "llvm/TableGen/TableGenBackend.h" +#include +#include +using namespace llvm; + +#define DEBUG_TYPE "cahp-compress-inst-emitter" + +namespace { +class CAHPCompressInstEmitter { + struct OpData { + enum MapKind { Operand, Imm, Reg }; + MapKind Kind; + union { + unsigned Operand; // Operand number mapped to. + uint64_t Imm; // Integer immediate value. + Record *Reg; // Physical register. + } Data; + int TiedOpIdx = -1; // Tied operand index within the instruction. + }; + struct CompressPat { + CodeGenInstruction Source; // The source instruction definition. + CodeGenInstruction Dest; // The destination instruction to transform to. + std::vector + PatReqFeatures; // Required target features to enable pattern. + IndexedMap + SourceOperandMap; // Maps operands in the Source Instruction to + // the corresponding Dest instruction operand. + IndexedMap + DestOperandMap; // Maps operands in the Dest Instruction + // to the corresponding Source instruction operand. + CompressPat(CodeGenInstruction &S, CodeGenInstruction &D, + std::vector RF, IndexedMap &SourceMap, + IndexedMap &DestMap) + : Source(S), Dest(D), PatReqFeatures(RF), SourceOperandMap(SourceMap), + DestOperandMap(DestMap) {} + }; + + RecordKeeper &Records; + CodeGenTarget Target; + SmallVector CompressPatterns; + + void addDagOperandMapping(Record *Rec, DagInit *Dag, CodeGenInstruction &Inst, + IndexedMap &OperandMap, bool IsSourceInst); + void evaluateCompressPat(Record *Compress); + void emitCompressInstEmitter(raw_ostream &o, bool Compress); + bool validateTypes(Record *SubType, Record *Type, bool IsSourceInst); + bool validateRegister(Record *Reg, Record *RegClass); + void createDagOperandMapping(Record *Rec, StringMap &SourceOperands, + StringMap &DestOperands, + DagInit *SourceDag, DagInit *DestDag, + IndexedMap &SourceOperandMap); + + void createInstOperandMapping(Record *Rec, DagInit *SourceDag, + DagInit *DestDag, + IndexedMap &SourceOperandMap, + IndexedMap &DestOperandMap, + StringMap &SourceOperands, + CodeGenInstruction &DestInst); + +public: + CAHPCompressInstEmitter(RecordKeeper &R) : Records(R), Target(R) {} + + void run(raw_ostream &o); +}; +} // End anonymous namespace. + +bool CAHPCompressInstEmitter::validateRegister(Record *Reg, Record *RegClass) { + assert(Reg->isSubClassOf("Register") && "Reg record should be a Register\n"); + assert(RegClass->isSubClassOf("RegisterClass") && "RegClass record should be" + " a RegisterClass\n"); + CodeGenRegisterClass RC = Target.getRegisterClass(RegClass); + const CodeGenRegister *R = Target.getRegisterByName(Reg->getName().lower()); + assert((R != nullptr) && + ("Register" + Reg->getName().str() + " not defined!!\n").c_str()); + return RC.contains(R); +} + +bool CAHPCompressInstEmitter::validateTypes(Record *DagOpType, + Record *InstOpType, + bool IsSourceInst) { + if (DagOpType == InstOpType) + return true; + // Only source instruction operands are allowed to not match Input Dag + // operands. + if (!IsSourceInst) + return false; + + if (DagOpType->isSubClassOf("RegisterClass") && + InstOpType->isSubClassOf("RegisterClass")) { + CodeGenRegisterClass RC = Target.getRegisterClass(InstOpType); + CodeGenRegisterClass SubRC = Target.getRegisterClass(DagOpType); + return RC.hasSubClass(&SubRC); + } + + // At this point either or both types are not registers, reject the pattern. + if (DagOpType->isSubClassOf("RegisterClass") || + InstOpType->isSubClassOf("RegisterClass")) + return false; + + // Let further validation happen when compress()/uncompress() functions are + // invoked. + LLVM_DEBUG(dbgs() << (IsSourceInst ? "Input" : "Output") + << " Dag Operand Type: '" << DagOpType->getName() + << "' and " + << "Instruction Operand Type: '" << InstOpType->getName() + << "' can't be checked at pattern validation time!\n"); + return true; +} + +/// The patterns in the Dag contain different types of operands: +/// Register operands, e.g.: GPR:$rs1; Fixed registers, e.g: X1; Immediate +/// operands, e.g.: simm6:$imm; Fixed immediate operands, e.g.: 0. This function +/// maps Dag operands to its corresponding instruction operands. For register +/// operands and fixed registers it expects the Dag operand type to be contained +/// in the instantiated instruction operand type. For immediate operands and +/// immediates no validation checks are enforced at pattern validation time. +void CAHPCompressInstEmitter::addDagOperandMapping( + Record *Rec, DagInit *Dag, CodeGenInstruction &Inst, + IndexedMap &OperandMap, bool IsSourceInst) { + // TiedCount keeps track of the number of operands skipped in Inst + // operands list to get to the corresponding Dag operand. This is + // necessary because the number of operands in Inst might be greater + // than number of operands in the Dag due to how tied operands + // are represented. + unsigned TiedCount = 0; + for (unsigned i = 0, e = Inst.Operands.size(); i != e; ++i) { + int TiedOpIdx = Inst.Operands[i].getTiedRegister(); + if (-1 != TiedOpIdx) { + // Set the entry in OperandMap for the tied operand we're skipping. + OperandMap[i].Kind = OperandMap[TiedOpIdx].Kind; + OperandMap[i].Data = OperandMap[TiedOpIdx].Data; + TiedCount++; + continue; + } + if (DefInit *DI = dyn_cast(Dag->getArg(i - TiedCount))) { + if (DI->getDef()->isSubClassOf("Register")) { + // Check if the fixed register belongs to the Register class. + if (!validateRegister(DI->getDef(), Inst.Operands[i].Rec)) + PrintFatalError(Rec->getLoc(), + "Error in Dag '" + Dag->getAsString() + + "'Register: '" + DI->getDef()->getName() + + "' is not in register class '" + + Inst.Operands[i].Rec->getName() + "'"); + OperandMap[i].Kind = OpData::Reg; + OperandMap[i].Data.Reg = DI->getDef(); + continue; + } + // Validate that Dag operand type matches the type defined in the + // corresponding instruction. Operands in the input Dag pattern are + // allowed to be a subclass of the type specified in corresponding + // instruction operand instead of being an exact match. + if (!validateTypes(DI->getDef(), Inst.Operands[i].Rec, IsSourceInst)) + PrintFatalError(Rec->getLoc(), + "Error in Dag '" + Dag->getAsString() + "'. Operand '" + + Dag->getArgNameStr(i - TiedCount) + "' has type '" + + DI->getDef()->getName() + + "' which does not match the type '" + + Inst.Operands[i].Rec->getName() + + "' in the corresponding instruction operand!"); + + OperandMap[i].Kind = OpData::Operand; + } else if (IntInit *II = dyn_cast(Dag->getArg(i - TiedCount))) { + // Validate that corresponding instruction operand expects an immediate. + if (Inst.Operands[i].Rec->isSubClassOf("RegisterClass")) + PrintFatalError( + Rec->getLoc(), + ("Error in Dag '" + Dag->getAsString() + "' Found immediate: '" + + II->getAsString() + + "' but corresponding instruction operand expected a register!")); + // No pattern validation check possible for values of fixed immediate. + OperandMap[i].Kind = OpData::Imm; + OperandMap[i].Data.Imm = II->getValue(); + LLVM_DEBUG( + dbgs() << " Found immediate '" << II->getValue() << "' at " + << (IsSourceInst ? "input " : "output ") + << "Dag. No validation time check possible for values of " + "fixed immediate.\n"); + } else + llvm_unreachable("Unhandled CompressPat argument type!"); + } +} + +// Verify the Dag operand count is enough to build an instruction. +static bool verifyDagOpCount(CodeGenInstruction &Inst, DagInit *Dag, + bool IsSource) { + if (Dag->getNumArgs() == Inst.Operands.size()) + return true; + // Source instructions are non compressed instructions and don't have tied + // operands. + if (IsSource) + PrintFatalError(Inst.TheDef->getLoc(), + "Input operands for Inst '" + Inst.TheDef->getName() + + "' and input Dag operand count mismatch"); + // The Dag can't have more arguments than the Instruction. + if (Dag->getNumArgs() > Inst.Operands.size()) + PrintFatalError(Inst.TheDef->getLoc(), + "Inst '" + Inst.TheDef->getName() + + "' and Dag operand count mismatch"); + + // The Instruction might have tied operands so the Dag might have + // a fewer operand count. + unsigned RealCount = Inst.Operands.size(); + for (unsigned i = 0; i < Inst.Operands.size(); i++) + if (Inst.Operands[i].getTiedRegister() != -1) + --RealCount; + + if (Dag->getNumArgs() != RealCount) + PrintFatalError(Inst.TheDef->getLoc(), + "Inst '" + Inst.TheDef->getName() + + "' and Dag operand count mismatch"); + return true; +} + +static bool validateArgsTypes(Init *Arg1, Init *Arg2) { + DefInit *Type1 = dyn_cast(Arg1); + DefInit *Type2 = dyn_cast(Arg2); + assert(Type1 && ("Arg1 type not found\n")); + assert(Type2 && ("Arg2 type not found\n")); + return Type1->getDef() == Type2->getDef(); +} + +// Creates a mapping between the operand name in the Dag (e.g. $rs1) and +// its index in the list of Dag operands and checks that operands with the same +// name have the same types. For example in 'ADD2 $rs1, $rs2' we generate the +// mapping $rs1 --> 0, $rs2 ---> 1. If the operand appears twice in the (tied) +// same Dag we use the last occurrence for indexing. +void CAHPCompressInstEmitter::createDagOperandMapping( + Record *Rec, StringMap &SourceOperands, + StringMap &DestOperands, DagInit *SourceDag, DagInit *DestDag, + IndexedMap &SourceOperandMap) { + for (unsigned i = 0; i < DestDag->getNumArgs(); ++i) { + // Skip fixed immediates and registers, they were handled in + // addDagOperandMapping. + if ("" == DestDag->getArgNameStr(i)) + continue; + DestOperands[DestDag->getArgNameStr(i)] = i; + } + + for (unsigned i = 0; i < SourceDag->getNumArgs(); ++i) { + // Skip fixed immediates and registers, they were handled in + // addDagOperandMapping. + if ("" == SourceDag->getArgNameStr(i)) + continue; + + StringMap::iterator it = + SourceOperands.find(SourceDag->getArgNameStr(i)); + if (it != SourceOperands.end()) { + // Operand sharing the same name in the Dag should be mapped as tied. + SourceOperandMap[i].TiedOpIdx = it->getValue(); + if (!validateArgsTypes(SourceDag->getArg(it->getValue()), + SourceDag->getArg(i))) + PrintFatalError(Rec->getLoc(), + "Input Operand '" + SourceDag->getArgNameStr(i) + + "' has a mismatched tied operand!\n"); + } + it = DestOperands.find(SourceDag->getArgNameStr(i)); + if (it == DestOperands.end()) + PrintFatalError(Rec->getLoc(), "Operand " + SourceDag->getArgNameStr(i) + + " defined in Input Dag but not used in" + " Output Dag!\n"); + // Input Dag operand types must match output Dag operand type. + if (!validateArgsTypes(DestDag->getArg(it->getValue()), + SourceDag->getArg(i))) + PrintFatalError(Rec->getLoc(), "Type mismatch between Input and " + "Output Dag operand '" + + SourceDag->getArgNameStr(i) + "'!"); + SourceOperands[SourceDag->getArgNameStr(i)] = i; + } +} + +/// Map operand names in the Dag to their index in both corresponding input and +/// output instructions. Validate that operands defined in the input are +/// used in the output pattern while populating the maps. +void CAHPCompressInstEmitter::createInstOperandMapping( + Record *Rec, DagInit *SourceDag, DagInit *DestDag, + IndexedMap &SourceOperandMap, IndexedMap &DestOperandMap, + StringMap &SourceOperands, CodeGenInstruction &DestInst) { + // TiedCount keeps track of the number of operands skipped in Inst + // operands list to get to the corresponding Dag operand. + unsigned TiedCount = 0; + LLVM_DEBUG(dbgs() << " Operand mapping:\n Source Dest\n"); + for (unsigned i = 0, e = DestInst.Operands.size(); i != e; ++i) { + int TiedInstOpIdx = DestInst.Operands[i].getTiedRegister(); + if (TiedInstOpIdx != -1) { + ++TiedCount; + DestOperandMap[i].Data = DestOperandMap[TiedInstOpIdx].Data; + DestOperandMap[i].Kind = DestOperandMap[TiedInstOpIdx].Kind; + if (DestOperandMap[i].Kind == OpData::Operand) + // No need to fill the SourceOperandMap here since it was mapped to + // destination operand 'TiedInstOpIdx' in a previous iteration. + LLVM_DEBUG(dbgs() << " " << DestOperandMap[i].Data.Operand + << " ====> " << i + << " Dest operand tied with operand '" + << TiedInstOpIdx << "'\n"); + continue; + } + // Skip fixed immediates and registers, they were handled in + // addDagOperandMapping. + if (DestOperandMap[i].Kind != OpData::Operand) + continue; + + unsigned DagArgIdx = i - TiedCount; + StringMap::iterator SourceOp = + SourceOperands.find(DestDag->getArgNameStr(DagArgIdx)); + if (SourceOp == SourceOperands.end()) + PrintFatalError(Rec->getLoc(), + "Output Dag operand '" + + DestDag->getArgNameStr(DagArgIdx) + + "' has no matching input Dag operand."); + + assert(DestDag->getArgNameStr(DagArgIdx) == + SourceDag->getArgNameStr(SourceOp->getValue()) && + "Incorrect operand mapping detected!\n"); + DestOperandMap[i].Data.Operand = SourceOp->getValue(); + SourceOperandMap[SourceOp->getValue()].Data.Operand = i; + LLVM_DEBUG(dbgs() << " " << SourceOp->getValue() << " ====> " << i + << "\n"); + } +} + +/// Validates the CompressPattern and create operand mapping. +/// These are the checks to validate a CompressPat pattern declarations. +/// Error out with message under these conditions: +/// - Dag Input opcode is an expanded instruction and Dag Output opcode is a +/// compressed instruction. +/// - Operands in Dag Input must be all used in Dag Output. +/// Register Operand type in Dag Input Type must be contained in the +/// corresponding Source Instruction type. +/// - Register Operand type in Dag Input must be the same as in Dag Ouput. +/// - Register Operand type in Dag Output must be the same as the +/// corresponding Destination Inst type. +/// - Immediate Operand type in Dag Input must be the same as in Dag Ouput. +/// - Immediate Operand type in Dag Ouput must be the same as the corresponding +/// Destination Instruction type. +/// - Fixed register must be contained in the corresponding Source Instruction +/// type. +/// - Fixed register must be contained in the corresponding Destination +/// Instruction type. Warning message printed under these conditions: +/// - Fixed immediate in Dag Input or Dag Ouput cannot be checked at this time +/// and generate warning. +/// - Immediate operand type in Dag Input differs from the corresponding Source +/// Instruction type and generate a warning. +void CAHPCompressInstEmitter::evaluateCompressPat(Record *Rec) { + // Validate input Dag operands. + DagInit *SourceDag = Rec->getValueAsDag("Input"); + assert(SourceDag && "Missing 'Input' in compress pattern!"); + LLVM_DEBUG(dbgs() << "Input: " << *SourceDag << "\n"); + + DefInit *OpDef = dyn_cast(SourceDag->getOperator()); + if (!OpDef) + PrintFatalError(Rec->getLoc(), + Rec->getName() + " has unexpected operator type!"); + // Checking we are transforming from compressed to uncompressed instructions. + Record *Operator = OpDef->getDef(); + if (!Operator->isSubClassOf("CAHPInst24")) + PrintFatalError(Rec->getLoc(), "Input instruction '" + Operator->getName() + + "' is not a 24 bit wide instruction!"); + CodeGenInstruction SourceInst(Operator); + verifyDagOpCount(SourceInst, SourceDag, true); + + // Validate output Dag operands. + DagInit *DestDag = Rec->getValueAsDag("Output"); + assert(DestDag && "Missing 'Output' in compress pattern!"); + LLVM_DEBUG(dbgs() << "Output: " << *DestDag << "\n"); + + DefInit *DestOpDef = dyn_cast(DestDag->getOperator()); + if (!DestOpDef) + PrintFatalError(Rec->getLoc(), + Rec->getName() + " has unexpected operator type!"); + + Record *DestOperator = DestOpDef->getDef(); + if (!DestOperator->isSubClassOf("CAHPInst16")) + PrintFatalError(Rec->getLoc(), "Output instruction '" + + DestOperator->getName() + + "' is not a 16 bit wide instruction!"); + CodeGenInstruction DestInst(DestOperator); + verifyDagOpCount(DestInst, DestDag, false); + + // Fill the mapping from the source to destination instructions. + + IndexedMap SourceOperandMap; + SourceOperandMap.grow(SourceInst.Operands.size()); + // Create a mapping between source Dag operands and source Inst operands. + addDagOperandMapping(Rec, SourceDag, SourceInst, SourceOperandMap, + /*IsSourceInst*/ true); + + IndexedMap DestOperandMap; + DestOperandMap.grow(DestInst.Operands.size()); + // Create a mapping between destination Dag operands and destination Inst + // operands. + addDagOperandMapping(Rec, DestDag, DestInst, DestOperandMap, + /*IsSourceInst*/ false); + + StringMap SourceOperands; + StringMap DestOperands; + createDagOperandMapping(Rec, SourceOperands, DestOperands, SourceDag, DestDag, + SourceOperandMap); + // Create operand mapping between the source and destination instructions. + createInstOperandMapping(Rec, SourceDag, DestDag, SourceOperandMap, + DestOperandMap, SourceOperands, DestInst); + + // Get the target features for the CompressPat. + std::vector PatReqFeatures; + std::vector RF = Rec->getValueAsListOfDefs("Predicates"); + copy_if(RF, std::back_inserter(PatReqFeatures), [](Record *R) { + return R->getValueAsBit("AssemblerMatcherPredicate"); + }); + + CompressPatterns.push_back(CompressPat(SourceInst, DestInst, PatReqFeatures, + SourceOperandMap, DestOperandMap)); +} + +static void getReqFeatures(std::set &FeaturesSet, + const std::vector &ReqFeatures) { + for (auto &R : ReqFeatures) { + StringRef AsmCondString = R->getValueAsString("AssemblerCondString"); + + // AsmCondString has syntax [!]F(,[!]F)* + SmallVector Ops; + SplitString(AsmCondString, Ops, ","); + assert(!Ops.empty() && "AssemblerCondString cannot be empty"); + for (auto &Op : Ops) { + assert(!Op.empty() && "Empty operator"); + FeaturesSet.insert(Op); + } + } +} + +static unsigned +getMCOpPredicate(DenseMap &MCOpPredicateMap, + std::vector &MCOpPredicates, Record *Rec) { + unsigned Entry = MCOpPredicateMap[Rec]; + if (Entry) + return Entry; + + if (!Rec->isValueUnset("MCOperandPredicate")) { + MCOpPredicates.push_back(Rec); + Entry = MCOpPredicates.size(); + MCOpPredicateMap[Rec] = Entry; + return Entry; + } + + PrintFatalError(Rec->getLoc(), + "No MCOperandPredicate on this operand at all: " + + Rec->getName().str() + "'"); + return 0; +} + +static std::string mergeCondAndCode(raw_string_ostream &CondStream, + raw_string_ostream &CodeStream) { + std::string S; + raw_string_ostream CombinedStream(S); + CombinedStream.indent(4) + << "if (" + << CondStream.str().substr( + 6, CondStream.str().length() - + 10) // remove first indentation and last '&&'. + << ") {\n"; + CombinedStream << CodeStream.str(); + CombinedStream.indent(4) << " return true;\n"; + CombinedStream.indent(4) << "} // if\n"; + return CombinedStream.str(); +} + +void CAHPCompressInstEmitter::emitCompressInstEmitter(raw_ostream &o, + bool Compress) { + Record *AsmWriter = Target.getAsmWriter(); + if (!AsmWriter->getValueAsInt("PassSubtarget")) + PrintFatalError(AsmWriter->getLoc(), + "'PassSubtarget' is false. SubTargetInfo object is needed " + "for target features.\n"); + + std::string Namespace = Target.getName(); + + // Sort entries in CompressPatterns to handle instructions that can have more + // than one candidate for compression\uncompression, e.g ADD can be + // transformed to a C_ADD or a C_MV. When emitting 'uncompress()' function the + // source and destination are flipped and the sort key needs to change + // accordingly. + llvm::stable_sort(CompressPatterns, + [Compress](const CompressPat &LHS, const CompressPat &RHS) { + if (Compress) + return (LHS.Source.TheDef->getName().str() < + RHS.Source.TheDef->getName().str()); + else + return (LHS.Dest.TheDef->getName().str() < + RHS.Dest.TheDef->getName().str()); + }); + + // A list of MCOperandPredicates for all operands in use, and the reverse map. + std::vector MCOpPredicates; + DenseMap MCOpPredicateMap; + + std::string F; + std::string FH; + raw_string_ostream Func(F); + raw_string_ostream FuncH(FH); + bool NeedMRI = false; + + if (Compress) + o << "\n#ifdef GEN_COMPRESS_INSTR\n" + << "#undef GEN_COMPRESS_INSTR\n\n"; + else + o << "\n#ifdef GEN_UNCOMPRESS_INSTR\n" + << "#undef GEN_UNCOMPRESS_INSTR\n\n"; + + if (Compress) { + FuncH << "static bool compressInst(MCInst& OutInst,\n"; + FuncH.indent(25) << "const MCInst &MI,\n"; + FuncH.indent(25) << "const MCSubtargetInfo &STI,\n"; + FuncH.indent(25) << "MCContext &Context) {\n"; + } else { + FuncH << "static bool uncompressInst(MCInst& OutInst,\n"; + FuncH.indent(27) << "const MCInst &MI,\n"; + FuncH.indent(27) << "const MCRegisterInfo &MRI,\n"; + FuncH.indent(27) << "const MCSubtargetInfo &STI) {\n"; + } + + if (CompressPatterns.empty()) { + o << FuncH.str(); + o.indent(2) << "return false;\n}\n"; + if (Compress) + o << "\n#endif //GEN_COMPRESS_INSTR\n"; + else + o << "\n#endif //GEN_UNCOMPRESS_INSTR\n\n"; + return; + } + + std::string CaseString(""); + raw_string_ostream CaseStream(CaseString); + std::string PrevOp(""); + std::string CurOp(""); + CaseStream << " switch (MI.getOpcode()) {\n"; + CaseStream << " default: return false;\n"; + + for (auto &CompressPat : CompressPatterns) { + std::string CondString; + std::string CodeString; + raw_string_ostream CondStream(CondString); + raw_string_ostream CodeStream(CodeString); + CodeGenInstruction &Source = + Compress ? CompressPat.Source : CompressPat.Dest; + CodeGenInstruction &Dest = Compress ? CompressPat.Dest : CompressPat.Source; + IndexedMap SourceOperandMap = + Compress ? CompressPat.SourceOperandMap : CompressPat.DestOperandMap; + IndexedMap &DestOperandMap = + Compress ? CompressPat.DestOperandMap : CompressPat.SourceOperandMap; + + CurOp = Source.TheDef->getName().str(); + // Check current and previous opcode to decide to continue or end a case. + if (CurOp != PrevOp) { + if (PrevOp != "") + CaseStream.indent(6) << "break;\n } // case " + PrevOp + "\n"; + CaseStream.indent(4) << "case " + Namespace + "::" + CurOp + ": {\n"; + } + + std::set FeaturesSet; + // Add CompressPat required features. + getReqFeatures(FeaturesSet, CompressPat.PatReqFeatures); + + // Add Dest instruction required features. + std::vector ReqFeatures; + std::vector RF = Dest.TheDef->getValueAsListOfDefs("Predicates"); + copy_if(RF, std::back_inserter(ReqFeatures), [](Record *R) { + return R->getValueAsBit("AssemblerMatcherPredicate"); + }); + getReqFeatures(FeaturesSet, ReqFeatures); + + // Emit checks for all required features. + for (auto &Op : FeaturesSet) { + if (Op[0] == '!') + CondStream.indent(6) << ("!STI.getFeatureBits()[" + Namespace + + "::" + Op.substr(1) + "]") + .str() + + " &&\n"; + else + CondStream.indent(6) + << ("STI.getFeatureBits()[" + Namespace + "::" + Op + "]").str() + + " &&\n"; + } + + // Start Source Inst operands validation. + unsigned OpNo = 0; + for (OpNo = 0; OpNo < Source.Operands.size(); ++OpNo) { + if (SourceOperandMap[OpNo].TiedOpIdx != -1) { + if (Source.Operands[OpNo].Rec->isSubClassOf("RegisterClass")) + CondStream.indent(6) + << "(MI.getOperand(" + << std::to_string(OpNo) + ").getReg() == MI.getOperand(" + << std::to_string(SourceOperandMap[OpNo].TiedOpIdx) + << ").getReg()) &&\n"; + else + PrintFatalError("Unexpected tied operand types!\n"); + } + // Check for fixed immediates\registers in the source instruction. + switch (SourceOperandMap[OpNo].Kind) { + case OpData::Operand: + // We don't need to do anything for source instruction operand checks. + break; + case OpData::Imm: + CondStream.indent(6) + << "(MI.getOperand(" + std::to_string(OpNo) + ").isImm()) &&\n" + + " (MI.getOperand(" + std::to_string(OpNo) + + ").getImm() == " + + std::to_string(SourceOperandMap[OpNo].Data.Imm) + ") &&\n"; + break; + case OpData::Reg: { + Record *Reg = SourceOperandMap[OpNo].Data.Reg; + CondStream.indent(6) << "(MI.getOperand(" + std::to_string(OpNo) + + ").getReg() == " + Namespace + + "::" + Reg->getName().str() + ") &&\n"; + break; + } + } + } + CodeStream.indent(6) << "// " + Dest.AsmString + "\n"; + CodeStream.indent(6) << "OutInst.setOpcode(" + Namespace + + "::" + Dest.TheDef->getName().str() + ");\n"; + OpNo = 0; + for (const auto &DestOperand : Dest.Operands) { + CodeStream.indent(6) << "// Operand: " + DestOperand.Name + "\n"; + switch (DestOperandMap[OpNo].Kind) { + case OpData::Operand: { + unsigned OpIdx = DestOperandMap[OpNo].Data.Operand; + // Check that the operand in the Source instruction fits + // the type for the Dest instruction. + if (DestOperand.Rec->isSubClassOf("RegisterClass")) { + NeedMRI = true; + // This is a register operand. Check the register class. + // Don't check register class if this is a tied operand, it was done + // for the operand its tied to. + if (DestOperand.getTiedRegister() == -1) + CondStream.indent(6) + << "(MRI.getRegClass(" + Namespace + + "::" + DestOperand.Rec->getName().str() + + "RegClassID).contains(" + "MI.getOperand(" + + std::to_string(OpIdx) + ").getReg())) &&\n"; + + CodeStream.indent(6) << "OutInst.addOperand(MI.getOperand(" + + std::to_string(OpIdx) + "));\n"; + } else { + // Handling immediate operands. + unsigned Entry = getMCOpPredicate(MCOpPredicateMap, MCOpPredicates, + DestOperand.Rec); + CondStream.indent(6) << Namespace + "ValidateMCOperand(" + + "MI.getOperand(" + std::to_string(OpIdx) + + "), STI, " + std::to_string(Entry) + + ") &&\n"; + CodeStream.indent(6) << "OutInst.addOperand(MI.getOperand(" + + std::to_string(OpIdx) + "));\n"; + } + break; + } + case OpData::Imm: { + unsigned Entry = + getMCOpPredicate(MCOpPredicateMap, MCOpPredicates, DestOperand.Rec); + CondStream.indent(6) + << Namespace + "ValidateMCOperand(" + "MCOperand::createImm(" + + std::to_string(DestOperandMap[OpNo].Data.Imm) + "), STI, " + + std::to_string(Entry) + ") &&\n"; + CodeStream.indent(6) + << "OutInst.addOperand(MCOperand::createImm(" + + std::to_string(DestOperandMap[OpNo].Data.Imm) + "));\n"; + } break; + case OpData::Reg: { + // Fixed register has been validated at pattern validation time. + Record *Reg = DestOperandMap[OpNo].Data.Reg; + CodeStream.indent(6) << "OutInst.addOperand(MCOperand::createReg(" + + Namespace + "::" + Reg->getName().str() + + "));\n"; + } break; + } + ++OpNo; + } + CaseStream << mergeCondAndCode(CondStream, CodeStream); + PrevOp = CurOp; + } + Func << CaseStream.str() << "\n"; + // Close brace for the last case. + Func.indent(4) << "} // case " + CurOp + "\n"; + Func.indent(2) << "} // switch\n"; + Func.indent(2) << "return false;\n}\n"; + + if (!MCOpPredicates.empty()) { + o << "static bool " << Namespace + << "ValidateMCOperand(const MCOperand &MCOp,\n" + << " const MCSubtargetInfo &STI,\n" + << " unsigned PredicateIndex) {\n" + << " switch (PredicateIndex) {\n" + << " default:\n" + << " llvm_unreachable(\"Unknown MCOperandPredicate kind\");\n" + << " break;\n"; + + for (unsigned i = 0; i < MCOpPredicates.size(); ++i) { + Init *MCOpPred = MCOpPredicates[i]->getValueInit("MCOperandPredicate"); + if (CodeInit *SI = dyn_cast(MCOpPred)) + o << " case " << i + 1 << ": {\n" + << " // " << MCOpPredicates[i]->getName().str() << SI->getValue() + << "\n" + << " }\n"; + else + llvm_unreachable("Unexpected MCOperandPredicate field!"); + } + o << " }\n" + << "}\n\n"; + } + + o << FuncH.str(); + if (NeedMRI && Compress) + o.indent(2) << "const MCRegisterInfo &MRI = *Context.getRegisterInfo();\n"; + o << Func.str(); + + if (Compress) + o << "\n#endif //GEN_COMPRESS_INSTR\n"; + else + o << "\n#endif //GEN_UNCOMPRESS_INSTR\n\n"; +} + +void CAHPCompressInstEmitter::run(raw_ostream &o) { + Record *CompressClass = Records.getClass("CompressPat"); + assert(CompressClass && "Compress class definition missing!"); + std::vector Insts; + for (const auto &D : Records.getDefs()) { + if (D.second->isSubClassOf(CompressClass)) + Insts.push_back(D.second.get()); + } + + // Process the CompressPat definitions, validating them as we do so. + for (unsigned i = 0, e = Insts.size(); i != e; ++i) + evaluateCompressPat(Insts[i]); + + // Emit file header. + emitSourceFileHeader("Compress instruction Source Fragment", o); + // Generate compressInst() function. + emitCompressInstEmitter(o, true); + // Generate uncompressInst() function. + emitCompressInstEmitter(o, false); +} + +namespace llvm { + +void EmitCAHPCompressInst(RecordKeeper &RK, raw_ostream &OS) { + CAHPCompressInstEmitter(RK).run(OS); +} + +} // namespace llvm diff --git a/llvm/utils/TableGen/CMakeLists.txt b/llvm/utils/TableGen/CMakeLists.txt index c88365a2b8ce..07907f62e09b 100644 --- a/llvm/utils/TableGen/CMakeLists.txt +++ b/llvm/utils/TableGen/CMakeLists.txt @@ -6,6 +6,7 @@ add_tablegen(llvm-tblgen LLVM AsmWriterInst.cpp Attributes.cpp CallingConvEmitter.cpp + CAHPCompressInstEmitter.cpp CodeEmitterGen.cpp CodeGenDAGPatterns.cpp CodeGenHwModes.cpp diff --git a/llvm/utils/TableGen/TableGen.cpp b/llvm/utils/TableGen/TableGen.cpp index c485ed2feb7a..5129feb34dfe 100644 --- a/llvm/utils/TableGen/TableGen.cpp +++ b/llvm/utils/TableGen/TableGen.cpp @@ -33,6 +33,7 @@ enum ActionType { GenDisassembler, GenPseudoLowering, GenCompressInst, + GenCAHPCompressInst, GenCallingConv, GenDAGISel, GenDFAPacketizer, @@ -86,6 +87,8 @@ namespace { "Generate pseudo instruction lowering"), clEnumValN(GenCompressInst, "gen-compress-inst-emitter", "Generate RISCV compressed instructions."), + clEnumValN(GenCAHPCompressInst, "gen-cahp-compress-inst-emitter", + "Generate CAHP compressed instructions."), clEnumValN(GenAsmMatcher, "gen-asm-matcher", "Generate assembly instruction matcher"), clEnumValN(GenDAGISel, "gen-dag-isel", @@ -175,6 +178,9 @@ bool LLVMTableGenMain(raw_ostream &OS, RecordKeeper &Records) { case GenCompressInst: EmitCompressInst(Records, OS); break; + case GenCAHPCompressInst: + EmitCAHPCompressInst(Records, OS); + break; case GenDAGISel: EmitDAGISel(Records, OS); break; diff --git a/llvm/utils/TableGen/TableGenBackends.h b/llvm/utils/TableGen/TableGenBackends.h index 135ec65c0f95..ca41bcf2810d 100644 --- a/llvm/utils/TableGen/TableGenBackends.h +++ b/llvm/utils/TableGen/TableGenBackends.h @@ -77,6 +77,7 @@ void EmitInstrInfo(RecordKeeper &RK, raw_ostream &OS); void EmitInstrDocs(RecordKeeper &RK, raw_ostream &OS); void EmitPseudoLowering(RecordKeeper &RK, raw_ostream &OS); void EmitCompressInst(RecordKeeper &RK, raw_ostream &OS); +void EmitCAHPCompressInst(RecordKeeper &RK, raw_ostream &OS); void EmitRegisterInfo(RecordKeeper &RK, raw_ostream &OS); void EmitSubtarget(RecordKeeper &RK, raw_ostream &OS); void EmitMapTable(RecordKeeper &RK, raw_ostream &OS); From c6d49a76353727a0b1620ac8f1392362c661adec Mon Sep 17 00:00:00 2001 From: Ushitora Anqou Date: Sun, 3 Nov 2019 11:31:31 +0900 Subject: [PATCH 260/289] [CAHP] Add CAHP target to Clang --- clang/lib/Basic/CMakeLists.txt | 2 +- clang/lib/Basic/Targets.cpp | 4 ++ clang/lib/Basic/Targets/CAHP.cpp | 33 +++++++++++++ clang/lib/Basic/Targets/CAHP.h | 85 ++++++++++++++++++++++++++++++++ 4 files changed, 123 insertions(+), 1 deletion(-) create mode 100644 clang/lib/Basic/Targets/CAHP.cpp create mode 100644 clang/lib/Basic/Targets/CAHP.h diff --git a/clang/lib/Basic/CMakeLists.txt b/clang/lib/Basic/CMakeLists.txt index 18dd7d61fbb4..12a12db43b6a 100644 --- a/clang/lib/Basic/CMakeLists.txt +++ b/clang/lib/Basic/CMakeLists.txt @@ -67,6 +67,7 @@ add_clang_library(clangBasic Targets/ARM.cpp Targets/AVR.cpp Targets/BPF.cpp + Targets/CAHP.cpp Targets/Hexagon.cpp Targets/Lanai.cpp Targets/Le64.cpp @@ -91,4 +92,3 @@ add_clang_library(clangBasic XRayLists.cpp ${version_inc} ) - diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp index a08e399e7270..cecd31aba1c5 100644 --- a/clang/lib/Basic/Targets.cpp +++ b/clang/lib/Basic/Targets.cpp @@ -19,6 +19,7 @@ #include "Targets/ARM.h" #include "Targets/AVR.h" #include "Targets/BPF.h" +#include "Targets/CAHP.h" #include "Targets/Hexagon.h" #include "Targets/Lanai.h" #include "Targets/Le64.h" @@ -362,6 +363,9 @@ TargetInfo *AllocateTarget(const llvm::Triple &Triple, case llvm::Triple::r600: return new AMDGPUTargetInfo(Triple, Opts); + case llvm::Triple::cahp: + return new CAHPTargetInfo(Triple, Opts); + case llvm::Triple::riscv32: // TODO: add cases for FreeBSD, NetBSD, RTEMS once tested. if (os == llvm::Triple::Linux) diff --git a/clang/lib/Basic/Targets/CAHP.cpp b/clang/lib/Basic/Targets/CAHP.cpp new file mode 100644 index 000000000000..c705c03f8d91 --- /dev/null +++ b/clang/lib/Basic/Targets/CAHP.cpp @@ -0,0 +1,33 @@ +// This file is copied and modified from The LLVM Compiler Infrastructure, which +// is distributed under the Apache License v2.0 with LLVM Exceptions (see +// LICENSE.TXT for details). This file is licensed under the same license. + +#include "CAHP.h" +#include "clang/Basic/MacroBuilder.h" +#include "llvm/ADT/StringSwitch.h" + +using namespace clang; +using namespace clang::targets; + +ArrayRef CAHPTargetInfo::getGCCRegNames() const { + static const char *const GCCRegNames[] = { + "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", + "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15"}; + return llvm::makeArrayRef(GCCRegNames); +} + +ArrayRef CAHPTargetInfo::getGCCRegAliases() const { + static const TargetInfo::GCCRegAlias GCCRegAliases[] = { + {{"ra"}, "x0"}, {{"sp"}, "x1"}, {{"fp"}, "x2"}, {{"s0"}, "x3"}, + {{"s1"}, "x4"}, {{"s2"}, "x5"}, {{"s3"}, "x6"}, {{"s4"}, "x7"}, + {{"a0"}, "x8"}, {{"a1"}, "x9"}, {{"a2"}, "x10"}, {{"a3"}, "x11"}, + {{"a4"}, "x12"}, {{"a5"}, "x13"}, {{"t0"}, "x15"}, {{"t1"}, "x15"}}; + return llvm::makeArrayRef(GCCRegAliases); +} + +void CAHPTargetInfo::getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const { + + Builder.defineMacro("__cahp__"); + Builder.defineMacro("__cahpv3__"); +} diff --git a/clang/lib/Basic/Targets/CAHP.h b/clang/lib/Basic/Targets/CAHP.h new file mode 100644 index 000000000000..759f04380961 --- /dev/null +++ b/clang/lib/Basic/Targets/CAHP.h @@ -0,0 +1,85 @@ +// This file is copied and modified from The LLVM Compiler Infrastructure, which +// is distributed under the Apache License v2.0 with LLVM Exceptions (see +// LICENSE.TXT for details). This file is licensed under the same license. + +#ifndef LLVM_CLANG_LIB_BASIC_TARGETS_CAHP_H +#define LLVM_CLANG_LIB_BASIC_TARGETS_CAHP_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 { + +// CAHP Target +class LLVM_LIBRARY_VISIBILITY CAHPTargetInfo : public TargetInfo { +protected: + std::string ABI; + +public: + CAHPTargetInfo(const llvm::Triple &Triple, const TargetOptions &) + : TargetInfo(Triple) { + TLSSupported = false; + PointerWidth = 16; + PointerAlign = 16; + IntWidth = 16; + IntAlign = 16; + LongWidth = 32; + LongAlign = 16; + LongLongWidth = 32; + LongLongAlign = 16; + SuitableAlign = 16; + DefaultAlignForAttributeAligned = 16; + HalfWidth = 8; + HalfAlign = 8; + FloatWidth = 32; + FloatAlign = 16; + DoubleWidth = 32; + DoubleAlign = 16; + DoubleFormat = &llvm::APFloat::IEEEsingle(); + LongDoubleWidth = 32; + LongDoubleAlign = 16; + LongDoubleFormat = &llvm::APFloat::IEEEsingle(); + SizeType = UnsignedInt; + PtrDiffType = SignedInt; + IntPtrType = SignedInt; + Char16Type = UnsignedInt; + WIntType = SignedInt; + Char32Type = UnsignedLong; + SigAtomicType = SignedChar; + + resetDataLayout("e" // Little endian + "-m:e" // ELF name manging + "-p:16:16" // 16-bit pointers, 16 bit aligned + "-i16:16" // 16 bit integers, 16 bit aligned + "-n16" // 16 bit native integer width + "-S16" // 16 bit natural stack alignment + ); + } + + void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const override; + + ArrayRef getTargetBuiltins() const override { return None; } + + BuiltinVaListKind getBuiltinVaListKind() const override { + return TargetInfo::VoidPtrBuiltinVaList; + } + + const char *getClobbers() const override { return ""; } + + ArrayRef getGCCRegNames() const override; + + ArrayRef getGCCRegAliases() const override; + + bool validateAsmConstraint(const char *&Name, + TargetInfo::ConstraintInfo &Info) const override { + return false; + } +}; +} // namespace targets +} // namespace clang + +#endif // LLVM_CLANG_LIB_BASIC_TARGETS_CAHP_H From 43f204d61d0fed48cf5746eeaf1f20f062c4f88c Mon Sep 17 00:00:00 2001 From: Ushitora Anqou Date: Sun, 3 Nov 2019 16:31:00 +0900 Subject: [PATCH 261/289] [CAHP] Add Clang driver --- clang/lib/Driver/CMakeLists.txt | 1 + clang/lib/Driver/Driver.cpp | 4 ++ clang/lib/Driver/ToolChains/CAHP.cpp | 40 +++++++++++++++++++ clang/lib/Driver/ToolChains/CAHP.h | 60 ++++++++++++++++++++++++++++ 4 files changed, 105 insertions(+) create mode 100644 clang/lib/Driver/ToolChains/CAHP.cpp create mode 100644 clang/lib/Driver/ToolChains/CAHP.h diff --git a/clang/lib/Driver/CMakeLists.txt b/clang/lib/Driver/CMakeLists.txt index d90c0ff43607..d2dc61c85e5b 100644 --- a/clang/lib/Driver/CMakeLists.txt +++ b/clang/lib/Driver/CMakeLists.txt @@ -34,6 +34,7 @@ add_clang_library(clangDriver ToolChains/AMDGPU.cpp ToolChains/AVR.cpp ToolChains/BareMetal.cpp + ToolChains/CAHP.cpp ToolChains/Clang.cpp ToolChains/CloudABI.cpp ToolChains/CommonArgs.cpp diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index a9a273529b46..3b0938d83253 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -12,6 +12,7 @@ #include "ToolChains/AVR.h" #include "ToolChains/Ananas.h" #include "ToolChains/BareMetal.h" +#include "ToolChains/CAHP.h" #include "ToolChains/Clang.h" #include "ToolChains/CloudABI.h" #include "ToolChains/Contiki.h" @@ -4720,6 +4721,9 @@ const ToolChain &Driver::getToolChain(const ArgList &Args, TC = llvm::make_unique(*this, Target, Args); break; + case llvm::Triple::cahp: + TC = llvm::make_unique(*this, Target, Args); + break; case llvm::Triple::riscv32: case llvm::Triple::riscv64: TC = llvm::make_unique(*this, Target, Args); diff --git a/clang/lib/Driver/ToolChains/CAHP.cpp b/clang/lib/Driver/ToolChains/CAHP.cpp new file mode 100644 index 000000000000..7855b710a431 --- /dev/null +++ b/clang/lib/Driver/ToolChains/CAHP.cpp @@ -0,0 +1,40 @@ +#include "CAHP.h" +#include "CommonArgs.h" +#include "InputInfo.h" +#include "clang/Driver/Compilation.h" +#include "clang/Driver/Options.h" +#include "llvm/Option/ArgList.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/raw_ostream.h" + +using namespace clang::driver; +using namespace clang::driver::toolchains; +using namespace clang::driver::tools; +using namespace clang; +using namespace llvm::opt; + +Tool *CAHPToolChain::buildLinker() const { + return new tools::CAHP::Linker(*this); +} + +void CAHP::Linker::ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, + const InputInfoList &Inputs, + const ArgList &Args, + const char *LinkingOutput) const { + const ToolChain &ToolChain = getToolChain(); + ArgStringList CmdArgs; + + std::string Linker = getToolChain().GetProgramPath(getShortName()); + + AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA); + + // The beginning of .text section should be placed address 0. + CmdArgs.push_back("-Ttext=0"); + + CmdArgs.push_back("-o"); + CmdArgs.push_back(Output.getFilename()); + C.addCommand(llvm::make_unique(JA, *this, Args.MakeArgString(Linker), + CmdArgs, Inputs)); +} diff --git a/clang/lib/Driver/ToolChains/CAHP.h b/clang/lib/Driver/ToolChains/CAHP.h new file mode 100644 index 000000000000..ad5b89cea9d7 --- /dev/null +++ b/clang/lib/Driver/ToolChains/CAHP.h @@ -0,0 +1,60 @@ +// This file is copied and modified from The LLVM Compiler Infrastructure, which +// is distributed under the Apache License v2.0 with LLVM Exceptions (see +// LICENSE.TXT for details). This file is licensed under the same license. + +#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_CAHP_H +#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_CAHP_H + +#include "Gnu.h" +#include "clang/Driver/ToolChain.h" + +namespace clang { +namespace driver { +namespace toolchains { + +class LLVM_LIBRARY_VISIBILITY CAHPToolChain : public Generic_ELF { +public: + CAHPToolChain(const Driver &D, const llvm::Triple &Triple, + const llvm::opt::ArgList &Args) + : Generic_ELF(D, Triple, Args) {} + + bool IsIntegratedAssemblerDefault() const override { return true; } + + // No support for finding a C++ standard library yet. + void addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const override { + } + void + addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const override {} + + // No default include flags. + void + AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const override {} + +protected: + Tool *buildLinker() const override; +}; + +} // end namespace toolchains + + +namespace tools { +namespace CAHP { +class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool { +public: + Linker(const ToolChain &TC) : GnuTool("CAHP::Linker", "ld.lld", TC) {} + bool hasIntegratedCPP() const override { return false; } + bool isLinkJob() const override { return true; } + void ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, const InputInfoList &Inputs, + const llvm::opt::ArgList &TCArgs, + const char *LinkingOutput) const override; +}; +} // namespace CAHP +} // namespace tools +} // end namespace driver +} // end namespace clang + +#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_CAHP_H From 3ffccb9e9623518e7128170172158cc01927c259 Mon Sep 17 00:00:00 2001 From: Ushitora Anqou Date: Sun, 3 Nov 2019 16:41:25 +0900 Subject: [PATCH 262/289] [CAHP] Enable frame pointer elimination when optmization is enabled --- clang/lib/Driver/ToolChains/Clang.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index dd461a1976d9..363bf79c0a3f 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -523,6 +523,7 @@ static bool useFramePointerForTargetByDefault(const ArgList &Args, // XCore never wants frame pointers, regardless of OS. // WebAssembly never wants frame pointers. return false; + case llvm::Triple::cahp: case llvm::Triple::ppc: case llvm::Triple::ppc64: case llvm::Triple::ppc64le: From eebc5875f9d8bf77253e92bc4e0d4fc7f4ff1eef Mon Sep 17 00:00:00 2001 From: Ushitora Anqou Date: Wed, 6 Nov 2019 14:52:15 +0900 Subject: [PATCH 263/289] [CAHP] Add support for branch analysis --- llvm/lib/Target/CAHP/CAHPInstrInfo.cpp | 178 +++++++++++++++++++++++ llvm/lib/Target/CAHP/CAHPInstrInfo.h | 16 ++ llvm/test/CodeGen/CAHP/analyze-branch.ll | 85 +++++++++++ llvm/test/CodeGen/CAHP/branch.ll | 76 +++++----- llvm/test/CodeGen/CAHP/i16-icmp.ll | 101 ++++++------- llvm/test/CodeGen/CAHP/jumptable.ll | 63 ++++---- llvm/test/CodeGen/CAHP/select-cc.ll | 62 +++++--- 7 files changed, 433 insertions(+), 148 deletions(-) create mode 100644 llvm/test/CodeGen/CAHP/analyze-branch.ll diff --git a/llvm/lib/Target/CAHP/CAHPInstrInfo.cpp b/llvm/lib/Target/CAHP/CAHPInstrInfo.cpp index fd38d3d0b2d8..f05de337c603 100644 --- a/llvm/lib/Target/CAHP/CAHPInstrInfo.cpp +++ b/llvm/lib/Target/CAHP/CAHPInstrInfo.cpp @@ -79,3 +79,181 @@ void CAHPInstrInfo::movImm16(MachineBasicBlock &MBB, .addImm(Lo10) .setMIFlag(Flag); } + +// The contents of values added to Cond are not examined outside of +// CAHPInstrInfo, giving us flexibility in what to push to it. For CAHP, we +// push BranchOpcode, Reg1, Reg2. +static void parseCondBranch(MachineInstr &LastInst, MachineBasicBlock *&Target, + SmallVectorImpl &Cond) { + // Block ends with fall-through condbranch. + assert(LastInst.getDesc().isConditionalBranch() && + "Unknown conditional branch"); + Target = LastInst.getOperand(2).getMBB(); + Cond.push_back(MachineOperand::CreateImm(LastInst.getOpcode())); + Cond.push_back(LastInst.getOperand(0)); + Cond.push_back(LastInst.getOperand(1)); +} + +bool CAHPInstrInfo::analyzeBranch(MachineBasicBlock &MBB, + MachineBasicBlock *&TBB, + MachineBasicBlock *&FBB, + SmallVectorImpl &Cond, + bool AllowModify) const { + TBB = FBB = nullptr; + Cond.clear(); + + // If the block has no terminators, it just falls into the block after it. + MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr(); + if (I == MBB.end() || !isUnpredicatedTerminator(*I)) + return false; + + // Count the number of terminators and find the first unconditional or + // indirect branch. + MachineBasicBlock::iterator FirstUncondOrIndirectBr = MBB.end(); + int NumTerminators = 0; + for (auto J = I.getReverse(); J != MBB.rend() && isUnpredicatedTerminator(*J); + J++) { + NumTerminators++; + if (J->getDesc().isUnconditionalBranch() || + J->getDesc().isIndirectBranch()) { + FirstUncondOrIndirectBr = J.getReverse(); + } + } + + // If AllowModify is true, we can erase any terminators after + // FirstUncondOrIndirectBR. + if (AllowModify && FirstUncondOrIndirectBr != MBB.end()) { + while (std::next(FirstUncondOrIndirectBr) != MBB.end()) { + std::next(FirstUncondOrIndirectBr)->eraseFromParent(); + NumTerminators--; + } + I = FirstUncondOrIndirectBr; + } + + // We can't handle blocks that end in an indirect branch. + if (I->getDesc().isIndirectBranch()) + return true; + + // We can't handle blocks with more than 2 terminators. + if (NumTerminators > 2) + return true; + + // Handle a single unconditional branch. + if (NumTerminators == 1 && I->getDesc().isUnconditionalBranch()) { + TBB = I->getOperand(0).getMBB(); + return false; + } + + // Handle a single conditional branch. + if (NumTerminators == 1 && I->getDesc().isConditionalBranch()) { + parseCondBranch(*I, TBB, Cond); + return false; + } + + // Handle a conditional branch followed by an unconditional branch. + if (NumTerminators == 2 && std::prev(I)->getDesc().isConditionalBranch() && + I->getDesc().isUnconditionalBranch()) { + parseCondBranch(*std::prev(I), TBB, Cond); + FBB = I->getOperand(0).getMBB(); + return false; + } + + // Otherwise, we can't handle this. + return true; +} + +unsigned CAHPInstrInfo::removeBranch(MachineBasicBlock &MBB, + int *BytesRemoved) const { + assert(!BytesRemoved && "Code size not handled"); + MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr(); + if (I == MBB.end()) + return 0; + + if (!I->getDesc().isUnconditionalBranch() && + !I->getDesc().isConditionalBranch()) + return 0; + + // Remove the branch. + I->eraseFromParent(); + + I = MBB.end(); + + if (I == MBB.begin()) + return 1; + --I; + if (!I->getDesc().isConditionalBranch()) + return 1; + + // Remove the branch. + I->eraseFromParent(); + return 2; +} + +// Inserts a branch into the end of the specific MachineBasicBlock, returning +// the number of instructions inserted. +unsigned CAHPInstrInfo::insertBranch( + MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB, + ArrayRef Cond, const DebugLoc &DL, int *BytesAdded) const { + assert(!BytesAdded && "Code size not handled."); + + // Shouldn't be a fall through. + assert(TBB && "InsertBranch must not be told to insert a fallthrough"); + assert((Cond.size() == 3 || Cond.size() == 0) && + "CAHP branch conditions have two components!"); + + // Unconditional branch. + if (Cond.empty()) { + BuildMI(&MBB, DL, get(CAHP::JS)).addMBB(TBB); + return 1; + } + + // Either a one or two-way conditional branch. + unsigned Opc = Cond[0].getImm(); + BuildMI(&MBB, DL, get(Opc)).add(Cond[1]).add(Cond[2]).addMBB(TBB); + + // One-way conditional branch. + if (!FBB) + return 1; + + // Two-way conditional branch. + BuildMI(&MBB, DL, get(CAHP::JS)).addMBB(FBB); + return 2; +} + +bool CAHPInstrInfo::reverseBranchCondition( + SmallVectorImpl &Cond) const { + assert((Cond.size() == 3) && "Invalid branch condition!"); + + bool ShouldSwap = false; + switch (Cond[0].getImm()) { + case CAHP::BEQ: + Cond[0].setImm(CAHP::BNE); + break; + case CAHP::BNE: + Cond[0].setImm(CAHP::BEQ); + break; + case CAHP::BLT: + Cond[0].setImm(CAHP::BLE); + ShouldSwap = true; + break; + case CAHP::BLE: + Cond[0].setImm(CAHP::BLT); + ShouldSwap = true; + break; + case CAHP::BLTU: + Cond[0].setImm(CAHP::BLEU); + ShouldSwap = true; + break; + case CAHP::BLEU: + Cond[0].setImm(CAHP::BLTU); + ShouldSwap = true; + break; + } + + if (ShouldSwap) { + using std::swap; + swap(Cond[1], Cond[2]); + } + + return false; +} diff --git a/llvm/lib/Target/CAHP/CAHPInstrInfo.h b/llvm/lib/Target/CAHP/CAHPInstrInfo.h index c8e9099ead8c..ac6c3eebca22 100644 --- a/llvm/lib/Target/CAHP/CAHPInstrInfo.h +++ b/llvm/lib/Target/CAHP/CAHPInstrInfo.h @@ -34,6 +34,22 @@ class CAHPInstrInfo : public CAHPGenInstrInfo { void movImm16(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, unsigned DstReg, uint64_t Val, MachineInstr::MIFlag Flag = MachineInstr::NoFlags) const; + + bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, + MachineBasicBlock *&FBB, + SmallVectorImpl &Cond, + bool AllowModify) const override; + + unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, + MachineBasicBlock *FBB, ArrayRef Cond, + const DebugLoc &dl, + int *BytesAdded = nullptr) const override; + + unsigned removeBranch(MachineBasicBlock &MBB, + int *BytesRemoved = nullptr) const override; + + bool + reverseBranchCondition(SmallVectorImpl &Cond) const override; }; } // namespace llvm diff --git a/llvm/test/CodeGen/CAHP/analyze-branch.ll b/llvm/test/CodeGen/CAHP/analyze-branch.ll new file mode 100644 index 000000000000..61c0e556a38d --- /dev/null +++ b/llvm/test/CodeGen/CAHP/analyze-branch.ll @@ -0,0 +1,85 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=cahp -verify-machineinstrs < %s \ +; RUN: | FileCheck -check-prefix=CAHP %s + +; This test checks that LLVM can do basic stripping and reapplying of branches +; to basic blocks. + +declare void @test_true() +declare void @test_false() + +; !0 corresponds to a branch being taken, !1 to not being takne. +!0 = !{!"branch_weights", i32 64, i32 4} +!1 = !{!"branch_weights", i32 4, i32 64} + +define void @test_bcc_fallthrough_taken(i16 %in) nounwind { +; CAHP-LABEL: test_bcc_fallthrough_taken: +; CAHP: # %bb.0: +; CAHP-NEXT: addi2 sp, -2 +; CAHP-NEXT: swsp ra, 0(sp) +; CAHP-NEXT: li a1, 42 +; CAHP-NEXT: bne a0, a1, .LBB0_3 +; CAHP-NEXT:# %bb.1: # %true +; CAHP-NEXT: lui a0, %hi(test_true) +; CAHP-NEXT: addi a0, a0, %lo(test_true) +; CAHP-NEXT:.LBB0_2: # %true +; CAHP-NEXT: jalr a0 +; CAHP-NEXT: lwsp ra, 0(sp) +; CAHP-NEXT: addi2 sp, 2 +; CAHP-NEXT: jr ra +; CAHP-NEXT:.LBB0_3: # %false +; CAHP-NEXT: lui a0, %hi(test_false) +; CAHP-NEXT: addi a0, a0, %lo(test_false) +; CAHP-NEXT: js .LBB0_2 + %tst = icmp eq i16 %in, 42 + br i1 %tst, label %true, label %false, !prof !0 + +; Expected layout order is: Entry, TrueBlock, FalseBlock +; Entry->TrueBlock is the common path, which should be taken whenever the +; conditional branch is false. + +true: + call void @test_true() + ret void + +false: + call void @test_false() + ret void +} + +define void @test_bcc_fallthrough_nottaken(i16 %in) nounwind { +; CAHP-LABEL: test_bcc_fallthrough_nottaken: +; CAHP: # %bb.0: +; CAHP-NEXT: addi2 sp, -2 +; CAHP-NEXT: swsp ra, 0(sp) +; CAHP-NEXT: li a1, 42 +; CAHP-NEXT: beq a0, a1, .LBB1_1 +; CAHP-NEXT:# %bb.3: # %false +; CAHP-NEXT: lui a0, %hi(test_false) +; CAHP-NEXT: addi a0, a0, %lo(test_false) +; CAHP-NEXT:.LBB1_2: # %true +; CAHP-NEXT: jalr a0 +; CAHP-NEXT: lwsp ra, 0(sp) +; CAHP-NEXT: addi2 sp, 2 +; CAHP-NEXT: jr ra +; CAHP-NEXT:.LBB1_1: # %true +; CAHP-NEXT: lui a0, %hi(test_true) +; CAHP-NEXT: addi a0, a0, %lo(test_true) +; CAHP-NEXT: js .LBB1_2 +%tst = icmp eq i16 %in, 42 +br i1 %tst, label %true, label %false, !prof !1 + +; Expected layout order is: Entry, FalseBlock, TrueBlock +; Entry->FalseBlock is the common path, which should be taken whenever the +; conditional branch is false + +true: + call void @test_true() + ret void + +false: + call void @test_false() + ret void +} + +; TODO: how can we expand the coverage of the branch analysis functions? diff --git a/llvm/test/CodeGen/CAHP/branch.ll b/llvm/test/CodeGen/CAHP/branch.ll index d50d8a79a7f9..27c897e8462f 100644 --- a/llvm/test/CodeGen/CAHP/branch.ll +++ b/llvm/test/CodeGen/CAHP/branch.ll @@ -5,49 +5,39 @@ define void @foo(i16 %a, i16 *%b, i1 %c) { ; CAHP-LABEL: foo: ; CAHP: # %bb.0: -; CAHP-NEXT: lw a2, 0(a1) -; CAHP-NEXT: beq a2, a0, .LBB0_11 -; CAHP-NEXT: js .LBB0_1 -; CAHP-NEXT:.LBB0_1: -; CAHP-NEXT: lw a2, 0(a1) -; CAHP-NEXT: bne a2, a0, .LBB0_11 -; CAHP-NEXT: js .LBB0_2 -; CAHP-NEXT:.LBB0_2: -; CAHP-NEXT: lw a2, 0(a1) -; CAHP-NEXT: blt a2, a0, .LBB0_11 -; CAHP-NEXT: js .LBB0_3 -; CAHP-NEXT:.LBB0_3: -; CAHP-NEXT: lw a2, 0(a1) -; CAHP-NEXT: ble a2, a0, .LBB0_11 -; CAHP-NEXT: js .LBB0_4 -; CAHP-NEXT:.LBB0_4: -; CAHP-NEXT: lw a2, 0(a1) -; CAHP-NEXT: bltu a2, a0, .LBB0_11 -; CAHP-NEXT: js .LBB0_5 -; CAHP-NEXT:.LBB0_5: -; CAHP-NEXT: lw a2, 0(a1) -; CAHP-NEXT: bleu a2, a0, .LBB0_11 -; CAHP-NEXT: js .LBB0_6 -; CAHP-NEXT:.LBB0_6: -; CAHP-NEXT: lw a2, 0(a1) -; CAHP-NEXT: blt a0, a2, .LBB0_11 -; CAHP-NEXT: js .LBB0_7 -; CAHP-NEXT:.LBB0_7: -; CAHP-NEXT: lw a2, 0(a1) -; CAHP-NEXT: ble a0, a2, .LBB0_11 -; CAHP-NEXT: js .LBB0_8 -; CAHP-NEXT:.LBB0_8: -; CAHP-NEXT: lw a2, 0(a1) -; CAHP-NEXT: bltu a0, a2, .LBB0_11 -; CAHP-NEXT: js .LBB0_9 -; CAHP-NEXT:.LBB0_9: -; CAHP-NEXT: lw a2, 0(a1) -; CAHP-NEXT: bleu a0, a2, .LBB0_11 -; CAHP-NEXT: js .LBB0_10 -; CAHP-NEXT:.LBB0_10: -; CAHP-NEXT: lw a0, 0(a1) -; CAHP-NEXT:.LBB0_11: # %end -; CAHP-NEXT: jr ra +; CAHP-NEXT: lw a2, 0(a1) +; CAHP-NEXT: beq a2, a0, .LBB0_11 +; CAHP-NEXT: # %bb.1: # %test2 +; CAHP-NEXT: lw a2, 0(a1) +; CAHP-NEXT: bne a2, a0, .LBB0_11 +; CAHP-NEXT: # %bb.2: # %test3 +; CAHP-NEXT: lw a2, 0(a1) +; CAHP-NEXT: blt a2, a0, .LBB0_11 +; CAHP-NEXT: # %bb.3: # %test4 +; CAHP-NEXT: lw a2, 0(a1) +; CAHP-NEXT: ble a2, a0, .LBB0_11 +; CAHP-NEXT: # %bb.4: # %test5 +; CAHP-NEXT: lw a2, 0(a1) +; CAHP-NEXT: bltu a2, a0, .LBB0_11 +; CAHP-NEXT: # %bb.5: # %test6 +; CAHP-NEXT: lw a2, 0(a1) +; CAHP-NEXT: bleu a2, a0, .LBB0_11 +; CAHP-NEXT: # %bb.6: # %test7 +; CAHP-NEXT: lw a2, 0(a1) +; CAHP-NEXT: blt a0, a2, .LBB0_11 +; CAHP-NEXT: # %bb.7: # %test8 +; CAHP-NEXT: lw a2, 0(a1) +; CAHP-NEXT: ble a0, a2, .LBB0_11 +; CAHP-NEXT: # %bb.8: # %test9 +; CAHP-NEXT: lw a2, 0(a1) +; CAHP-NEXT: bltu a0, a2, .LBB0_11 +; CAHP-NEXT: # %bb.9: # %test10 +; CAHP-NEXT: lw a2, 0(a1) +; CAHP-NEXT: bleu a0, a2, .LBB0_11 +; CAHP-NEXT: # %bb.10: # %test12 +; CAHP-NEXT: lw a0, 0(a1) +; CAHP-NEXT: .LBB0_11: # %end +; CAHP-NEXT: jr ra %val1 = load volatile i16, i16* %b %tst1 = icmp eq i16 %val1, %a diff --git a/llvm/test/CodeGen/CAHP/i16-icmp.ll b/llvm/test/CodeGen/CAHP/i16-icmp.ll index 912618a39b61..4e57d3c95a7a 100644 --- a/llvm/test/CodeGen/CAHP/i16-icmp.ll +++ b/llvm/test/CodeGen/CAHP/i16-icmp.ll @@ -8,12 +8,12 @@ define i16 @icmp_eq(i16 %a, i16 %b) nounwind { ; CAHP-LABEL: icmp_eq: ; CAHP: # %bb.0: -; CAHP-NEXT: mov a2, a0 -; CAHP-NEXT: lsi a0, 1 -; CAHP-NEXT: beq a2, a1, .LBB0_2 -; CAHP-NEXT:# %bb.1: +; CAHP-NEXT: beq a0, a1, .LBB0_1 +; CAHP-NEXT:# %bb.2: ; CAHP-NEXT: lsi a0, 0 -; CAHP-NEXT:.LBB0_2: +; CAHP-NEXT: jr ra +; CAHP-NEXT:.LBB0_1: +; CAHP-NEXT: lsi a0, 1 ; CAHP-NEXT: jr ra %1 = icmp eq i16 %a, %b @@ -24,12 +24,12 @@ define i16 @icmp_eq(i16 %a, i16 %b) nounwind { define i16 @icmp_ne(i16 %a, i16 %b) nounwind { ; CAHP-LABEL: icmp_ne: ; CAHP: # %bb.0: -; CAHP-NEXT: mov a2, a0 -; CAHP-NEXT: lsi a0, 1 -; CAHP-NEXT: bne a2, a1, .LBB1_2 -; CAHP-NEXT:# %bb.1: +; CAHP-NEXT: bne a0, a1, .LBB1_1 +; CAHP-NEXT:# %bb.2: ; CAHP-NEXT: lsi a0, 0 -; CAHP-NEXT:.LBB1_2: +; CAHP-NEXT: jr ra +; CAHP-NEXT:.LBB1_1: +; CAHP-NEXT: lsi a0, 1 ; CAHP-NEXT: jr ra %1 = icmp ne i16 %a, %b @@ -40,13 +40,14 @@ define i16 @icmp_ne(i16 %a, i16 %b) nounwind { define i16 @icmp_ugt(i16 %a, i16 %b) nounwind { ; CAHP-LABEL: icmp_ugt: ; CAHP: # %bb.0: -; CAHP-NEXT: mov a2, a0 -; CAHP-NEXT: lsi a0, 1 -; CAHP-NEXT: bltu a1, a2, .LBB2_2 -; CAHP-NEXT:# %bb.1: +; CAHP-NEXT: bltu a1, a0, .LBB2_1 +; CAHP-NEXT:# %bb.2: ; CAHP-NEXT: lsi a0, 0 -; CAHP-NEXT:.LBB2_2: ; CAHP-NEXT: jr ra +; CAHP-NEXT:.LBB2_1: +; CAHP-NEXT: lsi a0, 1 +; CAHP-NEXT: jr ra + %1 = icmp ugt i16 %a, %b %2 = zext i1 %1 to i16 ret i16 %2 @@ -55,12 +56,12 @@ define i16 @icmp_ugt(i16 %a, i16 %b) nounwind { define i16 @icmp_uge(i16 %a, i16 %b) nounwind { ; CAHP-LABEL: icmp_uge: ; CAHP: # %bb.0: -; CAHP-NEXT: mov a2, a0 -; CAHP-NEXT: lsi a0, 1 -; CAHP-NEXT: bleu a1, a2, .LBB3_2 -; CAHP-NEXT:# %bb.1: +; CAHP-NEXT: bleu a1, a0, .LBB3_1 +; CAHP-NEXT:# %bb.2: ; CAHP-NEXT: lsi a0, 0 -; CAHP-NEXT:.LBB3_2: +; CAHP-NEXT: jr ra +; CAHP-NEXT:.LBB3_1: +; CAHP-NEXT: lsi a0, 1 ; CAHP-NEXT: jr ra %1 = icmp uge i16 %a, %b @@ -71,12 +72,12 @@ define i16 @icmp_uge(i16 %a, i16 %b) nounwind { define i16 @icmp_ult(i16 %a, i16 %b) nounwind { ; CAHP-LABEL: icmp_ult: ; CAHP: # %bb.0: -; CAHP-NEXT: mov a2, a0 -; CAHP-NEXT: lsi a0, 1 -; CAHP-NEXT: bltu a2, a1, .LBB4_2 -; CAHP-NEXT:# %bb.1: +; CAHP-NEXT: bltu a0, a1, .LBB4_1 +; CAHP-NEXT:# %bb.2: ; CAHP-NEXT: lsi a0, 0 -; CAHP-NEXT:.LBB4_2: +; CAHP-NEXT: jr ra +; CAHP-NEXT:.LBB4_1: +; CAHP-NEXT: lsi a0, 1 ; CAHP-NEXT: jr ra %1 = icmp ult i16 %a, %b @@ -87,12 +88,12 @@ define i16 @icmp_ult(i16 %a, i16 %b) nounwind { define i16 @icmp_ule(i16 %a, i16 %b) nounwind { ; CAHP-LABEL: icmp_ule: ; CAHP: # %bb.0: -; CAHP-NEXT: mov a2, a0 -; CAHP-NEXT: lsi a0, 1 -; CAHP-NEXT: bleu a2, a1, .LBB5_2 -; CAHP-NEXT:# %bb.1: +; CAHP-NEXT: bleu a0, a1, .LBB5_1 +; CAHP-NEXT:# %bb.2: ; CAHP-NEXT: lsi a0, 0 -; CAHP-NEXT:.LBB5_2: +; CAHP-NEXT: jr ra +; CAHP-NEXT:.LBB5_1: +; CAHP-NEXT: lsi a0, 1 ; CAHP-NEXT: jr ra %1 = icmp ule i16 %a, %b @@ -103,12 +104,12 @@ define i16 @icmp_ule(i16 %a, i16 %b) nounwind { define i16 @icmp_sgt(i16 %a, i16 %b) nounwind { ; CAHP-LABEL: icmp_sgt: ; CAHP: # %bb.0: -; CAHP-NEXT: mov a2, a0 -; CAHP-NEXT: lsi a0, 1 -; CAHP-NEXT: blt a1, a2, .LBB6_2 -; CAHP-NEXT:# %bb.1: +; CAHP-NEXT: blt a1, a0, .LBB6_1 +; CAHP-NEXT:# %bb.2: ; CAHP-NEXT: lsi a0, 0 -; CAHP-NEXT:.LBB6_2: +; CAHP-NEXT: jr ra +; CAHP-NEXT:.LBB6_1: +; CAHP-NEXT: lsi a0, 1 ; CAHP-NEXT: jr ra %1 = icmp sgt i16 %a, %b @@ -119,12 +120,12 @@ define i16 @icmp_sgt(i16 %a, i16 %b) nounwind { define i16 @icmp_sge(i16 %a, i16 %b) nounwind { ; CAHP-LABEL: icmp_sge: ; CAHP: # %bb.0: -; CAHP-NEXT: mov a2, a0 -; CAHP-NEXT: lsi a0, 1 -; CAHP-NEXT: ble a1, a2, .LBB7_2 -; CAHP-NEXT:# %bb.1: +; CAHP-NEXT: ble a1, a0, .LBB7_1 +; CAHP-NEXT:# %bb.2: ; CAHP-NEXT: lsi a0, 0 -; CAHP-NEXT:.LBB7_2: +; CAHP-NEXT: jr ra +; CAHP-NEXT:.LBB7_1: +; CAHP-NEXT: lsi a0, 1 ; CAHP-NEXT: jr ra %1 = icmp sge i16 %a, %b @@ -135,12 +136,12 @@ define i16 @icmp_sge(i16 %a, i16 %b) nounwind { define i16 @icmp_slt(i16 %a, i16 %b) nounwind { ; CAHP-LABEL: icmp_slt: ; CAHP: # %bb.0: -; CAHP-NEXT: mov a2, a0 -; CAHP-NEXT: lsi a0, 1 -; CAHP-NEXT: blt a2, a1, .LBB8_2 -; CAHP-NEXT:# %bb.1: +; CAHP-NEXT: blt a0, a1, .LBB8_1 +; CAHP-NEXT:# %bb.2: ; CAHP-NEXT: lsi a0, 0 -; CAHP-NEXT:.LBB8_2: +; CAHP-NEXT: jr ra +; CAHP-NEXT:.LBB8_1: +; CAHP-NEXT: lsi a0, 1 ; CAHP-NEXT: jr ra %1 = icmp slt i16 %a, %b @@ -151,12 +152,12 @@ define i16 @icmp_slt(i16 %a, i16 %b) nounwind { define i16 @icmp_sle(i16 %a, i16 %b) nounwind { ; CAHP-LABEL: icmp_sle: ; CAHP: # %bb.0: -; CAHP-NEXT: mov a2, a0 -; CAHP-NEXT: lsi a0, 1 -; CAHP-NEXT: ble a2, a1, .LBB9_2 -; CAHP-NEXT:# %bb.1: +; CAHP-NEXT: ble a0, a1, .LBB9_1 +; CAHP-NEXT:# %bb.2: ; CAHP-NEXT: lsi a0, 0 -; CAHP-NEXT:.LBB9_2: +; CAHP-NEXT: jr ra +; CAHP-NEXT:.LBB9_1: +; CAHP-NEXT: lsi a0, 1 ; CAHP-NEXT: jr ra %1 = icmp sle i16 %a, %b diff --git a/llvm/test/CodeGen/CAHP/jumptable.ll b/llvm/test/CodeGen/CAHP/jumptable.ll index 51bbe3892496..d336a5c4e14a 100644 --- a/llvm/test/CodeGen/CAHP/jumptable.ll +++ b/llvm/test/CodeGen/CAHP/jumptable.ll @@ -5,40 +5,35 @@ define void @jt(i16 %in, i16* %out) { ; CAHP-LABEL: jt: ; CAHP: # %bb.0: # %entry -; CAHP-NEXT: lsi a2, 2 -; CAHP-NEXT: blt a2, a0, .LBB0_3 -; CAHP-NEXT: js .LBB0_1 -; CAHP-NEXT:.LBB0_1: # %entry -; CAHP-NEXT: lsi a3, 1 -; CAHP-NEXT: beq a0, a3, .LBB0_5 -; CAHP-NEXT: js .LBB0_2 -; CAHP-NEXT:.LBB0_2: # %entry -; CAHP-NEXT: beq a0, a2, .LBB0_6 -; CAHP-NEXT: js .LBB0_9 -; CAHP-NEXT:.LBB0_6: # %bb2 -; CAHP-NEXT: lsi a0, 3 -; CAHP-NEXT: sw a0, 0(a1) -; CAHP-NEXT: js .LBB0_9 -; CAHP-NEXT:.LBB0_3: # %entry -; CAHP-NEXT: lsi a3, 3 -; CAHP-NEXT: beq a0, a3, .LBB0_7 -; CAHP-NEXT: js .LBB0_4 -; CAHP-NEXT:.LBB0_4: # %entry -; CAHP-NEXT: lsi a2, 4 -; CAHP-NEXT: beq a0, a2, .LBB0_8 -; CAHP-NEXT: js .LBB0_9 -; CAHP-NEXT:.LBB0_8: # %bb4 -; CAHP-NEXT: lsi a0, 1 -; CAHP-NEXT: sw a0, 0(a1) -; CAHP-NEXT:.LBB0_9: # %exit -; CAHP-NEXT: jr ra -; CAHP-NEXT:.LBB0_5: # %bb1 -; CAHP-NEXT: lsi a0, 4 -; CAHP-NEXT: sw a0, 0(a1) -; CAHP-NEXT: js .LBB0_9 -; CAHP-NEXT:.LBB0_7: # %bb3 -; CAHP-NEXT: sw a2, 0(a1) -; CAHP-NEXT: js .LBB0_9 +; CAHP-NEXT: lsi a2, 2 +; CAHP-NEXT: blt a2, a0, .LBB0_4 +; CAHP-NEXT: # %bb.1: # %entry +; CAHP-NEXT: lsi a3, 1 +; CAHP-NEXT: beq a0, a3, .LBB0_8 +; CAHP-NEXT: # %bb.2: # %entry +; CAHP-NEXT: bne a0, a2, .LBB0_10 +; CAHP-NEXT: # %bb.3: # %bb2 +; CAHP-NEXT: lsi a0, 3 +; CAHP-NEXT: sw a0, 0(a1) +; CAHP-NEXT: jr ra +; CAHP-NEXT: .LBB0_4: # %entry +; CAHP-NEXT: lsi a3, 3 +; CAHP-NEXT: beq a0, a3, .LBB0_9 +; CAHP-NEXT: # %bb.5: # %entry +; CAHP-NEXT: lsi a2, 4 +; CAHP-NEXT: bne a0, a2, .LBB0_10 +; CAHP-NEXT: # %bb.6: # %bb4 +; CAHP-NEXT: lsi a0, 1 +; CAHP-NEXT: sw a0, 0(a1) +; CAHP-NEXT: jr ra +; CAHP-NEXT: .LBB0_8: # %bb1 +; CAHP-NEXT: lsi a0, 4 +; CAHP-NEXT: sw a0, 0(a1) +; CAHP-NEXT: jr ra +; CAHP-NEXT: .LBB0_9: # %bb3 +; CAHP-NEXT: sw a2, 0(a1) +; CAHP-NEXT: .LBB0_10: # %exit +; CAHP-NEXT: jr ra entry: switch i16 %in, label %exit [ diff --git a/llvm/test/CodeGen/CAHP/select-cc.ll b/llvm/test/CodeGen/CAHP/select-cc.ll index 5e6a035fb8fd..e9ad9932efe3 100644 --- a/llvm/test/CodeGen/CAHP/select-cc.ll +++ b/llvm/test/CodeGen/CAHP/select-cc.ll @@ -6,56 +6,76 @@ define i16 @foo(i16 %a, i16 *%b) { ; CAHP-LABEL: foo: ; CAHP: # %bb.0: ; CAHP-NEXT: lw a2, 0(a1) -; CAHP-NEXT: beq a0, a2, .LBB0_2 -; CAHP-NEXT:# %bb.1: +; CAHP-NEXT: bne a0, a2, .LBB0_1 +; CAHP-NEXT:# %bb.2: +; CAHP-NEXT: lw a2, 0(a1) +; CAHP-NEXT: beq a0, a2, .LBB0_3 +; CAHP-NEXT:.LBB0_4: +; CAHP-NEXT: lw a2, 0(a1) +; CAHP-NEXT: bleu a0, a2, .LBB0_5 +; CAHP-NEXT:.LBB0_6: +; CAHP-NEXT: lw a2, 0(a1) +; CAHP-NEXT: bltu a0, a2, .LBB0_7 +; CAHP-NEXT:.LBB0_8: +; CAHP-NEXT: lw a2, 0(a1) +; CAHP-NEXT: bleu a2, a0, .LBB0_9 +; CAHP-NEXT:.LBB0_10: +; CAHP-NEXT: lw a2, 0(a1) +; CAHP-NEXT: bltu a2, a0, .LBB0_11 +; CAHP-NEXT:.LBB0_12: +; CAHP-NEXT: lw a2, 0(a1) +; CAHP-NEXT: ble a0, a2, .LBB0_13 +; CAHP-NEXT:.LBB0_14: +; CAHP-NEXT: lw a2, 0(a1) +; CAHP-NEXT: blt a0, a2, .LBB0_15 +; CAHP-NEXT:.LBB0_16: +; CAHP-NEXT: lw a2, 0(a1) +; CAHP-NEXT: ble a2, a0, .LBB0_17 +; CAHP-NEXT:.LBB0_18: +; CAHP-NEXT: lw a1, 0(a1) +; CAHP-NEXT: blt a1, a0, .LBB0_19 +; CAHP-NEXT:.LBB0_20: +; CAHP-NEXT: jr ra +; CAHP-NEXT:.LBB0_1: ; CAHP-NEXT: mov a0, a2 -; CAHP-NEXT:.LBB0_2: ; CAHP-NEXT: lw a2, 0(a1) ; CAHP-NEXT: bne a0, a2, .LBB0_4 -; CAHP-NEXT:# %bb.3: +; CAHP-NEXT:.LBB0_3: ; CAHP-NEXT: mov a0, a2 -; CAHP-NEXT:.LBB0_4: ; CAHP-NEXT: lw a2, 0(a1) ; CAHP-NEXT: bltu a2, a0, .LBB0_6 -; CAHP-NEXT:# %bb.5: +; CAHP-NEXT:.LBB0_5: ; CAHP-NEXT: mov a0, a2 -; CAHP-NEXT:.LBB0_6: ; CAHP-NEXT: lw a2, 0(a1) ; CAHP-NEXT: bleu a2, a0, .LBB0_8 -; CAHP-NEXT:# %bb.7: +; CAHP-NEXT:.LBB0_7: ; CAHP-NEXT: mov a0, a2 -; CAHP-NEXT:.LBB0_8: ; CAHP-NEXT: lw a2, 0(a1) ; CAHP-NEXT: bltu a0, a2, .LBB0_10 -; CAHP-NEXT:# %bb.9: +; CAHP-NEXT:.LBB0_9: ; CAHP-NEXT: mov a0, a2 -; CAHP-NEXT:.LBB0_10: ; CAHP-NEXT: lw a2, 0(a1) ; CAHP-NEXT: bleu a0, a2, .LBB0_12 -; CAHP-NEXT:# %bb.11: +; CAHP-NEXT:.LBB0_11: ; CAHP-NEXT: mov a0, a2 -; CAHP-NEXT:.LBB0_12: ; CAHP-NEXT: lw a2, 0(a1) ; CAHP-NEXT: blt a2, a0, .LBB0_14 -; CAHP-NEXT:# %bb.13: +; CAHP-NEXT:.LBB0_13: ; CAHP-NEXT: mov a0, a2 -; CAHP-NEXT:.LBB0_14: ; CAHP-NEXT: lw a2, 0(a1) ; CAHP-NEXT: ble a2, a0, .LBB0_16 -; CAHP-NEXT:# %bb.15: +; CAHP-NEXT:.LBB0_15: ; CAHP-NEXT: mov a0, a2 -; CAHP-NEXT:.LBB0_16: ; CAHP-NEXT: lw a2, 0(a1) ; CAHP-NEXT: blt a0, a2, .LBB0_18 -; CAHP-NEXT:# %bb.17: +; CAHP-NEXT:.LBB0_17: ; CAHP-NEXT: mov a0, a2 -; CAHP-NEXT:.LBB0_18: ; CAHP-NEXT: lw a1, 0(a1) ; CAHP-NEXT: ble a0, a1, .LBB0_20 -; CAHP-NEXT:# %bb.19: +; CAHP-NEXT:.LBB0_19: ; CAHP-NEXT: mov a0, a1 -; CAHP-NEXT:.LBB0_20: ; CAHP-NEXT: jr ra + %val1 = load volatile i16, i16* %b %tst1 = icmp eq i16 %a, %val1 %val2 = select i1 %tst1, i16 %a, i16 %val1 From 24bcafcf442f5aa90ed40815841abd90288f481b Mon Sep 17 00:00:00 2001 From: Ushitora Anqou Date: Wed, 6 Nov 2019 15:49:18 +0900 Subject: [PATCH 264/289] [CAHP] Add support for inline assembly --- llvm/lib/Target/CAHP/CAHPAsmPrinter.cpp | 45 +++++++++++++++++++ llvm/lib/Target/CAHP/CAHPISelDAGToDAG.cpp | 19 ++++++++ llvm/lib/Target/CAHP/CAHPISelLowering.cpp | 18 ++++++++ llvm/lib/Target/CAHP/CAHPISelLowering.h | 4 ++ llvm/test/CodeGen/CAHP/inline-asm.ll | 53 +++++++++++++++++++++++ 5 files changed, 139 insertions(+) create mode 100644 llvm/test/CodeGen/CAHP/inline-asm.ll diff --git a/llvm/lib/Target/CAHP/CAHPAsmPrinter.cpp b/llvm/lib/Target/CAHP/CAHPAsmPrinter.cpp index 220fc13dd9bc..25811b6e4c66 100644 --- a/llvm/lib/Target/CAHP/CAHPAsmPrinter.cpp +++ b/llvm/lib/Target/CAHP/CAHPAsmPrinter.cpp @@ -31,6 +31,11 @@ class CAHPAsmPrinter : public AsmPrinter { void EmitInstruction(const MachineInstr *MI) override; + bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, + const char *ExtraCode, raw_ostream &OS) override; + bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, + const char *ExtraCode, raw_ostream &OS) override; + // TableGen'erated function. bool emitPseudoExpansionLowering(MCStreamer &OutStreamer, const MachineInstr *MI); @@ -56,6 +61,46 @@ void CAHPAsmPrinter::EmitInstruction(const MachineInstr *MI) { EmitToStreamer(*OutStreamer, Res ? CInst : TmpInst); } +bool CAHPAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, + const char *ExtraCode, raw_ostream &OS) { + // First try the generic code, which knows about modifiers like 'c' and 'n'. + if (!AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS)) + return false; + + if (!ExtraCode) { + const MachineOperand &MO = MI->getOperand(OpNo); + switch (MO.getType()) { + case MachineOperand::MO_Immediate: + OS << MO.getImm(); + return false; + case MachineOperand::MO_Register: + OS << CAHPInstPrinter::getRegisterName(MO.getReg()); + return false; + default: + break; + } + } + + return true; +} + +bool CAHPAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, + unsigned OpNo, const char *ExtraCode, + raw_ostream &OS) { + if (!ExtraCode) { + const MachineOperand &MO = MI->getOperand(OpNo); + // For now, we only support register memory operands in registers and + // assume there is no addend + if (!MO.isReg()) + return true; + + OS << "0(" << CAHPInstPrinter::getRegisterName(MO.getReg()) << ")"; + return false; + } + + return AsmPrinter::PrintAsmMemoryOperand(MI, OpNo, ExtraCode, OS); +} + // Force static initialization. extern "C" void LLVMInitializeCAHPAsmPrinter() { RegisterAsmPrinter X(getTheCAHPTarget()); diff --git a/llvm/lib/Target/CAHP/CAHPISelDAGToDAG.cpp b/llvm/lib/Target/CAHP/CAHPISelDAGToDAG.cpp index 7e9d8c3d3147..2160502e73ca 100644 --- a/llvm/lib/Target/CAHP/CAHPISelDAGToDAG.cpp +++ b/llvm/lib/Target/CAHP/CAHPISelDAGToDAG.cpp @@ -27,6 +27,9 @@ class CAHPDAGToDAGISel final : public SelectionDAGISel { void Select(SDNode *Node) override; + bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID, + std::vector &OutOps) override; + bool SelectAddrFI(SDValue Addr, SDValue &Base); // Include the pieces autogenerated from the target description. @@ -56,6 +59,22 @@ void CAHPDAGToDAGISel::Select(SDNode *Node) { SelectCode(Node); } +bool CAHPDAGToDAGISel::SelectInlineAsmMemoryOperand( + const SDValue &Op, unsigned ConstraintID, std::vector &OutOps) { + switch (ConstraintID) { + case InlineAsm::Constraint_i: + case InlineAsm::Constraint_m: + // We just support simple memory operands that have a single address + // operand and need no special handling. + OutOps.push_back(Op); + return false; + default: + break; + } + + return true; +} + bool CAHPDAGToDAGISel::SelectAddrFI(SDValue Addr, SDValue &Base) { if (auto FIN = dyn_cast(Addr)) { Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i16); diff --git a/llvm/lib/Target/CAHP/CAHPISelLowering.cpp b/llvm/lib/Target/CAHP/CAHPISelLowering.cpp index 95a4d0cf6d5a..b324eba03b58 100644 --- a/llvm/lib/Target/CAHP/CAHPISelLowering.cpp +++ b/llvm/lib/Target/CAHP/CAHPISelLowering.cpp @@ -498,3 +498,21 @@ const char *CAHPTargetLowering::getTargetNodeName(unsigned Opcode) const { } return nullptr; } + +std::pair +CAHPTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, + StringRef Constraint, + MVT VT) const { + // First, see if this is a constraint that directly corresponds to a + // CAHP register class. + if (Constraint.size() == 1) { + switch (Constraint[0]) { + case 'r': + return std::make_pair(0U, &CAHP::GPRRegClass); + default: + break; + } + } + + return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT); +} diff --git a/llvm/lib/Target/CAHP/CAHPISelLowering.h b/llvm/lib/Target/CAHP/CAHPISelLowering.h index 101fa9f38372..c5a5121a56ca 100644 --- a/llvm/lib/Target/CAHP/CAHPISelLowering.h +++ b/llvm/lib/Target/CAHP/CAHPISelLowering.h @@ -40,6 +40,10 @@ class CAHPTargetLowering : public TargetLowering { EmitInstrWithCustomInserter(MachineInstr &MI, MachineBasicBlock *BB) const override; + std::pair + getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, + StringRef Constraint, MVT VT) const override; + private: // Lower incoming arguments, copy physregs into vregs SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, diff --git a/llvm/test/CodeGen/CAHP/inline-asm.ll b/llvm/test/CodeGen/CAHP/inline-asm.ll new file mode 100644 index 000000000000..6ffd6333ccae --- /dev/null +++ b/llvm/test/CodeGen/CAHP/inline-asm.ll @@ -0,0 +1,53 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=cahp -verify-machineinstrs < %s \ +; RUN: | FileCheck -check-prefix=CAHP %s + +@gi = external global i16 + +define i16 @constraint_r(i16 %a) { +; CAHP-LABEL: constraint_r: +; CAHP: # %bb.0: +; CAHP-NEXT: lui a1, %hi(gi) +; CAHP-NEXT: addi a1, a1, %lo(gi) +; CAHP-NEXT: lw a1, 0(a1) +; CAHP-NEXT: #APP +; CAHP-NEXT: add a0, a0, a1 +; CAHP-NEXT: #NO_APP +; CAHP-NEXT: jr ra + %1 = load i16, i16* @gi + %2 = tail call i16 asm "add $0, $1, $2", "=r,r,r"(i16 %a, i16 %1) + ret i16 %2 +} + +define i16 @constraint_i(i16 %a) { +; CAHP-LABEL: constraint_i: +; CAHP: # %bb.0: +; CAHP-NEXT: #APP +; CAHP-NEXT: addi a0, a0, 113 +; CAHP-NEXT: #NO_APP +; CAHP-NEXT: jr ra + %1 = load i16, i16* @gi + %2 = tail call i16 asm "addi $0, $1, $2", "=r,r,i"(i16 %a, i16 113) + ret i16 %2 +} + +define void @constraint_m(i16* %a) { +; CAHP-LABEL: constraint_m: +; CAHP: # %bb.0: +; CAHP-NEXT: #APP +; CAHP-NEXT: #NO_APP +; CAHP-NEXT: jr ra + call void asm sideeffect "", "=*m"(i16* %a) + ret void +} + +define i16 @constraint_m2(i16* %a) { +; CAHP-LABEL: constraint_m2: +; CAHP: # %bb.0: +; CAHP-NEXT: #APP +; CAHP-NEXT: lw a0, 0(a0) +; CAHP-NEXT: #NO_APP +; CAHP-NEXT: jr ra + %1 = tail call i16 asm "lw $0, $1", "=r,*m"(i16* %a) nounwind + ret i16 %1 +} From f940fa928e9488f50a4c67623254575f39e36bac Mon Sep 17 00:00:00 2001 From: Ushitora Anqou Date: Wed, 6 Nov 2019 16:44:32 +0900 Subject: [PATCH 265/289] [CAHP] Add support for branch relaxation --- llvm/lib/Target/CAHP/CAHPInstrInfo.cpp | 74 +++++++++++++++++-- llvm/lib/Target/CAHP/CAHPInstrInfo.h | 7 ++ llvm/lib/Target/CAHP/CAHPTargetMachine.cpp | 3 + llvm/test/CodeGen/CAHP/analyze-branch.ll | 6 +- llvm/test/CodeGen/CAHP/branch-relaxation.ll | 27 +++++++ llvm/test/CodeGen/CAHP/i16-icmp.ll | 60 ++++++++-------- llvm/test/CodeGen/CAHP/jumptable.ll | 58 +++++++-------- llvm/test/CodeGen/CAHP/select-cc.ll | 79 ++++++++++----------- 8 files changed, 207 insertions(+), 107 deletions(-) create mode 100644 llvm/test/CodeGen/CAHP/branch-relaxation.ll diff --git a/llvm/lib/Target/CAHP/CAHPInstrInfo.cpp b/llvm/lib/Target/CAHP/CAHPInstrInfo.cpp index f05de337c603..344de59e9d99 100644 --- a/llvm/lib/Target/CAHP/CAHPInstrInfo.cpp +++ b/llvm/lib/Target/CAHP/CAHPInstrInfo.cpp @@ -164,7 +164,9 @@ bool CAHPInstrInfo::analyzeBranch(MachineBasicBlock &MBB, unsigned CAHPInstrInfo::removeBranch(MachineBasicBlock &MBB, int *BytesRemoved) const { - assert(!BytesRemoved && "Code size not handled"); + if (BytesRemoved) + *BytesRemoved = 0; + MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr(); if (I == MBB.end()) return 0; @@ -175,6 +177,8 @@ unsigned CAHPInstrInfo::removeBranch(MachineBasicBlock &MBB, // Remove the branch. I->eraseFromParent(); + if (BytesRemoved) + *BytesRemoved += getInstSizeInBytes(*I); I = MBB.end(); @@ -186,6 +190,8 @@ unsigned CAHPInstrInfo::removeBranch(MachineBasicBlock &MBB, // Remove the branch. I->eraseFromParent(); + if (BytesRemoved) + *BytesRemoved += getInstSizeInBytes(*I); return 2; } @@ -194,7 +200,8 @@ unsigned CAHPInstrInfo::removeBranch(MachineBasicBlock &MBB, unsigned CAHPInstrInfo::insertBranch( MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB, ArrayRef Cond, const DebugLoc &DL, int *BytesAdded) const { - assert(!BytesAdded && "Code size not handled."); + if (BytesAdded) + *BytesAdded = 0; // Shouldn't be a fall through. assert(TBB && "InsertBranch must not be told to insert a fallthrough"); @@ -203,20 +210,27 @@ unsigned CAHPInstrInfo::insertBranch( // Unconditional branch. if (Cond.empty()) { - BuildMI(&MBB, DL, get(CAHP::JS)).addMBB(TBB); + MachineInstr &MI = *BuildMI(&MBB, DL, get(CAHP::JS)).addMBB(TBB); + if (BytesAdded) + *BytesAdded = getInstSizeInBytes(MI); return 1; } // Either a one or two-way conditional branch. unsigned Opc = Cond[0].getImm(); - BuildMI(&MBB, DL, get(Opc)).add(Cond[1]).add(Cond[2]).addMBB(TBB); + MachineInstr &CondMI = + *BuildMI(&MBB, DL, get(Opc)).add(Cond[1]).add(Cond[2]).addMBB(TBB); + if (BytesAdded) + *BytesAdded += getInstSizeInBytes(CondMI); // One-way conditional branch. if (!FBB) return 1; // Two-way conditional branch. - BuildMI(&MBB, DL, get(CAHP::JS)).addMBB(FBB); + MachineInstr &MI = *BuildMI(&MBB, DL, get(CAHP::JS)).addMBB(FBB); + if (BytesAdded) + *BytesAdded += getInstSizeInBytes(MI); return 2; } @@ -257,3 +271,53 @@ bool CAHPInstrInfo::reverseBranchCondition( return false; } + +MachineBasicBlock * +CAHPInstrInfo::getBranchDestBlock(const MachineInstr &MI) const { + assert(MI.getDesc().isBranch() && "Unexpected opcode!"); + // The branch target is always the last operand. + int NumOp = MI.getNumExplicitOperands(); + return MI.getOperand(NumOp - 1).getMBB(); +} + +bool CAHPInstrInfo::isBranchOffsetInRange(unsigned BranchOp, + int64_t BrOffset) const { + switch (BranchOp) { + default: + llvm_unreachable("Unexpected opcode!"); + + case CAHP::BEQ: + case CAHP::BNE: + case CAHP::BLT: + case CAHP::BLE: + case CAHP::BLTU: + case CAHP::BLEU: + return isInt<10>(BrOffset); + + case CAHP::JSAL: + case CAHP::JS: + return isInt<11>(BrOffset); + } +} + +unsigned CAHPInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const { + unsigned Opcode = MI.getOpcode(); + + switch (Opcode) { + default: + return get(Opcode).getSize(); + + case TargetOpcode::EH_LABEL: + case TargetOpcode::IMPLICIT_DEF: + case TargetOpcode::KILL: + case TargetOpcode::DBG_VALUE: + return 0; + + case TargetOpcode::INLINEASM: { + const MachineFunction &MF = *MI.getParent()->getParent(); + const auto &TM = static_cast(MF.getTarget()); + return getInlineAsmLength(MI.getOperand(0).getSymbolName(), + *TM.getMCAsmInfo()); + } + } +} diff --git a/llvm/lib/Target/CAHP/CAHPInstrInfo.h b/llvm/lib/Target/CAHP/CAHPInstrInfo.h index ac6c3eebca22..2ae849da637d 100644 --- a/llvm/lib/Target/CAHP/CAHPInstrInfo.h +++ b/llvm/lib/Target/CAHP/CAHPInstrInfo.h @@ -50,6 +50,13 @@ class CAHPInstrInfo : public CAHPGenInstrInfo { bool reverseBranchCondition(SmallVectorImpl &Cond) const override; + + unsigned getInstSizeInBytes(const MachineInstr &MI) const override; + + bool isBranchOffsetInRange(unsigned BranchOpc, + int64_t BrOffset) const override; + + MachineBasicBlock *getBranchDestBlock(const MachineInstr &MI) const override; }; } // namespace llvm diff --git a/llvm/lib/Target/CAHP/CAHPTargetMachine.cpp b/llvm/lib/Target/CAHP/CAHPTargetMachine.cpp index fc1c8f9a7a1b..08b90f2ac02c 100644 --- a/llvm/lib/Target/CAHP/CAHPTargetMachine.cpp +++ b/llvm/lib/Target/CAHP/CAHPTargetMachine.cpp @@ -58,6 +58,7 @@ class CAHPPassConfig : public TargetPassConfig { } bool addInstSelector() override; + void addPreEmitPass() override; }; } // namespace @@ -70,3 +71,5 @@ bool CAHPPassConfig::addInstSelector() { return false; } + +void CAHPPassConfig::addPreEmitPass() { addPass(&BranchRelaxationPassID); } diff --git a/llvm/test/CodeGen/CAHP/analyze-branch.ll b/llvm/test/CodeGen/CAHP/analyze-branch.ll index 61c0e556a38d..a7f8306c246e 100644 --- a/llvm/test/CodeGen/CAHP/analyze-branch.ll +++ b/llvm/test/CodeGen/CAHP/analyze-branch.ll @@ -53,8 +53,8 @@ define void @test_bcc_fallthrough_nottaken(i16 %in) nounwind { ; CAHP-NEXT: addi2 sp, -2 ; CAHP-NEXT: swsp ra, 0(sp) ; CAHP-NEXT: li a1, 42 -; CAHP-NEXT: beq a0, a1, .LBB1_1 -; CAHP-NEXT:# %bb.3: # %false +; CAHP-NEXT: beq a0, a1, .LBB1_3 +; CAHP-NEXT:# %bb.1: # %false ; CAHP-NEXT: lui a0, %hi(test_false) ; CAHP-NEXT: addi a0, a0, %lo(test_false) ; CAHP-NEXT:.LBB1_2: # %true @@ -62,7 +62,7 @@ define void @test_bcc_fallthrough_nottaken(i16 %in) nounwind { ; CAHP-NEXT: lwsp ra, 0(sp) ; CAHP-NEXT: addi2 sp, 2 ; CAHP-NEXT: jr ra -; CAHP-NEXT:.LBB1_1: # %true +; CAHP-NEXT:.LBB1_3: # %true ; CAHP-NEXT: lui a0, %hi(test_true) ; CAHP-NEXT: addi a0, a0, %lo(test_true) ; CAHP-NEXT: js .LBB1_2 diff --git a/llvm/test/CodeGen/CAHP/branch-relaxation.ll b/llvm/test/CodeGen/CAHP/branch-relaxation.ll new file mode 100644 index 000000000000..a6704639e8bc --- /dev/null +++ b/llvm/test/CodeGen/CAHP/branch-relaxation.ll @@ -0,0 +1,27 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=cahp -verify-machineinstrs -filetype=obj < %s \ +; RUN: -o /dev/null 2>&1 +; RUN: llc -mtriple=cahp -verify-machineinstrs < %s | FileCheck %s + +define void @relax_bcc(i1 %a) { +; CHECK-LABEL: relax_bcc: +; CHECK: # %bb.0: +; CHECK-NEXT: andi2 a0, 1 +; CHECK-NEXT: lsi a1, 0 +; CHECK-NEXT: bne a0, a1, .LBB0_1 +; CHECK-NEXT: js .LBB0_2 +; CHECK-NEXT:.LBB0_1: # %iftrue +; CHECK-NEXT: #APP +; CHECK-NEXT: .space 512 +; CHECK-NEXT: #NO_APP +; CHECK-NEXT:.LBB0_2: # %tail +; CHECK-NEXT: jr ra + br i1 %a, label %iftrue, label %tail + +iftrue: + call void asm sideeffect ".space 512", ""() + br label %tail + +tail: + ret void +} diff --git a/llvm/test/CodeGen/CAHP/i16-icmp.ll b/llvm/test/CodeGen/CAHP/i16-icmp.ll index 4e57d3c95a7a..dfb0d7083fd2 100644 --- a/llvm/test/CodeGen/CAHP/i16-icmp.ll +++ b/llvm/test/CodeGen/CAHP/i16-icmp.ll @@ -8,11 +8,11 @@ define i16 @icmp_eq(i16 %a, i16 %b) nounwind { ; CAHP-LABEL: icmp_eq: ; CAHP: # %bb.0: -; CAHP-NEXT: beq a0, a1, .LBB0_1 -; CAHP-NEXT:# %bb.2: +; CAHP-NEXT: beq a0, a1, .LBB0_2 +; CAHP-NEXT:# %bb.1: ; CAHP-NEXT: lsi a0, 0 ; CAHP-NEXT: jr ra -; CAHP-NEXT:.LBB0_1: +; CAHP-NEXT:.LBB0_2: ; CAHP-NEXT: lsi a0, 1 ; CAHP-NEXT: jr ra @@ -24,11 +24,11 @@ define i16 @icmp_eq(i16 %a, i16 %b) nounwind { define i16 @icmp_ne(i16 %a, i16 %b) nounwind { ; CAHP-LABEL: icmp_ne: ; CAHP: # %bb.0: -; CAHP-NEXT: bne a0, a1, .LBB1_1 -; CAHP-NEXT:# %bb.2: +; CAHP-NEXT: bne a0, a1, .LBB1_2 +; CAHP-NEXT:# %bb.1: ; CAHP-NEXT: lsi a0, 0 ; CAHP-NEXT: jr ra -; CAHP-NEXT:.LBB1_1: +; CAHP-NEXT:.LBB1_2: ; CAHP-NEXT: lsi a0, 1 ; CAHP-NEXT: jr ra @@ -40,11 +40,11 @@ define i16 @icmp_ne(i16 %a, i16 %b) nounwind { define i16 @icmp_ugt(i16 %a, i16 %b) nounwind { ; CAHP-LABEL: icmp_ugt: ; CAHP: # %bb.0: -; CAHP-NEXT: bltu a1, a0, .LBB2_1 -; CAHP-NEXT:# %bb.2: +; CAHP-NEXT: bltu a1, a0, .LBB2_2 +; CAHP-NEXT:# %bb.1: ; CAHP-NEXT: lsi a0, 0 ; CAHP-NEXT: jr ra -; CAHP-NEXT:.LBB2_1: +; CAHP-NEXT:.LBB2_2: ; CAHP-NEXT: lsi a0, 1 ; CAHP-NEXT: jr ra @@ -56,11 +56,11 @@ define i16 @icmp_ugt(i16 %a, i16 %b) nounwind { define i16 @icmp_uge(i16 %a, i16 %b) nounwind { ; CAHP-LABEL: icmp_uge: ; CAHP: # %bb.0: -; CAHP-NEXT: bleu a1, a0, .LBB3_1 -; CAHP-NEXT:# %bb.2: +; CAHP-NEXT: bleu a1, a0, .LBB3_2 +; CAHP-NEXT:# %bb.1: ; CAHP-NEXT: lsi a0, 0 ; CAHP-NEXT: jr ra -; CAHP-NEXT:.LBB3_1: +; CAHP-NEXT:.LBB3_2: ; CAHP-NEXT: lsi a0, 1 ; CAHP-NEXT: jr ra @@ -72,11 +72,11 @@ define i16 @icmp_uge(i16 %a, i16 %b) nounwind { define i16 @icmp_ult(i16 %a, i16 %b) nounwind { ; CAHP-LABEL: icmp_ult: ; CAHP: # %bb.0: -; CAHP-NEXT: bltu a0, a1, .LBB4_1 -; CAHP-NEXT:# %bb.2: +; CAHP-NEXT: bltu a0, a1, .LBB4_2 +; CAHP-NEXT:# %bb.1: ; CAHP-NEXT: lsi a0, 0 ; CAHP-NEXT: jr ra -; CAHP-NEXT:.LBB4_1: +; CAHP-NEXT:.LBB4_2: ; CAHP-NEXT: lsi a0, 1 ; CAHP-NEXT: jr ra @@ -88,11 +88,11 @@ define i16 @icmp_ult(i16 %a, i16 %b) nounwind { define i16 @icmp_ule(i16 %a, i16 %b) nounwind { ; CAHP-LABEL: icmp_ule: ; CAHP: # %bb.0: -; CAHP-NEXT: bleu a0, a1, .LBB5_1 -; CAHP-NEXT:# %bb.2: +; CAHP-NEXT: bleu a0, a1, .LBB5_2 +; CAHP-NEXT:# %bb.1: ; CAHP-NEXT: lsi a0, 0 ; CAHP-NEXT: jr ra -; CAHP-NEXT:.LBB5_1: +; CAHP-NEXT:.LBB5_2: ; CAHP-NEXT: lsi a0, 1 ; CAHP-NEXT: jr ra @@ -104,11 +104,11 @@ define i16 @icmp_ule(i16 %a, i16 %b) nounwind { define i16 @icmp_sgt(i16 %a, i16 %b) nounwind { ; CAHP-LABEL: icmp_sgt: ; CAHP: # %bb.0: -; CAHP-NEXT: blt a1, a0, .LBB6_1 -; CAHP-NEXT:# %bb.2: +; CAHP-NEXT: blt a1, a0, .LBB6_2 +; CAHP-NEXT:# %bb.1: ; CAHP-NEXT: lsi a0, 0 ; CAHP-NEXT: jr ra -; CAHP-NEXT:.LBB6_1: +; CAHP-NEXT:.LBB6_2: ; CAHP-NEXT: lsi a0, 1 ; CAHP-NEXT: jr ra @@ -120,11 +120,11 @@ define i16 @icmp_sgt(i16 %a, i16 %b) nounwind { define i16 @icmp_sge(i16 %a, i16 %b) nounwind { ; CAHP-LABEL: icmp_sge: ; CAHP: # %bb.0: -; CAHP-NEXT: ble a1, a0, .LBB7_1 -; CAHP-NEXT:# %bb.2: +; CAHP-NEXT: ble a1, a0, .LBB7_2 +; CAHP-NEXT:# %bb.1: ; CAHP-NEXT: lsi a0, 0 ; CAHP-NEXT: jr ra -; CAHP-NEXT:.LBB7_1: +; CAHP-NEXT:.LBB7_2: ; CAHP-NEXT: lsi a0, 1 ; CAHP-NEXT: jr ra @@ -136,11 +136,11 @@ define i16 @icmp_sge(i16 %a, i16 %b) nounwind { define i16 @icmp_slt(i16 %a, i16 %b) nounwind { ; CAHP-LABEL: icmp_slt: ; CAHP: # %bb.0: -; CAHP-NEXT: blt a0, a1, .LBB8_1 -; CAHP-NEXT:# %bb.2: +; CAHP-NEXT: blt a0, a1, .LBB8_2 +; CAHP-NEXT:# %bb.1: ; CAHP-NEXT: lsi a0, 0 ; CAHP-NEXT: jr ra -; CAHP-NEXT:.LBB8_1: +; CAHP-NEXT:.LBB8_2: ; CAHP-NEXT: lsi a0, 1 ; CAHP-NEXT: jr ra @@ -152,11 +152,11 @@ define i16 @icmp_slt(i16 %a, i16 %b) nounwind { define i16 @icmp_sle(i16 %a, i16 %b) nounwind { ; CAHP-LABEL: icmp_sle: ; CAHP: # %bb.0: -; CAHP-NEXT: ble a0, a1, .LBB9_1 -; CAHP-NEXT:# %bb.2: +; CAHP-NEXT: ble a0, a1, .LBB9_2 +; CAHP-NEXT:# %bb.1: ; CAHP-NEXT: lsi a0, 0 ; CAHP-NEXT: jr ra -; CAHP-NEXT:.LBB9_1: +; CAHP-NEXT:.LBB9_2: ; CAHP-NEXT: lsi a0, 1 ; CAHP-NEXT: jr ra diff --git a/llvm/test/CodeGen/CAHP/jumptable.ll b/llvm/test/CodeGen/CAHP/jumptable.ll index d336a5c4e14a..33965ca9defa 100644 --- a/llvm/test/CodeGen/CAHP/jumptable.ll +++ b/llvm/test/CodeGen/CAHP/jumptable.ll @@ -5,35 +5,35 @@ define void @jt(i16 %in, i16* %out) { ; CAHP-LABEL: jt: ; CAHP: # %bb.0: # %entry -; CAHP-NEXT: lsi a2, 2 -; CAHP-NEXT: blt a2, a0, .LBB0_4 -; CAHP-NEXT: # %bb.1: # %entry -; CAHP-NEXT: lsi a3, 1 -; CAHP-NEXT: beq a0, a3, .LBB0_8 -; CAHP-NEXT: # %bb.2: # %entry -; CAHP-NEXT: bne a0, a2, .LBB0_10 -; CAHP-NEXT: # %bb.3: # %bb2 -; CAHP-NEXT: lsi a0, 3 -; CAHP-NEXT: sw a0, 0(a1) -; CAHP-NEXT: jr ra -; CAHP-NEXT: .LBB0_4: # %entry -; CAHP-NEXT: lsi a3, 3 -; CAHP-NEXT: beq a0, a3, .LBB0_9 -; CAHP-NEXT: # %bb.5: # %entry -; CAHP-NEXT: lsi a2, 4 -; CAHP-NEXT: bne a0, a2, .LBB0_10 -; CAHP-NEXT: # %bb.6: # %bb4 -; CAHP-NEXT: lsi a0, 1 -; CAHP-NEXT: sw a0, 0(a1) -; CAHP-NEXT: jr ra -; CAHP-NEXT: .LBB0_8: # %bb1 -; CAHP-NEXT: lsi a0, 4 -; CAHP-NEXT: sw a0, 0(a1) -; CAHP-NEXT: jr ra -; CAHP-NEXT: .LBB0_9: # %bb3 -; CAHP-NEXT: sw a2, 0(a1) -; CAHP-NEXT: .LBB0_10: # %exit -; CAHP-NEXT: jr ra +; CAHP-NEXT: lsi a2, 2 +; CAHP-NEXT: blt a2, a0, .LBB0_4 +; CAHP-NEXT:# %bb.1: # %entry +; CAHP-NEXT: lsi a3, 1 +; CAHP-NEXT: beq a0, a3, .LBB0_7 +; CAHP-NEXT:# %bb.2: # %entry +; CAHP-NEXT: bne a0, a2, .LBB0_9 +; CAHP-NEXT:# %bb.3: # %bb2 +; CAHP-NEXT: lsi a0, 3 +; CAHP-NEXT: sw a0, 0(a1) +; CAHP-NEXT: jr ra +; CAHP-NEXT:.LBB0_4: # %entry +; CAHP-NEXT: lsi a3, 3 +; CAHP-NEXT: beq a0, a3, .LBB0_8 +; CAHP-NEXT:# %bb.5: # %entry +; CAHP-NEXT: lsi a2, 4 +; CAHP-NEXT: bne a0, a2, .LBB0_9 +; CAHP-NEXT:# %bb.6: # %bb4 +; CAHP-NEXT: lsi a0, 1 +; CAHP-NEXT: sw a0, 0(a1) +; CAHP-NEXT: jr ra +; CAHP-NEXT:.LBB0_7: # %bb1 +; CAHP-NEXT: lsi a0, 4 +; CAHP-NEXT: sw a0, 0(a1) +; CAHP-NEXT: jr ra +; CAHP-NEXT:.LBB0_8: # %bb3 +; CAHP-NEXT: sw a2, 0(a1) +; CAHP-NEXT:.LBB0_9: # %exit +; CAHP-NEXT: jr ra entry: switch i16 %in, label %exit [ diff --git a/llvm/test/CodeGen/CAHP/select-cc.ll b/llvm/test/CodeGen/CAHP/select-cc.ll index e9ad9932efe3..811d5f715def 100644 --- a/llvm/test/CodeGen/CAHP/select-cc.ll +++ b/llvm/test/CodeGen/CAHP/select-cc.ll @@ -6,76 +6,75 @@ define i16 @foo(i16 %a, i16 *%b) { ; CAHP-LABEL: foo: ; CAHP: # %bb.0: ; CAHP-NEXT: lw a2, 0(a1) -; CAHP-NEXT: bne a0, a2, .LBB0_1 -; CAHP-NEXT:# %bb.2: +; CAHP-NEXT: bne a0, a2, .LBB0_11 +; CAHP-NEXT:# %bb.1: ; CAHP-NEXT: lw a2, 0(a1) -; CAHP-NEXT: beq a0, a2, .LBB0_3 -; CAHP-NEXT:.LBB0_4: +; CAHP-NEXT: beq a0, a2, .LBB0_12 +; CAHP-NEXT:.LBB0_2: ; CAHP-NEXT: lw a2, 0(a1) -; CAHP-NEXT: bleu a0, a2, .LBB0_5 -; CAHP-NEXT:.LBB0_6: +; CAHP-NEXT: bleu a0, a2, .LBB0_13 +; CAHP-NEXT:.LBB0_3: ; CAHP-NEXT: lw a2, 0(a1) -; CAHP-NEXT: bltu a0, a2, .LBB0_7 -; CAHP-NEXT:.LBB0_8: +; CAHP-NEXT: bltu a0, a2, .LBB0_14 +; CAHP-NEXT:.LBB0_4: ; CAHP-NEXT: lw a2, 0(a1) -; CAHP-NEXT: bleu a2, a0, .LBB0_9 -; CAHP-NEXT:.LBB0_10: +; CAHP-NEXT: bleu a2, a0, .LBB0_15 +; CAHP-NEXT:.LBB0_5: ; CAHP-NEXT: lw a2, 0(a1) -; CAHP-NEXT: bltu a2, a0, .LBB0_11 -; CAHP-NEXT:.LBB0_12: +; CAHP-NEXT: bltu a2, a0, .LBB0_16 +; CAHP-NEXT:.LBB0_6: ; CAHP-NEXT: lw a2, 0(a1) -; CAHP-NEXT: ble a0, a2, .LBB0_13 -; CAHP-NEXT:.LBB0_14: +; CAHP-NEXT: ble a0, a2, .LBB0_17 +; CAHP-NEXT:.LBB0_7: ; CAHP-NEXT: lw a2, 0(a1) -; CAHP-NEXT: blt a0, a2, .LBB0_15 -; CAHP-NEXT:.LBB0_16: +; CAHP-NEXT: blt a0, a2, .LBB0_18 +; CAHP-NEXT:.LBB0_8: ; CAHP-NEXT: lw a2, 0(a1) -; CAHP-NEXT: ble a2, a0, .LBB0_17 -; CAHP-NEXT:.LBB0_18: +; CAHP-NEXT: ble a2, a0, .LBB0_19 +; CAHP-NEXT:.LBB0_9: ; CAHP-NEXT: lw a1, 0(a1) -; CAHP-NEXT: blt a1, a0, .LBB0_19 -; CAHP-NEXT:.LBB0_20: +; CAHP-NEXT: blt a1, a0, .LBB0_20 +; CAHP-NEXT:.LBB0_10: ; CAHP-NEXT: jr ra -; CAHP-NEXT:.LBB0_1: +; CAHP-NEXT:.LBB0_11: ; CAHP-NEXT: mov a0, a2 ; CAHP-NEXT: lw a2, 0(a1) -; CAHP-NEXT: bne a0, a2, .LBB0_4 -; CAHP-NEXT:.LBB0_3: +; CAHP-NEXT: bne a0, a2, .LBB0_2 +; CAHP-NEXT:.LBB0_12: ; CAHP-NEXT: mov a0, a2 ; CAHP-NEXT: lw a2, 0(a1) -; CAHP-NEXT: bltu a2, a0, .LBB0_6 -; CAHP-NEXT:.LBB0_5: +; CAHP-NEXT: bltu a2, a0, .LBB0_3 +; CAHP-NEXT:.LBB0_13: ; CAHP-NEXT: mov a0, a2 ; CAHP-NEXT: lw a2, 0(a1) -; CAHP-NEXT: bleu a2, a0, .LBB0_8 -; CAHP-NEXT:.LBB0_7: +; CAHP-NEXT: bleu a2, a0, .LBB0_4 +; CAHP-NEXT:.LBB0_14: ; CAHP-NEXT: mov a0, a2 ; CAHP-NEXT: lw a2, 0(a1) -; CAHP-NEXT: bltu a0, a2, .LBB0_10 -; CAHP-NEXT:.LBB0_9: +; CAHP-NEXT: bltu a0, a2, .LBB0_5 +; CAHP-NEXT:.LBB0_15: ; CAHP-NEXT: mov a0, a2 ; CAHP-NEXT: lw a2, 0(a1) -; CAHP-NEXT: bleu a0, a2, .LBB0_12 -; CAHP-NEXT:.LBB0_11: +; CAHP-NEXT: bleu a0, a2, .LBB0_6 +; CAHP-NEXT:.LBB0_16: ; CAHP-NEXT: mov a0, a2 ; CAHP-NEXT: lw a2, 0(a1) -; CAHP-NEXT: blt a2, a0, .LBB0_14 -; CAHP-NEXT:.LBB0_13: +; CAHP-NEXT: blt a2, a0, .LBB0_7 +; CAHP-NEXT:.LBB0_17: ; CAHP-NEXT: mov a0, a2 ; CAHP-NEXT: lw a2, 0(a1) -; CAHP-NEXT: ble a2, a0, .LBB0_16 -; CAHP-NEXT:.LBB0_15: +; CAHP-NEXT: ble a2, a0, .LBB0_8 +; CAHP-NEXT:.LBB0_18: ; CAHP-NEXT: mov a0, a2 ; CAHP-NEXT: lw a2, 0(a1) -; CAHP-NEXT: blt a0, a2, .LBB0_18 -; CAHP-NEXT:.LBB0_17: +; CAHP-NEXT: blt a0, a2, .LBB0_9 +; CAHP-NEXT:.LBB0_19: ; CAHP-NEXT: mov a0, a2 ; CAHP-NEXT: lw a1, 0(a1) -; CAHP-NEXT: ble a0, a1, .LBB0_20 -; CAHP-NEXT:.LBB0_19: +; CAHP-NEXT: ble a0, a1, .LBB0_10 +; CAHP-NEXT:.LBB0_20: ; CAHP-NEXT: mov a0, a1 ; CAHP-NEXT: jr ra - %val1 = load volatile i16, i16* %b %tst1 = icmp eq i16 %a, %val1 %val2 = select i1 %tst1, i16 %a, i16 %val1 From f57ab626c81d5017ff568be64a60f08b78e07a9b Mon Sep 17 00:00:00 2001 From: Ushitora Anqou Date: Wed, 6 Nov 2019 22:52:58 +0900 Subject: [PATCH 266/289] [CAHP] Add support for sext/zext/trunc --- llvm/lib/Target/CAHP/CAHPISelLowering.cpp | 2 + llvm/test/CodeGen/CAHP/sext-zext-trunc.ll | 180 ++++++++++++++++++++++ 2 files changed, 182 insertions(+) create mode 100644 llvm/test/CodeGen/CAHP/sext-zext-trunc.ll diff --git a/llvm/lib/Target/CAHP/CAHPISelLowering.cpp b/llvm/lib/Target/CAHP/CAHPISelLowering.cpp index b324eba03b58..2e8d00f80a88 100644 --- a/llvm/lib/Target/CAHP/CAHPISelLowering.cpp +++ b/llvm/lib/Target/CAHP/CAHPISelLowering.cpp @@ -49,6 +49,8 @@ CAHPTargetLowering::CAHPTargetLowering(const TargetMachine &TM, setOperationAction(ISD::SELECT, MVT::i16, Custom); setOperationAction(ISD::SELECT_CC, MVT::i16, Expand); setOperationAction(ISD::SETCC, MVT::i16, Expand); + for (auto VT : {MVT::i1, MVT::i8}) + setOperationAction(ISD::SIGN_EXTEND_INREG, VT, Expand); setBooleanContents(ZeroOrOneBooleanContent); diff --git a/llvm/test/CodeGen/CAHP/sext-zext-trunc.ll b/llvm/test/CodeGen/CAHP/sext-zext-trunc.ll new file mode 100644 index 000000000000..eea9f5d4ab33 --- /dev/null +++ b/llvm/test/CodeGen/CAHP/sext-zext-trunc.ll @@ -0,0 +1,180 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=cahp -verify-machineinstrs < %s \ +; RUN: | FileCheck %s -check-prefix=CAHP + +; FIXME: an unncessary register is allocated just to store 0. X0 should be +; used instead + +define i8 @sext_i1_to_i8(i1 %a) { +; TODO: the addi that stores 0 in t1 is unnecessary +; CAHP-LABEL: sext_i1_to_i8: +; CAHP: # %bb.0: +; CAHP-NEXT: andi2 a0, 1 +; CAHP-NEXT: lsi a1, 0 +; CAHP-NEXT: sub a0, a1, a0 +; CAHP-NEXT: jr ra + %1 = sext i1 %a to i8 + ret i8 %1 +} + +define i16 @sext_i1_to_i16(i1 %a) { +; TODO: the addi that stores 0 in t1 is unnecessary +; CAHP-LABEL: sext_i1_to_i16: +; CAHP: # %bb.0: +; CAHP-NEXT: andi2 a0, 1 +; CAHP-NEXT: lsi a1, 0 +; CAHP-NEXT: sub a0, a1, a0 +; CAHP-NEXT: jr ra + %1 = sext i1 %a to i16 + ret i16 %1 +} + +define i32 @sext_i1_to_i32(i1 %a) { +; TODO: the addi that stores 0 in t1 is unnecessary +; CAHP-LABEL: sext_i1_to_i32: +; CAHP: # %bb.0: +; CAHP-NEXT: andi2 a0, 1 +; CAHP-NEXT: lsi a1, 0 +; CAHP-NEXT: sub a0, a1, a0 +; CAHP-NEXT: mov a1, a0 +; CAHP-NEXT: jr ra + %1 = sext i1 %a to i32 + ret i32 %1 +} + +define i16 @sext_i8_to_i16(i8 %a) { +; CAHP-LABEL: sext_i8_to_i16: +; CAHP: # %bb.0: +; CAHP-NEXT: lsli2 a0, 8 +; CAHP-NEXT: asri2 a0, 8 +; CAHP-NEXT: jr ra + %1 = sext i8 %a to i16 + ret i16 %1 +} + +define i32 @sext_i8_to_i32(i8 %a) { +; CAHP-LABEL: sext_i8_to_i32: +; CAHP: # %bb.0: +; CAHP-NEXT: lsli a1, a0, 8 +; CAHP-NEXT: asri a0, a1, 8 +; CAHP-NEXT: asri2 a1, 15 +; CAHP-NEXT: jr ra + %1 = sext i8 %a to i32 + ret i32 %1 +} + +define i32 @sext_i16_to_i32(i16 %a) { +; CAHP-LABEL: sext_i16_to_i32: +; CAHP: # %bb.0: +; CAHP-NEXT: asri a1, a0, 15 +; CAHP-NEXT: jr ra + %1 = sext i16 %a to i32 + ret i32 %1 +} + +define i8 @zext_i1_to_i8(i1 %a) { +; CAHP-LABEL: zext_i1_to_i8: +; CAHP: # %bb.0: +; CAHP-NEXT: andi2 a0, 1 +; CAHP-NEXT: jr ra + %1 = zext i1 %a to i8 + ret i8 %1 +} + +define i16 @zext_i1_to_i16(i1 %a) { +; CAHP-LABEL: zext_i1_to_i16: +; CAHP: # %bb.0: +; CAHP-NEXT: andi2 a0, 1 +; CAHP-NEXT: jr ra + %1 = zext i1 %a to i16 + ret i16 %1 +} + +define i32 @zext_i1_to_i32(i1 %a) { +; CAHP-LABEL: zext_i1_to_i32: +; CAHP: # %bb.0: +; CAHP-NEXT: andi2 a0, 1 +; CAHP-NEXT: lsi a1, 0 +; CAHP-NEXT: jr ra + %1 = zext i1 %a to i32 + ret i32 %1 +} + +define i16 @zext_i8_to_i16(i8 %a) { +; CAHP-LABEL: zext_i8_to_i16: +; CAHP: # %bb.0: +; CAHP-NEXT: andi a0, a0, 255 +; CAHP-NEXT: jr ra + %1 = zext i8 %a to i16 + ret i16 %1 +} + +define i32 @zext_i8_to_i32(i8 %a) { +; CAHP-LABEL: zext_i8_to_i32: +; CAHP: # %bb.0: +; CAHP-NEXT: andi a0, a0, 255 +; CAHP-NEXT: lsi a1, 0 +; CAHP-NEXT: jr ra + %1 = zext i8 %a to i32 + ret i32 %1 +} + +define i32 @zext_i16_to_i32(i16 %a) { +; CAHP-LABEL: zext_i16_to_i32: +; CAHP: # %bb.0: +; CAHP-NEXT: lsi a1, 0 +; CAHP-NEXT: jr ra + %1 = zext i16 %a to i32 + ret i32 %1 +} + +; TODO: should the trunc tests explicitly ensure no code is generated before +; jalr? + +define i1 @trunc_i8_to_i1(i8 %a) { +; CAHP-LABEL: trunc_i8_to_i1: +; CAHP: # %bb.0: +; CAHP-NEXT: jr ra + %1 = trunc i8 %a to i1 + ret i1 %1 +} + +define i1 @trunc_i16_to_i1(i16 %a) { +; CAHP-LABEL: trunc_i16_to_i1: +; CAHP: # %bb.0: +; CAHP-NEXT: jr ra + %1 = trunc i16 %a to i1 + ret i1 %1 +} + +define i1 @trunc_i32_to_i1(i32 %a) { +; CAHP-LABEL: trunc_i32_to_i1: +; CAHP: # %bb.0: +; CAHP-NEXT: jr ra + %1 = trunc i32 %a to i1 + ret i1 %1 +} + +define i8 @trunc_i16_to_i8(i16 %a) { +; CAHP-LABEL: trunc_i16_to_i8: +; CAHP: # %bb.0: +; CAHP-NEXT: jr ra + %1 = trunc i16 %a to i8 + ret i8 %1 +} + +define i8 @trunc_i32_to_i8(i32 %a) { +; CAHP-LABEL: trunc_i32_to_i8: +; CAHP: # %bb.0: +; CAHP-NEXT: jr ra + %1 = trunc i32 %a to i8 + ret i8 %1 +} + +define i16 @trunc_i32_to_i16(i32 %a) { +; CAHP-LABEL: trunc_i32_to_i16: +; CAHP: # %bb.0: +; CAHP-NEXT: jr ra + %1 = trunc i32 %a to i16 + ret i16 %1 +} From 332084c88d013b11046339d637b0608070920062 Mon Sep 17 00:00:00 2001 From: Ushitora Anqou Date: Wed, 6 Nov 2019 23:15:51 +0900 Subject: [PATCH 267/289] [CAHP] Add support for fastcc; currently same as ccc --- llvm/lib/Target/CAHP/CAHPISelLowering.cpp | 1 + llvm/test/CodeGen/CAHP/calls.ll | 31 +++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/llvm/lib/Target/CAHP/CAHPISelLowering.cpp b/llvm/lib/Target/CAHP/CAHPISelLowering.cpp index 2e8d00f80a88..49456967aa36 100644 --- a/llvm/lib/Target/CAHP/CAHPISelLowering.cpp +++ b/llvm/lib/Target/CAHP/CAHPISelLowering.cpp @@ -280,6 +280,7 @@ SDValue CAHPTargetLowering::LowerFormalArguments( default: report_fatal_error("Unsupported calling convention"); case CallingConv::C: + case CallingConv::Fast: break; } diff --git a/llvm/test/CodeGen/CAHP/calls.ll b/llvm/test/CodeGen/CAHP/calls.ll index 83f822da64a8..660034194c91 100644 --- a/llvm/test/CodeGen/CAHP/calls.ll +++ b/llvm/test/CodeGen/CAHP/calls.ll @@ -57,3 +57,34 @@ define i16 @test_call_indirect(i16 (i16)* %a, i16 %b) nounwind { %1 = call i16 %a(i16 %b) ret i16 %1 } + +define fastcc i16 @fastcc_function(i16 %a, i16 %b) nounwind { +; CAHP-LABEL: fastcc_function: +; CAHP: # %bb.0: +; CAHP-NEXT: add2 a0, a1 +; CAHP-NEXT: jr ra + + %1 = add i16 %a, %b + ret i16 %1 +} + +define i16 @test_call_fastcc(i16 %a, i16 %b) nounwind { +; CAHP-LABEL: test_call_fastcc: +; CAHP: # %bb.0: +; CAHP-NEXT: addi2 sp, -4 +; CAHP-NEXT: swsp ra, 2(sp) +; CAHP-NEXT: swsp s0, 0(sp) +; CAHP-NEXT: mov s0, a0 +; CAHP-NEXT: lui a0, %hi(fastcc_function) +; CAHP-NEXT: addi a2, a0, %lo(fastcc_function) +; CAHP-NEXT: mov a0, s0 +; CAHP-NEXT: jalr a2 +; CAHP-NEXT: mov a0, s0 +; CAHP-NEXT: lwsp s0, 0(sp) +; CAHP-NEXT: lwsp ra, 2(sp) +; CAHP-NEXT: addi2 sp, 4 +; CAHP-NEXT: jr ra + + %1 = call fastcc i16 @fastcc_function(i16 %a, i16 %b) + ret i16 %a +} From 42dda4bf716fa560b7e0bb5daca2fb7b3a47c10c Mon Sep 17 00:00:00 2001 From: Ushitora Anqou Date: Sat, 9 Nov 2019 20:57:32 +0900 Subject: [PATCH 268/289] [CAHP] Use jsal rather than jalr with lui and addi --- llvm/lib/Target/CAHP/CAHPISelLowering.cpp | 28 ++++------------------- llvm/lib/Target/CAHP/CAHPISelLowering.h | 1 - llvm/lib/Target/CAHP/CAHPInstrInfo.td | 13 ++++++++--- llvm/lib/Target/CAHP/CAHPMCInstLower.cpp | 3 ++- llvm/test/CodeGen/CAHP/analyze-branch.ll | 14 ++++-------- llvm/test/CodeGen/CAHP/calls.ll | 13 +++-------- llvm/test/CodeGen/CAHP/frame.ll | 4 +--- llvm/test/CodeGen/CAHP/frameindex.ll | 4 +--- 8 files changed, 25 insertions(+), 55 deletions(-) diff --git a/llvm/lib/Target/CAHP/CAHPISelLowering.cpp b/llvm/lib/Target/CAHP/CAHPISelLowering.cpp index 49456967aa36..c3e5b491a22a 100644 --- a/llvm/lib/Target/CAHP/CAHPISelLowering.cpp +++ b/llvm/lib/Target/CAHP/CAHPISelLowering.cpp @@ -136,23 +136,6 @@ SDValue CAHPTargetLowering::LowerGlobalAddress(SDValue Op, return MNLo; } -SDValue CAHPTargetLowering::LowerExternalSymbol(SDValue Op, - SelectionDAG &DAG) const { - SDLoc DL(Op); - EVT Ty = Op.getValueType(); - ExternalSymbolSDNode *N = cast(Op); - const char *Sym = N->getSymbol(); - - if (isPositionIndependent()) - report_fatal_error("Unable to LowerExternalSymbol"); - - SDValue GAHi = DAG.getTargetExternalSymbol(Sym, Ty, CAHPII::MO_HI); - SDValue GALo = DAG.getTargetExternalSymbol(Sym, Ty, CAHPII::MO_LO); - SDValue MNHi = SDValue(DAG.getMachineNode(CAHP::LUI, DL, Ty, GAHi), 0); - SDValue MNLo = SDValue(DAG.getMachineNode(CAHP::ADDI, DL, Ty, MNHi, GALo), 0); - return MNLo; -} - SDValue CAHPTargetLowering::LowerSELECT(SDValue Op, SelectionDAG &DAG) const { SDValue CondV = Op.getOperand(0); SDValue TrueV = Op.getOperand(1); @@ -385,13 +368,10 @@ SDValue CAHPTargetLowering::LowerCall(CallLoweringInfo &CLI, Glue = Chain.getValue(1); } - if (isa(Callee)) { - // GlobalAddressSDNode *S = dyn_cast(Callee); - // Callee = DAG.getTargetGlobalAddress(S->getGlobal(), DL, PtrVT, 0, 0); - Callee = LowerGlobalAddress(Callee, DAG); - } else if (isa(Callee)) { - Callee = LowerExternalSymbol(Callee, DAG); - } + if (GlobalAddressSDNode *S = dyn_cast(Callee)) + Callee = DAG.getTargetGlobalAddress(S->getGlobal(), DL, PtrVT, 0, 0); + else if (ExternalSymbolSDNode *S = dyn_cast(Callee)) + Callee = DAG.getTargetExternalSymbol(S->getSymbol(), PtrVT, 0); // The first call operand is the chain and the second is the target address. SmallVector Ops; diff --git a/llvm/lib/Target/CAHP/CAHPISelLowering.h b/llvm/lib/Target/CAHP/CAHPISelLowering.h index c5a5121a56ca..07eb218e9a4e 100644 --- a/llvm/lib/Target/CAHP/CAHPISelLowering.h +++ b/llvm/lib/Target/CAHP/CAHPISelLowering.h @@ -63,7 +63,6 @@ class CAHPTargetLowering : public TargetLowering { } SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const; - SDValue LowerExternalSymbol(SDValue Op, SelectionDAG &DAG) const; SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG) const; SDValue LowerSELECT(SDValue Op, SelectionDAG &DAG) const; }; diff --git a/llvm/lib/Target/CAHP/CAHPInstrInfo.td b/llvm/lib/Target/CAHP/CAHPInstrInfo.td index bc34b515153a..47be23112a37 100644 --- a/llvm/lib/Target/CAHP/CAHPInstrInfo.td +++ b/llvm/lib/Target/CAHP/CAHPInstrInfo.td @@ -83,7 +83,13 @@ def simm10_branch : Operand { let EncoderMethod = "getImmOpValue"; } -def simm11 : Operand { +def simm11 : Operand, ImmLeaf(Imm);}]> { + let ParserMatchClass = SImmAsmOperand<11>; + let DecoderMethod = "decodeSImmOperand<11>"; + let EncoderMethod = "getImmOpValue"; +} + +def simm11_branch : Operand { let ParserMatchClass = SImmAsmOperand<11>; let DecoderMethod = "decodeSImmOperand<11>"; let EncoderMethod = "getImmOpValue"; @@ -324,7 +330,7 @@ let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in { def JR : CAHPInst16JR<0b00110, (ins GPR:$rs), "jr", "$rs">; let isBranch = 1, isTerminator = 1, isBarrier = 1 in - def JS : CAHPInst16JI<0b01110, (ins simm11:$imm), "js", "$imm">; + def JS : CAHPInst16JI<0b01110, (ins simm11_branch:$imm), "js", "$imm">; let isCall = 1, Defs = [/* RA */ X0] in def JSAL : CAHPInst16JI<0b11110, (ins simm11:$imm), "jsal", "$imm">; @@ -440,9 +446,10 @@ def : BccSwapPat; // condition was calculated elsewhere). def : Pat<(brcond GPR:$cond, bb:$imm), (BNE GPR:$cond, (LSI 0), bb:$imm)>; -def : Pat<(br bb:$imm), (JS simm11:$imm)>; +def : Pat<(br bb:$imm), (JS simm11_branch:$imm)>; def : Pat<(Call GPR:$rs), (JALR GPR:$rs)>; def : Pat<(Call tglobaladdr:$dst), (JSAL tglobaladdr:$dst)>; +def : Pat<(Call texternalsym:$dst), (JSAL texternalsym:$dst)>; // Compress patterns diff --git a/llvm/lib/Target/CAHP/CAHPMCInstLower.cpp b/llvm/lib/Target/CAHP/CAHPMCInstLower.cpp index bb2bd7325de8..a26f5fc3b88f 100644 --- a/llvm/lib/Target/CAHP/CAHPMCInstLower.cpp +++ b/llvm/lib/Target/CAHP/CAHPMCInstLower.cpp @@ -43,7 +43,8 @@ static MCOperand LowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym, ME = MCBinaryExpr::createAdd( ME, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx); - ME = CAHPMCExpr::create(ME, Kind, Ctx); + if (Kind != CAHPMCExpr::VK_CAHP_None) + ME = CAHPMCExpr::create(ME, Kind, Ctx); return MCOperand::createExpr(ME); } diff --git a/llvm/test/CodeGen/CAHP/analyze-branch.ll b/llvm/test/CodeGen/CAHP/analyze-branch.ll index a7f8306c246e..861d06e7deb6 100644 --- a/llvm/test/CodeGen/CAHP/analyze-branch.ll +++ b/llvm/test/CodeGen/CAHP/analyze-branch.ll @@ -20,16 +20,13 @@ define void @test_bcc_fallthrough_taken(i16 %in) nounwind { ; CAHP-NEXT: li a1, 42 ; CAHP-NEXT: bne a0, a1, .LBB0_3 ; CAHP-NEXT:# %bb.1: # %true -; CAHP-NEXT: lui a0, %hi(test_true) -; CAHP-NEXT: addi a0, a0, %lo(test_true) +; CAHP-NEXT: jsal test_true ; CAHP-NEXT:.LBB0_2: # %true -; CAHP-NEXT: jalr a0 ; CAHP-NEXT: lwsp ra, 0(sp) ; CAHP-NEXT: addi2 sp, 2 ; CAHP-NEXT: jr ra ; CAHP-NEXT:.LBB0_3: # %false -; CAHP-NEXT: lui a0, %hi(test_false) -; CAHP-NEXT: addi a0, a0, %lo(test_false) +; CAHP-NEXT: jsal test_false ; CAHP-NEXT: js .LBB0_2 %tst = icmp eq i16 %in, 42 br i1 %tst, label %true, label %false, !prof !0 @@ -55,16 +52,13 @@ define void @test_bcc_fallthrough_nottaken(i16 %in) nounwind { ; CAHP-NEXT: li a1, 42 ; CAHP-NEXT: beq a0, a1, .LBB1_3 ; CAHP-NEXT:# %bb.1: # %false -; CAHP-NEXT: lui a0, %hi(test_false) -; CAHP-NEXT: addi a0, a0, %lo(test_false) +; CAHP-NEXT: jsal test_false ; CAHP-NEXT:.LBB1_2: # %true -; CAHP-NEXT: jalr a0 ; CAHP-NEXT: lwsp ra, 0(sp) ; CAHP-NEXT: addi2 sp, 2 ; CAHP-NEXT: jr ra ; CAHP-NEXT:.LBB1_3: # %true -; CAHP-NEXT: lui a0, %hi(test_true) -; CAHP-NEXT: addi a0, a0, %lo(test_true) +; CAHP-NEXT: jsal test_true ; CAHP-NEXT: js .LBB1_2 %tst = icmp eq i16 %in, 42 br i1 %tst, label %true, label %false, !prof !1 diff --git a/llvm/test/CodeGen/CAHP/calls.ll b/llvm/test/CodeGen/CAHP/calls.ll index 660034194c91..93e740af4ee5 100644 --- a/llvm/test/CodeGen/CAHP/calls.ll +++ b/llvm/test/CodeGen/CAHP/calls.ll @@ -9,9 +9,7 @@ define i16 @test_call_external(i16 %a) nounwind { ; CAHP: # %bb.0: ; CAHP-NEXT: addi2 sp, -2 ; CAHP-NEXT: swsp ra, 0(sp) -; CAHP-NEXT: lui a1, %hi(external_function) -; CAHP-NEXT: addi a1, a1, %lo(external_function) -; CAHP-NEXT: jalr a1 +; CAHP-NEXT: jsal external_function ; CAHP-NEXT: lwsp ra, 0(sp) ; CAHP-NEXT: addi2 sp, 2 ; CAHP-NEXT: jr ra @@ -33,9 +31,7 @@ define i16 @test_call_defined(i16 %a) nounwind { ; CAHP: # %bb.0: ; CAHP-NEXT: addi2 sp, -2 ; CAHP-NEXT: swsp ra, 0(sp) -; CAHP-NEXT: lui a1, %hi(defined_function) -; CAHP-NEXT: addi a1, a1, %lo(defined_function) -; CAHP-NEXT: jalr a1 +; CAHP-NEXT: jsal defined_function ; CAHP-NEXT: lwsp ra, 0(sp) ; CAHP-NEXT: addi2 sp, 2 ; CAHP-NEXT: jr ra @@ -75,10 +71,7 @@ define i16 @test_call_fastcc(i16 %a, i16 %b) nounwind { ; CAHP-NEXT: swsp ra, 2(sp) ; CAHP-NEXT: swsp s0, 0(sp) ; CAHP-NEXT: mov s0, a0 -; CAHP-NEXT: lui a0, %hi(fastcc_function) -; CAHP-NEXT: addi a2, a0, %lo(fastcc_function) -; CAHP-NEXT: mov a0, s0 -; CAHP-NEXT: jalr a2 +; CAHP-NEXT: jsal fastcc_function ; CAHP-NEXT: mov a0, s0 ; CAHP-NEXT: lwsp s0, 0(sp) ; CAHP-NEXT: lwsp ra, 2(sp) diff --git a/llvm/test/CodeGen/CAHP/frame.ll b/llvm/test/CodeGen/CAHP/frame.ll index f587920ebe79..6a88d65e843b 100644 --- a/llvm/test/CodeGen/CAHP/frame.ll +++ b/llvm/test/CodeGen/CAHP/frame.ll @@ -21,10 +21,8 @@ define i16 @test() nounwind { ; CAHP-NEXT: sw s0, -20(fp) ; CAHP-NEXT: sw s0, -22(fp) ; CAHP-NEXT: sw s0, -24(fp) -; CAHP-NEXT: lui a0, %hi(test1) -; CAHP-NEXT: addi a1, a0, %lo(test1) ; CAHP-NEXT: addi a0, fp, -22 -; CAHP-NEXT: jalr a1 +; CAHP-NEXT: jsal test1 ; CAHP-NEXT: mov a0, s0 ; CAHP-NEXT: addi sp, fp, -24 ; CAHP-NEXT: lwsp s0, 18(sp) diff --git a/llvm/test/CodeGen/CAHP/frameindex.ll b/llvm/test/CodeGen/CAHP/frameindex.ll index fcddb9c3e98a..e790f255877e 100644 --- a/llvm/test/CodeGen/CAHP/frameindex.ll +++ b/llvm/test/CodeGen/CAHP/frameindex.ll @@ -9,10 +9,8 @@ define i16 @foo() { ; CAHP: # %bb.0: ; CAHP-NEXT: addi2 sp, -4 ; CAHP-NEXT: swsp ra, 2(sp) -; CAHP-NEXT: lui a0, %hi(bar) -; CAHP-NEXT: addi a1, a0, %lo(bar) ; CAHP-NEXT: addi a0, sp, 0 -; CAHP-NEXT: jalr a1 +; CAHP-NEXT: jsal bar ; CAHP-NEXT: lwsp a0, 0(sp) ; CAHP-NEXT: lwsp ra, 2(sp) ; CAHP-NEXT: addi2 sp, 4 From 4c5dd31793d429cdd3d778d458f8d876782b0f8b Mon Sep 17 00:00:00 2001 From: Ushitora Anqou Date: Sat, 9 Nov 2019 21:29:01 +0900 Subject: [PATCH 269/289] [CAHP] Expand mul into __mulhi3/__mulsi3 --- llvm/lib/Target/CAHP/CAHPISelLowering.cpp | 6 ++ llvm/test/CodeGen/CAHP/mul.ll | 81 +++++++++++++++++++++++ 2 files changed, 87 insertions(+) create mode 100644 llvm/test/CodeGen/CAHP/mul.ll diff --git a/llvm/lib/Target/CAHP/CAHPISelLowering.cpp b/llvm/lib/Target/CAHP/CAHPISelLowering.cpp index c3e5b491a22a..20410f082f89 100644 --- a/llvm/lib/Target/CAHP/CAHPISelLowering.cpp +++ b/llvm/lib/Target/CAHP/CAHPISelLowering.cpp @@ -52,6 +52,12 @@ CAHPTargetLowering::CAHPTargetLowering(const TargetMachine &TM, for (auto VT : {MVT::i1, MVT::i8}) setOperationAction(ISD::SIGN_EXTEND_INREG, VT, Expand); + setOperationAction(ISD::MUL, MVT::i16, Expand); + setOperationAction(ISD::SMUL_LOHI, MVT::i16, Expand); + setOperationAction(ISD::UMUL_LOHI, MVT::i16, Expand); + setOperationAction(ISD::MULHS, MVT::i16, Expand); + setOperationAction(ISD::MULHU, MVT::i16, Expand); + setBooleanContents(ZeroOrOneBooleanContent); // Function alignments (log2). diff --git a/llvm/test/CodeGen/CAHP/mul.ll b/llvm/test/CodeGen/CAHP/mul.ll new file mode 100644 index 000000000000..645d0f52e5f4 --- /dev/null +++ b/llvm/test/CodeGen/CAHP/mul.ll @@ -0,0 +1,81 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=cahp -verify-machineinstrs < %s \ +; RUN: | FileCheck %s -check-prefix=CAHP + +define i16 @square(i16 %a) nounwind { +; CAHP-LABEL: square: +; CAHP: # %bb.0: +; CAHP-NEXT: addi2 sp, -2 +; CAHP-NEXT: swsp ra, 0(sp) +; CAHP-NEXT: mov a1, a0 +; CAHP-NEXT: jsal __mulhi3 +; CAHP-NEXT: lwsp ra, 0(sp) +; CAHP-NEXT: addi2 sp, 2 +; CAHP-NEXT: jr ra + %1 = mul i16 %a, %a + ret i16 %1 +} + +define i16 @mul(i16 %a, i16 %b) nounwind { +; CAHP-LABEL: mul: +; CAHP: # %bb.0: +; CAHP-NEXT: addi2 sp, -2 +; CAHP-NEXT: swsp ra, 0(sp) +; CAHP-NEXT: jsal __mulhi3 +; CAHP-NEXT: lwsp ra, 0(sp) +; CAHP-NEXT: addi2 sp, 2 +; CAHP-NEXT: jr ra + %1 = mul i16 %a, %b + ret i16 %1 +} + +define i16 @mul_constant(i16 %a) nounwind { +; CAHP-LABEL: mul_constant: +; CAHP: # %bb.0: +; CAHP-NEXT: addi2 sp, -2 +; CAHP-NEXT: swsp ra, 0(sp) +; CAHP-NEXT: lsi a1, 5 +; CAHP-NEXT: jsal __mulhi3 +; CAHP-NEXT: lwsp ra, 0(sp) +; CAHP-NEXT: addi2 sp, 2 +; CAHP-NEXT: jr ra + %1 = mul i16 %a, 5 + ret i16 %1 +} + +define i16 @mul_pow2(i16 %a) nounwind { +; CAHP-LABEL: mul_pow2: +; CAHP: # %bb.0: +; CAHP-NEXT: lsli2 a0, 3 +; CAHP-NEXT: jr ra + %1 = mul i16 %a, 8 + ret i16 %1 +} + +define i32 @mul32(i32 %a, i32 %b) nounwind { +; CAHP-LABEL: mul32: +; CAHP: # %bb.0: +; CAHP-NEXT: addi2 sp, -2 +; CAHP-NEXT: swsp ra, 0(sp) +; CAHP-NEXT: jsal __mulsi3 +; CAHP-NEXT: lwsp ra, 0(sp) +; CAHP-NEXT: addi2 sp, 2 +; CAHP-NEXT: jr ra + %1 = mul i32 %a, %b + ret i32 %1 +} + +define i32 @mul32_constant(i32 %a) nounwind { +; CAHP-LABEL: mul32_constant: +; CAHP: # %bb.0: +; CAHP-NEXT: addi2 sp, -2 +; CAHP-NEXT: swsp ra, 0(sp) +; CAHP-NEXT: lsi a2, 5 +; CAHP-NEXT: lsi a3, 0 +; CAHP-NEXT: jsal __mulsi3 +; CAHP-NEXT: lwsp ra, 0(sp) +; CAHP-NEXT: addi2 sp, 2 +; CAHP-NEXT: jr ra + %1 = mul i32 %a, 5 + ret i32 %1 +} From 1b4a7760d5a3852b5fc5e8763ba126bebe1498f3 Mon Sep 17 00:00:00 2001 From: Ushitora Anqou Date: Sat, 9 Nov 2019 22:17:59 +0900 Subject: [PATCH 270/289] [CAHP] Expand div/rem into __udivhi3/__udivsi3/__divhi3/__divsi3/__umodhi3/__modhi3 --- llvm/lib/Target/CAHP/CAHPISelLowering.cpp | 7 ++ llvm/test/CodeGen/CAHP/div.ll | 134 ++++++++++++++++++++++ llvm/test/CodeGen/CAHP/rem.ll | 29 +++++ 3 files changed, 170 insertions(+) create mode 100644 llvm/test/CodeGen/CAHP/div.ll create mode 100644 llvm/test/CodeGen/CAHP/rem.ll diff --git a/llvm/lib/Target/CAHP/CAHPISelLowering.cpp b/llvm/lib/Target/CAHP/CAHPISelLowering.cpp index 20410f082f89..7cb2a5efe28e 100644 --- a/llvm/lib/Target/CAHP/CAHPISelLowering.cpp +++ b/llvm/lib/Target/CAHP/CAHPISelLowering.cpp @@ -58,6 +58,13 @@ CAHPTargetLowering::CAHPTargetLowering(const TargetMachine &TM, setOperationAction(ISD::MULHS, MVT::i16, Expand); setOperationAction(ISD::MULHU, MVT::i16, Expand); + setOperationAction(ISD::SREM, MVT::i16, Expand); + setOperationAction(ISD::SDIVREM, MVT::i16, Expand); + setOperationAction(ISD::SDIV, MVT::i16, Expand); + setOperationAction(ISD::UREM, MVT::i16, Expand); + setOperationAction(ISD::UDIVREM, MVT::i16, Expand); + setOperationAction(ISD::UDIV, MVT::i16, Expand); + setBooleanContents(ZeroOrOneBooleanContent); // Function alignments (log2). diff --git a/llvm/test/CodeGen/CAHP/div.ll b/llvm/test/CodeGen/CAHP/div.ll new file mode 100644 index 000000000000..8a1d475b744f --- /dev/null +++ b/llvm/test/CodeGen/CAHP/div.ll @@ -0,0 +1,134 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=cahp -verify-machineinstrs < %s \ +; RUN: | FileCheck %s -check-prefix=CAHP + +define i16 @udiv(i16 %a, i16 %b) nounwind { +; CAHP-LABEL: udiv: +; CAHP: # %bb.0: +; CAHP-NEXT: addi2 sp, -2 +; CAHP-NEXT: swsp ra, 0(sp) +; CAHP-NEXT: jsal __udivhi3 +; CAHP-NEXT: lwsp ra, 0(sp) +; CAHP-NEXT: addi2 sp, 2 +; CAHP-NEXT: jr ra + %1 = udiv i16 %a, %b + ret i16 %1 +} + +define i16 @udiv_constant(i16 %a) nounwind { +; CAHP-LABEL: udiv_constant: +; CAHP: # %bb.0: +; CAHP-NEXT: addi2 sp, -2 +; CAHP-NEXT: swsp ra, 0(sp) +; CAHP-NEXT: lsi a1, 5 +; CAHP-NEXT: jsal __udivhi3 +; CAHP-NEXT: lwsp ra, 0(sp) +; CAHP-NEXT: addi2 sp, 2 +; CAHP-NEXT: jr ra + %1 = udiv i16 %a, 5 + ret i16 %1 +} + +define i16 @udiv_pow2(i16 %a) nounwind { +; CAHP-LABEL: udiv_pow2: +; CAHP: # %bb.0: +; CAHP-NEXT: lsri2 a0, 3 +; CAHP-NEXT: jr ra + %1 = udiv i16 %a, 8 + ret i16 %1 +} + +define i32 @udiv32(i32 %a, i32 %b) nounwind { +; CAHP-LABEL: udiv32: +; CAHP: # %bb.0: +; CAHP-NEXT: addi2 sp, -2 +; CAHP-NEXT: swsp ra, 0(sp) +; CAHP-NEXT: jsal __udivsi3 +; CAHP-NEXT: lwsp ra, 0(sp) +; CAHP-NEXT: addi2 sp, 2 +; CAHP-NEXT: jr ra + %1 = udiv i32 %a, %b + ret i32 %1 +} + +define i32 @udiv32_constant(i32 %a) nounwind { +; CAHP-LABEL: udiv32_constant: +; CAHP: # %bb.0: +; CAHP-NEXT: addi2 sp, -2 +; CAHP-NEXT: swsp ra, 0(sp) +; CAHP-NEXT: lsi a2, 5 +; CAHP-NEXT: lsi a3, 0 +; CAHP-NEXT: jsal __udivsi3 +; CAHP-NEXT: lwsp ra, 0(sp) +; CAHP-NEXT: addi2 sp, 2 +; CAHP-NEXT: jr ra + %1 = udiv i32 %a, 5 + ret i32 %1 +} + +define i16 @sdiv(i16 %a, i16 %b) nounwind { +; CAHP-LABEL: sdiv: +; CAHP: # %bb.0: +; CAHP-NEXT: addi2 sp, -2 +; CAHP-NEXT: swsp ra, 0(sp) +; CAHP-NEXT: jsal __divhi3 +; CAHP-NEXT: lwsp ra, 0(sp) +; CAHP-NEXT: addi2 sp, 2 +; CAHP-NEXT: jr ra + %1 = sdiv i16 %a, %b + ret i16 %1 +} + +define i16 @sdiv_constant(i16 %a) nounwind { +; CAHP-LABEL: sdiv_constant: +; CAHP: # %bb.0: +; CAHP-NEXT: addi2 sp, -2 +; CAHP-NEXT: swsp ra, 0(sp) +; CAHP-NEXT: lsi a1, 5 +; CAHP-NEXT: jsal __divhi3 +; CAHP-NEXT: lwsp ra, 0(sp) +; CAHP-NEXT: addi2 sp, 2 +; CAHP-NEXT: jr ra + %1 = sdiv i16 %a, 5 + ret i16 %1 +} + +define i16 @sdiv_pow2(i16 %a) nounwind { +; CAHP-LABEL: sdiv_pow2: +; CAHP: # %bb.0: +; CAHP-NEXT: asri a1, a0, 15 +; CAHP-NEXT: lsri2 a1, 13 +; CAHP-NEXT: add2 a0, a1 +; CAHP-NEXT: asri2 a0, 3 +; CAHP-NEXT: jr ra + %1 = sdiv i16 %a, 8 + ret i16 %1 +} + +define i32 @sdiv32(i32 %a, i32 %b) nounwind { +; CAHP-LABEL: sdiv32: +; CAHP: # %bb.0: +; CAHP-NEXT: addi2 sp, -2 +; CAHP-NEXT: swsp ra, 0(sp) +; CAHP-NEXT: jsal __divsi3 +; CAHP-NEXT: lwsp ra, 0(sp) +; CAHP-NEXT: addi2 sp, 2 +; CAHP-NEXT: jr ra + %1 = sdiv i32 %a, %b + ret i32 %1 +} + +define i32 @sdiv32_constant(i32 %a) nounwind { +; CAHP-LABEL: sdiv32_constant: +; CAHP: # %bb.0: +; CAHP-NEXT: addi2 sp, -2 +; CAHP-NEXT: swsp ra, 0(sp) +; CAHP-NEXT: lsi a2, 5 +; CAHP-NEXT: lsi a3, 0 +; CAHP-NEXT: jsal __divsi3 +; CAHP-NEXT: lwsp ra, 0(sp) +; CAHP-NEXT: addi2 sp, 2 +; CAHP-NEXT: jr ra + %1 = sdiv i32 %a, 5 + ret i32 %1 +} diff --git a/llvm/test/CodeGen/CAHP/rem.ll b/llvm/test/CodeGen/CAHP/rem.ll new file mode 100644 index 000000000000..f7c34b5f0712 --- /dev/null +++ b/llvm/test/CodeGen/CAHP/rem.ll @@ -0,0 +1,29 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=cahp -verify-machineinstrs < %s \ +; RUN: | FileCheck %s -check-prefix=CAHP + +define i16 @urem(i16 %a, i16 %b) nounwind { +; CAHP-LABEL: urem: +; CAHP: # %bb.0: +; CAHP-NEXT: addi2 sp, -2 +; CAHP-NEXT: swsp ra, 0(sp) +; CAHP-NEXT: jsal __umodhi3 +; CAHP-NEXT: lwsp ra, 0(sp) +; CAHP-NEXT: addi2 sp, 2 +; CAHP-NEXT: jr ra + %1 = urem i16 %a, %b + ret i16 %1 +} + +define i16 @srem(i16 %a, i16 %b) nounwind { +; CAHP-LABEL: srem: +; CAHP: # %bb.0: +; CAHP-NEXT: addi2 sp, -2 +; CAHP-NEXT: swsp ra, 0(sp) +; CAHP-NEXT: jsal __modhi3 +; CAHP-NEXT: lwsp ra, 0(sp) +; CAHP-NEXT: addi2 sp, 2 +; CAHP-NEXT: jr ra + %1 = srem i16 %a, %b + ret i16 %1 +} From 7bf51dd8b1b103a4377f385cb42a7e8ac2f07546 Mon Sep 17 00:00:00 2001 From: Ushitora Anqou Date: Sat, 9 Nov 2019 22:38:31 +0900 Subject: [PATCH 271/289] [CAHP] Add hlt pseudo instruction --- llvm/lib/Target/CAHP/CAHPInstrInfo.td | 5 +++++ .../CAHP/MCTargetDesc/CAHPMCCodeEmitter.cpp | 22 +++++++++++++++++++ llvm/test/MC/CAHP/hlt.s | 9 ++++++++ 3 files changed, 36 insertions(+) create mode 100644 llvm/test/MC/CAHP/hlt.s diff --git a/llvm/lib/Target/CAHP/CAHPInstrInfo.td b/llvm/lib/Target/CAHP/CAHPInstrInfo.td index 47be23112a37..c3bcbc0e0f17 100644 --- a/llvm/lib/Target/CAHP/CAHPInstrInfo.td +++ b/llvm/lib/Target/CAHP/CAHPInstrInfo.td @@ -362,6 +362,11 @@ def Select_GPR_Using_CC_GPR [(set i16:$dst, (SelectCC GPR:$lhs, GPR:$rhs, (i16 imm:$imm), GPR:$src, GPR:$src2))]>; +let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isCodeGenOnly = 0 in +def PseudoHLT : Pseudo16<(outs), (ins), []> { + let AsmString = "hlt"; +} + // Codegen patterns. /// FrameIndex calculations diff --git a/llvm/lib/Target/CAHP/MCTargetDesc/CAHPMCCodeEmitter.cpp b/llvm/lib/Target/CAHP/MCTargetDesc/CAHPMCCodeEmitter.cpp index 17859dd88761..226092a4938c 100644 --- a/llvm/lib/Target/CAHP/MCTargetDesc/CAHPMCCodeEmitter.cpp +++ b/llvm/lib/Target/CAHP/MCTargetDesc/CAHPMCCodeEmitter.cpp @@ -11,6 +11,7 @@ #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" +#include "llvm/MC/MCInstBuilder.h" #include "llvm/MC/MCInstrDesc.h" #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCRegisterInfo.h" @@ -58,6 +59,11 @@ class CAHPMCCodeEmitter : public MCCodeEmitter { unsigned getImmOpValue(const MCInst &MI, unsigned OpNo, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; + +private: + void expandHlt(const MCInst &MI, raw_ostream &OS, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; }; } // end anonymous namespace @@ -67,10 +73,26 @@ MCCodeEmitter *llvm::createCAHPMCCodeEmitter(const MCInstrInfo &MCII, return new CAHPMCCodeEmitter(Ctx, MCII); } +void CAHPMCCodeEmitter::expandHlt(const MCInst &MI, raw_ostream &OS, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + // Emit `js 0` + MCInst TmpInst = MCInstBuilder(CAHP::JS).addImm(0); + uint16_t Bits = getBinaryCodeForInstr(TmpInst, Fixups, STI); + support::endian::write(OS, Bits, support::little); +} + void CAHPMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS, SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const { const MCInstrDesc &Desc = MCII.get(MI.getOpcode()); + + if (MI.getOpcode() == CAHP::PseudoHLT) { + expandHlt(MI, OS, Fixups, STI); + MCNumEmitted += 2; + return; + } + // Get byte count of instruction. unsigned Size = Desc.getSize(); diff --git a/llvm/test/MC/CAHP/hlt.s b/llvm/test/MC/CAHP/hlt.s new file mode 100644 index 000000000000..b4225aa568d3 --- /dev/null +++ b/llvm/test/MC/CAHP/hlt.s @@ -0,0 +1,9 @@ +# RUN: llvm-mc %s -triple=cahp -show-encoding \ +# RUN: | FileCheck -check-prefixes=CHECK,CHECK-INST %s +# RUN: llvm-mc -filetype=obj -triple=cahp < %s \ +# RUN: | llvm-objdump -d - | FileCheck -check-prefix=CHECK-INSTDUMP %s + +# CHECK-INST: hlt +# CHECK-INSTDUMP: js 0 +# CHECK: encoding: [0x0e,0x00] +hlt From b76b67f2a96b728d964e3293124536ac53d4da87 Mon Sep 17 00:00:00 2001 From: Ushitora Anqou Date: Sun, 10 Nov 2019 14:39:29 +0900 Subject: [PATCH 272/289] [CAHP] Link crt0.s unless -nostdlib or -nostartfiles specified --- clang/lib/Driver/ToolChains/CAHP.cpp | 31 +++++++++++++++++++++------- clang/lib/Driver/ToolChains/CAHP.h | 4 +--- 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/clang/lib/Driver/ToolChains/CAHP.cpp b/clang/lib/Driver/ToolChains/CAHP.cpp index 7855b710a431..6202239681a6 100644 --- a/clang/lib/Driver/ToolChains/CAHP.cpp +++ b/clang/lib/Driver/ToolChains/CAHP.cpp @@ -14,24 +14,41 @@ using namespace clang::driver::tools; using namespace clang; using namespace llvm::opt; +CAHPToolChain::CAHPToolChain(const Driver &D, const llvm::Triple &Triple, + const llvm::opt::ArgList &Args) + : Generic_ELF(D, Triple, Args) { + if (!D.SysRoot.empty()) + getFilePaths().push_back(D.SysRoot); +} + Tool *CAHPToolChain::buildLinker() const { return new tools::CAHP::Linker(*this); } void CAHP::Linker::ConstructJob(Compilation &C, const JobAction &JA, - const InputInfo &Output, - const InputInfoList &Inputs, - const ArgList &Args, - const char *LinkingOutput) const { + const InputInfo &Output, + const InputInfoList &Inputs, + const ArgList &Args, + const char *LinkingOutput) const { const ToolChain &ToolChain = getToolChain(); + const Driver &D = ToolChain.getDriver(); ArgStringList CmdArgs; + if (!D.SysRoot.empty()) + CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot)); std::string Linker = getToolChain().GetProgramPath(getShortName()); - AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA); + bool WantCRTs = + !Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles); - // The beginning of .text section should be placed address 0. - CmdArgs.push_back("-Ttext=0"); + if (WantCRTs) { + CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crt0.o"))); + } + + Args.AddAllArgs(CmdArgs, options::OPT_L); + ToolChain.AddFilePathLibArgs(Args, CmdArgs); + + AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA); CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); diff --git a/clang/lib/Driver/ToolChains/CAHP.h b/clang/lib/Driver/ToolChains/CAHP.h index ad5b89cea9d7..08f890e36e95 100644 --- a/clang/lib/Driver/ToolChains/CAHP.h +++ b/clang/lib/Driver/ToolChains/CAHP.h @@ -15,8 +15,7 @@ namespace toolchains { class LLVM_LIBRARY_VISIBILITY CAHPToolChain : public Generic_ELF { public: CAHPToolChain(const Driver &D, const llvm::Triple &Triple, - const llvm::opt::ArgList &Args) - : Generic_ELF(D, Triple, Args) {} + const llvm::opt::ArgList &Args); bool IsIntegratedAssemblerDefault() const override { return true; } @@ -39,7 +38,6 @@ class LLVM_LIBRARY_VISIBILITY CAHPToolChain : public Generic_ELF { } // end namespace toolchains - namespace tools { namespace CAHP { class LLVM_LIBRARY_VISIBILITY Linker : public GnuTool { From 4cda22efda4f7c3d35608c2566b3ff3188b41551 Mon Sep 17 00:00:00 2001 From: Ushitora Anqou Date: Sun, 10 Nov 2019 14:40:05 +0900 Subject: [PATCH 273/289] [CAHP] Use linker script chap.lds as default --- clang/lib/Driver/ToolChains/CAHP.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/clang/lib/Driver/ToolChains/CAHP.cpp b/clang/lib/Driver/ToolChains/CAHP.cpp index 6202239681a6..e73450268ea5 100644 --- a/clang/lib/Driver/ToolChains/CAHP.cpp +++ b/clang/lib/Driver/ToolChains/CAHP.cpp @@ -50,6 +50,9 @@ void CAHP::Linker::ConstructJob(Compilation &C, const JobAction &JA, AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA); + CmdArgs.push_back( + Args.MakeArgString("--script=" + ToolChain.GetFilePath("cahp.lds"))); + CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); C.addCommand(llvm::make_unique(JA, *this, Args.MakeArgString(Linker), From 7bab48a6b5b6f8282653739cf03f35c55ed62ae8 Mon Sep 17 00:00:00 2001 From: Ushitora Anqou Date: Sun, 10 Nov 2019 14:47:33 +0900 Subject: [PATCH 274/289] [CAHP] Set LLD's --nmagic option to make output smaller --- clang/lib/Driver/ToolChains/CAHP.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/clang/lib/Driver/ToolChains/CAHP.cpp b/clang/lib/Driver/ToolChains/CAHP.cpp index e73450268ea5..5ab7b35bb4cc 100644 --- a/clang/lib/Driver/ToolChains/CAHP.cpp +++ b/clang/lib/Driver/ToolChains/CAHP.cpp @@ -53,6 +53,9 @@ void CAHP::Linker::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back( Args.MakeArgString("--script=" + ToolChain.GetFilePath("cahp.lds"))); + // To make the output as small as possible. + CmdArgs.push_back("--nmagic"); + CmdArgs.push_back("-o"); CmdArgs.push_back(Output.getFilename()); C.addCommand(llvm::make_unique(JA, *this, Args.MakeArgString(Linker), From 7e63f8893bc8409ef5789193450721be0663c6b1 Mon Sep 17 00:00:00 2001 From: Ushitora Anqou Date: Sun, 10 Nov 2019 14:51:27 +0900 Subject: [PATCH 275/289] [CAHP] Enable linking of libc unless -nostdlib or -nodefaultlibs specified --- clang/lib/Driver/ToolChains/CAHP.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/clang/lib/Driver/ToolChains/CAHP.cpp b/clang/lib/Driver/ToolChains/CAHP.cpp index 5ab7b35bb4cc..bc7efbc460a4 100644 --- a/clang/lib/Driver/ToolChains/CAHP.cpp +++ b/clang/lib/Driver/ToolChains/CAHP.cpp @@ -50,6 +50,11 @@ void CAHP::Linker::ConstructJob(Compilation &C, const JobAction &JA, AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA); + if (!Args.hasArg(options::OPT_nostdlib) && + !Args.hasArg(options::OPT_nodefaultlibs)) { + CmdArgs.push_back("-lc"); + } + CmdArgs.push_back( Args.MakeArgString("--script=" + ToolChain.GetFilePath("cahp.lds"))); From 04c5758074551048c7f5642f6e499f795f336176 Mon Sep 17 00:00:00 2001 From: Ushitora Anqou Date: Wed, 20 Nov 2019 16:06:42 +0900 Subject: [PATCH 276/289] [CAHP] Reject bare symbols for simm10 operands of arithmetic instructions --- .../Target/CAHP/AsmParser/CAHPAsmParser.cpp | 13 +++++++--- llvm/lib/Target/CAHP/CAHPInstrInfo.td | 2 +- llvm/test/MC/CAHP/cahp-invalid.s | 26 ++++++++++--------- 3 files changed, 25 insertions(+), 16 deletions(-) diff --git a/llvm/lib/Target/CAHP/AsmParser/CAHPAsmParser.cpp b/llvm/lib/Target/CAHP/AsmParser/CAHPAsmParser.cpp index 52f76312c1b3..23ff8c109227 100644 --- a/llvm/lib/Target/CAHP/AsmParser/CAHPAsmParser.cpp +++ b/llvm/lib/Target/CAHP/AsmParser/CAHPAsmParser.cpp @@ -192,10 +192,12 @@ struct CAHPOperand : public MCParsedAsmOperand { else IsValid = CAHPAsmParser::classifySymbolRef(getImm(), VK, Imm); - return IsValid && - (VK == CAHPMCExpr::VK_CAHP_None || VK == CAHPMCExpr::VK_CAHP_LO); + return IsValid && ((IsConstantImm && VK == CAHPMCExpr::VK_CAHP_None) || + VK == CAHPMCExpr::VK_CAHP_LO); } + bool isBareSImm10() const { return isBareImm(isInt<10>); } + bool isSImm11() const { return isBareImm(isInt<11>); } bool isUImm7Lsb0() const { return isBareImm(isShiftedUInt<6, 1>); } @@ -364,9 +366,14 @@ bool CAHPAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, CASE_MATCH_INVALID_UIMM(4); CASE_MATCH_INVALID_SIMM(6); - CASE_MATCH_INVALID_SIMM(10); CASE_MATCH_INVALID_SIMM(11); CASE_MATCH_INVALID_UIMM_LSB0(7); + + case Match_InvalidSImm10: + return generateImmOutOfRangeError( + Operands, ErrorInfo, -(1 << 9), (1 << 9) - 1, + "operand must be a symbol with %lo modifier or an integer in " + "the range"); } llvm_unreachable("Unknown match type detected!"); diff --git a/llvm/lib/Target/CAHP/CAHPInstrInfo.td b/llvm/lib/Target/CAHP/CAHPInstrInfo.td index c3bcbc0e0f17..5fb4a362197e 100644 --- a/llvm/lib/Target/CAHP/CAHPInstrInfo.td +++ b/llvm/lib/Target/CAHP/CAHPInstrInfo.td @@ -78,7 +78,7 @@ def simm10 : Operand, ImmLeaf(Imm);}]> { } def simm10_branch : Operand { - let ParserMatchClass = SImmAsmOperand<10>; + let ParserMatchClass = ImmAsmOperand<"BareS", 10, "">; let DecoderMethod = "decodeSImmOperand<10>"; let EncoderMethod = "getImmOpValue"; } diff --git a/llvm/test/MC/CAHP/cahp-invalid.s b/llvm/test/MC/CAHP/cahp-invalid.s index ca0af3855372..fcd661bb7b4f 100644 --- a/llvm/test/MC/CAHP/cahp-invalid.s +++ b/llvm/test/MC/CAHP/cahp-invalid.s @@ -1,17 +1,18 @@ # RUN: not llvm-mc -triple cahp < %s 2>&1 | FileCheck %s # Out of range immediates -lw a4, 512(a2) # CHECK: :[[@LINE]]:8: error: immediate must be an integer in the range [-512, 511] -lb a4, -513(a2) # CHECK: :[[@LINE]]:8: error: immediate must be an integer in the range [-512, 511] -lbu a4, -513(a2) # CHECK: :[[@LINE]]:9: error: immediate must be an integer in the range [-512, 511] -sw a4, -513(a2) # CHECK: :[[@LINE]]:8: error: immediate must be an integer in the range [-512, 511] -sb a4, 512(a2) # CHECK: :[[@LINE]]:8: error: immediate must be an integer in the range [-512, 511] -li t0, -513 # CHECK: :[[@LINE]]:8: error: immediate must be an integer in the range [-512, 511] -li s0, 512 # CHECK: :[[@LINE]]:8: error: immediate must be an integer in the range [-512, 511] -addi a0, a1, 512 # CHECK: :[[@LINE]]:14: error: immediate must be an integer in the range [-512, 511] -addi a0, a1, -513 # CHECK: :[[@LINE]]:14: error: immediate must be an integer in the range [-512, 511] -andi a0, a1, 512 # CHECK: :[[@LINE]]:14: error: immediate must be an integer in the range [-512, 511] -xori a0, a1, -513 # CHECK: :[[@LINE]]:14: error: immediate must be an integer in the range [-512, 511] +#operand must be a symbol with %lo modifier or an integer in the range [-512, 511] +lw a4, 512(a2) # CHECK: :[[@LINE]]:8: error: operand must be a symbol with %lo modifier or an integer in the range [-512, 511] +lb a4, -513(a2) # CHECK: :[[@LINE]]:8: error: operand must be a symbol with %lo modifier or an integer in the range [-512, 511] +lbu a4, -513(a2) # CHECK: :[[@LINE]]:9: error: operand must be a symbol with %lo modifier or an integer in the range [-512, 511] +sw a4, -513(a2) # CHECK: :[[@LINE]]:8: error: operand must be a symbol with %lo modifier or an integer in the range [-512, 511] +sb a4, 512(a2) # CHECK: :[[@LINE]]:8: error: operand must be a symbol with %lo modifier or an integer in the range [-512, 511] +li t0, -513 # CHECK: :[[@LINE]]:8: error: operand must be a symbol with %lo modifier or an integer in the range [-512, 511] +li s0, 512 # CHECK: :[[@LINE]]:8: error: operand must be a symbol with %lo modifier or an integer in the range [-512, 511] +addi a0, a1, 512 # CHECK: :[[@LINE]]:14: error: operand must be a symbol with %lo modifier or an integer in the range [-512, 511] +addi a0, a1, -513 # CHECK: :[[@LINE]]:14: error: operand must be a symbol with %lo modifier or an integer in the range [-512, 511] +andi a0, a1, 512 # CHECK: :[[@LINE]]:14: error: operand must be a symbol with %lo modifier or an integer in the range [-512, 511] +xori a0, a1, -513 # CHECK: :[[@LINE]]:14: error: operand must be a symbol with %lo modifier or an integer in the range [-512, 511] lsli a0, a1, 16 # CHECK: :[[@LINE]]:14: error: immediate must be an integer in the range [0, 15] asri a0, a1, -1 # CHECK: :[[@LINE]]:14: error: immediate must be an integer in the range [0, 15] lwsp a4, 128(sp) # CHECK: :[[@LINE]]:10: error: immediate must be a multiple of 2 bytes in the range [0, 126] @@ -45,7 +46,8 @@ mov x13 # CHECK: :[[@LINE]]:1: error: too few operands for instruction # Illegal operand modifier lsli a0, a0, %lo(1) # CHECK: :[[@LINE]]:14: error: immediate must be an integer in the range [0, 15] -ori a0, a1, %hi(foo) # CHECK: :[[@LINE]]:13: error: immediate must be an integer in the range [-512, 511] +ori a0, a1, %hi(foo) # CHECK: :[[@LINE]]:13: error: operand must be a symbol with %lo modifier or an integer in the range [-512, 511] lui a0, %lo(1) # CHECK: :[[@LINE]]:9: error: immediate must be an integer in the range [-32, 31] addi t0, sp, %modifer(255) # CHECK: :[[@LINE]]:15: error: unrecognized operand modifier addi t1, %lo(t2), 1 # CHECK: :[[@LINE]]:10: error: invalid operand for instruction +addi a0, a1, foo # CHECK: :[[@LINE]]:14: error: operand must be a symbol with %lo modifier or an integer in the range [-512, 511] From b67a802f90f8214073a16aab6fc5dcdf85aa6143 Mon Sep 17 00:00:00 2001 From: Ushitora Anqou Date: Fri, 22 Nov 2019 17:23:33 +0900 Subject: [PATCH 277/289] [CAHP] Reject bare symbols for simm6 operands --- llvm/lib/Target/CAHP/AsmParser/CAHPAsmParser.cpp | 11 ++++++++--- llvm/test/MC/CAHP/cahp-invalid.s | 11 ++++++----- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/llvm/lib/Target/CAHP/AsmParser/CAHPAsmParser.cpp b/llvm/lib/Target/CAHP/AsmParser/CAHPAsmParser.cpp index 23ff8c109227..8f93e54c42db 100644 --- a/llvm/lib/Target/CAHP/AsmParser/CAHPAsmParser.cpp +++ b/llvm/lib/Target/CAHP/AsmParser/CAHPAsmParser.cpp @@ -174,8 +174,8 @@ struct CAHPOperand : public MCParsedAsmOperand { else IsValid = CAHPAsmParser::classifySymbolRef(getImm(), VK, Imm); - return IsValid && - (VK == CAHPMCExpr::VK_CAHP_None || VK == CAHPMCExpr::VK_CAHP_HI); + return IsValid && ((IsConstantImm && VK == CAHPMCExpr::VK_CAHP_None) || + VK == CAHPMCExpr::VK_CAHP_HI); } bool isSImm10() const { @@ -365,10 +365,15 @@ bool CAHPAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, "immediate must be a multiple of 2 bytes in the range"); CASE_MATCH_INVALID_UIMM(4); - CASE_MATCH_INVALID_SIMM(6); CASE_MATCH_INVALID_SIMM(11); CASE_MATCH_INVALID_UIMM_LSB0(7); + case Match_InvalidSImm6: + return generateImmOutOfRangeError( + Operands, ErrorInfo, -(1 << 5), (1 << 5) - 1, + "operand must be a symbol with %hi modifier or an integer in " + "the range"); + case Match_InvalidSImm10: return generateImmOutOfRangeError( Operands, ErrorInfo, -(1 << 9), (1 << 9) - 1, diff --git a/llvm/test/MC/CAHP/cahp-invalid.s b/llvm/test/MC/CAHP/cahp-invalid.s index fcd661bb7b4f..73ea4237e8f6 100644 --- a/llvm/test/MC/CAHP/cahp-invalid.s +++ b/llvm/test/MC/CAHP/cahp-invalid.s @@ -17,10 +17,10 @@ lsli a0, a1, 16 # CHECK: :[[@LINE]]:14: error: immediate must be an integer in t asri a0, a1, -1 # CHECK: :[[@LINE]]:14: error: immediate must be an integer in the range [0, 15] lwsp a4, 128(sp) # CHECK: :[[@LINE]]:10: error: immediate must be a multiple of 2 bytes in the range [0, 126] swsp a3, -2(sp) # CHECK: :[[@LINE]]:10: error: immediate must be a multiple of 2 bytes in the range [0, 126] -lsi a5, 32 # CHECK: :[[@LINE]]:9: error: immediate must be an integer in the range [-32, 31] -lsi a5, -33 # CHECK: :[[@LINE]]:9: error: immediate must be an integer in the range [-32, 31] -lui a5, 32 # CHECK: :[[@LINE]]:9: error: immediate must be an integer in the range [-32, 31] -lui a5, -33 # CHECK: :[[@LINE]]:9: error: immediate must be an integer in the range [-32, 31] +lsi a5, 32 # CHECK: :[[@LINE]]:9: error: operand must be a symbol with %hi modifier or an integer in the range [-32, 31] +lsi a5, -33 # CHECK: :[[@LINE]]:9: error: operand must be a symbol with %hi modifier or an integer in the range [-32, 31] +lui a5, 32 # CHECK: :[[@LINE]]:9: error: operand must be a symbol with %hi modifier or an integer in the range [-32, 31] +lui a5, -33 # CHECK: :[[@LINE]]:9: error: operand must be a symbol with %hi modifier or an integer in the range [-32, 31] js 1024 # CHECK: :[[@LINE]]:4: error: immediate must be an integer in the range [-1024, 1023] js -1025 # CHECK: :[[@LINE]]:4: error: immediate must be an integer in the range [-1024, 1023] @@ -47,7 +47,8 @@ mov x13 # CHECK: :[[@LINE]]:1: error: too few operands for instruction # Illegal operand modifier lsli a0, a0, %lo(1) # CHECK: :[[@LINE]]:14: error: immediate must be an integer in the range [0, 15] ori a0, a1, %hi(foo) # CHECK: :[[@LINE]]:13: error: operand must be a symbol with %lo modifier or an integer in the range [-512, 511] -lui a0, %lo(1) # CHECK: :[[@LINE]]:9: error: immediate must be an integer in the range [-32, 31] +lui a0, %lo(1) # CHECK: :[[@LINE]]:9: error: operand must be a symbol with %hi modifier or an integer in the range [-32, 31] addi t0, sp, %modifer(255) # CHECK: :[[@LINE]]:15: error: unrecognized operand modifier addi t1, %lo(t2), 1 # CHECK: :[[@LINE]]:10: error: invalid operand for instruction addi a0, a1, foo # CHECK: :[[@LINE]]:14: error: operand must be a symbol with %lo modifier or an integer in the range [-512, 511] +addi2 a0, foo # CHECK: :[[@LINE]]:11: error: operand must be a symbol with %hi modifier or an integer in the range [-32, 31] From 02670cc44cc3c391b7bccce4aa1a480723a9922a Mon Sep 17 00:00:00 2001 From: Ushitora Anqou Date: Fri, 22 Nov 2019 17:40:25 +0900 Subject: [PATCH 278/289] [CAHP] uimm4 is 4-bit unsigned immediate --- llvm/lib/Target/CAHP/CAHPInstrInfo.td | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/llvm/lib/Target/CAHP/CAHPInstrInfo.td b/llvm/lib/Target/CAHP/CAHPInstrInfo.td index 5fb4a362197e..e834917d5a05 100644 --- a/llvm/lib/Target/CAHP/CAHPInstrInfo.td +++ b/llvm/lib/Target/CAHP/CAHPInstrInfo.td @@ -41,7 +41,7 @@ class UImmAsmOperand : ImmAsmOperand<"U", width, suffix> { } -def uimm4 : Operand, ImmLeaf(Imm);}]> { +def uimm4 : Operand, ImmLeaf(Imm);}]> { let ParserMatchClass = UImmAsmOperand<4>; let DecoderMethod = "decodeUImmOperand<4>"; let EncoderMethod = "getImmOpValue"; From 67cea36b9345d6574f94527ca3e7b2d0d5460f2a Mon Sep 17 00:00:00 2001 From: Ushitora Anqou Date: Sun, 8 Dec 2019 17:40:47 +0900 Subject: [PATCH 279/289] [CAHP] Handle invalid byte sequence correctly --- llvm/lib/Target/CAHP/CAHPInstrFormats.td | 35 ++++++++++++++++--- llvm/lib/Target/CAHP/CAHPInstrInfo.td | 24 ++++++------- .../disassemble-invalid-byte-sequences.test | 20 +++++++++++ .../tools/llvm-objdump/CAHP/lit.local.cfg | 2 ++ 4 files changed, 65 insertions(+), 16 deletions(-) create mode 100644 llvm/test/tools/llvm-objdump/CAHP/disassemble-invalid-byte-sequences.test create mode 100644 llvm/test/tools/llvm-objdump/CAHP/lit.local.cfg diff --git a/llvm/lib/Target/CAHP/CAHPInstrFormats.td b/llvm/lib/Target/CAHP/CAHPInstrFormats.td index 97af073d257b..e244a9625258 100644 --- a/llvm/lib/Target/CAHP/CAHPInstrFormats.td +++ b/llvm/lib/Target/CAHP/CAHPInstrFormats.td @@ -93,8 +93,8 @@ class CAHPInst24R opcode, dag outs, dag ins, string opcodestr, string ar let Inst{7-0} = opcode; } -// 24-bit I-instruction format. -class CAHPInst24I opcode, dag outs, dag ins, string opcodestr, string argstr> +// 24-bit I-instruction format for 10bit immediate. +class CAHPInst24I_10 opcode, dag outs, dag ins, string opcodestr, string argstr> : CAHPInst24 { bits<4> rd; bits<4> rs1; @@ -107,6 +107,21 @@ class CAHPInst24I opcode, dag outs, dag ins, string opcodestr, string ar let Inst{5-0} = opcode; } +// 24-bit I-instruction format for 4bit immediate. +class CAHPInst24I_4 opcode, dag outs, dag ins, string opcodestr, string argstr> +: CAHPInst24 { + bits<4> rd; + bits<4> rs1; + bits<4> imm; + + let Inst{23-20} = 0; + let Inst{19-16} = imm{3-0}; + let Inst{15-12} = rs1; + let Inst{11-8} = rd; + let Inst{7-6} = 0; + let Inst{5-0} = opcode; +} + // 24-bit J-instruction format. class CAHPInst24J opcode, dag ins, string opcodestr, string argstr> : CAHPInst24<(outs), ins, opcodestr, argstr> { @@ -149,8 +164,8 @@ class CAHPInst16R opcode, dag outs, dag ins, string opcodestr, string ar let Inst{7-0} = opcode; } -// 16-bit I-instruction format. -class CAHPInst16I opcode, dag outs, dag ins, string opcodestr, string argstr> +// 16-bit I-instruction format for 6bit immediate. +class CAHPInst16I_6 opcode, dag outs, dag ins, string opcodestr, string argstr> : CAHPInst16 { bits<4> rd; bits<6> imm; @@ -161,6 +176,18 @@ class CAHPInst16I opcode, dag outs, dag ins, string opcodestr, string ar let Inst{5-0} = opcode; } +// 16-bit I-instruction format for 4bit immediate. +class CAHPInst16I_4 opcode, dag outs, dag ins, string opcodestr, string argstr> +: CAHPInst16 { + bits<4> rd; + bits<4> imm; + + let Inst{15-12} = imm{3-0}; + let Inst{11-8} = rd; + let Inst{7-6} = 0; + let Inst{5-0} = opcode; +} + // 16-bit J-instruction format. class CAHPInst16JR opcode, dag ins, string opcodestr, string argstr> : CAHPInst16<(outs), ins, opcodestr, argstr> { diff --git a/llvm/lib/Target/CAHP/CAHPInstrInfo.td b/llvm/lib/Target/CAHP/CAHPInstrInfo.td index e834917d5a05..5bf643f03290 100644 --- a/llvm/lib/Target/CAHP/CAHPInstrInfo.td +++ b/llvm/lib/Target/CAHP/CAHPInstrInfo.td @@ -207,19 +207,19 @@ let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in { // 24-bit I-instructions. let hasSideEffects = 0, mayLoad = 0, mayStore = 0 in { - def ADDI : CAHPInst24I<0b000011, (outs GPR:$rd), (ins GPR:$rs1, simm10:$imm), + def ADDI : CAHPInst24I_10<0b000011, (outs GPR:$rd), (ins GPR:$rs1, simm10:$imm), "addi", "$rd, $rs1, $imm">; - def ANDI : CAHPInst24I<0b010011, (outs GPR:$rd), (ins GPR:$rs1, simm10:$imm), + def ANDI : CAHPInst24I_10<0b010011, (outs GPR:$rd), (ins GPR:$rs1, simm10:$imm), "andi", "$rd, $rs1, $imm">; - def XORI : CAHPInst24I<0b011011, (outs GPR:$rd), (ins GPR:$rs1, simm10:$imm), + def XORI : CAHPInst24I_10<0b011011, (outs GPR:$rd), (ins GPR:$rs1, simm10:$imm), "xori", "$rd, $rs1, $imm">; - def ORI : CAHPInst24I<0b100011, (outs GPR:$rd), (ins GPR:$rs1, simm10:$imm), + def ORI : CAHPInst24I_10<0b100011, (outs GPR:$rd), (ins GPR:$rs1, simm10:$imm), "ori", "$rd, $rs1, $imm">; - def LSLI : CAHPInst24I<0b101011, (outs GPR:$rd), (ins GPR:$rs1, uimm4:$imm), + def LSLI : CAHPInst24I_4 <0b101011, (outs GPR:$rd), (ins GPR:$rs1, uimm4:$imm), "lsli", "$rd, $rs1, $imm">; - def LSRI : CAHPInst24I<0b110011, (outs GPR:$rd), (ins GPR:$rs1, uimm4:$imm), + def LSRI : CAHPInst24I_4 <0b110011, (outs GPR:$rd), (ins GPR:$rs1, uimm4:$imm), "lsri", "$rd, $rs1, $imm">; - def ASRI : CAHPInst24I<0b111011, (outs GPR:$rd), (ins GPR:$rs1, uimm4:$imm), + def ASRI : CAHPInst24I_4 <0b111011, (outs GPR:$rd), (ins GPR:$rs1, uimm4:$imm), "asri", "$rd, $rs1, $imm">; } @@ -308,15 +308,15 @@ let hasSideEffects = 0, mayLoad = 0, mayStore = 0, let hasSideEffects = 0, mayLoad = 0, mayStore = 0, Constraints = "$rd = $rd_w" in { - def LSLI2 : CAHPInst16I<0b101010, (outs GPR:$rd_w), (ins GPR:$rd, uimm4:$imm), + def LSLI2 : CAHPInst16I_4<0b101010, (outs GPR:$rd_w), (ins GPR:$rd, uimm4:$imm), "lsli2", "$rd, $imm">; - def LSRI2 : CAHPInst16I<0b110010, (outs GPR:$rd_w), (ins GPR:$rd, uimm4:$imm), + def LSRI2 : CAHPInst16I_4<0b110010, (outs GPR:$rd_w), (ins GPR:$rd, uimm4:$imm), "lsri2", "$rd, $imm">; - def ASRI2 : CAHPInst16I<0b111010, (outs GPR:$rd_w), (ins GPR:$rd, uimm4:$imm), + def ASRI2 : CAHPInst16I_4<0b111010, (outs GPR:$rd_w), (ins GPR:$rd, uimm4:$imm), "asri2", "$rd, $imm">; - def ADDI2 : CAHPInst16I<0b000010, (outs GPR:$rd_w), (ins GPR:$rd, simm6:$imm), + def ADDI2 : CAHPInst16I_6<0b000010, (outs GPR:$rd_w), (ins GPR:$rd, simm6:$imm), "addi2", "$rd, $imm">; - def ANDI2 : CAHPInst16I<0b010010, (outs GPR:$rd_w), (ins GPR:$rd, simm6:$imm), + def ANDI2 : CAHPInst16I_6<0b010010, (outs GPR:$rd_w), (ins GPR:$rd, simm6:$imm), "andi2", "$rd, $imm">; } diff --git a/llvm/test/tools/llvm-objdump/CAHP/disassemble-invalid-byte-sequences.test b/llvm/test/tools/llvm-objdump/CAHP/disassemble-invalid-byte-sequences.test new file mode 100644 index 000000000000..15edf5135619 --- /dev/null +++ b/llvm/test/tools/llvm-objdump/CAHP/disassemble-invalid-byte-sequences.test @@ -0,0 +1,20 @@ +## Show that llvm-objdump handles invalid byte sequences, and continues. + +# RUN: yaml2obj %s -o %t.o +# RUN: llvm-objdump %t.o -d | FileCheck %s + +# CHECK: 00000000 .text: +# CHECK-NEXT: 0: 73 68 69 +# CHECK-NEXT: 3: 72 61 + +--- !ELF +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_CAHP +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [SHF_ALLOC, SHF_EXECINSTR] + Content: '7368697261' diff --git a/llvm/test/tools/llvm-objdump/CAHP/lit.local.cfg b/llvm/test/tools/llvm-objdump/CAHP/lit.local.cfg new file mode 100644 index 000000000000..9c4893bff785 --- /dev/null +++ b/llvm/test/tools/llvm-objdump/CAHP/lit.local.cfg @@ -0,0 +1,2 @@ +if "CAHP" not in config.root.targets: + config.unsupported = True From bd25923ae73990bd452e15ca689199f658da9a2a Mon Sep 17 00:00:00 2001 From: Ushitora Anqou Date: Sun, 8 Dec 2019 18:16:53 +0900 Subject: [PATCH 280/289] [CAHP] Pass arguments via stack when necessary --- llvm/lib/Target/CAHP/CAHPISelLowering.cpp | 59 +++++++++++---- llvm/test/CodeGen/CAHP/calls.ll | 90 +++++++++++++++++++++++ 2 files changed, 135 insertions(+), 14 deletions(-) diff --git a/llvm/lib/Target/CAHP/CAHPISelLowering.cpp b/llvm/lib/Target/CAHP/CAHPISelLowering.cpp index 7cb2a5efe28e..e4733429ec64 100644 --- a/llvm/lib/Target/CAHP/CAHPISelLowering.cpp +++ b/llvm/lib/Target/CAHP/CAHPISelLowering.cpp @@ -292,21 +292,36 @@ SDValue CAHPTargetLowering::LowerFormalArguments( CCInfo.AnalyzeFormalArguments(Ins, CC_CAHP); for (auto &VA : ArgLocs) { - if (!VA.isRegLoc()) - report_fatal_error("Defined with too many args"); - - // Arguments passed in registers. - EVT RegVT = VA.getLocVT(); - if (RegVT != MVT::i16) { - LLVM_DEBUG(dbgs() << "LowerFormalArguments Unhandled argument type: " - << RegVT.getEVTString() << "\n"); - report_fatal_error("unhandled argument type"); + SDValue ArgVal; + if (VA.isRegLoc()) { + // Arguments passed in registers. + EVT RegVT = VA.getLocVT(); + if (RegVT != MVT::i16) { + LLVM_DEBUG(dbgs() << "LowerFormalArguments Unhandled argument type: " + << RegVT.getEVTString() << "\n"); + report_fatal_error("unhandled argument type"); + } + const unsigned VReg = RegInfo.createVirtualRegister(&CAHP::GPRRegClass); + RegInfo.addLiveIn(VA.getLocReg(), VReg); + ArgVal = DAG.getCopyFromReg(Chain, DL, VReg, RegVT); + } else { + assert(VA.isMemLoc()); + assert(VA.getValVT() == MVT::i16); + assert(VA.getLocVT() == MVT::i16); + + // Create the frame index object for this incoming parameter. + int FI = + MF.getFrameInfo().CreateFixedObject(2, VA.getLocMemOffset(), true); + + // Create the SelectionDAG nodes corresponding to a load from this + // parameter. + SDValue FIN = DAG.getFrameIndex(FI, MVT::i16); + ArgVal = DAG.getLoad( + VA.getLocVT(), DL, Chain, FIN, + MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI)); } - const unsigned VReg = RegInfo.createVirtualRegister(&CAHP::GPRRegClass); - RegInfo.addLiveIn(VA.getLocReg(), VReg); - SDValue ArgIn = DAG.getCopyFromReg(Chain, DL, VReg, RegVT); - InVals.push_back(ArgIn); + InVals.push_back(ArgVal); } return Chain; } @@ -351,6 +366,8 @@ SDValue CAHPTargetLowering::LowerCall(CallLoweringInfo &CLI, // Copy argument values to their designated locations. SmallVector, 8> RegsToPass; + SmallVector MemOpChains; + SDValue StackPtr; for (unsigned I = 0, E = ArgLocs.size(); I != E; ++I) { CCValAssign &VA = ArgLocs[I]; SDValue ArgValue = OutVals[I]; @@ -369,10 +386,24 @@ SDValue CAHPTargetLowering::LowerCall(CallLoweringInfo &CLI, RegsToPass.push_back(std::make_pair(VA.getLocReg(), ArgValue)); } else { assert(VA.isMemLoc() && "Argument not register or memory"); - report_fatal_error("Passing arguments via the stack not yet implemented"); + + if (!StackPtr.getNode()) + StackPtr = DAG.getCopyFromReg(Chain, DL, CAHP::X1, MVT::i16); + + SDValue Address = + DAG.getNode(ISD::ADD, DL, MVT::i16, StackPtr, + DAG.getIntPtrConstant(VA.getLocMemOffset(), DL)); + + MemOpChains.push_back( + DAG.getStore(Chain, DL, ArgValue, Address, MachinePointerInfo())); } } + // Transform all store nodes into one single node because all store nodes are + // independent of each other. + if (!MemOpChains.empty()) + Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, MemOpChains); + SDValue Glue; // Build a sequence of copy-to-reg nodes, chained and glued together. diff --git a/llvm/test/CodeGen/CAHP/calls.ll b/llvm/test/CodeGen/CAHP/calls.ll index 93e740af4ee5..f6b4db00b9ef 100644 --- a/llvm/test/CodeGen/CAHP/calls.ll +++ b/llvm/test/CodeGen/CAHP/calls.ll @@ -81,3 +81,93 @@ define i16 @test_call_fastcc(i16 %a, i16 %b) nounwind { %1 = call fastcc i16 @fastcc_function(i16 %a, i16 %b) ret i16 %a } + +declare i16 @external_many_args(i16, i16, i16, i16, i16, i16, i16, i16, i16, i16) nounwind + +define i16 @test_call_external_many_args(i16 %a) nounwind { +; CAHP-LABEL: test_call_external_many_args: +; CAHP: # %bb.0: +; CAHP-NEXT: addi2 sp, -12 +; CAHP-NEXT: swsp ra, 10(sp) +; CAHP-NEXT: swsp s0, 8(sp) +; CAHP-NEXT: mov s0, a0 +; CAHP-NEXT: swsp a0, 6(sp) +; CAHP-NEXT: swsp a0, 4(sp) +; CAHP-NEXT: swsp a0, 2(sp) +; CAHP-NEXT: swsp a0, 0(sp) +; CAHP-NEXT: mov a1, a0 +; CAHP-NEXT: mov a2, a0 +; CAHP-NEXT: mov a3, a0 +; CAHP-NEXT: mov a4, a0 +; CAHP-NEXT: mov a5, a0 +; CAHP-NEXT: jsal external_many_args +; CAHP-NEXT: mov a0, s0 +; CAHP-NEXT: lwsp s0, 8(sp) +; CAHP-NEXT: lwsp ra, 10(sp) +; CAHP-NEXT: addi2 sp, 12 +; CAHP-NEXT: jr ra + %1 = call i16 @external_many_args(i16 %a, i16 %a, i16 %a, i16 %a, i16 %a, + i16 %a, i16 %a, i16 %a, i16 %a, i16 %a) + ret i16 %a +} + +define i16 @defined_many_args(i16, i16, i16, i16, i16, i16, i16, i16, i16, i16 %j) nounwind { +; CAHP-LABEL: defined_many_args: +; CAHP: # %bb.0: +; CAHP-NEXT: lwsp a0, 6(sp) +; CAHP-NEXT: addi2 a0, 1 +; CAHP-NEXT: jr ra + %added = add i16 %j, 1 + ret i16 %added +} + +define i16 @test_call_defined_many_args(i16 %a) nounwind { +; CAHP-LABEL: test_call_defined_many_args: +; CAHP: # %bb.0: +; CAHP-NEXT: addi2 sp, -10 +; CAHP-NEXT: swsp ra, 8(sp) +; CAHP-NEXT: swsp a0, 6(sp) +; CAHP-NEXT: swsp a0, 4(sp) +; CAHP-NEXT: swsp a0, 2(sp) +; CAHP-NEXT: swsp a0, 0(sp) +; CAHP-NEXT: mov a1, a0 +; CAHP-NEXT: mov a2, a0 +; CAHP-NEXT: mov a3, a0 +; CAHP-NEXT: mov a4, a0 +; CAHP-NEXT: mov a5, a0 +; CAHP-NEXT: jsal defined_many_args +; CAHP-NEXT: lwsp ra, 8(sp) +; CAHP-NEXT: addi2 sp, 10 +; CAHP-NEXT: jr ra + %1 = call i16 @defined_many_args(i16 %a, i16 %a, i16 %a, i16 %a, i16 %a, + i16 %a, i16 %a, i16 %a, i16 %a, i16 %a) + ret i16 %1 +} + +declare i16 @callee_i32_scalars(i16, i32, i32, i32, i32, i32, i32) + +define i16 @caller_i32_scalars(i32 %a) nounwind { +; CAHP-LABEL: caller_i32_scalars: +; CAHP: # %bb.0: +; CAHP-NEXT: addi2 sp, -16 +; CAHP-NEXT: swsp ra, 14(sp) +; CAHP-NEXT: mov a2, a1 +; CAHP-NEXT: mov a1, a0 +; CAHP-NEXT: swsp a2, 12(sp) +; CAHP-NEXT: swsp a0, 10(sp) +; CAHP-NEXT: swsp a2, 8(sp) +; CAHP-NEXT: swsp a0, 6(sp) +; CAHP-NEXT: swsp a2, 4(sp) +; CAHP-NEXT: swsp a0, 2(sp) +; CAHP-NEXT: swsp a2, 0(sp) +; CAHP-NEXT: li a0, 42 +; CAHP-NEXT: mov a3, a1 +; CAHP-NEXT: mov a4, a2 +; CAHP-NEXT: mov a5, a1 +; CAHP-NEXT: jsal callee_i32_scalars +; CAHP-NEXT: lwsp ra, 14(sp) +; CAHP-NEXT: addi2 sp, 16 +; CAHP-NEXT: jr ra + %1 = call i16 @callee_i32_scalars(i16 42, i32 %a, i32 %a, i32 %a, i32 %a, i32 %a, i32 %a) + ret i16 %1 +} From 9db6cd3b97c0bb1ea2243704d1e56e145f9e633a Mon Sep 17 00:00:00 2001 From: Ushitora Anqou Date: Sun, 8 Dec 2019 18:56:49 +0900 Subject: [PATCH 281/289] [CAHP] Add support for byval arguments --- llvm/lib/Target/CAHP/CAHPISelLowering.cpp | 29 +++++++++++-- llvm/test/CodeGen/CAHP/byval.ll | 50 +++++++++++++++++++++++ 2 files changed, 75 insertions(+), 4 deletions(-) create mode 100644 llvm/test/CodeGen/CAHP/byval.ll diff --git a/llvm/lib/Target/CAHP/CAHPISelLowering.cpp b/llvm/lib/Target/CAHP/CAHPISelLowering.cpp index e4733429ec64..f9987402e0b1 100644 --- a/llvm/lib/Target/CAHP/CAHPISelLowering.cpp +++ b/llvm/lib/Target/CAHP/CAHPISelLowering.cpp @@ -356,10 +356,27 @@ SDValue CAHPTargetLowering::LowerCall(CallLoweringInfo &CLI, // Get a count of how many bytes are to be pushed on the stack. unsigned NumBytes = ArgCCInfo.getNextStackOffset(); - for (auto &Arg : Outs) { - if (!Arg.Flags.isByVal()) + // Create local copies for byval args + SmallVector ByValArgs; + for (unsigned i = 0, e = Outs.size(); i != e; ++i) { + ISD::ArgFlagsTy Flags = Outs[i].Flags; + if (!Flags.isByVal()) continue; - report_fatal_error("Passing arguments byval not yet implemented"); + + SDValue Arg = OutVals[i]; + unsigned Size = Flags.getByValSize(); + unsigned Align = Flags.getByValAlign(); + + int FI = MF.getFrameInfo().CreateStackObject(Size, Align, + /*isSillSlot=*/false); + SDValue FIPtr = DAG.getFrameIndex(FI, MVT::i16); + SDValue SizeNode = DAG.getConstant(Size, DL, MVT::i16); + + Chain = DAG.getMemcpy(Chain, DL, FIPtr, Arg, SizeNode, Align, + /*IsVolatile=*/false, + /*AlwaysInline=*/false, CLI.IsTailCall, + MachinePointerInfo(), MachinePointerInfo()); + ByValArgs.push_back(FIPtr); } Chain = DAG.getCALLSEQ_START(Chain, NumBytes, 0, CLI.DL); @@ -368,9 +385,10 @@ SDValue CAHPTargetLowering::LowerCall(CallLoweringInfo &CLI, SmallVector, 8> RegsToPass; SmallVector MemOpChains; SDValue StackPtr; - for (unsigned I = 0, E = ArgLocs.size(); I != E; ++I) { + for (unsigned I = 0, J = 0, E = ArgLocs.size(); I != E; ++I) { CCValAssign &VA = ArgLocs[I]; SDValue ArgValue = OutVals[I]; + ISD::ArgFlagsTy Flags = Outs[I].Flags; // Promote the value if needed. // For now, only handle fully promoted arguments. @@ -381,6 +399,9 @@ SDValue CAHPTargetLowering::LowerCall(CallLoweringInfo &CLI, llvm_unreachable("Unknown loc info!"); } + if (Flags.isByVal()) + ArgValue = ByValArgs[J++]; + if (VA.isRegLoc()) { // Queue up the argument copies and emit them at the end. RegsToPass.push_back(std::make_pair(VA.getLocReg(), ArgValue)); diff --git a/llvm/test/CodeGen/CAHP/byval.ll b/llvm/test/CodeGen/CAHP/byval.ll new file mode 100644 index 000000000000..c9998bd20f54 --- /dev/null +++ b/llvm/test/CodeGen/CAHP/byval.ll @@ -0,0 +1,50 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=cahp -verify-machineinstrs < %s \ +; RUN: | FileCheck -check-prefix=CAHP %s + +%struct.Foo = type { i16, i16, i16, i16, i8 } +@foo = global %struct.Foo { i16 1, i16 2, i16 3, i16 4, i8 5 } + +define i16 @callee(%struct.Foo* byval %f) { +; CAHP-LABEL: callee: +; CAHP: # %bb.0: +; CAHP-NEXT: lw a0, 0(a0) +; CAHP-NEXT: jr ra + %1 = getelementptr inbounds %struct.Foo, %struct.Foo* %f, i32 0, i32 0 + %2 = load i16, i16* %1 + ret i16 %2 +} + +define void @caller() { +; CAHP-LABEL: caller: +; CAHP: # %bb.0: +; CAHP-NEXT: addi2 sp, -12 +; CAHP-NEXT: swsp ra, 10(sp) +; CAHP-NEXT: lui a0, %hi(foo+8) +; CAHP-NEXT: addi a0, a0, %lo(foo+8) +; CAHP-NEXT: lw a0, 0(a0) +; CAHP-NEXT: swsp a0, 8(sp) +; CAHP-NEXT: lui a0, %hi(foo+6) +; CAHP-NEXT: addi a0, a0, %lo(foo+6) +; CAHP-NEXT: lw a0, 0(a0) +; CAHP-NEXT: swsp a0, 6(sp) +; CAHP-NEXT: lui a0, %hi(foo+4) +; CAHP-NEXT: addi a0, a0, %lo(foo+4) +; CAHP-NEXT: lw a0, 0(a0) +; CAHP-NEXT: swsp a0, 4(sp) +; CAHP-NEXT: lui a0, %hi(foo+2) +; CAHP-NEXT: addi a0, a0, %lo(foo+2) +; CAHP-NEXT: lw a0, 0(a0) +; CAHP-NEXT: swsp a0, 2(sp) +; CAHP-NEXT: lui a0, %hi(foo) +; CAHP-NEXT: addi a0, a0, %lo(foo) +; CAHP-NEXT: lw a0, 0(a0) +; CAHP-NEXT: swsp a0, 0(sp) +; CAHP-NEXT: addi a0, sp, 0 +; CAHP-NEXT: jsal callee +; CAHP-NEXT: lwsp ra, 10(sp) +; CAHP-NEXT: addi2 sp, 12 +; CAHP-NEXT: jr ra + %call = call i16 @callee(%struct.Foo* byval @foo) + ret void +} From 6b4404268f05374ab6eb1cb6f253632c1f194bc3 Mon Sep 17 00:00:00 2001 From: Ushitora Anqou Date: Fri, 27 Dec 2019 13:04:50 +0900 Subject: [PATCH 282/289] [CAHP] Allow to pass -mcpu option to clang --- clang/lib/Basic/Targets/CAHP.cpp | 14 +++++++++++- clang/lib/Basic/Targets/CAHP.h | 10 +++++++-- clang/lib/Driver/CMakeLists.txt | 1 + clang/lib/Driver/ToolChains/Arch/CAHP.cpp | 21 ++++++++++++++++++ clang/lib/Driver/ToolChains/Arch/CAHP.h | 22 +++++++++++++++++++ clang/lib/Driver/ToolChains/CommonArgs.cpp | 4 ++++ llvm/lib/Target/CAHP/CAHP.td | 3 ++- llvm/lib/Target/CAHP/CAHPSubtarget.cpp | 2 +- .../CAHP/MCTargetDesc/CAHPMCTargetDesc.cpp | 2 +- 9 files changed, 73 insertions(+), 6 deletions(-) create mode 100644 clang/lib/Driver/ToolChains/Arch/CAHP.cpp create mode 100644 clang/lib/Driver/ToolChains/Arch/CAHP.h diff --git a/clang/lib/Basic/Targets/CAHP.cpp b/clang/lib/Basic/Targets/CAHP.cpp index c705c03f8d91..8318c0f33955 100644 --- a/clang/lib/Basic/Targets/CAHP.cpp +++ b/clang/lib/Basic/Targets/CAHP.cpp @@ -26,8 +26,20 @@ ArrayRef CAHPTargetInfo::getGCCRegAliases() const { } void CAHPTargetInfo::getTargetDefines(const LangOptions &Opts, - MacroBuilder &Builder) const { + MacroBuilder &Builder) const { Builder.defineMacro("__cahp__"); Builder.defineMacro("__cahpv3__"); } + +bool CAHPTargetInfo::isValidCPUName(StringRef Name) const { + if (Name == "generic") + return true; + + CPUKind CPU = llvm::StringSwitch(Name).Default(CK_NONE); + return CPU != CK_NONE; +} + +bool CAHPTargetInfo::setCPU(const std::string &Name) { + return isValidCPUName(Name); +} diff --git a/clang/lib/Basic/Targets/CAHP.h b/clang/lib/Basic/Targets/CAHP.h index 759f04380961..28e6200d86af 100644 --- a/clang/lib/Basic/Targets/CAHP.h +++ b/clang/lib/Basic/Targets/CAHP.h @@ -15,8 +15,11 @@ namespace targets { // CAHP Target class LLVM_LIBRARY_VISIBILITY CAHPTargetInfo : public TargetInfo { -protected: - std::string ABI; + // Class for CAHP. + // The CPU profiles supported by the CAHP backend + enum CPUKind { + CK_NONE, + }; public: CAHPTargetInfo(const llvm::Triple &Triple, const TargetOptions &) @@ -62,6 +65,9 @@ class LLVM_LIBRARY_VISIBILITY CAHPTargetInfo : public TargetInfo { void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const override; + bool isValidCPUName(StringRef Name) const override; + bool setCPU(const std::string &Name) override; + ArrayRef getTargetBuiltins() const override { return None; } BuiltinVaListKind getBuiltinVaListKind() const override { diff --git a/clang/lib/Driver/CMakeLists.txt b/clang/lib/Driver/CMakeLists.txt index d2dc61c85e5b..bee1f52e87f7 100644 --- a/clang/lib/Driver/CMakeLists.txt +++ b/clang/lib/Driver/CMakeLists.txt @@ -24,6 +24,7 @@ add_clang_library(clangDriver ToolChain.cpp ToolChains/Arch/AArch64.cpp ToolChains/Arch/ARM.cpp + ToolChains/Arch/CAHP.cpp ToolChains/Arch/Mips.cpp ToolChains/Arch/PPC.cpp ToolChains/Arch/RISCV.cpp diff --git a/clang/lib/Driver/ToolChains/Arch/CAHP.cpp b/clang/lib/Driver/ToolChains/Arch/CAHP.cpp new file mode 100644 index 000000000000..fce8c8670bd5 --- /dev/null +++ b/clang/lib/Driver/ToolChains/Arch/CAHP.cpp @@ -0,0 +1,21 @@ +// This file is copied and modified from The LLVM Compiler Infrastructure, which +// is distributed under the Apache License v2.0 with LLVM Exceptions (see +// LICENSE.TXT for details). This file is licensed under the same license. + +#include "CAHP.h" +#include "clang/Driver/Options.h" +#include "llvm/Option/ArgList.h" + +using namespace clang::driver; +using namespace clang::driver::tools; +using namespace llvm::opt; + +std::string cahp::getCAHPTargetCPU(const ArgList &Args) { + // If we have -mcpu, use that. + if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) { + return A->getValue(); + } + + // Otherwise use 'generic'. + return "generic"; +} diff --git a/clang/lib/Driver/ToolChains/Arch/CAHP.h b/clang/lib/Driver/ToolChains/Arch/CAHP.h new file mode 100644 index 000000000000..73e3a3f7f9c3 --- /dev/null +++ b/clang/lib/Driver/ToolChains/Arch/CAHP.h @@ -0,0 +1,22 @@ +// This file is copied and modified from The LLVM Compiler Infrastructure, which +// is distributed under the Apache License v2.0 with LLVM Exceptions (see +// LICENSE.TXT for details). This file is licensed under the same license. + +#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ARCH_CAHP_H +#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ARCH_CAHP_H + +#include "llvm/Option/Option.h" + +namespace clang { +namespace driver { +namespace tools { +namespace cahp { + +std::string getCAHPTargetCPU(const llvm::opt::ArgList &Args); + +} // namespace cahp +} // namespace tools +} // namespace driver +} // namespace clang + +#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_ARCH_CAHP_H diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index 99691cb43dc4..dd96b68ba568 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -9,6 +9,7 @@ #include "CommonArgs.h" #include "Arch/AArch64.h" #include "Arch/ARM.h" +#include "Arch/CAHP.h" #include "Arch/Mips.h" #include "Arch/PPC.h" #include "Arch/SystemZ.h" @@ -335,6 +336,9 @@ std::string tools::getCPUName(const ArgList &Args, const llvm::Triple &T, case llvm::Triple::wasm32: case llvm::Triple::wasm64: return getWebAssemblyTargetCPU(Args); + + case llvm::Triple::cahp: + return cahp::getCAHPTargetCPU(Args); } } diff --git a/llvm/lib/Target/CAHP/CAHP.td b/llvm/lib/Target/CAHP/CAHP.td index 39b8099d1496..224b6147618b 100644 --- a/llvm/lib/Target/CAHP/CAHP.td +++ b/llvm/lib/Target/CAHP/CAHP.td @@ -8,6 +8,7 @@ include "llvm/Target/Target.td" // Register file, calling conventions, instruction descriptions. //===----------------------------------------------------------------------===// +include "CAHPSchedule.td" include "CAHPRegisterInfo.td" include "CAHPCallingConv.td" include "CAHPInstrInfo.td" @@ -16,7 +17,7 @@ include "CAHPInstrInfo.td" // CAHP processors supported. //===----------------------------------------------------------------------===// -def : ProcessorModel<"generic-cahp", NoSchedModel, []>; +def : ProcessorModel<"generic", NoSchedModel, []>; //===----------------------------------------------------------------------===// // Define the CAHP target. diff --git a/llvm/lib/Target/CAHP/CAHPSubtarget.cpp b/llvm/lib/Target/CAHP/CAHPSubtarget.cpp index 7f26657b9a74..e78e8414e049 100644 --- a/llvm/lib/Target/CAHP/CAHPSubtarget.cpp +++ b/llvm/lib/Target/CAHP/CAHPSubtarget.cpp @@ -22,7 +22,7 @@ CAHPSubtarget &CAHPSubtarget::initializeSubtargetDependencies(StringRef CPU, // Determine default and user-specified characteristics std::string CPUName = CPU; if (CPUName.empty()) - CPUName = "generic-cahp"; + CPUName = "generic"; ParseSubtargetFeatures(CPUName, FS); return *this; } diff --git a/llvm/lib/Target/CAHP/MCTargetDesc/CAHPMCTargetDesc.cpp b/llvm/lib/Target/CAHP/MCTargetDesc/CAHPMCTargetDesc.cpp index bdd45e74c3df..5c85711b2920 100644 --- a/llvm/lib/Target/CAHP/MCTargetDesc/CAHPMCTargetDesc.cpp +++ b/llvm/lib/Target/CAHP/MCTargetDesc/CAHPMCTargetDesc.cpp @@ -49,7 +49,7 @@ static MCSubtargetInfo *createCAHPMCSubtargetInfo(const Triple &TT, StringRef CPU, StringRef FS) { std::string CPUName = CPU; if (CPUName.empty()) - CPUName = "generic-cahp"; + CPUName = "generic"; return createCAHPMCSubtargetInfoImpl(TT, CPUName, FS); } From d20c8f1b6628962c053c8ba2d242ee437ab95de8 Mon Sep 17 00:00:00 2001 From: Ushitora Anqou Date: Fri, 27 Dec 2019 16:28:07 +0900 Subject: [PATCH 283/289] [CAHP] Add WriteALU and WriteLDST to schedule intructions --- llvm/lib/Target/CAHP/CAHPInstrFormats.td | 45 +++++++++++++++++------- llvm/lib/Target/CAHP/CAHPInstrInfo.td | 10 +++--- llvm/lib/Target/CAHP/CAHPSchedule.td | 6 ++++ 3 files changed, 44 insertions(+), 17 deletions(-) create mode 100644 llvm/lib/Target/CAHP/CAHPSchedule.td diff --git a/llvm/lib/Target/CAHP/CAHPInstrFormats.td b/llvm/lib/Target/CAHP/CAHPInstrFormats.td index e244a9625258..2f44d82607a2 100644 --- a/llvm/lib/Target/CAHP/CAHPInstrFormats.td +++ b/llvm/lib/Target/CAHP/CAHPInstrFormats.td @@ -54,7 +54,20 @@ class Pseudo24 pattern> // 24-bit M-instruction format. class CAHPInst24MLoad opcode, dag outs, dag ins, string opcodestr, string argstr> -: CAHPInst24 { +: CAHPInst24, Sched<[WriteLDST]> { + bits<4> rd; + bits<4> rs; + bits<10> imm; + + let Inst{23-16} = imm{7-0}; + let Inst{15-12} = rs; + let Inst{11-8} = rd; + let Inst{7-6} = imm{9-8}; + let Inst{5-0} = opcode; +} + +class CAHPInst24MLoadI opcode, dag outs, dag ins, string opcodestr, string argstr> +: CAHPInst24, Sched<[WriteALU]> { bits<4> rd; bits<4> rs; bits<10> imm; @@ -67,7 +80,7 @@ class CAHPInst24MLoad opcode, dag outs, dag ins, string opcodestr, strin } class CAHPInst24MStore opcode, dag outs, dag ins, string opcodestr, string argstr> -: CAHPInst24 { +: CAHPInst24, Sched<[WriteLDST]> { bits<4> rs; bits<4> rd; bits<10> imm; @@ -81,7 +94,7 @@ class CAHPInst24MStore opcode, dag outs, dag ins, string opcodestr, stri // 24-bit R-instruction format. class CAHPInst24R opcode, dag outs, dag ins, string opcodestr, string argstr> -: CAHPInst24 { +: CAHPInst24, Sched<[WriteALU]> { bits<4> rd; bits<4> rs1; bits<4> rs2; @@ -95,7 +108,7 @@ class CAHPInst24R opcode, dag outs, dag ins, string opcodestr, string ar // 24-bit I-instruction format for 10bit immediate. class CAHPInst24I_10 opcode, dag outs, dag ins, string opcodestr, string argstr> -: CAHPInst24 { +: CAHPInst24, Sched<[WriteALU]> { bits<4> rd; bits<4> rs1; bits<10> imm; @@ -109,7 +122,7 @@ class CAHPInst24I_10 opcode, dag outs, dag ins, string opcodestr, string // 24-bit I-instruction format for 4bit immediate. class CAHPInst24I_4 opcode, dag outs, dag ins, string opcodestr, string argstr> -: CAHPInst24 { +: CAHPInst24, Sched<[WriteALU]> { bits<4> rd; bits<4> rs1; bits<4> imm; @@ -137,16 +150,24 @@ class CAHPInst24J opcode, dag ins, string opcodestr, string argstr> } // 16-bit M-instruction format. -class CAHPInst16Load opcode, dag outs, dag ins, string opcodestr, string argstr> -: CAHPInst16 { +class CAHPInst16MLoad opcode, dag outs, dag ins, string opcodestr, string argstr> +: CAHPInst16, Sched<[WriteLDST]> { + bits<4> rd; + + let Inst{11-8} = rd; + let Inst{5-0} = opcode; +} + +class CAHPInst16MLoadI opcode, dag outs, dag ins, string opcodestr, string argstr> +: CAHPInst16, Sched<[WriteALU]> { bits<4> rd; let Inst{11-8} = rd; let Inst{5-0} = opcode; } -class CAHPInst16Store opcode, dag outs, dag ins, string opcodestr, string argstr> -: CAHPInst16 { +class CAHPInst16MStore opcode, dag outs, dag ins, string opcodestr, string argstr> +: CAHPInst16, Sched<[WriteLDST]> { bits<4> rs; let Inst{11-8} = rs; @@ -155,7 +176,7 @@ class CAHPInst16Store opcode, dag outs, dag ins, string opcodestr, strin // 16-bit R-instruction format. class CAHPInst16R opcode, dag outs, dag ins, string opcodestr, string argstr> -: CAHPInst16 { +: CAHPInst16, Sched<[WriteALU]> { bits<4> rd; bits<4> rs; @@ -166,7 +187,7 @@ class CAHPInst16R opcode, dag outs, dag ins, string opcodestr, string ar // 16-bit I-instruction format for 6bit immediate. class CAHPInst16I_6 opcode, dag outs, dag ins, string opcodestr, string argstr> -: CAHPInst16 { +: CAHPInst16, Sched<[WriteALU]> { bits<4> rd; bits<6> imm; @@ -178,7 +199,7 @@ class CAHPInst16I_6 opcode, dag outs, dag ins, string opcodestr, string // 16-bit I-instruction format for 4bit immediate. class CAHPInst16I_4 opcode, dag outs, dag ins, string opcodestr, string argstr> -: CAHPInst16 { +: CAHPInst16, Sched<[WriteALU]> { bits<4> rd; bits<4> imm; diff --git a/llvm/lib/Target/CAHP/CAHPInstrInfo.td b/llvm/lib/Target/CAHP/CAHPInstrInfo.td index 5bf643f03290..227119dfd751 100644 --- a/llvm/lib/Target/CAHP/CAHPInstrInfo.td +++ b/llvm/lib/Target/CAHP/CAHPInstrInfo.td @@ -175,7 +175,7 @@ let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in { } let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isMoveImm = 1 in -def LI : CAHPInst24MLoad <0b110101, (outs GPR:$rd), (ins simm10:$imm), +def LI : CAHPInst24MLoadI <0b110101, (outs GPR:$rd), (ins simm10:$imm), "li", "$rd, $imm"> { let rs = 0; } @@ -244,7 +244,7 @@ let hasSideEffects = 0, mayLoad = 0, mayStore = 0, // 16-bit M-instructions. let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in -def LWSP : CAHPInst16Load <0b010100, (outs GPR:$rd), (ins SP:$rs, uimm7_lsb0:$imm), +def LWSP : CAHPInst16MLoad <0b010100, (outs GPR:$rd), (ins SP:$rs, uimm7_lsb0:$imm), "lwsp", "$rd, ${imm}(${rs})"> { bits<7> imm; let Inst{15-12} = imm{4-1}; @@ -252,7 +252,7 @@ def LWSP : CAHPInst16Load <0b010100, (outs GPR:$rd), (ins SP:$rs, uimm7_lsb0:$im } let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in -def SWSP : CAHPInst16Store<0b011100, (outs), (ins GPR:$rs, SP:$rd, uimm7_lsb0:$imm), +def SWSP : CAHPInst16MStore<0b011100, (outs), (ins GPR:$rs, SP:$rd, uimm7_lsb0:$imm), "swsp", "$rs, ${imm}(${rd})"> { bits<7> imm; let Inst{15-12} = imm{4-1}; @@ -260,7 +260,7 @@ def SWSP : CAHPInst16Store<0b011100, (outs), (ins GPR:$rs, SP:$rd, uimm7_lsb0:$i } let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isMoveImm = 1 in -def LSI : CAHPInst16Load <0b110100, (outs GPR:$rd), (ins simm6:$imm), +def LSI : CAHPInst16MLoadI <0b110100, (outs GPR:$rd), (ins simm6:$imm), "lsi", "$rd, $imm"> { bits<6> imm; let Inst{15-12} = imm{3-0}; @@ -268,7 +268,7 @@ def LSI : CAHPInst16Load <0b110100, (outs GPR:$rd), (ins simm6:$imm), } let hasSideEffects = 0, mayLoad = 0, mayStore = 0, isMoveImm = 1 in -def LUI : CAHPInst16Load <0b000100, (outs GPR:$rd), (ins simm6:$imm), +def LUI : CAHPInst16MLoadI <0b000100, (outs GPR:$rd), (ins simm6:$imm), "lui", "$rd, $imm"> { bits<6> imm; let Inst{15-12} = imm{3-0}; diff --git a/llvm/lib/Target/CAHP/CAHPSchedule.td b/llvm/lib/Target/CAHP/CAHPSchedule.td new file mode 100644 index 000000000000..67706e883de2 --- /dev/null +++ b/llvm/lib/Target/CAHP/CAHPSchedule.td @@ -0,0 +1,6 @@ +// This file is copied and modified from The LLVM Compiler Infrastructure, which +// is distributed under the Apache License v2.0 with LLVM Exceptions (see +// LICENSE.TXT for details). This file is licensed under the same license. + +def WriteALU : SchedWrite; +def WriteLDST : SchedWrite; From 06555ba774c9f140fdc88a66ef6a4182b70343ff Mon Sep 17 00:00:00 2001 From: Ushitora Anqou Date: Mon, 30 Dec 2019 20:43:54 +0900 Subject: [PATCH 284/289] [CAHP] Enable MIScheduler --- llvm/lib/Target/CAHP/CAHPSubtarget.h | 2 ++ llvm/test/CodeGen/CAHP/bare-select.ll | 17 +++++++------ llvm/test/CodeGen/CAHP/calls.ll | 2 +- llvm/test/CodeGen/CAHP/mem.ll | 36 ++++++++++++++------------- 4 files changed, 31 insertions(+), 26 deletions(-) diff --git a/llvm/lib/Target/CAHP/CAHPSubtarget.h b/llvm/lib/Target/CAHP/CAHPSubtarget.h index 2592c29ded33..670a762db1e7 100644 --- a/llvm/lib/Target/CAHP/CAHPSubtarget.h +++ b/llvm/lib/Target/CAHP/CAHPSubtarget.h @@ -51,6 +51,8 @@ class CAHPSubtarget : public CAHPGenSubtargetInfo { const SelectionDAGTargetInfo *getSelectionDAGInfo() const override { return &TSInfo; } + + bool enableMachineScheduler() const override { return true; } }; } // namespace llvm diff --git a/llvm/test/CodeGen/CAHP/bare-select.ll b/llvm/test/CodeGen/CAHP/bare-select.ll index e97fe05a4739..4b6009ce672a 100644 --- a/llvm/test/CodeGen/CAHP/bare-select.ll +++ b/llvm/test/CodeGen/CAHP/bare-select.ll @@ -5,14 +5,15 @@ define i16 @bare_select(i1 %a, i16 %b, i16 %c) { ; CAHP-LABEL: bare_select: ; CAHP: # %bb.0: -; CAHP-NEXT: andi2 a0, 1 -; CAHP-NEXT: lsi a3, 0 -; CAHP-NEXT: bne a0, a3, .LBB0_2 -; CAHP-NEXT:# %bb.1: -; CAHP-NEXT: mov a1, a2 -; CAHP-NEXT:.LBB0_2: -; CAHP-NEXT: mov a0, a1 -; CAHP-NEXT: jr ra +; CHAP-NEXT: andi a3, a0, 1 +; CHAP-NEXT: lsi a4, 0 +; CHAP-NEXT: mov a0, a1 +; CHAP-NEXT: bne a3, a4, .LBB0_2 +; CHAP-NEXT:# %bb.1: +; CHAP-NEXT: mov a0, a2 +; CHAP-NEXT:.LBB0_2: +; CHAP-NEXT: jr ra + %1 = select i1 %a, i16 %b, i16 %c ret i16 %1 } diff --git a/llvm/test/CodeGen/CAHP/calls.ll b/llvm/test/CodeGen/CAHP/calls.ll index f6b4db00b9ef..12264d979e6b 100644 --- a/llvm/test/CodeGen/CAHP/calls.ll +++ b/llvm/test/CodeGen/CAHP/calls.ll @@ -159,8 +159,8 @@ define i16 @caller_i32_scalars(i32 %a) nounwind { ; CAHP-NEXT: swsp a0, 6(sp) ; CAHP-NEXT: swsp a2, 4(sp) ; CAHP-NEXT: swsp a0, 2(sp) -; CAHP-NEXT: swsp a2, 0(sp) ; CAHP-NEXT: li a0, 42 +; CAHP-NEXT: swsp a2, 0(sp) ; CAHP-NEXT: mov a3, a1 ; CAHP-NEXT: mov a4, a2 ; CAHP-NEXT: mov a5, a1 diff --git a/llvm/test/CodeGen/CAHP/mem.ll b/llvm/test/CodeGen/CAHP/mem.ll index 91c3d5b9c8d0..2c460b410ad9 100644 --- a/llvm/test/CodeGen/CAHP/mem.ll +++ b/llvm/test/CodeGen/CAHP/mem.ll @@ -7,9 +7,10 @@ define i16 @lb(i8 *%a) nounwind { ; CAHP-LABEL: lb: ; CAHP: # %bb.0: -; CAHP-NEXT: lb a1, 0(a0) -; CAHP-NEXT: lb a0, 1(a0) -; CAHP-NEXT: jr ra +; CAHP-NEXT: lb a1, 1(a0) +; CAHP-NEXT: lb a0, 0(a0) +; CAHP-NEXT: mov a0, a1 +; CAHP-NEXT: jr ra %1 = getelementptr i8, i8* %a, i16 1 %2 = load i8, i8* %1 %3 = sext i8 %2 to i16 @@ -21,9 +22,10 @@ define i16 @lb(i8 *%a) nounwind { define i16 @lw(i16 *%a) nounwind { ; CAHP-LABEL: lw: ; CAHP: # %bb.0: -; CAHP-NEXT: lw a1, 0(a0) -; CAHP-NEXT: lw a0, 6(a0) -; CAHP-NEXT: jr ra +; CAHP-NEXT: lw a1, 6(a0) +; CAHP-NEXT: lw a0, 0(a0) +; CAHP-NEXT: mov a0, a1 +; CAHP-NEXT: jr ra %1 = getelementptr i16, i16* %a, i16 3 %2 = load i16, i16* %1 %3 = load volatile i16, i16* %a @@ -33,10 +35,10 @@ define i16 @lw(i16 *%a) nounwind { define i16 @lbu(i8 *%a) nounwind { ; CAHP-LABEL: lbu: ; CAHP: # %bb.0: -; CAHP-NEXT: lbu a1, 0(a0) -; CAHP-NEXT: lbu a0, 4(a0) -; CAHP-NEXT: add2 a0, a1 -; CAHP-NEXT: jr ra +; CAHP-NEXT: lbu a1, 4(a0) +; CAHP-NEXT: lbu a0, 0(a0) +; CAHP-NEXT: add2 a0, a1 +; CAHP-NEXT: jr ra %1 = getelementptr i8, i8* %a, i16 4 %2 = load i8, i8* %1 %3 = zext i8 %2 to i16 @@ -51,8 +53,8 @@ define i16 @lbu(i8 *%a) nounwind { define void @sb(i8 *%a, i8 %b) nounwind { ; CAHP-LABEL: sb: ; CAHP: # %bb.0: -; CAHP-NEXT: sb a1, 6(a0) ; CAHP-NEXT: sb a1, 0(a0) +; CAHP-NEXT: sb a1, 6(a0) ; CAHP-NEXT: jr ra store i8 %b, i8* %a %1 = getelementptr i8, i8* %a, i16 6 @@ -63,8 +65,8 @@ define void @sb(i8 *%a, i8 %b) nounwind { define void @sw(i16 *%a, i16 %b) nounwind { ; CAHP-LABEL: sw: ; CAHP: # %bb.0: -; CAHP-NEXT: sw a1, 16(a0) ; CAHP-NEXT: sw a1, 0(a0) +; CAHP-NEXT: sw a1, 16(a0) ; CAHP-NEXT: jr ra store i16 %b, i16* %a %1 = getelementptr i16, i16* %a, i16 8 @@ -76,11 +78,11 @@ define void @sw(i16 *%a, i16 %b) nounwind { define i16 @load_sext_zext_anyext_i1(i1 *%a) nounwind { ; CAHP-LABEL: load_sext_zext_anyext_i1: ; CAHP: # %bb.0: -; CAHP-NEXT: lb a1, 0(a0) -; CAHP-NEXT: lbu a1, 1(a0) -; CAHP-NEXT: lbu a0, 2(a0) -; CAHP-NEXT: sub2 a0, a1 -; CAHP-NEXT: jr ra +; CAHP-NEXT: lbu a1, 1(a0) +; CAHP-NEXT: lbu a2, 2(a0) +; CAHP-NEXT: lb a0, 0(a0) +; CAHP-NEXT: sub a0, a2, a1 +; CAHP-NEXT: jr ra ; sextload i1 %1 = getelementptr i1, i1* %a, i16 1 %2 = load i1, i1* %1 From cfb5c54eb15c69c1ed32d4350c497adb07ff78a1 Mon Sep 17 00:00:00 2001 From: Ushitora Anqou Date: Mon, 30 Dec 2019 20:44:14 +0900 Subject: [PATCH 285/289] [CAHP] Add scheduling for processor emerald --- clang/lib/Basic/Targets/CAHP.cpp | 4 +++- clang/lib/Basic/Targets/CAHP.h | 1 + llvm/lib/Target/CAHP/CAHP.td | 1 + llvm/lib/Target/CAHP/CAHPRegisterInfo.h | 4 ++++ llvm/lib/Target/CAHP/CAHPSchedule.td | 17 +++++++++++++++++ 5 files changed, 26 insertions(+), 1 deletion(-) diff --git a/clang/lib/Basic/Targets/CAHP.cpp b/clang/lib/Basic/Targets/CAHP.cpp index 8318c0f33955..c9fba021f126 100644 --- a/clang/lib/Basic/Targets/CAHP.cpp +++ b/clang/lib/Basic/Targets/CAHP.cpp @@ -36,7 +36,9 @@ bool CAHPTargetInfo::isValidCPUName(StringRef Name) const { if (Name == "generic") return true; - CPUKind CPU = llvm::StringSwitch(Name).Default(CK_NONE); + CPUKind CPU = llvm::StringSwitch(Name) + .Case("emerald", CK_EMERALD) + .Default(CK_NONE); return CPU != CK_NONE; } diff --git a/clang/lib/Basic/Targets/CAHP.h b/clang/lib/Basic/Targets/CAHP.h index 28e6200d86af..12755280028f 100644 --- a/clang/lib/Basic/Targets/CAHP.h +++ b/clang/lib/Basic/Targets/CAHP.h @@ -19,6 +19,7 @@ class LLVM_LIBRARY_VISIBILITY CAHPTargetInfo : public TargetInfo { // The CPU profiles supported by the CAHP backend enum CPUKind { CK_NONE, + CK_EMERALD, }; public: diff --git a/llvm/lib/Target/CAHP/CAHP.td b/llvm/lib/Target/CAHP/CAHP.td index 224b6147618b..c06a00ec9ae4 100644 --- a/llvm/lib/Target/CAHP/CAHP.td +++ b/llvm/lib/Target/CAHP/CAHP.td @@ -18,6 +18,7 @@ include "CAHPInstrInfo.td" //===----------------------------------------------------------------------===// def : ProcessorModel<"generic", NoSchedModel, []>; +def : ProcessorModel<"emerald", EmeraldModel, []>; //===----------------------------------------------------------------------===// // Define the CAHP target. diff --git a/llvm/lib/Target/CAHP/CAHPRegisterInfo.h b/llvm/lib/Target/CAHP/CAHPRegisterInfo.h index 37bea41c7d79..e5e95f3f7431 100644 --- a/llvm/lib/Target/CAHP/CAHPRegisterInfo.h +++ b/llvm/lib/Target/CAHP/CAHPRegisterInfo.h @@ -36,6 +36,10 @@ struct CAHPRegisterInfo : public CAHPGenRegisterInfo { bool requiresFrameIndexScavenging(const MachineFunction &MF) const override { return true; } + + bool trackLivenessAfterRegAlloc(const MachineFunction &) const override { + return true; + } }; } // namespace llvm diff --git a/llvm/lib/Target/CAHP/CAHPSchedule.td b/llvm/lib/Target/CAHP/CAHPSchedule.td index 67706e883de2..e5eb14dfa852 100644 --- a/llvm/lib/Target/CAHP/CAHPSchedule.td +++ b/llvm/lib/Target/CAHP/CAHPSchedule.td @@ -4,3 +4,20 @@ def WriteALU : SchedWrite; def WriteLDST : SchedWrite; + +def EmeraldModel : SchedMachineModel { + let MicroOpBufferSize = 0; + let IssueWidth = 2; + let LoadLatency = 2; + let MispredictPenalty = 2; + let CompleteModel = 0; + let PostRAScheduler = 1; +} + +def EmeraldALU : ProcResource<2> { let BufferSize = 0; } +def EmeraldLdSt : ProcResource<1> { let BufferSize = 0; } + +let SchedModel = EmeraldModel in { + def : WriteRes { let Latency = 3; } + def : WriteRes { let Latency = 3; } +} From ab23571c72671f17076d0288384fb4c7c585a8a3 Mon Sep 17 00:00:00 2001 From: Ushitora Anqou Date: Mon, 30 Dec 2019 20:45:40 +0900 Subject: [PATCH 286/289] [CAHP] Add support for dynamic stack allocation --- llvm/lib/Target/CAHP/CAHPISelLowering.cpp | 4 ++ llvm/test/CodeGen/CAHP/alloca.ll | 63 +++++++++++++++++++++++ 2 files changed, 67 insertions(+) create mode 100644 llvm/test/CodeGen/CAHP/alloca.ll diff --git a/llvm/lib/Target/CAHP/CAHPISelLowering.cpp b/llvm/lib/Target/CAHP/CAHPISelLowering.cpp index f9987402e0b1..63be1feb0abf 100644 --- a/llvm/lib/Target/CAHP/CAHPISelLowering.cpp +++ b/llvm/lib/Target/CAHP/CAHPISelLowering.cpp @@ -65,6 +65,10 @@ CAHPTargetLowering::CAHPTargetLowering(const TargetMachine &TM, setOperationAction(ISD::UDIVREM, MVT::i16, Expand); setOperationAction(ISD::UDIV, MVT::i16, Expand); + setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i16, Expand); + setOperationAction(ISD::STACKSAVE, MVT::Other, Expand); + setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand); + setBooleanContents(ZeroOrOneBooleanContent); // Function alignments (log2). diff --git a/llvm/test/CodeGen/CAHP/alloca.ll b/llvm/test/CodeGen/CAHP/alloca.ll new file mode 100644 index 000000000000..e84caa437c47 --- /dev/null +++ b/llvm/test/CodeGen/CAHP/alloca.ll @@ -0,0 +1,63 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=cahp -verify-machineinstrs < %s \ +; RUN: | FileCheck %s -check-prefix=CAHP + +declare void @notdead(i8*) + +; These tests must ensure the stack pointer is restored using the frame +; pointer + +define void @simple_alloca(i32 %n) nounwind { +; CAHP-LABEL: simple_alloca: +; CAHP: # %bb.0: +; CAHP-NEXT: addi2 sp, -4 +; CAHP-NEXT: swsp ra, 2(sp) +; CAHP-NEXT: swsp fp, 0(sp) +; CAHP-NEXT: addi fp, sp, 4 +; CAHP-NEXT: addi2 a0, 1 +; CAHP-NEXT: andi2 a0, -2 +; CAHP-NEXT: sub a0, sp, a0 +; CAHP-NEXT: mov sp, a0 +; CAHP-NEXT: jsal notdead +; CAHP-NEXT: addi sp, fp, -4 +; CAHP-NEXT: lwsp fp, 0(sp) +; CAHP-NEXT: lwsp ra, 2(sp) +; CAHP-NEXT: addi2 sp, 4 +; CAHP-NEXT: jr ra + + %1 = alloca i8, i32 %n + call void @notdead(i8* %1) + ret void +} + +declare i8* @llvm.stacksave() +declare void @llvm.stackrestore(i8*) + +define void @scoped_alloca(i32 %n) nounwind { +; CAHP-LABEL: scoped_alloca: +; CAHP: # %bb.0: +; CAHP-NEXT: addi2 sp, -6 +; CAHP-NEXT: swsp ra, 4(sp) +; CAHP-NEXT: swsp fp, 2(sp) +; CAHP-NEXT: swsp s0, 0(sp) +; CAHP-NEXT: addi fp, sp, 6 +; CAHP-NEXT: mov s0, sp +; CAHP-NEXT: addi2 a0, 1 +; CAHP-NEXT: andi2 a0, -2 +; CAHP-NEXT: sub a0, sp, a0 +; CAHP-NEXT: mov sp, a0 +; CAHP-NEXT: jsal notdead +; CAHP-NEXT: mov sp, s0 +; CAHP-NEXT: addi sp, fp, -6 +; CAHP-NEXT: lwsp s0, 0(sp) +; CAHP-NEXT: lwsp fp, 2(sp) +; CAHP-NEXT: lwsp ra, 4(sp) +; CAHP-NEXT: addi2 sp, 6 +; CAHP-NEXT: jr ra + + %sp = call i8* @llvm.stacksave() + %addr = alloca i8, i32 %n + call void @notdead(i8* %addr) + call void @llvm.stackrestore(i8* %sp) + ret void +} From 528751999dcb45d9c782dd7d0d687b6cec00a4ae Mon Sep 17 00:00:00 2001 From: Ushitora Anqou Date: Mon, 30 Dec 2019 21:25:03 +0900 Subject: [PATCH 287/289] [CAHP] Add support for frameaddr and returnaddr --- llvm/lib/Target/CAHP/CAHPISelLowering.cpp | 56 +++++++++++++++ llvm/lib/Target/CAHP/CAHPISelLowering.h | 2 + .../test/CodeGen/CAHP/frameaddr-returnaddr.ll | 70 +++++++++++++++++++ 3 files changed, 128 insertions(+) create mode 100644 llvm/test/CodeGen/CAHP/frameaddr-returnaddr.ll diff --git a/llvm/lib/Target/CAHP/CAHPISelLowering.cpp b/llvm/lib/Target/CAHP/CAHPISelLowering.cpp index 63be1feb0abf..9fcd69146f46 100644 --- a/llvm/lib/Target/CAHP/CAHPISelLowering.cpp +++ b/llvm/lib/Target/CAHP/CAHPISelLowering.cpp @@ -132,6 +132,12 @@ SDValue CAHPTargetLowering::LowerOperation(SDValue Op, case ISD::SELECT: return LowerSELECT(Op, DAG); + + case ISD::FRAMEADDR: + return LowerFRAMEADDR(Op, DAG); + + case ISD::RETURNADDR: + return LowerRETURNADDR(Op, DAG); } } @@ -188,6 +194,56 @@ SDValue CAHPTargetLowering::LowerSELECT(SDValue Op, SelectionDAG &DAG) const { return DAG.getNode(CAHPISD::SELECT_CC, DL, VTs, Ops); } +SDValue CAHPTargetLowering::LowerFRAMEADDR(SDValue Op, + SelectionDAG &DAG) const { + const CAHPRegisterInfo &RI = *Subtarget.getRegisterInfo(); + MachineFunction &MF = DAG.getMachineFunction(); + MachineFrameInfo &MFI = MF.getFrameInfo(); + MFI.setFrameAddressIsTaken(true); + unsigned FrameReg = RI.getFrameRegister(MF); + + EVT VT = Op.getValueType(); + SDLoc DL(Op); + SDValue FrameAddr = DAG.getCopyFromReg(DAG.getEntryNode(), DL, FrameReg, VT); + unsigned Depth = cast(Op.getOperand(0))->getZExtValue(); + while (Depth--) { + int Offset = -4; + SDValue Ptr = DAG.getNode(ISD::ADD, DL, VT, FrameAddr, + DAG.getIntPtrConstant(Offset, DL)); + FrameAddr = + DAG.getLoad(VT, DL, DAG.getEntryNode(), Ptr, MachinePointerInfo()); + } + return FrameAddr; +} + +SDValue CAHPTargetLowering::LowerRETURNADDR(SDValue Op, + SelectionDAG &DAG) const { + const CAHPRegisterInfo &RI = *Subtarget.getRegisterInfo(); + MachineFunction &MF = DAG.getMachineFunction(); + MachineFrameInfo &MFI = MF.getFrameInfo(); + MFI.setReturnAddressIsTaken(true); + + if (verifyReturnAddressArgumentIsConstant(Op, DAG)) + return SDValue(); + + EVT VT = Op.getValueType(); + SDLoc DL(Op); + unsigned Depth = cast(Op.getOperand(0))->getZExtValue(); + if (Depth) { + int Off = -2; + SDValue FrameAddr = LowerFRAMEADDR(Op, DAG); + SDValue Offset = DAG.getConstant(Off, DL, VT); + return DAG.getLoad(VT, DL, DAG.getEntryNode(), + DAG.getNode(ISD::ADD, DL, VT, FrameAddr, Offset), + MachinePointerInfo()); + } + + // Return the value of the return address register, marking it an implicit + // live-in. + unsigned Reg = MF.addLiveIn(RI.getRARegister(), &CAHP::GPRRegClass); + return DAG.getCopyFromReg(DAG.getEntryNode(), DL, Reg, MVT::i16); +} + MachineBasicBlock * CAHPTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI, MachineBasicBlock *BB) const { diff --git a/llvm/lib/Target/CAHP/CAHPISelLowering.h b/llvm/lib/Target/CAHP/CAHPISelLowering.h index 07eb218e9a4e..b4f01243ad3d 100644 --- a/llvm/lib/Target/CAHP/CAHPISelLowering.h +++ b/llvm/lib/Target/CAHP/CAHPISelLowering.h @@ -65,6 +65,8 @@ class CAHPTargetLowering : public TargetLowering { SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const; SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG) const; SDValue LowerSELECT(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const; }; } // namespace llvm diff --git a/llvm/test/CodeGen/CAHP/frameaddr-returnaddr.ll b/llvm/test/CodeGen/CAHP/frameaddr-returnaddr.ll new file mode 100644 index 000000000000..c9275a760a59 --- /dev/null +++ b/llvm/test/CodeGen/CAHP/frameaddr-returnaddr.ll @@ -0,0 +1,70 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=cahp -verify-machineinstrs < %s \ +; RUN: | FileCheck -check-prefix=CAHP %s + +declare i8* @llvm.frameaddress(i32) +declare i8* @llvm.returnaddress(i32) + +define i8* @test_frameaddress_0() nounwind { +; CAHP-LABEL: test_frameaddress_0: +; CAHP: # %bb.0: +; CAHP-NEXT: addi2 sp, -4 +; CAHP-NEXT: swsp ra, 2(sp) +; CAHP-NEXT: swsp fp, 0(sp) +; CAHP-NEXT: addi fp, sp, 4 +; CAHP-NEXT: mov a0, fp +; CAHP-NEXT: lwsp fp, 0(sp) +; CAHP-NEXT: lwsp ra, 2(sp) +; CAHP-NEXT: addi2 sp, 4 +; CAHP-NEXT: jr ra + + %1 = call i8* @llvm.frameaddress(i32 0) + ret i8* %1 +} + +define i8* @test_frameaddress_2() nounwind { +; CAHP-LABEL: test_frameaddress_2: +; CAHP: # %bb.0: +; CAHP-NEXT: addi2 sp, -4 +; CAHP-NEXT: swsp ra, 2(sp) +; CAHP-NEXT: swsp fp, 0(sp) +; CAHP-NEXT: addi fp, sp, 4 +; CAHP-NEXT: lw a0, -4(fp) +; CAHP-NEXT: lw a0, -4(a0) +; CAHP-NEXT: lwsp fp, 0(sp) +; CAHP-NEXT: lwsp ra, 2(sp) +; CAHP-NEXT: addi2 sp, 4 +; CAHP-NEXT: jr ra + + %1 = call i8* @llvm.frameaddress(i32 2) + ret i8* %1 +} + +define i8* @test_returnaddress_0() nounwind { +; CAHP-LABEL: test_returnaddress_0: +; CAHP: # %bb.0: +; CAHP-NEXT: mov a0, ra +; CAHP-NEXT: jr ra + + %1 = call i8* @llvm.returnaddress(i32 0) + ret i8* %1 +} + +define i8* @test_returnaddress_2() nounwind { +; CAHP-LABEL: test_returnaddress_2: +; CAHP: # %bb.0: +; CAHP-NEXT: addi2 sp, -4 +; CAHP-NEXT: swsp ra, 2(sp) +; CAHP-NEXT: swsp fp, 0(sp) +; CAHP-NEXT: addi fp, sp, 4 +; CAHP-NEXT: lw a0, -4(fp) +; CAHP-NEXT: lw a0, -4(a0) +; CAHP-NEXT: lw a0, -2(a0) +; CAHP-NEXT: lwsp fp, 0(sp) +; CAHP-NEXT: lwsp ra, 2(sp) +; CAHP-NEXT: addi2 sp, 4 +; CAHP-NEXT: jr ra + + %1 = call i8* @llvm.returnaddress(i32 2) + ret i8* %1 +} From 680e50ef80a6c21f07541dceb806f541378f9d46 Mon Sep 17 00:00:00 2001 From: Ushitora Anqou Date: Mon, 30 Dec 2019 23:05:35 +0900 Subject: [PATCH 288/289] [CAHP] Add support for emergency spill --- llvm/lib/Target/CAHP/CAHPFrameLowering.cpp | 13 ++ llvm/lib/Target/CAHP/CAHPFrameLowering.h | 3 + llvm/test/CodeGen/CAHP/large-stack.ll | 249 ++++++++++++++++++++- 3 files changed, 256 insertions(+), 9 deletions(-) diff --git a/llvm/lib/Target/CAHP/CAHPFrameLowering.cpp b/llvm/lib/Target/CAHP/CAHPFrameLowering.cpp index ea2adef56c2c..270a97c8ed6c 100644 --- a/llvm/lib/Target/CAHP/CAHPFrameLowering.cpp +++ b/llvm/lib/Target/CAHP/CAHPFrameLowering.cpp @@ -8,6 +8,7 @@ #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/RegisterScavenging.h" using namespace llvm; @@ -200,3 +201,15 @@ void CAHPFrameLowering::determineCalleeSaves(MachineFunction &MF, SavedRegs.set(CAHP::X2); } } + +void CAHPFrameLowering::processFunctionBeforeFrameFinalized( + MachineFunction &MF, RegScavenger *RS) const { + const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo(); + MachineFrameInfo &MFI = MF.getFrameInfo(); + const TargetRegisterClass *RC = &CAHP::GPRRegClass; + if (!isInt<9>(MFI.estimateStackSize(MF))) { + int RegScavFI = MFI.CreateStackObject( + RegInfo->getSpillSize(*RC), RegInfo->getSpillAlignment(*RC), false); + RS->addScavengingFrameIndex(RegScavFI); + } +} diff --git a/llvm/lib/Target/CAHP/CAHPFrameLowering.h b/llvm/lib/Target/CAHP/CAHPFrameLowering.h index 886ac48eb962..611d3beb714d 100644 --- a/llvm/lib/Target/CAHP/CAHPFrameLowering.h +++ b/llvm/lib/Target/CAHP/CAHPFrameLowering.h @@ -35,6 +35,9 @@ class CAHPFrameLowering : public TargetFrameLowering { void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, RegScavenger *RS) const override; + void processFunctionBeforeFrameFinalized(MachineFunction &MF, + RegScavenger *RS) const override; + bool hasFP(const MachineFunction &MF) const override; MachineBasicBlock::iterator diff --git a/llvm/test/CodeGen/CAHP/large-stack.ll b/llvm/test/CodeGen/CAHP/large-stack.ll index 5ca3da2f856e..0c8546f50da9 100644 --- a/llvm/test/CodeGen/CAHP/large-stack.ll +++ b/llvm/test/CodeGen/CAHP/large-stack.ll @@ -10,42 +10,273 @@ define void @test() nounwind { ; CAHP-WITHFP-LABEL: test: ; CAHP-WITHFP: # %bb.0: ; CAHP-WITHFP-NEXT: lui a0, 3 -; CAHP-WITHFP-NEXT: addi a0, a0, -68 +; CAHP-WITHFP-NEXT: addi a0, a0, -66 ; CAHP-WITHFP-NEXT: sub2 sp, a0 ; CAHP-WITHFP-NEXT: lui a0, 3 -; CAHP-WITHFP-NEXT: addi a0, a0, -70 +; CAHP-WITHFP-NEXT: addi a0, a0, -68 ; CAHP-WITHFP-NEXT: add2 a0, sp ; CAHP-WITHFP-NEXT: sw ra, 0(a0) ; CAHP-WITHFP-NEXT: lui a0, 3 -; CAHP-WITHFP-NEXT: addi a0, a0, -72 +; CAHP-WITHFP-NEXT: addi a0, a0, -70 ; CAHP-WITHFP-NEXT: add2 a0, sp ; CAHP-WITHFP-NEXT: sw fp, 0(a0) ; CAHP-WITHFP-NEXT: lui a0, 3 -; CAHP-WITHFP-NEXT: addi a0, a0, -68 +; CAHP-WITHFP-NEXT: addi a0, a0, -66 ; CAHP-WITHFP-NEXT: add fp, sp, a0 ; CAHP-WITHFP-NEXT: lui a0, 3 -; CAHP-WITHFP-NEXT: addi a0, a0, -72 +; CAHP-WITHFP-NEXT: addi a0, a0, -70 ; CAHP-WITHFP-NEXT: add2 a0, sp ; CAHP-WITHFP-NEXT: lw fp, 0(a0) ; CAHP-WITHFP-NEXT: lui a0, 3 -; CAHP-WITHFP-NEXT: addi a0, a0, -70 +; CAHP-WITHFP-NEXT: addi a0, a0, -68 ; CAHP-WITHFP-NEXT: add2 a0, sp ; CAHP-WITHFP-NEXT: lw ra, 0(a0) ; CAHP-WITHFP-NEXT: lui a0, 3 -; CAHP-WITHFP-NEXT: addi a0, a0, -68 +; CAHP-WITHFP-NEXT: addi a0, a0, -66 ; CAHP-WITHFP-NEXT: add2 sp, a0 ; CAHP-WITHFP-NEXT: jr ra ; CAHP-FPELIM-LABEL: test: ; CAHP-FPELIM: # %bb.0: ; CAHP-FPELIM-NEXT: lui a0, 3 -; CAHP-FPELIM-NEXT: addi a0, a0, -72 +; CAHP-FPELIM-NEXT: addi a0, a0, -70 ; CAHP-FPELIM-NEXT: sub2 sp, a0 ; CAHP-FPELIM-NEXT: lui a0, 3 -; CAHP-FPELIM-NEXT: addi a0, a0, -72 +; CAHP-FPELIM-NEXT: addi a0, a0, -70 ; CAHP-FPELIM-NEXT: add2 sp, a0 ; CAHP-FPELIM-NEXT: jr ra %tmp = alloca [ 3000 x i8 ] , align 2 ret void } + +; This test case artificially produces register pressure which should force +; use of the emergency spill slot. + +define void @test_emergency_spill_slot(i16 %a) nounwind { +; CAHP-LABEL: test_emergency_spill_slot: +; CAHP: # %bb.0: +; CAHP-NEXT: lui a1, 6 +; CAHP-NEXT: addi a1, a1, -98 +; CAHP-NEXT: sub2 sp, a1 +; CAHP-NEXT: lui a1, 6 +; CAHP-NEXT: addi a1, a1, -100 +; CAHP-NEXT: add2 a1, sp +; CAHP-NEXT: sw ra, 0(a1) +; CAHP-NEXT: lui a1, 6 +; CAHP-NEXT: addi a1, a1, -102 +; CAHP-NEXT: add2 a1, sp +; CAHP-NEXT: sw fp, 0(a1) +; CAHP-NEXT: lui a1, 6 +; CAHP-NEXT: addi a1, a1, -104 +; CAHP-NEXT: add2 a1, sp +; CAHP-NEXT: sw s0, 0(a1) +; CAHP-NEXT: lui a1, 6 +; CAHP-NEXT: addi a1, a1, -106 +; CAHP-NEXT: add2 a1, sp +; CAHP-NEXT: sw s1, 0(a1) +; CAHP-NEXT: lui a1, 6 +; CAHP-NEXT: addi a1, a1, -108 +; CAHP-NEXT: add2 a1, sp +; CAHP-NEXT: sw s2, 0(a1) +; CAHP-NEXT: lui a1, 6 +; CAHP-NEXT: addi a1, a1, -110 +; CAHP-NEXT: add2 a1, sp +; CAHP-NEXT: sw s3, 0(a1) +; CAHP-NEXT: lui a1, 6 +; CAHP-NEXT: addi a1, a1, -112 +; CAHP-NEXT: add2 a1, sp +; CAHP-NEXT: sw s4, 0(a1) +; CAHP-NEXT: lui a1, 6 +; CAHP-NEXT: addi a1, a1, -98 +; CAHP-NEXT: add fp, sp, a1 +; CAHP-NEXT: lui a1, 58 +; CAHP-NEXT: addi a1, a1, 100 +; CAHP-NEXT: add2 a1, fp +; CAHP-NEXT: sw a0, 0(a1) +; CAHP-NEXT: lui a1, 2 +; CAHP-NEXT: addi a1, a1, -48 +; CAHP-NEXT: lui a0, 58 +; CAHP-NEXT: addi a0, a0, 128 +; CAHP-NEXT: add2 a0, fp +; CAHP-NEXT: addi a2, a0, 0 +; CAHP-NEXT: add a0, a2, a1 +; CAHP-NEXT: lui a1, 58 +; CAHP-NEXT: addi a1, a1, 98 +; CAHP-NEXT: add2 a1, fp +; CAHP-NEXT: sw a0, 0(a1) +; CAHP-NEXT: #APP +; CAHP-NEXT: nop +; CAHP-NEXT: #NO_APP +; CAHP-NEXT: sw a1, -16(fp) +; CAHP-NEXT: lui a1, 58 +; CAHP-NEXT: addi a1, a1, 102 +; CAHP-NEXT: add2 a1, fp +; CAHP-NEXT: sw a0, 0(a1) +; CAHP-NEXT: lw a1, -16(fp) +; CAHP-NEXT: lui a0, 58 +; CAHP-NEXT: addi a0, a0, 104 +; CAHP-NEXT: add2 a0, fp +; CAHP-NEXT: sw a1, 0(a0) +; CAHP-NEXT: lui a0, 58 +; CAHP-NEXT: addi a0, a0, 106 +; CAHP-NEXT: add2 a0, fp +; CAHP-NEXT: sw s4, 0(a0) +; CAHP-NEXT: lui a0, 58 +; CAHP-NEXT: addi a0, a0, 108 +; CAHP-NEXT: add2 a0, fp +; CAHP-NEXT: sw s3, 0(a0) +; CAHP-NEXT: lui a0, 58 +; CAHP-NEXT: addi a0, a0, 110 +; CAHP-NEXT: add2 a0, fp +; CAHP-NEXT: sw s2, 0(a0) +; CAHP-NEXT: lui a0, 58 +; CAHP-NEXT: addi a0, a0, 112 +; CAHP-NEXT: add2 a0, fp +; CAHP-NEXT: sw s1, 0(a0) +; CAHP-NEXT: lui a0, 58 +; CAHP-NEXT: addi a0, a0, 114 +; CAHP-NEXT: add2 a0, fp +; CAHP-NEXT: sw s0, 0(a0) +; CAHP-NEXT: lui a0, 58 +; CAHP-NEXT: addi a0, a0, 116 +; CAHP-NEXT: add2 a0, fp +; CAHP-NEXT: sw t1, 0(a0) +; CAHP-NEXT: lui a0, 58 +; CAHP-NEXT: addi a0, a0, 118 +; CAHP-NEXT: add2 a0, fp +; CAHP-NEXT: sw t0, 0(a0) +; CAHP-NEXT: lui a0, 58 +; CAHP-NEXT: addi a0, a0, 120 +; CAHP-NEXT: add2 a0, fp +; CAHP-NEXT: sw a5, 0(a0) +; CAHP-NEXT: lui a0, 58 +; CAHP-NEXT: addi a0, a0, 122 +; CAHP-NEXT: add2 a0, fp +; CAHP-NEXT: sw a4, 0(a0) +; CAHP-NEXT: lui a0, 58 +; CAHP-NEXT: addi a0, a0, 124 +; CAHP-NEXT: add2 a0, fp +; CAHP-NEXT: sw a3, 0(a0) +; CAHP-NEXT: lui a0, 58 +; CAHP-NEXT: addi a0, a0, 126 +; CAHP-NEXT: add2 a0, fp +; CAHP-NEXT: sw a2, 0(a0) +; CAHP-NEXT: lui a0, 58 +; CAHP-NEXT: addi a0, a0, 100 +; CAHP-NEXT: add2 a0, fp +; CAHP-NEXT: lw a0, 0(a0) +; CAHP-NEXT: lui a1, 58 +; CAHP-NEXT: addi a1, a1, 98 +; CAHP-NEXT: add2 a1, fp +; CAHP-NEXT: lw a1, 0(a1) +; CAHP-NEXT: sw a0, 0(a1) +; CAHP-NEXT: lui a0, 58 +; CAHP-NEXT: addi a0, a0, 126 +; CAHP-NEXT: add2 a0, fp +; CAHP-NEXT: lw a0, 0(a0) +; CAHP-NEXT: lui a1, 58 +; CAHP-NEXT: addi a1, a1, 124 +; CAHP-NEXT: add2 a1, fp +; CAHP-NEXT: lw a1, 0(a1) +; CAHP-NEXT: lui a2, 58 +; CAHP-NEXT: addi a2, a2, 122 +; CAHP-NEXT: add2 a2, fp +; CAHP-NEXT: lw a2, 0(a2) +; CAHP-NEXT: lui a3, 58 +; CAHP-NEXT: addi a3, a3, 120 +; CAHP-NEXT: add2 a3, fp +; CAHP-NEXT: lw a3, 0(a3) +; CAHP-NEXT: lui a4, 58 +; CAHP-NEXT: addi a4, a4, 118 +; CAHP-NEXT: add2 a4, fp +; CAHP-NEXT: lw a4, 0(a4) +; CAHP-NEXT: lui a5, 58 +; CAHP-NEXT: addi a5, a5, 116 +; CAHP-NEXT: add2 a5, fp +; CAHP-NEXT: lw a5, 0(a5) +; CAHP-NEXT: lui t0, 58 +; CAHP-NEXT: addi t0, t0, 114 +; CAHP-NEXT: add2 t0, fp +; CAHP-NEXT: lw t0, 0(t0) +; CAHP-NEXT: lui t1, 58 +; CAHP-NEXT: addi t1, t1, 112 +; CAHP-NEXT: add2 t1, fp +; CAHP-NEXT: lw t1, 0(t1) +; CAHP-NEXT: lui s0, 58 +; CAHP-NEXT: addi s0, s0, 110 +; CAHP-NEXT: add2 s0, fp +; CAHP-NEXT: lw s0, 0(s0) +; CAHP-NEXT: lui s1, 58 +; CAHP-NEXT: addi s1, s1, 108 +; CAHP-NEXT: add2 s1, fp +; CAHP-NEXT: lw s1, 0(s1) +; CAHP-NEXT: lui s2, 58 +; CAHP-NEXT: addi s2, s2, 106 +; CAHP-NEXT: add2 s2, fp +; CAHP-NEXT: lw s2, 0(s2) +; CAHP-NEXT: lui s3, 58 +; CAHP-NEXT: addi s3, s3, 104 +; CAHP-NEXT: add2 s3, fp +; CAHP-NEXT: lw s3, 0(s3) +; CAHP-NEXT: lui s4, 58 +; CAHP-NEXT: addi s4, s4, 102 +; CAHP-NEXT: add2 s4, fp +; CAHP-NEXT: lw s4, 0(s4) +; CAHP-NEXT: #APP +; CAHP-NEXT: nop +; CAHP-NEXT: #NO_APP +; CAHP-NEXT: lui a0, 6 +; CAHP-NEXT: addi a0, a0, -112 +; CAHP-NEXT: add2 a0, sp +; CAHP-NEXT: lw s4, 0(a0) +; CAHP-NEXT: lui a0, 6 +; CAHP-NEXT: addi a0, a0, -110 +; CAHP-NEXT: add2 a0, sp +; CAHP-NEXT: lw s3, 0(a0) +; CAHP-NEXT: lui a0, 6 +; CAHP-NEXT: addi a0, a0, -108 +; CAHP-NEXT: add2 a0, sp +; CAHP-NEXT: lw s2, 0(a0) +; CAHP-NEXT: lui a0, 6 +; CAHP-NEXT: addi a0, a0, -106 +; CAHP-NEXT: add2 a0, sp +; CAHP-NEXT: lw s1, 0(a0) +; CAHP-NEXT: lui a0, 6 +; CAHP-NEXT: addi a0, a0, -104 +; CAHP-NEXT: add2 a0, sp +; CAHP-NEXT: lw s0, 0(a0) +; CAHP-NEXT: lui a0, 6 +; CAHP-NEXT: addi a0, a0, -102 +; CAHP-NEXT: add2 a0, sp +; CAHP-NEXT: lw fp, 0(a0) +; CAHP-NEXT: lui a0, 6 +; CAHP-NEXT: addi a0, a0, -100 +; CAHP-NEXT: add2 a0, sp +; CAHP-NEXT: lw ra, 0(a0) +; CAHP-NEXT: lui a0, 6 +; CAHP-NEXT: addi a0, a0, -98 +; CAHP-NEXT: add2 sp, a0 +; CAHP-NEXT: jr ra + + %data = alloca [ 3000 x i16 ], align 2 + %ptr = getelementptr inbounds [3000 x i16], [3000 x i16]* %data, i16 0, i16 1000 + %1 = tail call { i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16 } asm sideeffect "nop", "=r,=r,=r,=r,=r,=r,=r,=r,=r,=r,=r,=r,=r"() + %asmresult0 = extractvalue { i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16 } %1, 0 + %asmresult1 = extractvalue { i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16 } %1, 1 + %asmresult2 = extractvalue { i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16 } %1, 2 + %asmresult3 = extractvalue { i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16 } %1, 3 + %asmresult4 = extractvalue { i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16 } %1, 4 + %asmresult5 = extractvalue { i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16 } %1, 5 + %asmresult6 = extractvalue { i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16 } %1, 6 + %asmresult7 = extractvalue { i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16 } %1, 7 + %asmresult8 = extractvalue { i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16 } %1, 8 + %asmresult9 = extractvalue { i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16 } %1, 9 + %asmresult10 = extractvalue { i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16 } %1, 10 + %asmresult11 = extractvalue { i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16 } %1, 11 + %asmresult12 = extractvalue { i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16, i16 } %1, 12 + store volatile i16 %a, i16* %ptr + tail call void asm sideeffect "nop", "r,r,r,r,r,r,r,r,r,r,r,r,r"(i16 %asmresult0, i16 %asmresult1, i16 %asmresult2, i16 %asmresult3, i16 %asmresult4, i16 %asmresult5, i16 %asmresult6, i16 %asmresult7, i16 %asmresult8, i16 %asmresult9, i16 %asmresult10, i16 %asmresult11, i16 %asmresult12) + + ret void +} From 9b9f061455d87588bae322f39103e6d109f03d60 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 10 Nov 2022 07:55:45 +0000 Subject: [PATCH 289/289] Bump minimatch and mocha Bumps [minimatch](https://github.com/isaacs/minimatch) to 3.1.2 and updates ancestor dependency [mocha](https://github.com/mochajs/mocha). These dependencies need to be updated together. Updates `minimatch` from 3.0.4 to 3.1.2 - [Release notes](https://github.com/isaacs/minimatch/releases) - [Commits](https://github.com/isaacs/minimatch/compare/v3.0.4...v3.1.2) Updates `mocha` from 5.2.0 to 10.1.0 - [Release notes](https://github.com/mochajs/mocha/releases) - [Changelog](https://github.com/mochajs/mocha/blob/master/CHANGELOG.md) - [Commits](https://github.com/mochajs/mocha/compare/v5.2.0...v10.1.0) --- updated-dependencies: - dependency-name: minimatch dependency-type: indirect - dependency-name: mocha dependency-type: direct:development ... Signed-off-by: dependabot[bot] --- .../clients/clangd-vscode/package-lock.json | 622 ++++++++++++++++-- .../clangd/clients/clangd-vscode/package.json | 2 +- 2 files changed, 559 insertions(+), 65 deletions(-) diff --git a/clang-tools-extra/clangd/clients/clangd-vscode/package-lock.json b/clang-tools-extra/clangd/clients/clangd-vscode/package-lock.json index 8108e789b2e3..07ae3525525d 100644 --- a/clang-tools-extra/clangd/clients/clangd-vscode/package-lock.json +++ b/clang-tools-extra/clangd/clients/clangd-vscode/package-lock.json @@ -1,6 +1,6 @@ { "name": "vscode-clangd", - "version": "0.0.13", + "version": "0.0.15", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -28,6 +28,12 @@ "uri-js": "^4.2.2" } }, + "ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true + }, "ansi-cyan": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/ansi-cyan/-/ansi-cyan-0.1.1.tgz", @@ -46,12 +52,45 @@ "ansi-wrap": "0.1.0" } }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, "ansi-wrap": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", "dev": true }, + "anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "dependencies": { + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + } + } + }, "append-buffer": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", @@ -61,6 +100,12 @@ "buffer-equal": "^1.0.0" } }, + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, "arr-diff": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-1.1.0.tgz", @@ -152,8 +197,7 @@ "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" }, "bcrypt-pbkdf": { "version": "1.0.2", @@ -164,6 +208,12 @@ "tweetnacl": "^0.14.3" } }, + "binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true + }, "block-stream": { "version": "0.0.9", "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", @@ -183,6 +233,15 @@ "concat-map": "0.0.1" } }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, "browser-stdout": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", @@ -207,12 +266,98 @@ "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", "dev": true }, + "camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true + }, "caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", "dev": true }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "dependencies": { + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "dependencies": { + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + } + } + }, + "cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, "clone": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", @@ -242,6 +387,21 @@ "readable-stream": "^2.3.5" } }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, "combined-stream": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", @@ -251,12 +411,6 @@ "delayed-stream": "~1.0.0" } }, - "commander": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", - "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", - "dev": true - }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -288,14 +442,28 @@ } }, "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dev": true, "requires": { - "ms": "2.0.0" + "ms": "2.1.2" + }, + "dependencies": { + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } } }, + "decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "dev": true + }, "deep-assign": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/deep-assign/-/deep-assign-1.0.0.tgz", @@ -321,9 +489,9 @@ "dev": true }, "diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", + "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", "dev": true }, "duplexer": { @@ -354,6 +522,12 @@ "safer-buffer": "^2.1.0" } }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, "end-of-stream": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", @@ -363,10 +537,16 @@ "once": "^1.4.0" } }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true }, "event-stream": { @@ -426,6 +606,31 @@ "pend": "~1.2.0" } }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true + }, "flush-write-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.0.tgz", @@ -488,6 +693,13 @@ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "optional": true + }, "fstream": { "version": "1.0.12", "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", @@ -506,6 +718,12 @@ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", "dev": true }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, "getpass": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", @@ -516,9 +734,9 @@ } }, "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", "dev": true, "requires": { "fs.realpath": "^1.0.0", @@ -527,6 +745,17 @@ "minimatch": "^3.0.4", "once": "^1.3.0", "path-is-absolute": "^1.0.0" + }, + "dependencies": { + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + } } }, "glob-parent": { @@ -572,9 +801,9 @@ } }, "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "requires": { "brace-expansion": "^1.1.7" @@ -588,12 +817,6 @@ "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==", "dev": true }, - "growl": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", - "dev": true - }, "gulp-chmod": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/gulp-chmod/-/gulp-chmod-2.0.0.tgz", @@ -870,6 +1093,15 @@ "is-windows": "^1.0.1" } }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", @@ -882,6 +1114,12 @@ "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", "dev": true }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, "is-glob": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", @@ -897,12 +1135,24 @@ "integrity": "sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI=", "dev": true }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, "is-obj": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", "dev": true }, + "is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "dev": true + }, "is-relative": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", @@ -927,6 +1177,12 @@ "unc-path-regex": "^0.1.2" } }, + "is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true + }, "is-utf8": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", @@ -957,6 +1213,15 @@ "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", "dev": true }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + }, "jsbn": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", @@ -1023,6 +1288,25 @@ "flush-write-stream": "^1.0.2" } }, + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "requires": { + "p-locate": "^5.0.0" + } + }, + "log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "requires": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + } + }, "map-stream": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", @@ -1045,12 +1329,23 @@ } }, "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", + "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", "dev": true, "requires": { - "brace-expansion": "^1.1.7" + "brace-expansion": "^2.0.1" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + } } }, "minimist": { @@ -1069,36 +1364,60 @@ } }, "mocha": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz", - "integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.1.0.tgz", + "integrity": "sha512-vUF7IYxEoN7XhQpFLxQAEMtE4W91acW4B6En9l97MwE9stL1A9gusXfoHZCLVHDUJ/7V5+lbCM6yMqzo5vNymg==", "dev": true, "requires": { + "ansi-colors": "4.1.1", "browser-stdout": "1.3.1", - "commander": "2.15.1", - "debug": "3.1.0", - "diff": "3.5.0", - "escape-string-regexp": "1.0.5", - "glob": "7.1.2", - "growl": "1.10.5", - "he": "1.1.1", - "minimatch": "3.0.4", - "mkdirp": "0.5.1", - "supports-color": "5.4.0" + "chokidar": "3.5.3", + "debug": "4.3.4", + "diff": "5.0.0", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", + "glob": "7.2.0", + "he": "1.2.0", + "js-yaml": "4.1.0", + "log-symbols": "4.1.0", + "minimatch": "5.0.1", + "ms": "2.1.3", + "nanoid": "3.3.3", + "serialize-javascript": "6.0.0", + "strip-json-comments": "3.1.1", + "supports-color": "8.1.1", + "workerpool": "6.2.1", + "yargs": "16.2.0", + "yargs-parser": "20.2.4", + "yargs-unparser": "2.0.0" }, "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "requires": { + "balanced-match": "^1.0.0" + } + }, "browser-stdout": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true + }, + "he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true } } }, "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, "multimatch": { @@ -1114,9 +1433,9 @@ }, "dependencies": { "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "requires": { "brace-expansion": "^1.1.7" @@ -1124,6 +1443,12 @@ } } }, + "nanoid": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", + "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", + "dev": true + }, "node.extend": { "version": "1.1.8", "resolved": "https://registry.npmjs.org/node.extend/-/node.extend-1.1.8.tgz", @@ -1194,12 +1519,36 @@ "readable-stream": "^2.0.1" } }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "requires": { + "p-limit": "^3.0.2" + } + }, "path-dirname": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", "dev": true }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", @@ -1227,6 +1576,12 @@ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", "dev": true }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true + }, "plugin-error": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-0.1.2.tgz", @@ -1300,6 +1655,15 @@ "inherits": "~2.0.0" } }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.0" + } + }, "readable-stream": { "version": "2.3.6", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", @@ -1315,6 +1679,15 @@ "util-deprecate": "~1.0.1" } }, + "readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "requires": { + "picomatch": "^2.2.1" + } + }, "remove-bom-buffer": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", @@ -1376,6 +1749,12 @@ "uuid": "^3.3.2" } }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true + }, "requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", @@ -1413,6 +1792,15 @@ "once": "^1.3.0", "path-is-absolute": "^1.0.0" } + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } } } }, @@ -1433,6 +1821,15 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==" }, + "serialize-javascript": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", + "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -1511,6 +1908,17 @@ "integrity": "sha1-l+mNj6TRBdYqJpHR3AfoINuN/E8=", "dev": true }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, "string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", @@ -1520,19 +1928,34 @@ "safe-buffer": "~5.1.0" } }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + }, "supports-color": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, "requires": { - "has-flag": "^3.0.0" + "has-flag": "^4.0.0" }, "dependencies": { "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true } } @@ -1584,6 +2007,15 @@ "is-negated-glob": "^1.0.0" } }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, "to-through": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", @@ -1882,9 +2314,9 @@ "dev": true }, "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "requires": { "brace-expansion": "^1.1.7" @@ -1983,6 +2415,23 @@ "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-1.0.6.tgz", "integrity": "sha512-sLI2L0uGov3wKVb9EB+vIQBl9tVP90nqRvxSoJ35vI3NjxE8jfsE5DSOhWgSunHSZmKS4OCi2jrtfxK7uyp2ww==" }, + "workerpool": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", + "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", + "dev": true + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -1995,6 +2444,45 @@ "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", "dev": true }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true + }, + "yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + } + }, + "yargs-parser": { + "version": "20.2.4", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", + "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "dev": true + }, + "yargs-unparser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "dev": true, + "requires": { + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" + } + }, "yauzl": { "version": "2.10.0", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", @@ -2013,6 +2501,12 @@ "requires": { "buffer-crc32": "~0.2.3" } + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true } } } diff --git a/clang-tools-extra/clangd/clients/clangd-vscode/package.json b/clang-tools-extra/clangd/clients/clangd-vscode/package.json index 1bc6f4cb4621..12a6afec9b1c 100644 --- a/clang-tools-extra/clangd/clients/clangd-vscode/package.json +++ b/clang-tools-extra/clangd/clients/clangd-vscode/package.json @@ -41,7 +41,7 @@ "devDependencies": { "@types/mocha": "^2.2.32", "@types/node": "^6.0.40", - "mocha": "^5.2.0", + "mocha": "^10.1.0", "typescript": "^2.0.3", "vscode": "^1.1.0" },