[clang] [HLSL] Vector Usual Arithmetic Conversions (PR #108659)
Justin Bogner via cfe-commits
cfe-commits at lists.llvm.org
Wed Sep 25 14:51:25 PDT 2024
================
@@ -401,6 +401,194 @@ void SemaHLSL::DiagnoseAttrStageMismatch(
<< (AllowedStages.size() != 1) << join(StageStrings, ", ");
}
+template <CastKind Kind>
+static void castVector(Sema &S, ExprResult &E, QualType &Ty, unsigned Sz) {
+ if (const auto *VTy = Ty->getAs<VectorType>())
+ Ty = VTy->getElementType();
+ Ty = S.getASTContext().getExtVectorType(Ty, Sz);
+ E = S.ImpCastExprToType(E.get(), Ty, Kind);
+}
+
+template <CastKind Kind>
+static QualType castElement(Sema &S, ExprResult &E, QualType Ty) {
+ E = S.ImpCastExprToType(E.get(), Ty, Kind);
+ return Ty;
+}
+
+static QualType handleFloatVectorBinOpConversion(
+ Sema &SemaRef, ExprResult &LHS, ExprResult &RHS, QualType LHSType,
+ QualType RHSType, QualType LElTy, QualType RElTy, bool IsCompAssign) {
+ bool LHSFloat = LElTy->isRealFloatingType();
+ bool RHSFloat = RElTy->isRealFloatingType();
+
+ if (LHSFloat && RHSFloat) {
+ if (IsCompAssign ||
+ SemaRef.getASTContext().getFloatingTypeOrder(LElTy, RElTy) > 0)
+ return castElement<CK_FloatingCast>(SemaRef, RHS, LHSType);
+
+ return castElement<CK_FloatingCast>(SemaRef, LHS, RHSType);
+ }
+
+ if (LHSFloat)
+ return castElement<CK_IntegralToFloating>(SemaRef, RHS, LHSType);
+
+ assert(RHSFloat);
+ if (IsCompAssign)
+ return castElement<clang::CK_FloatingToIntegral>(SemaRef, RHS, LHSType);
+
+ return castElement<CK_IntegralToFloating>(SemaRef, LHS, RHSType);
+}
+
+static QualType handleIntegerVectorBinOpConversion(
+ Sema &SemaRef, ExprResult &LHS, ExprResult &RHS, QualType LHSType,
+ QualType RHSType, QualType LElTy, QualType RElTy, bool IsCompAssign) {
+
+ int IntOrder = SemaRef.Context.getIntegerTypeOrder(LElTy, RElTy);
+ bool LHSSigned = LElTy->hasSignedIntegerRepresentation();
+ bool RHSSigned = RElTy->hasSignedIntegerRepresentation();
+ auto &Ctx = SemaRef.getASTContext();
+
+ // If both types have the same signedness, use the higher ranked type.
+ if (LHSSigned == RHSSigned) {
+ if (IsCompAssign || IntOrder >= 0)
+ return castElement<CK_IntegralCast>(SemaRef, RHS, LHSType);
+
+ return castElement<CK_IntegralCast>(SemaRef, LHS, RHSType);
+ }
+
+ // If the unsigned type has greater than or equal rank of the signed type, use
+ // the unsigned type.
+ if (IntOrder != (LHSSigned ? 1 : -1)) {
+ if (IsCompAssign || RHSSigned)
+ return castElement<CK_IntegralCast>(SemaRef, RHS, LHSType);
+ return castElement<CK_IntegralCast>(SemaRef, LHS, RHSType);
+ }
+
+ // At this point the signed type has higher rank than the unsigned type, which
+ // means it will be the same size or bigger. If the signed type is bigger, it
+ // can represent all the values of the unsigned type, so select it.
+ if (Ctx.getIntWidth(LElTy) != Ctx.getIntWidth(RElTy)) {
+ if (IsCompAssign || LHSSigned)
+ return castElement<CK_IntegralCast>(SemaRef, RHS, LHSType);
+ return castElement<CK_IntegralCast>(SemaRef, LHS, RHSType);
+ }
+
+ // This is a bit of an odd duck case in HLSL. It shouldn't happen, but can due
+ // to C/C++ leaking through. The place this happens today is long vs long
+ // long. When arguments are vector<unsigned long, N> and vector<long long, N>,
+ // the long long has higher rank than long even though they are the same size.
----------------
bogner wrote:
Should we assert on the types to make sure this is indeed the `long`/`long long` case? If we somehow got here for some other case I'm not convinced what we do below would be correct.
https://github.com/llvm/llvm-project/pull/108659
More information about the cfe-commits
mailing list