@@ -401,6 +401,194 @@ void SemaHLSL::DiagnoseAttrStageMismatch(
401
401
<< (AllowedStages.size () != 1 ) << join (StageStrings, " , " );
402
402
}
403
403
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
+
404
592
void SemaHLSL::handleNumThreadsAttr (Decl *D, const ParsedAttr &AL) {
405
593
llvm::VersionTuple SMVersion =
406
594
getASTContext ().getTargetInfo ().getTriple ().getOSVersion ();
0 commit comments