@@ -401,6 +401,194 @@ void SemaHLSL::DiagnoseAttrStageMismatch(
401401 << (AllowedStages.size () != 1 ) << join (StageStrings, " , " );
402402}
403403
404+ template <CastKind Kind>
405+ static void castVector (Sema &S, ExprResult &E, QualType &Ty, unsigned Sz) {
406+ if (const auto *VTy = Ty->getAs <VectorType>())
407+ Ty = VTy->getElementType ();
408+ Ty = S.getASTContext ().getExtVectorType (Ty, Sz);
409+ E = S.ImpCastExprToType (E.get (), Ty, Kind);
410+ }
411+
412+ template <CastKind Kind>
413+ static QualType castElement (Sema &S, ExprResult &E, QualType Ty) {
414+ E = S.ImpCastExprToType (E.get (), Ty, Kind);
415+ return Ty;
416+ }
417+
418+ static QualType handleFloatVectorBinOpConversion (
419+ Sema &SemaRef, ExprResult &LHS, ExprResult &RHS, QualType LHSType,
420+ QualType RHSType, QualType LElTy, QualType RElTy, bool IsCompAssign) {
421+ bool LHSFloat = LElTy->isRealFloatingType ();
422+ bool RHSFloat = RElTy->isRealFloatingType ();
423+
424+ if (LHSFloat && RHSFloat) {
425+ if (IsCompAssign ||
426+ SemaRef.getASTContext ().getFloatingTypeOrder (LElTy, RElTy) > 0 )
427+ return castElement<CK_FloatingCast>(SemaRef, RHS, LHSType);
428+
429+ return castElement<CK_FloatingCast>(SemaRef, LHS, RHSType);
430+ }
431+
432+ if (LHSFloat)
433+ return castElement<CK_IntegralToFloating>(SemaRef, RHS, LHSType);
434+
435+ assert (RHSFloat);
436+ if (IsCompAssign)
437+ return castElement<clang::CK_FloatingToIntegral>(SemaRef, RHS, LHSType);
438+
439+ return castElement<CK_IntegralToFloating>(SemaRef, LHS, RHSType);
440+ }
441+
442+ static QualType handleIntegerVectorBinOpConversion (
443+ Sema &SemaRef, ExprResult &LHS, ExprResult &RHS, QualType LHSType,
444+ QualType RHSType, QualType LElTy, QualType RElTy, bool IsCompAssign) {
445+
446+ int IntOrder = SemaRef.Context .getIntegerTypeOrder (LElTy, RElTy);
447+ bool LHSSigned = LElTy->hasSignedIntegerRepresentation ();
448+ bool RHSSigned = RElTy->hasSignedIntegerRepresentation ();
449+ auto &Ctx = SemaRef.getASTContext ();
450+
451+ // If both types have the same signedness, use the higher ranked type.
452+ if (LHSSigned == RHSSigned) {
453+ if (IsCompAssign || IntOrder >= 0 )
454+ return castElement<CK_IntegralCast>(SemaRef, RHS, LHSType);
455+
456+ return castElement<CK_IntegralCast>(SemaRef, LHS, RHSType);
457+ }
458+
459+ // If the unsigned type has greater than or equal rank of the signed type, use
460+ // the unsigned type.
461+ if (IntOrder != (LHSSigned ? 1 : -1 )) {
462+ if (IsCompAssign || RHSSigned)
463+ return castElement<CK_IntegralCast>(SemaRef, RHS, LHSType);
464+ return castElement<CK_IntegralCast>(SemaRef, LHS, RHSType);
465+ }
466+
467+ // At this point the signed type has higher rank than the unsigned type, which
468+ // means it will be the same size or bigger. If the signed type is bigger, it
469+ // can represent all the values of the unsigned type, so select it.
470+ if (Ctx.getIntWidth (LElTy) != Ctx.getIntWidth (RElTy)) {
471+ if (IsCompAssign || LHSSigned)
472+ return castElement<CK_IntegralCast>(SemaRef, RHS, LHSType);
473+ return castElement<CK_IntegralCast>(SemaRef, LHS, RHSType);
474+ }
475+
476+ // This is a bit of an odd duck case in HLSL. It shouldn't happen, but can due
477+ // to C/C++ leaking through. The place this happens today is long vs long
478+ // long. When arguments are vector<unsigned long, N> and vector<long long, N>,
479+ // the long long has higher rank than long even though they are the same size.
480+
481+ // If this is a compound assignment cast the right hand side to the left hand
482+ // side's type.
483+ if (IsCompAssign)
484+ return castElement<CK_IntegralCast>(SemaRef, RHS, LHSType);
485+
486+ // If this isn't a compound assignment we convert to unsigned long long.
487+ QualType ElTy = Ctx.getCorrespondingUnsignedType (LHSSigned ? LElTy : RElTy);
488+ QualType NewTy = Ctx.getExtVectorType (
489+ ElTy, RHSType->castAs <VectorType>()->getNumElements ());
490+ (void )castElement<CK_IntegralCast>(SemaRef, RHS, NewTy);
491+
492+ return castElement<CK_IntegralCast>(SemaRef, LHS, NewTy);
493+ }
494+
495+ static CastKind getScalarCastKind (ASTContext &Ctx, QualType DestTy,
496+ QualType SrcTy) {
497+ if (DestTy->isRealFloatingType () && SrcTy->isRealFloatingType ())
498+ return CK_FloatingCast;
499+ if (DestTy->isIntegralType (Ctx) && SrcTy->isIntegralType (Ctx))
500+ return CK_IntegralCast;
501+ if (DestTy->isRealFloatingType ())
502+ return CK_IntegralToFloating;
503+ assert (SrcTy->isRealFloatingType () && DestTy->isIntegralType (Ctx));
504+ return CK_FloatingToIntegral;
505+ }
506+
507+ QualType SemaHLSL::handleVectorBinOpConversion (ExprResult &LHS, ExprResult &RHS,
508+ QualType LHSType,
509+ QualType RHSType,
510+ bool IsCompAssign) {
511+ const auto *LVecTy = LHSType->getAs <VectorType>();
512+ const auto *RVecTy = RHSType->getAs <VectorType>();
513+ auto &Ctx = getASTContext ();
514+
515+ // If the LHS is not a vector and this is a compound assignment, we truncate
516+ // the argument to a scalar then convert it to the LHS's type.
517+ if (!LVecTy && IsCompAssign) {
518+ QualType RElTy = RHSType->castAs <VectorType>()->getElementType ();
519+ RHS = SemaRef.ImpCastExprToType (RHS.get (), RElTy, CK_HLSLVectorTruncation);
520+ RHSType = RHS.get ()->getType ();
521+ if (Ctx.hasSameUnqualifiedType (LHSType, RHSType))
522+ return LHSType;
523+ RHS = SemaRef.ImpCastExprToType (RHS.get (), LHSType,
524+ getScalarCastKind (Ctx, LHSType, RHSType));
525+ return LHSType;
526+ }
527+
528+ unsigned EndSz = std::numeric_limits<unsigned >::max ();
529+ unsigned LSz = 0 ;
530+ if (LVecTy)
531+ LSz = EndSz = LVecTy->getNumElements ();
532+ if (RVecTy)
533+ EndSz = std::min (RVecTy->getNumElements (), EndSz);
534+ assert (EndSz != std::numeric_limits<unsigned >::max () &&
535+ " one of the above should have had a value" );
536+
537+ // In a compound assignment, the left operand does not change type, the right
538+ // operand is converted to the type of the left operand.
539+ if (IsCompAssign && LSz != EndSz) {
540+ Diag (LHS.get ()->getBeginLoc (),
541+ diag::err_hlsl_vector_compound_assignment_truncation)
542+ << LHSType << RHSType;
543+ return QualType ();
544+ }
545+
546+ if (RVecTy && RVecTy->getNumElements () > EndSz)
547+ castVector<CK_HLSLVectorTruncation>(SemaRef, RHS, RHSType, EndSz);
548+ if (!IsCompAssign && LVecTy && LVecTy->getNumElements () > EndSz)
549+ castVector<CK_HLSLVectorTruncation>(SemaRef, LHS, LHSType, EndSz);
550+
551+ if (!RVecTy)
552+ castVector<CK_VectorSplat>(SemaRef, RHS, RHSType, EndSz);
553+ if (!IsCompAssign && !LVecTy)
554+ castVector<CK_VectorSplat>(SemaRef, LHS, LHSType, EndSz);
555+
556+ // If we're at the same type after resizing we can stop here.
557+ if (Ctx.hasSameUnqualifiedType (LHSType, RHSType))
558+ return Ctx.getCommonSugaredType (LHSType, RHSType);
559+
560+ QualType LElTy = LHSType->castAs <VectorType>()->getElementType ();
561+ QualType RElTy = RHSType->castAs <VectorType>()->getElementType ();
562+
563+ // Handle conversion for floating point vectors.
564+ if (LElTy->isRealFloatingType () || RElTy->isRealFloatingType ())
565+ return handleFloatVectorBinOpConversion (SemaRef, LHS, RHS, LHSType, RHSType,
566+ LElTy, RElTy, IsCompAssign);
567+
568+ assert (LElTy->isIntegralType (Ctx) && RElTy->isIntegralType (Ctx) &&
569+ " HLSL Vectors can only contain integer or floating point types" );
570+ return handleIntegerVectorBinOpConversion (SemaRef, LHS, RHS, LHSType, RHSType,
571+ LElTy, RElTy, IsCompAssign);
572+ }
573+
574+ void SemaHLSL::emitLogicalOperatorFixIt (Expr *LHS, Expr *RHS,
575+ BinaryOperatorKind Opc) {
576+ assert ((Opc == BO_LOr || Opc == BO_LAnd) &&
577+ " Called with non-logical operator" );
578+ llvm::SmallVector<char , 256 > Buff;
579+ llvm::raw_svector_ostream OS (Buff);
580+ PrintingPolicy PP (SemaRef.getLangOpts ());
581+ StringRef NewFnName = Opc == BO_LOr ? " or" : " and" ;
582+ OS << NewFnName << " (" ;
583+ LHS->printPretty (OS, nullptr , PP);
584+ OS << " , " ;
585+ RHS->printPretty (OS, nullptr , PP);
586+ OS << " )" ;
587+ SourceRange FullRange = SourceRange (LHS->getBeginLoc (), RHS->getEndLoc ());
588+ SemaRef.Diag (LHS->getBeginLoc (), diag::note_function_suggestion)
589+ << NewFnName << FixItHint::CreateReplacement (FullRange, OS.str ());
590+ }
591+
404592void SemaHLSL::handleNumThreadsAttr (Decl *D, const ParsedAttr &AL) {
405593 llvm::VersionTuple SMVersion =
406594 getASTContext ().getTargetInfo ().getTriple ().getOSVersion ();
0 commit comments