diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/ASTContext.cpp | 9 | ||||
-rw-r--r-- | clang/lib/AST/Expr.cpp | 4 | ||||
-rw-r--r-- | clang/lib/AST/ExprConstant.cpp | 2 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGDebugInfo.cpp | 5 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGDebugInfo.h | 1 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExpr.cpp | 1 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExprAgg.cpp | 1 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExprComplex.cpp | 1 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExprConstant.cpp | 3 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExprScalar.cpp | 5 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGOpenCLRuntime.cpp | 11 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGOpenCLRuntime.h | 6 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.cpp | 17 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.h | 3 | ||||
-rw-r--r-- | clang/lib/Edit/RewriteObjCFoundationAPI.cpp | 1 | ||||
-rw-r--r-- | clang/lib/Frontend/CompilerInvocation.cpp | 7 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 5 | ||||
-rw-r--r-- | clang/lib/Sema/SemaInit.cpp | 91 | ||||
-rw-r--r-- | clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp | 1 |
19 files changed, 154 insertions, 20 deletions
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index cf7f5947a2f..0d6ad9d0d60 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -1734,11 +1734,12 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { Width = Target->getPointerWidth(0); Align = Target->getPointerAlign(0); break; - case BuiltinType::OCLSampler: - // Samplers are modeled as integers. - Width = Target->getIntWidth(); - Align = Target->getIntAlign(); + case BuiltinType::OCLSampler: { + auto AS = getTargetAddressSpace(LangAS::opencl_constant); + Width = Target->getPointerWidth(AS); + Align = Target->getPointerAlign(AS); break; + } case BuiltinType::OCLEvent: case BuiltinType::OCLClkEvent: case BuiltinType::OCLQueue: diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 71bbfdc3369..e835686a1a9 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -1569,6 +1569,7 @@ bool CastExpr::CastConsistency() const { case CK_ARCReclaimReturnedObject: case CK_ARCExtendBlockObject: case CK_ZeroToOCLEvent: + case CK_IntToOCLSampler: assert(!getType()->isBooleanType() && "unheralded conversion to bool"); goto CheckNoBasePath; @@ -2747,7 +2748,8 @@ bool Expr::isConstantInitializer(ASTContext &Ctx, bool IsForRef, CE->getCastKind() == CK_ToUnion || CE->getCastKind() == CK_ConstructorConversion || CE->getCastKind() == CK_NonAtomicToAtomic || - CE->getCastKind() == CK_AtomicToNonAtomic) + CE->getCastKind() == CK_AtomicToNonAtomic || + CE->getCastKind() == CK_IntToOCLSampler) return CE->getSubExpr()->isConstantInitializer(Ctx, false, Culprit); break; diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 760cda99c54..176f1ba8422 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -8056,6 +8056,7 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) { case CK_ZeroToOCLEvent: case CK_NonAtomicToAtomic: case CK_AddressSpaceConversion: + case CK_IntToOCLSampler: llvm_unreachable("invalid cast kind for integral value"); case CK_BitCast: @@ -8547,6 +8548,7 @@ bool ComplexExprEvaluator::VisitCastExpr(const CastExpr *E) { case CK_ZeroToOCLEvent: case CK_NonAtomicToAtomic: case CK_AddressSpaceConversion: + case CK_IntToOCLSampler: llvm_unreachable("invalid cast kind for complex value"); case CK_LValueToRValue: diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 9763e9b51a8..b99b519a966 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -518,9 +518,8 @@ llvm::DIType *CGDebugInfo::CreateType(const BuiltinType *BT) { SingletonId); #include "clang/Basic/OpenCLImageTypes.def" case BuiltinType::OCLSampler: - return DBuilder.createBasicType( - "opencl_sampler_t", CGM.getContext().getTypeSize(BT), - CGM.getContext().getTypeAlign(BT), llvm::dwarf::DW_ATE_unsigned); + return getOrCreateStructPtrType("opencl_sampler_t", + OCLSamplerDITy); case BuiltinType::OCLEvent: return getOrCreateStructPtrType("opencl_event_t", OCLEventDITy); case BuiltinType::OCLClkEvent: diff --git a/clang/lib/CodeGen/CGDebugInfo.h b/clang/lib/CodeGen/CGDebugInfo.h index 70c16462965..71c0df4cbf0 100644 --- a/clang/lib/CodeGen/CGDebugInfo.h +++ b/clang/lib/CodeGen/CGDebugInfo.h @@ -67,6 +67,7 @@ class CGDebugInfo { #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ llvm::DIType *SingletonId = nullptr; #include "clang/Basic/OpenCLImageTypes.def" + llvm::DIType *OCLSamplerDITy = nullptr; llvm::DIType *OCLEventDITy = nullptr; llvm::DIType *OCLClkEventDITy = nullptr; llvm::DIType *OCLQueueDITy = nullptr; diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 3e1ae3604f9..039936a3a64 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -3601,6 +3601,7 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) { case CK_ARCExtendBlockObject: case CK_CopyAndAutoreleaseBlockObject: case CK_AddressSpaceConversion: + case CK_IntToOCLSampler: return EmitUnsupportedLValue(E, "unexpected cast lvalue"); case CK_Dependent: diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp index 6d18843591f..f51330c8b19 100644 --- a/clang/lib/CodeGen/CGExprAgg.cpp +++ b/clang/lib/CodeGen/CGExprAgg.cpp @@ -750,6 +750,7 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) { case CK_BuiltinFnToFnPtr: case CK_ZeroToOCLEvent: case CK_AddressSpaceConversion: + case CK_IntToOCLSampler: llvm_unreachable("cast kind invalid for aggregate types"); } } diff --git a/clang/lib/CodeGen/CGExprComplex.cpp b/clang/lib/CodeGen/CGExprComplex.cpp index e0d3fc4c1c6..af7f190f793 100644 --- a/clang/lib/CodeGen/CGExprComplex.cpp +++ b/clang/lib/CodeGen/CGExprComplex.cpp @@ -481,6 +481,7 @@ ComplexPairTy ComplexExprEmitter::EmitCast(CastKind CK, Expr *Op, case CK_BuiltinFnToFnPtr: case CK_ZeroToOCLEvent: case CK_AddressSpaceConversion: + case CK_IntToOCLSampler: llvm_unreachable("invalid cast kind for complex value"); case CK_FloatingRealToComplex: diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp index 803b39907dd..0e818e99eec 100644 --- a/clang/lib/CodeGen/CGExprConstant.cpp +++ b/clang/lib/CodeGen/CGExprConstant.cpp @@ -690,6 +690,9 @@ public: case CK_ConstructorConversion: return C; + case CK_IntToOCLSampler: + llvm_unreachable("global sampler variables are not generated"); + case CK_Dependent: llvm_unreachable("saw dependent cast!"); case CK_BuiltinFnToFnPtr: diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 064bc9532a6..343d3fb5aa6 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -1573,7 +1573,10 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) { return llvm::Constant::getNullValue(ConvertType(DestTy)); } - } + case CK_IntToOCLSampler: + return CGF.CGM.createOpenCLIntToSamplerConversion(E, CGF);
+ + } // end of switch llvm_unreachable("unknown scalar cast"); } diff --git a/clang/lib/CodeGen/CGOpenCLRuntime.cpp b/clang/lib/CodeGen/CGOpenCLRuntime.cpp index c0af6deae2d..e4541d59c25 100644 --- a/clang/lib/CodeGen/CGOpenCLRuntime.cpp +++ b/clang/lib/CodeGen/CGOpenCLRuntime.cpp @@ -48,7 +48,7 @@ llvm::Type *CGOpenCLRuntime::convertOpenCLSpecificType(const Type *T) { ImgAddrSpc); #include "clang/Basic/OpenCLImageTypes.def" case BuiltinType::OCLSampler: - return llvm::IntegerType::get(Ctx, 32); + return getSamplerType(); case BuiltinType::OCLEvent: return llvm::PointerType::get(llvm::StructType::create( Ctx, "opencl.event_t"), 0); @@ -77,3 +77,12 @@ llvm::Type *CGOpenCLRuntime::getPipeType() { return PipeTy; } + +llvm::PointerType *CGOpenCLRuntime::getSamplerType() { + if (!SamplerTy) + SamplerTy = llvm::PointerType::get(llvm::StructType::create( + CGM.getLLVMContext(), "opencl.sampler_t"), + CGM.getContext().getTargetAddressSpace( + LangAS::opencl_constant)); + return SamplerTy; +} diff --git a/clang/lib/CodeGen/CGOpenCLRuntime.h b/clang/lib/CodeGen/CGOpenCLRuntime.h index f1a7a310644..41ead1010a2 100644 --- a/clang/lib/CodeGen/CGOpenCLRuntime.h +++ b/clang/lib/CodeGen/CGOpenCLRuntime.h @@ -33,9 +33,11 @@ class CGOpenCLRuntime { protected: CodeGenModule &CGM; llvm::Type *PipeTy; + llvm::PointerType *SamplerTy; public: - CGOpenCLRuntime(CodeGenModule &CGM) : CGM(CGM), PipeTy(nullptr) {} + CGOpenCLRuntime(CodeGenModule &CGM) : CGM(CGM), PipeTy(nullptr), + SamplerTy(nullptr) {} virtual ~CGOpenCLRuntime(); /// Emit the IR required for a work-group-local variable declaration, and add @@ -47,6 +49,8 @@ public: virtual llvm::Type *convertOpenCLSpecificType(const Type *T); virtual llvm::Type *getPipeType(); + + llvm::PointerType *getSamplerType(); }; } diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 96bb5bfe027..2affa57ca11 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -2384,8 +2384,13 @@ void CodeGenModule::maybeSetTrivialComdat(const Decl &D, /// Pass IsTentative as true if you want to create a tentative definition. void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D, bool IsTentative) { - llvm::Constant *Init = nullptr; + // OpenCL global variables of sampler type are translated to function calls, + // therefore no need to be translated. QualType ASTTy = D->getType(); + if (getLangOpts().OpenCL && ASTTy->isSamplerT()) + return; + + llvm::Constant *Init = nullptr; CXXRecordDecl *RD = ASTTy->getBaseElementTypeUnsafe()->getAsCXXRecordDecl(); bool NeedsGlobalCtor = false; bool NeedsGlobalDtor = RD && !RD->hasTrivialDestructor(); @@ -4317,3 +4322,13 @@ llvm::SanitizerStatReport &CodeGenModule::getSanStats() { return *SanStats; } +llvm::Value * +CodeGenModule::createOpenCLIntToSamplerConversion(const Expr *E, + CodeGenFunction &CGF) { + llvm::Constant *C = EmitConstantExpr(E, E->getType(), &CGF); + auto SamplerT = getOpenCLRuntime().getSamplerType(); + auto FTy = llvm::FunctionType::get(SamplerT, {C->getType()}, false); + return CGF.Builder.CreateCall(CreateRuntimeFunction(FTy, + "__translate_sampler_initializer"), + {C}); +} diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h index 94904997d62..54354451b85 100644 --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/lib/CodeGen/CodeGenModule.h @@ -1145,6 +1145,9 @@ public: llvm::SanitizerStatReport &getSanStats(); + llvm::Value * + createOpenCLIntToSamplerConversion(const Expr *E, CodeGenFunction &CGF); + private: llvm::Constant * GetOrCreateLLVMFunction(StringRef MangledName, llvm::Type *Ty, GlobalDecl D, diff --git a/clang/lib/Edit/RewriteObjCFoundationAPI.cpp b/clang/lib/Edit/RewriteObjCFoundationAPI.cpp index 482c0f6f856..0ae1ec7e4b1 100644 --- a/clang/lib/Edit/RewriteObjCFoundationAPI.cpp +++ b/clang/lib/Edit/RewriteObjCFoundationAPI.cpp @@ -1076,6 +1076,7 @@ static bool rewriteToNumericBoxedExpression(const ObjCMessageExpr *Msg, case CK_CopyAndAutoreleaseBlockObject: case CK_BuiltinFnToFnPtr: case CK_ZeroToOCLEvent: + case CK_IntToOCLSampler: return false; case CK_BooleanToSignedIntegral: diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 04da24870f1..386e5773f90 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -2399,6 +2399,13 @@ bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res, ParsePreprocessorArgs(Res.getPreprocessorOpts(), Args, FileMgr, Diags); ParsePreprocessorOutputArgs(Res.getPreprocessorOutputOpts(), Args, Res.getFrontendOpts().ProgramAction); + + // Turn on -Wspir-compat for SPIR target. + llvm::Triple T(Res.getTargetOpts().Triple); + auto Arch = T.getArch(); + if (Arch == llvm::Triple::spir || Arch == llvm::Triple::spir64) { + Res.getDiagnosticOpts().Warnings.push_back("spir-compat"); + } return Success; } diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 42c44b183e5..19a3d035d37 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -7661,6 +7661,11 @@ Sema::CheckAssignmentConstraints(QualType LHSType, ExprResult &RHS, } } + if (LHSType->isSamplerT() && RHSType->isIntegerType()) { + Kind = CK_IntToOCLSampler; + return Compatible; + } + return Incompatible; } diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index af7fdc40c7b..fc896941df0 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -4885,7 +4885,8 @@ static bool TryOCLSamplerInitialization(Sema &S, QualType DestType, Expr *Initializer) { if (!S.getLangOpts().OpenCL || !DestType->isSamplerT() || - !Initializer->isIntegerConstantExpr(S.getASTContext())) + (!Initializer->isIntegerConstantExpr(S.Context) && + !Initializer->getType()->isSamplerT())) return false; Sequence.AddOCLSamplerInitStep(DestType); @@ -6903,19 +6904,93 @@ InitializationSequence::Perform(Sema &S, } case SK_OCLSamplerInit: { - assert(Step->Type->isSamplerT() && + // Sampler initialzation have 5 cases: + // 1. function argument passing + // 1a. argument is a file-scope variable + // 1b. argument is a function-scope variable + // 1c. argument is one of caller function's parameters + // 2. variable initialization + // 2a. initializing a file-scope variable + // 2b. initializing a function-scope variable + // + // For file-scope variables, since they cannot be initialized by function + // call of __translate_sampler_initializer in LLVM IR, their references + // need to be replaced by a cast from their literal initializers to + // sampler type. Since sampler variables can only be used in function + // calls as arguments, we only need to replace them when handling the + // argument passing. + assert(Step->Type->isSamplerT() && "Sampler initialization on non-sampler type."); - - QualType SourceType = CurInit.get()->getType(); - + Expr *Init = CurInit.get(); + QualType SourceType = Init->getType(); + // Case 1 if (Entity.isParameterKind()) { - if (!SourceType->isSamplerT()) + if (!SourceType->isSamplerT()) { S.Diag(Kind.getLocation(), diag::err_sampler_argument_required) << SourceType; - } else if (Entity.getKind() != InitializedEntity::EK_Variable) { - llvm_unreachable("Invalid EntityKind!"); + break; + } else if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Init)) { + auto Var = cast<VarDecl>(DRE->getDecl()); + // Case 1b and 1c + // No cast from integer to sampler is needed. + if (!Var->hasGlobalStorage()) { + CurInit = ImplicitCastExpr::Create(S.Context, Step->Type, + CK_LValueToRValue, Init, + /*BasePath=*/nullptr, VK_RValue); + break; + } + // Case 1a + // For function call with a file-scope sampler variable as argument, + // get the integer literal. + // Do not diagnose if the file-scope variable does not have initializer + // since this has already been diagnosed when parsing the variable + // declaration. + if (!Var->getInit() || !isa<ImplicitCastExpr>(Var->getInit())) + break; + Init = cast<ImplicitCastExpr>(const_cast<Expr*>( + Var->getInit()))->getSubExpr(); + SourceType = Init->getType(); + } + } else { + // Case 2 + // Check initializer is 32 bit integer constant. + // If the initializer is taken from global variable, do not diagnose since + // this has already been done when parsing the variable declaration. + if (!Init->isConstantInitializer(S.Context, false)) + break; + + if (!SourceType->isIntegerType() || + 32 != S.Context.getIntWidth(SourceType)) { + S.Diag(Kind.getLocation(), diag::err_sampler_initializer_not_integer) + << SourceType; + break; + } + + llvm::APSInt Result; + Init->EvaluateAsInt(Result, S.Context); + const uint64_t SamplerValue = Result.getLimitedValue(); + // 32-bit value of sampler's initializer is interpreted as + // bit-field with the following structure: + // |unspecified|Filter|Addressing Mode| Normalized Coords| + // |31 6|5 4|3 1| 0| + // This structure corresponds to enum values of sampler properties + // defined in SPIR spec v1.2 and also opencl-c.h + unsigned AddressingMode = (0x0E & SamplerValue) >> 1; + unsigned FilterMode = (0x30 & SamplerValue) >> 4; + if (FilterMode != 1 && FilterMode != 2) + S.Diag(Kind.getLocation(), + diag::warn_sampler_initializer_invalid_bits) + << "Filter Mode"; + if (AddressingMode > 4) + S.Diag(Kind.getLocation(), + diag::warn_sampler_initializer_invalid_bits) + << "Addressing Mode"; } + // Cases 1a, 2a and 2b + // Insert cast from integer to sampler. + CurInit = S.ImpCastExprToType(Init, S.Context.OCLSamplerTy, + CK_IntToOCLSampler); break; } case SK_OCLZeroEvent: { diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp index 175225ba0de..542399d4bcb 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp @@ -341,6 +341,7 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex, case CK_AnyPointerToBlockPointerCast: case CK_ObjCObjectLValueCast: case CK_ZeroToOCLEvent: + case CK_IntToOCLSampler: case CK_LValueBitCast: { // Delegate to SValBuilder to process. SVal V = state->getSVal(Ex, LCtx); |