diff options
Diffstat (limited to 'clang/lib/Sema/SemaInit.cpp')
-rw-r--r-- | clang/lib/Sema/SemaInit.cpp | 91 |
1 files changed, 83 insertions, 8 deletions
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: { |