@@ -2266,6 +2266,85 @@ static bool BuiltinCountZeroBitsGeneric(Sema &S, CallExpr *TheCall) {
22662266 return false;
22672267}
22682268
2269+ static bool CheckMaskedBuiltinArgs(Sema &S, Expr *MaskArg, Expr *PtrArg,
2270+ unsigned Pos) {
2271+ QualType MaskTy = MaskArg->getType();
2272+ if (!MaskTy->isExtVectorBoolType())
2273+ return S.Diag(MaskArg->getBeginLoc(), diag::err_builtin_invalid_arg_type)
2274+ << 1 << /* vector of */ 4 << /* booleans */ 6 << /* no fp */ 0
2275+ << MaskTy;
2276+
2277+ QualType PtrTy = PtrArg->getType();
2278+ if (!PtrTy->isPointerType() || !PtrTy->getPointeeType()->isVectorType())
2279+ return S.Diag(PtrArg->getExprLoc(), diag::err_vec_masked_load_store_ptr)
2280+ << Pos << "pointer to vector";
2281+ return false;
2282+ }
2283+
2284+ static ExprResult BuiltinMaskedLoad(Sema &S, CallExpr *TheCall) {
2285+ if (S.checkArgCount(TheCall, 2))
2286+ return ExprError();
2287+
2288+ Expr *MaskArg = TheCall->getArg(0);
2289+ Expr *PtrArg = TheCall->getArg(1);
2290+ if (CheckMaskedBuiltinArgs(S, MaskArg, PtrArg, 2))
2291+ return ExprError();
2292+
2293+ QualType MaskTy = MaskArg->getType();
2294+ QualType PtrTy = PtrArg->getType();
2295+ QualType PointeeTy = PtrTy->getPointeeType();
2296+ const VectorType *MaskVecTy = MaskTy->getAs<VectorType>();
2297+ const VectorType *DataVecTy = PointeeTy->getAs<VectorType>();
2298+ if (MaskVecTy->getNumElements() != DataVecTy->getNumElements())
2299+ return ExprError(
2300+ S.Diag(TheCall->getBeginLoc(), diag::err_vec_masked_load_store_size)
2301+ << "__builtin_masked_load" << MaskTy << PointeeTy);
2302+
2303+ TheCall->setType(PointeeTy);
2304+ return TheCall;
2305+ }
2306+
2307+ static ExprResult BuiltinMaskedStore(Sema &S, CallExpr *TheCall) {
2308+ if (S.checkArgCount(TheCall, 3))
2309+ return ExprError();
2310+
2311+ Expr *MaskArg = TheCall->getArg(0);
2312+ Expr *ValArg = TheCall->getArg(1);
2313+ Expr *PtrArg = TheCall->getArg(2);
2314+
2315+ if (CheckMaskedBuiltinArgs(S, MaskArg, PtrArg, 3))
2316+ return ExprError();
2317+
2318+ QualType MaskTy = MaskArg->getType();
2319+ QualType PtrTy = PtrArg->getType();
2320+ QualType ValTy = ValArg->getType();
2321+ if (!ValTy->isVectorType())
2322+ return ExprError(
2323+ S.Diag(ValArg->getExprLoc(), diag::err_vec_masked_load_store_ptr)
2324+ << 2 << "vector");
2325+
2326+ QualType PointeeTy = PtrTy->getPointeeType();
2327+ const VectorType *MaskVecTy = MaskTy->getAs<VectorType>();
2328+ const VectorType *ValVecTy = ValTy->getAs<VectorType>();
2329+ const VectorType *PtrVecTy = PointeeTy->getAs<VectorType>();
2330+
2331+ if (MaskVecTy->getNumElements() != ValVecTy->getNumElements() ||
2332+ MaskVecTy->getNumElements() != PtrVecTy->getNumElements())
2333+ return ExprError(
2334+ S.Diag(TheCall->getBeginLoc(), diag::err_vec_masked_load_store_size)
2335+ << "__builtin_masked_store" << MaskTy << PointeeTy);
2336+
2337+ if (!S.Context.hasSameType(ValTy, PointeeTy))
2338+ return ExprError(S.Diag(TheCall->getBeginLoc(),
2339+ diag::err_vec_builtin_incompatible_vector)
2340+ << TheCall->getDirectCallee() << /*isMorethantwoArgs*/ 2
2341+ << SourceRange(TheCall->getArg(1)->getBeginLoc(),
2342+ TheCall->getArg(1)->getEndLoc()));
2343+
2344+ TheCall->setType(S.Context.VoidTy);
2345+ return TheCall;
2346+ }
2347+
22692348static ExprResult BuiltinInvoke(Sema &S, CallExpr *TheCall) {
22702349 SourceLocation Loc = TheCall->getBeginLoc();
22712350 MutableArrayRef Args(TheCall->getArgs(), TheCall->getNumArgs());
@@ -2518,6 +2597,10 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
25182597 return BuiltinShuffleVector(TheCall);
25192598 // TheCall will be freed by the smart pointer here, but that's fine, since
25202599 // BuiltinShuffleVector guts it, but then doesn't release it.
2600+ case Builtin::BI__builtin_masked_load:
2601+ return BuiltinMaskedLoad(*this, TheCall);
2602+ case Builtin::BI__builtin_masked_store:
2603+ return BuiltinMaskedStore(*this, TheCall);
25212604 case Builtin::BI__builtin_invoke:
25222605 return BuiltinInvoke(*this, TheCall);
25232606 case Builtin::BI__builtin_prefetch:
0 commit comments