https://github.com/llvm-beanz updated https://github.com/llvm/llvm-project/pull/71098
>From 91e8d9d9f63fe2ac481bb01549e3d69ac59d68f8 Mon Sep 17 00:00:00 2001 From: Chris Bieneman <chris.biene...@me.com> Date: Wed, 1 Nov 2023 12:18:43 -0500 Subject: [PATCH 1/6] [HLSL] Vector vector standard conversions HLSL supports vector truncation and element conversions as part of standard conversion sequences. The vector truncation conversion is a C++ second conversion in the conversion sequence. If a vector truncation is in a conversion sequence an element conversion may occur after it before the standard C++ third conversion. Vector element conversions can be boolean conversions, floating point or integral conversions or promotions. [HLSL Draft Specification](https://microsoft.github.io/hlsl-specs/specs/hlsl.pdf) ../clang/test/CodeGenHLSL/BasicFeatures/standard_conversion_sequences.hl sl ../clang/test/SemaHLSL/BuiltIns/vector-constructors-erros.hlsl ../clang/test/SemaHLSL/standard_conversion_sequences.hlsl --- clang/include/clang/AST/OperationKinds.def | 3 + .../clang/Basic/DiagnosticSemaKinds.td | 3 + clang/include/clang/Sema/Overload.h | 12 +- clang/lib/AST/Expr.cpp | 1 + clang/lib/AST/ExprConstant.cpp | 2 + clang/lib/CodeGen/CGExpr.cpp | 2 + clang/lib/CodeGen/CGExprAgg.cpp | 2 + clang/lib/CodeGen/CGExprComplex.cpp | 1 + clang/lib/CodeGen/CGExprConstant.cpp | 1 + clang/lib/CodeGen/CGExprScalar.cpp | 23 +- clang/lib/Edit/RewriteObjCFoundationAPI.cpp | 4 + clang/lib/Sema/SemaChecking.cpp | 11 +- clang/lib/Sema/SemaExprCXX.cpp | 84 ++++++ clang/lib/Sema/SemaInit.cpp | 2 +- clang/lib/Sema/SemaOverload.cpp | 281 +++++++++++------- clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp | 3 +- .../standard_conversion_sequences.hlsl | 119 ++++++++ .../BuiltIns/vector-constructors-erros.hlsl | 2 +- .../standard_conversion_sequences.hlsl | 92 ++++++ 19 files changed, 536 insertions(+), 112 deletions(-) create mode 100644 clang/test/CodeGenHLSL/BasicFeatures/standard_conversion_sequences.hlsl create mode 100644 clang/test/SemaHLSL/standard_conversion_sequences.hlsl diff --git a/clang/include/clang/AST/OperationKinds.def b/clang/include/clang/AST/OperationKinds.def index 8dd98730dff7426..e497fe4d1f93ff4 100644 --- a/clang/include/clang/AST/OperationKinds.def +++ b/clang/include/clang/AST/OperationKinds.def @@ -361,6 +361,9 @@ CAST_OPERATION(AddressSpaceConversion) // Convert an integer initializer to an OpenCL sampler. CAST_OPERATION(IntToOCLSampler) +// Truncate a vector type (HLSL only). +CAST_OPERATION(VectorTruncation) + //===- Binary Operations -------------------------------------------------===// // Operators listed in order of precedence. // Note that additions to this should also update the StmtVisitor class, diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index d164177251e4db7..6f21674d21fa54d 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -12023,6 +12023,9 @@ def err_hlsl_operator_unsupported : Error< def err_hlsl_param_qualifier_mismatch : Error<"conflicting parameter qualifier %0 on parameter %1">; +def warn_hlsl_impcast_vector_truncation : Warning< + "implicit conversion truncates vector: %0 to %1">, InGroup<Conversion>; + // Layout randomization diagnostics. def err_non_designated_init_used : Error< "a randomized struct can only be initialized with a designated initializer">; diff --git a/clang/include/clang/Sema/Overload.h b/clang/include/clang/Sema/Overload.h index 6ccabad3af54468..2f93fee4d9806ad 100644 --- a/clang/include/clang/Sema/Overload.h +++ b/clang/include/clang/Sema/Overload.h @@ -195,6 +195,9 @@ class Sema; /// Fixed point type conversions according to N1169. ICK_Fixed_Point_Conversion, + /// HLSL vector truncation. + ICK_HLSL_Vector_Truncation, + /// The number of conversion kinds ICK_Num_Conversion_Kinds, }; @@ -271,6 +274,12 @@ class Sema; /// pointer-to-member conversion, or boolean conversion. ImplicitConversionKind Second : 8; + /// Element - Between the second and third conversion a vector or matrix + /// element conversion may occur. If this is not ICK_Identity this + /// conversion is applied element-wise to each element in the vector or + /// matrix. + ImplicitConversionKind Element : 8; + /// Third - The third conversion can be a qualification conversion /// or a function conversion. ImplicitConversionKind Third : 8; @@ -357,7 +366,8 @@ class Sema; void setAsIdentityConversion(); bool isIdentityConversion() const { - return Second == ICK_Identity && Third == ICK_Identity; + return Second == ICK_Identity && Element == ICK_Identity && + Third == ICK_Identity; } ImplicitConversionRank getRank() const; diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 55c6b732b7081f4..bfbdb6cf0f929d4 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -1898,6 +1898,7 @@ bool CastExpr::CastConsistency() const { case CK_FixedPointToIntegral: case CK_IntegralToFixedPoint: case CK_MatrixCast: + case CK_VectorTruncation: assert(!getType()->isBooleanType() && "unheralded conversion to bool"); goto CheckNoBasePath; diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 16697e5f076a8f8..24c12cd0fd939d5 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -13875,6 +13875,7 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) { case CK_FixedPointCast: case CK_IntegralToFixedPoint: case CK_MatrixCast: + case CK_VectorTruncation: llvm_unreachable("invalid cast kind for integral value"); case CK_BitCast: @@ -14713,6 +14714,7 @@ bool ComplexExprEvaluator::VisitCastExpr(const CastExpr *E) { case CK_FixedPointToIntegral: case CK_IntegralToFixedPoint: case CK_MatrixCast: + case CK_VectorTruncation: llvm_unreachable("invalid cast kind for complex value"); case CK_LValueToRValue: diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 9d1f1a58f9e1c5e..9101f81c718b711 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -4933,6 +4933,7 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) { case CK_FixedPointToIntegral: case CK_IntegralToFixedPoint: case CK_MatrixCast: + case CK_VectorTruncation: return EmitUnsupportedLValue(E, "unexpected cast lvalue"); case CK_Dependent: @@ -5060,6 +5061,7 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) { return MakeAddrLValue(V, E->getType(), LV.getBaseInfo(), CGM.getTBAAInfoForSubobject(LV, E->getType())); } + case CK_ZeroToOCLOpaqueType: llvm_unreachable("NULL to OpenCL opaque type lvalue cast is not valid"); diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp index 810b28f25fa18bf..f9278133e5ddc6b 100644 --- a/clang/lib/CodeGen/CGExprAgg.cpp +++ b/clang/lib/CodeGen/CGExprAgg.cpp @@ -930,6 +930,7 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) { case CK_BuiltinFnToFnPtr: case CK_ZeroToOCLOpaqueType: case CK_MatrixCast: + case CK_VectorTruncation: case CK_IntToOCLSampler: case CK_FloatingToFixedPoint: @@ -1454,6 +1455,7 @@ static bool castPreservesZero(const CastExpr *CE) { case CK_MatrixCast: case CK_NonAtomicToAtomic: case CK_AtomicToNonAtomic: + case CK_VectorTruncation: return true; case CK_BaseToDerivedMemberPointer: diff --git a/clang/lib/CodeGen/CGExprComplex.cpp b/clang/lib/CodeGen/CGExprComplex.cpp index f3cbd1d0451ebe4..45862701d59bb4a 100644 --- a/clang/lib/CodeGen/CGExprComplex.cpp +++ b/clang/lib/CodeGen/CGExprComplex.cpp @@ -556,6 +556,7 @@ ComplexPairTy ComplexExprEmitter::EmitCast(CastKind CK, Expr *Op, case CK_FixedPointToIntegral: case CK_IntegralToFixedPoint: case CK_MatrixCast: + case CK_VectorTruncation: llvm_unreachable("invalid cast kind for complex value"); case CK_FloatingRealToComplex: diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp index 604e3958161db23..577eee2ee1ff0fc 100644 --- a/clang/lib/CodeGen/CGExprConstant.cpp +++ b/clang/lib/CodeGen/CGExprConstant.cpp @@ -1225,6 +1225,7 @@ class ConstExprEmitter : case CK_IntegralToFixedPoint: case CK_ZeroToOCLOpaqueType: case CK_MatrixCast: + case CK_VectorTruncation: return nullptr; } llvm_unreachable("Invalid CastKind"); diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 378437364767f69..7b57f33865c03b9 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -610,6 +610,8 @@ class ScalarExprEmitter llvm::Value *EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV, bool isInc, bool isPre); + llvm::Value *EmitVectorElementConversion(QualType SrcType, QualType DstType, + llvm::Value *Src); Value *VisitUnaryAddrOf(const UnaryOperator *E) { if (isa<MemberPointerType>(E->getType())) // never sugared @@ -1422,6 +1424,9 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType, return Builder.CreateVectorSplat(NumElements, Src, "splat"); } + if (SrcType->isExtVectorType() && DstType->isExtVectorType()) + return EmitVectorElementConversion(SrcType, DstType, Src); + if (SrcType->isMatrixType() && DstType->isMatrixType()) return EmitScalarCast(Src, SrcType, DstType, SrcTy, DstTy, Opts); @@ -1701,10 +1706,14 @@ Value *ScalarExprEmitter::VisitShuffleVectorExpr(ShuffleVectorExpr *E) { } Value *ScalarExprEmitter::VisitConvertVectorExpr(ConvertVectorExpr *E) { - QualType SrcType = E->getSrcExpr()->getType(), - DstType = E->getType(); + QualType SrcType = E->getSrcExpr()->getType(), DstType = E->getType(); + Value *Src = CGF.EmitScalarExpr(E->getSrcExpr()); + return EmitVectorElementConversion(SrcType, DstType, Src); +} - Value *Src = CGF.EmitScalarExpr(E->getSrcExpr()); +llvm::Value *ScalarExprEmitter::EmitVectorElementConversion(QualType SrcType, + QualType DstType, + Value *Src) { SrcType = CGF.getContext().getCanonicalType(SrcType); DstType = CGF.getContext().getCanonicalType(DstType); @@ -2466,6 +2475,14 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) { case CK_IntToOCLSampler: return CGF.CGM.createOpenCLIntToSamplerConversion(E, CGF); + case CK_VectorTruncation: { + assert(DestTy->isVectorType() && "Expected dest type to be vector type"); + Value *Vec = Visit(const_cast<Expr *>(E)); + SmallVector<int, 16> Mask; + Mask.insert(Mask.begin(), DestTy->getAs<VectorType>()->getNumElements(), 0); + return Builder.CreateShuffleVector(Vec, Mask, "trunc"); + } + } // end of switch llvm_unreachable("unknown scalar cast"); diff --git a/clang/lib/Edit/RewriteObjCFoundationAPI.cpp b/clang/lib/Edit/RewriteObjCFoundationAPI.cpp index adb34eba4970306..d42532cc15d27e1 100644 --- a/clang/lib/Edit/RewriteObjCFoundationAPI.cpp +++ b/clang/lib/Edit/RewriteObjCFoundationAPI.cpp @@ -1087,6 +1087,10 @@ static bool rewriteToNumericBoxedExpression(const ObjCMessageExpr *Msg, case CK_BooleanToSignedIntegral: llvm_unreachable("OpenCL-specific cast in Objective-C?"); + case CK_VectorTruncation: + llvm_unreachable("HLSL-specific cast in Objective-C?"); + break; + case CK_FloatingToFixedPoint: case CK_FixedPointToFloating: case CK_FixedPointCast: diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 9dfff132cd88db3..4d35dc35139a325 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -15433,11 +15433,18 @@ static void CheckImplicitConversion(Sema &S, Expr *E, QualType T, if (S.SourceMgr.isInSystemMacro(CC)) return; return DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_vector_scalar); + } else if (S.getLangOpts().HLSL && + Target->getAs<VectorType>()->getNumElements() < + Source->getAs<VectorType>()->getNumElements()) { + // Diagnose vector truncation but don't return. We may also want to + // diagnose an element conversion. + DiagnoseImpCast(S, E, T, CC, diag::warn_hlsl_impcast_vector_truncation); } // If the vector cast is cast between two vectors of the same size, it is - // a bitcast, not a conversion. - if (S.Context.getTypeSize(Source) == S.Context.getTypeSize(Target)) + // a bitcast, not a conversion, except under HLSL where it is a conversion. + if (!S.getLangOpts().HLSL && + S.Context.getTypeSize(Source) == S.Context.getTypeSize(Target)) return; Source = cast<VectorType>(Source)->getElementType().getTypePtr(); diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 081b568762ae228..5052af7905ca140 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -4763,6 +4763,20 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, CK_ZeroToOCLOpaqueType, From->getValueKind()).get(); break; + case ICK_HLSL_Vector_Truncation: { + // Note: HLSL vectors are ExtVectors. Since this truncates a vector to a + // smaller vector, this can only operate on arguments where the source and + // destination types are ExtVectors. + auto *FromVec = From->getType()->castAs<ExtVectorType>(); + auto *ToVec = ToType->castAs<ExtVectorType>(); + QualType ElType = FromVec->getElementType(); + QualType TruncTy = + Context.getExtVectorType(ElType, ToVec->getNumElements()); + From = ImpCastExprToType(From, TruncTy, CK_VectorTruncation, + From->getValueKind()) + .get(); + break; + } case ICK_Lvalue_To_Rvalue: case ICK_Array_To_Pointer: @@ -4775,6 +4789,76 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, llvm_unreachable("Improper second standard conversion"); } + if (SCS.Element != ICK_Identity) { + // if SCS.Element is not ICK_Identity the To and From types must be HLSL + // vectors or matrices. HLSL matrices aren't yet supported so this code only + // handles vectors for now. + + assert(From->getType()->isVectorType() && ToType->isVectorType() && + "Element conversion is only supported for vector types."); + assert(From->getType()->getAs<VectorType>()->getNumElements() == + ToType->getAs<VectorType>()->getNumElements() && + "Element conversion is only supported for vectors with the same " + "element counts."); + QualType FromElTy = From->getType()->getAs<VectorType>()->getElementType(); + unsigned NumElts = ToType->getAs<VectorType>()->getNumElements(); + switch (SCS.Element) { + case ICK_Identity: + // Nothing to do. + break; + case ICK_Boolean_Conversion: + // Perform half-to-boolean conversion via float. + if (FromElTy->isHalfType()) { + QualType FPExtType = Context.getExtVectorType(FromElTy, NumElts); + From = ImpCastExprToType(From, FPExtType, CK_FloatingCast).get(); + FromType = FPExtType; + } + + From = + ImpCastExprToType(From, ToType, ScalarTypeToBooleanCastKind(FromElTy), + VK_PRValue, + /*BasePath=*/nullptr, CCK) + .get(); + break; + case ICK_Integral_Promotion: + case ICK_Integral_Conversion: + if (ToType->isBooleanType()) { + assert(FromType->castAs<EnumType>()->getDecl()->isFixed() && + SCS.Second == ICK_Integral_Promotion && + "only enums with fixed underlying type can promote to bool"); + From = ImpCastExprToType(From, ToType, CK_IntegralToBoolean, VK_PRValue, + /*BasePath=*/nullptr, CCK) + .get(); + } else { + From = ImpCastExprToType(From, ToType, CK_IntegralCast, VK_PRValue, + /*BasePath=*/nullptr, CCK) + .get(); + } + break; + + case ICK_Floating_Promotion: + case ICK_Floating_Conversion: + From = ImpCastExprToType(From, ToType, CK_FloatingCast, VK_PRValue, + /*BasePath=*/nullptr, CCK) + .get(); + break; + case ICK_Floating_Integral: + if (ToType->isRealFloatingType()) + From = + ImpCastExprToType(From, ToType, CK_IntegralToFloating, VK_PRValue, + /*BasePath=*/nullptr, CCK) + .get(); + else + From = + ImpCastExprToType(From, ToType, CK_FloatingToIntegral, VK_PRValue, + /*BasePath=*/nullptr, CCK) + .get(); + break; + default: + llvm_unreachable("Improper element standard conversion"); + } + } + switch (SCS.Third) { case ICK_Identity: // Nothing to do. diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 50ee0a5acb5586a..b2f7eb65be3f138 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -6427,7 +6427,7 @@ void InitializationSequence::InitializeFrom(Sema &S, // For HLSL ext vector types we allow list initialization behavior for C++ // constructor syntax. This is accomplished by converting initialization // arguments an InitListExpr late. - if (S.getLangOpts().HLSL && DestType->isExtVectorType() && + if (S.getLangOpts().HLSL && Args.size() > 1 && DestType->isExtVectorType() && (SourceType.isNull() || !Context.hasSameUnqualifiedType(SourceType, DestType))) { diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 3a3e9234469d393..e3509546acc0c73 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -120,87 +120,88 @@ CompareDerivedToBaseConversions(Sema &S, SourceLocation Loc, const StandardConversionSequence& SCS1, const StandardConversionSequence& SCS2); +// clang-format off - disable clang format for this block. /// GetConversionRank - Retrieve the implicit conversion rank /// corresponding to the given implicit conversion kind. ImplicitConversionRank clang::GetConversionRank(ImplicitConversionKind Kind) { - static const ImplicitConversionRank - Rank[] = { - ICR_Exact_Match, - ICR_Exact_Match, - ICR_Exact_Match, - ICR_Exact_Match, - ICR_Exact_Match, - ICR_Exact_Match, - ICR_Promotion, - ICR_Promotion, - ICR_Promotion, - ICR_Conversion, - ICR_Conversion, - ICR_Conversion, - ICR_Conversion, - ICR_Conversion, - ICR_Conversion, - ICR_Conversion, - ICR_Conversion, - ICR_Conversion, - ICR_Conversion, - ICR_Conversion, - ICR_Conversion, - ICR_OCL_Scalar_Widening, - ICR_Complex_Real_Conversion, - ICR_Conversion, - ICR_Conversion, - ICR_Writeback_Conversion, - ICR_Exact_Match, // NOTE(gbiv): This may not be completely right -- - // it was omitted by the patch that added - // ICK_Zero_Event_Conversion - ICR_Exact_Match, // NOTE(ctopper): This may not be completely right -- - // it was omitted by the patch that added - // ICK_Zero_Queue_Conversion - ICR_C_Conversion, - ICR_C_Conversion_Extension, - ICR_Conversion, + static const ImplicitConversionRank Rank[] = { + ICR_Exact_Match, + ICR_Exact_Match, + ICR_Exact_Match, + ICR_Exact_Match, + ICR_Exact_Match, + ICR_Exact_Match, + ICR_Promotion, + ICR_Promotion, + ICR_Promotion, + ICR_Conversion, + ICR_Conversion, + ICR_Conversion, + ICR_Conversion, + ICR_Conversion, + ICR_Conversion, + ICR_Conversion, + ICR_Conversion, + ICR_Conversion, + ICR_Conversion, + ICR_Conversion, + ICR_Conversion, + ICR_OCL_Scalar_Widening, + ICR_Complex_Real_Conversion, + ICR_Conversion, + ICR_Conversion, + ICR_Writeback_Conversion, + ICR_Exact_Match, // NOTE(gbiv): This may not be completely right -- + // it was omitted by the patch that added + // ICK_Zero_Event_Conversion + ICR_Exact_Match, // NOTE(ctopper): This may not be completely right -- + // it was omitted by the patch that added + // ICK_Zero_Queue_Conversion + ICR_C_Conversion, + ICR_C_Conversion_Extension, + ICR_Conversion, + ICR_Conversion, }; static_assert(std::size(Rank) == (int)ICK_Num_Conversion_Kinds); return Rank[(int)Kind]; } +// clang-format on /// GetImplicitConversionName - Return the name of this kind of /// implicit conversion. -static const char* GetImplicitConversionName(ImplicitConversionKind Kind) { - static const char* const Name[] = { - "No conversion", - "Lvalue-to-rvalue", - "Array-to-pointer", - "Function-to-pointer", - "Function pointer conversion", - "Qualification", - "Integral promotion", - "Floating point promotion", - "Complex promotion", - "Integral conversion", - "Floating conversion", - "Complex conversion", - "Floating-integral conversion", - "Pointer conversion", - "Pointer-to-member conversion", - "Boolean conversion", - "Compatible-types conversion", - "Derived-to-base conversion", - "Vector conversion", - "SVE Vector conversion", - "RVV Vector conversion", - "Vector splat", - "Complex-real conversion", - "Block Pointer conversion", - "Transparent Union Conversion", - "Writeback conversion", - "OpenCL Zero Event Conversion", - "OpenCL Zero Queue Conversion", - "C specific type conversion", - "Incompatible pointer conversion", - "Fixed point conversion", - }; +static const char *GetImplicitConversionName(ImplicitConversionKind Kind) { + static const char *const Name[] = {"No conversion", + "Lvalue-to-rvalue", + "Array-to-pointer", + "Function-to-pointer", + "Function pointer conversion", + "Qualification", + "Integral promotion", + "Floating point promotion", + "Complex promotion", + "Integral conversion", + "Floating conversion", + "Complex conversion", + "Floating-integral conversion", + "Pointer conversion", + "Pointer-to-member conversion", + "Boolean conversion", + "Compatible-types conversion", + "Derived-to-base conversion", + "Vector conversion", + "SVE Vector conversion", + "RVV Vector conversion", + "Vector splat", + "Complex-real conversion", + "Block Pointer conversion", + "Transparent Union Conversion", + "Writeback conversion", + "OpenCL Zero Event Conversion", + "OpenCL Zero Queue Conversion", + "C specific type conversion", + "Incompatible pointer conversion", + "Fixed point conversion", + "HLSL vector truncation"}; static_assert(std::size(Name) == (int)ICK_Num_Conversion_Kinds); return Name[Kind]; } @@ -210,6 +211,7 @@ static const char* GetImplicitConversionName(ImplicitConversionKind Kind) { void StandardConversionSequence::setAsIdentityConversion() { First = ICK_Identity; Second = ICK_Identity; + Element = ICK_Identity; Third = ICK_Identity; DeprecatedStringLiteralToCharPtr = false; QualificationIncludesObjCLifetime = false; @@ -1843,13 +1845,86 @@ bool Sema::IsFunctionConversion(QualType FromType, QualType ToType, return true; } +/// Determine whether the conversion from FromType to ToType is a valid +/// floating point conversion. +/// +static bool IsFloatingPointConversion(Sema &S, QualType FromType, + QualType ToType) { + if (!FromType->isRealFloatingType() || !ToType->isRealFloatingType()) + return false; + // FIXME: disable conversions between long double, __ibm128 and __float128 + // if their representation is different until there is back end support + // We of course allow this conversion if long double is really double. + + // Conversions between bfloat16 and float16 are currently not supported. + if ((FromType->isBFloat16Type() && + (ToType->isFloat16Type() || ToType->isHalfType())) || + (ToType->isBFloat16Type() && + (FromType->isFloat16Type() || FromType->isHalfType()))) + return false; + + // Conversions between IEEE-quad and IBM-extended semantics are not + // permitted. + const llvm::fltSemantics &FromSem = S.Context.getFloatTypeSemantics(FromType); + const llvm::fltSemantics &ToSem = S.Context.getFloatTypeSemantics(ToType); + if ((&FromSem == &llvm::APFloat::PPCDoubleDouble() && + &ToSem == &llvm::APFloat::IEEEquad()) || + (&FromSem == &llvm::APFloat::IEEEquad() && + &ToSem == &llvm::APFloat::PPCDoubleDouble())) + return false; + return true; +} + +static bool IsVectorElementConversion(Sema &S, QualType FromType, + QualType ToType, + ImplicitConversionKind &ICK, Expr *From) { + if (S.Context.hasSameUnqualifiedType(FromType, ToType)) + return true; + + if (IsFloatingPointConversion(S, FromType, ToType)) { + ICK = ICK_Floating_Conversion; + return true; + } + + if (S.IsFloatingPointPromotion(FromType, ToType)) { + ICK = ICK_Floating_Promotion; + return true; + } + + if (ToType->isBooleanType() && FromType->isArithmeticType()) { + ICK = ICK_Boolean_Conversion; + return true; + } + + if (FromType->isIntegralOrUnscopedEnumerationType() && + ToType->isIntegralType(S.Context)) { + ICK = ICK_Integral_Conversion; + return true; + } + + if (S.IsIntegralPromotion(From, FromType, ToType)) { + ICK = ICK_Integral_Promotion; + return true; + } + + if ((FromType->isRealFloatingType() && ToType->isIntegralType(S.Context)) || + (FromType->isIntegralOrUnscopedEnumerationType() && + ToType->isRealFloatingType())) { + ICK = ICK_Floating_Integral; + return true; + } + + return false; +} + /// Determine whether the conversion from FromType to ToType is a valid /// vector conversion. /// /// \param ICK Will be set to the vector conversion kind, if this is a vector /// conversion. static bool IsVectorConversion(Sema &S, QualType FromType, QualType ToType, - ImplicitConversionKind &ICK, Expr *From, + ImplicitConversionKind &ICK, + ImplicitConversionKind &ElConv, Expr *From, bool InOverloadResolution, bool CStyle) { // We need at least one of these types to be a vector type to have a vector // conversion. @@ -1862,10 +1937,28 @@ static bool IsVectorConversion(Sema &S, QualType FromType, QualType ToType, // There are no conversions between extended vector types, only identity. if (ToType->isExtVectorType()) { - // There are no conversions between extended vector types other than the - // identity conversion. - if (FromType->isExtVectorType()) + if (FromType->isExtVectorType()) { + // HLSL allows implicit truncation of vector types. + if (S.getLangOpts().HLSL) { + unsigned FromElts = FromType->getAs<VectorType>()->getNumElements(); + unsigned ToElts = ToType->getAs<VectorType>()->getNumElements(); + if (FromElts < ToElts) + return false; + if (FromElts == ToElts) + ICK = ICK_Identity; + else + ICK = ICK_HLSL_Vector_Truncation; + + QualType FromElTy = FromType->getAs<VectorType>()->getElementType(); + QualType ToElTy = ToType->getAs<VectorType>()->getElementType(); + if (S.Context.hasSameUnqualifiedType(FromElTy, ToElTy)) + return true; + return IsVectorElementConversion(S, FromElTy, ToElTy, ElConv, From); + } + // There are no conversions between extended vector types other than the + // identity conversion. return false; + } // Vector splat from any arithmetic type to a vector. if (FromType->isArithmeticType()) { @@ -2071,6 +2164,7 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, // conversion. bool IncompatibleObjC = false; ImplicitConversionKind SecondICK = ICK_Identity; + ImplicitConversionKind ElementICK = ICK_Identity; if (S.Context.hasSameUnqualifiedType(FromType, ToType)) { // The unqualified versions of the types are the same: there's no // conversion to do. @@ -2109,29 +2203,7 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, // Complex-real conversions (C99 6.3.1.7) SCS.Second = ICK_Complex_Real; FromType = ToType.getUnqualifiedType(); - } else if (FromType->isRealFloatingType() && ToType->isRealFloatingType()) { - // FIXME: disable conversions between long double, __ibm128 and __float128 - // if their representation is different until there is back end support - // We of course allow this conversion if long double is really double. - - // Conversions between bfloat16 and float16 are currently not supported. - if ((FromType->isBFloat16Type() && - (ToType->isFloat16Type() || ToType->isHalfType())) || - (ToType->isBFloat16Type() && - (FromType->isFloat16Type() || FromType->isHalfType()))) - return false; - - // Conversions between IEEE-quad and IBM-extended semantics are not - // permitted. - const llvm::fltSemantics &FromSem = - S.Context.getFloatTypeSemantics(FromType); - const llvm::fltSemantics &ToSem = S.Context.getFloatTypeSemantics(ToType); - if ((&FromSem == &llvm::APFloat::PPCDoubleDouble() && - &ToSem == &llvm::APFloat::IEEEquad()) || - (&FromSem == &llvm::APFloat::IEEEquad() && - &ToSem == &llvm::APFloat::PPCDoubleDouble())) - return false; - + } else if (IsFloatingPointConversion(S, FromType, ToType)) { // Floating point conversions (C++ 4.8). SCS.Second = ICK_Floating_Conversion; FromType = ToType.getUnqualifiedType(); @@ -2158,18 +2230,18 @@ static bool IsStandardConversion(Sema &S, Expr* From, QualType ToType, InOverloadResolution, FromType)) { // Pointer to member conversions (4.11). SCS.Second = ICK_Pointer_Member; - } else if (IsVectorConversion(S, FromType, ToType, SecondICK, From, - InOverloadResolution, CStyle)) { + } else if (IsVectorConversion(S, FromType, ToType, SecondICK, ElementICK, + From, InOverloadResolution, CStyle)) { SCS.Second = SecondICK; + SCS.Element = ElementICK; FromType = ToType.getUnqualifiedType(); } else if (!S.getLangOpts().CPlusPlus && S.Context.typesAreCompatible(ToType, FromType)) { // Compatible conversions (Clang extension for C function overloading) SCS.Second = ICK_Compatible_Conversion; FromType = ToType.getUnqualifiedType(); - } else if (IsTransparentUnionStandardConversion(S, From, ToType, - InOverloadResolution, - SCS, CStyle)) { + } else if (IsTransparentUnionStandardConversion( + S, From, ToType, InOverloadResolution, SCS, CStyle)) { SCS.Second = ICK_TransparentUnionConversion; FromType = ToType; } else if (tryAtomicConversion(S, From, ToType, InOverloadResolution, SCS, @@ -5054,6 +5126,7 @@ TryReferenceInit(Sema &S, Expr *Init, QualType DeclType, : (RefConv & Sema::ReferenceConversions::ObjC) ? ICK_Compatible_Conversion : ICK_Identity; + ICS.Standard.Element = ICK_Identity; // FIXME: As a speculative fix to a defect introduced by CWG2352, we rank // a reference binding that performs a non-top-level qualification // conversion as a qualification conversion, not as an identity conversion. @@ -5975,6 +6048,7 @@ static bool CheckConvertedConstantConversions(Sema &S, case ICK_C_Only_Conversion: case ICK_Incompatible_Pointer_Conversion: case ICK_Fixed_Point_Conversion: + case ICK_HLSL_Vector_Truncation: return false; case ICK_Lvalue_To_Rvalue: @@ -6233,6 +6307,7 @@ ExprResult Sema::CheckConvertedConstantExpression(Expr *From, QualType T, static void dropPointerConversion(StandardConversionSequence &SCS) { if (SCS.Second == ICK_Pointer_Conversion) { SCS.Second = ICK_Identity; + SCS.Element = ICK_Identity; SCS.Third = ICK_Identity; SCS.ToTypePtrs[2] = SCS.ToTypePtrs[1] = SCS.ToTypePtrs[0]; } diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp index 7e431f7e598c4cb..c90423784a3425e 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp @@ -520,7 +520,8 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex, // Various C++ casts that are not handled yet. case CK_ToUnion: case CK_MatrixCast: - case CK_VectorSplat: { + case CK_VectorSplat: + case CK_VectorTruncation: { QualType resultType = CastE->getType(); if (CastE->isGLValue()) resultType = getContext().getPointerType(resultType); diff --git a/clang/test/CodeGenHLSL/BasicFeatures/standard_conversion_sequences.hlsl b/clang/test/CodeGenHLSL/BasicFeatures/standard_conversion_sequences.hlsl new file mode 100644 index 000000000000000..85b8eed4dafbe5d --- /dev/null +++ b/clang/test/CodeGenHLSL/BasicFeatures/standard_conversion_sequences.hlsl @@ -0,0 +1,119 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s + +// CHECK-LABEL: f3_to_d4 +// CHECK: [[f3:%.*]] = alloca <3 x float> +// CHECK: [[d4:%.*]] = alloca <4 x double> +// CHECK: store <3 x float> <float 1.000000e+00, float 1.000000e+00, float 1.000000e+00>, ptr [[f3]] +// CHECK: [[vecf3:%.*]] = load <3 x float>, ptr [[f3]] +// CHECK: [[vecf4:%.*]] = shufflevector <3 x float> [[vecf3]], <3 x float> poison, <4 x i32> <i32 0, i32 1, i32 2, i32 0> +// CHECK: [[vecd4:%.*]] = fpext <4 x float> [[vecf4]] to <4 x double> +// CHECK: store <4 x double> [[vecd4]], ptr [[d4]] +void f3_to_d4() { + vector<float,3> f3 = 1.0; + vector<double,4> d4 = f3.xyzx; +} + +// CHECK-LABEL: f3_to_f2 +// CHECK: [[f3:%.*]] = alloca <3 x float> +// CHECK: [[f2:%.*]] = alloca <2 x float> +// CHECK: store <3 x float> <float 2.000000e+00, float 2.000000e+00, float 2.000000e+00>, ptr [[f3]] +// CHECK: [[vecf3:%.*]] = load <3 x float>, ptr [[f3]] +// CHECK: [[vecf2:%.*]] = shufflevector <3 x float> [[vecf3]], <3 x float> poison, <2 x i32> zeroinitializer +// CHECK: store <2 x float> [[vecf2]], ptr [[f2]] +void f3_to_f2() { + vector<float,3> f3 = 2.0; + vector<float,2> f2 = f3; +} + +// CHECK-LABEL: d4_to_f2 +// CHECK: [[d4:%.*]] = alloca <4 x double> +// CHECK: [[f2:%.*]] = alloca <2 x float> +// CHECK: store <4 x double> <double 3.000000e+00, double 3.000000e+00, double 3.000000e+00, double 3.000000e+00>, ptr [[d4]] +// CHECK: [[vecd4:%.*]] = load <4 x double>, ptr [[d4]] +// CHECK: [[vecd2:%.*]] = shufflevector <4 x double> [[vecd4]], <4 x double> poison, <2 x i32> zeroinitializer +// CHECK: [[vecf2:%.*]] = fptrunc <2 x double> [[vecd2]] to <2 x float> +// CHECK: store <2 x float> [[vecf2]], ptr [[f2]] +void d4_to_f2() { + vector<double,4> d4 = 3.0; + vector<float,2> f2 = d4; +} + +// CHECK-LABEL: f2_to_i2 +// CHECK: [[f2:%.*]] = alloca <2 x float> +// CHECK: [[i2:%.*]] = alloca <2 x i32> +// CHECK: store <2 x float> <float 4.000000e+00, float 4.000000e+00>, ptr [[f2]] +// CHECK: [[vecf2:%.*]] = load <2 x float>, ptr [[f2]] +// CHECK: [[veci2:%.*]] = fptosi <2 x float> [[vecf2]] to <2 x i32> +// CHECK: store <2 x i32> [[veci2]], ptr [[i2]] +void f2_to_i2() { + vector<float,2> f2 = 4.0; + vector<int,2> i2 = f2; +} + +// CHECK-LABEL: d4_to_i2 +// CHECK: [[f4:%.*]] = alloca <4 x double> +// CHECK: [[i2:%.*]] = alloca <2 x i32> +// CHECK: store <4 x double> <double 5.000000e+00, double 5.000000e+00, double 5.000000e+00, double 5.000000e+00>, ptr [[d4]] +// CHECK: [[vecd4:%.*]] = load <4 x double>, ptr [[d4]] +// CHECK: [[vecd2:%.*]] = shufflevector <4 x double> [[vecd4]], <4 x double> poison, <2 x i32> zeroinitializer +// CHECK: [[veci2]] = fptosi <2 x double> [[vecd2]] to <2 x i32> +// CHECK: store <2 x i32> [[veci2]], ptr [[i2]] +void d4_to_i2() { + vector<double,4> d4 = 5.0; + vector<int,2> i2 = d4; +} + +// CHECK-LABEL: d4_to_l4 +// CHECK: [[d4:%.*]] = alloca <4 x double> +// CHECK: [[l4:%.*]] = alloca <4 x i64> +// CHECK: store <4 x double> <double 6.000000e+00, double 6.000000e+00, double 6.000000e+00, double 6.000000e+00>, ptr [[d4]] +// CHECK: [[vecd4:%.*]] = load <4 x double>, ptr [[d4]] +// CHECK: [[vecl4:%.*]] = fptosi <4 x double> [[vecd4]] to <4 x i64> +// CHECK: store <4 x i64> [[vecl4]], ptr [[l4]] +void d4_to_l4() { + vector<double,4> d4 = 6.0; + vector<long,4> l4 = d4; +} + + +// CHECK-LABEL: l4_to_i2 +// CHECK: [[l4:%.*]] = alloca <4 x i64> +// CHECK: [[i2:%.*]] = alloca <2 x i32> +// CHECK: store <4 x i64> <i64 7, i64 7, i64 7, i64 7>, ptr [[l4]] +// CHECK: [[vecl4:%.*]] = load <4 x i64>, ptr [[l4]] +// CHECK: [[vecl2:%.*]] = shufflevector <4 x i64> [[vecl4]], <4 x i64> poison, <2 x i32> zeroinitializer +// CHECK: [[veci2:%.*]] = trunc <2 x i64> [[vecl2]] to <2 x i32> +// CHECK: store <2 x i32> [[veci2]], ptr [[i2]] +void l4_to_i2() { + vector<long, 4> l4 = 7; + vector<int,2> i2 = l4; +} + +// CHECK-LABEL: i2_to_b2 +// CHECK: [[l2:%.*]] = alloca <2 x i32> +// CHECK: [[b2:%.*]] = alloca i8 +// CHECK: store <2 x i32> <i32 8, i32 8>, ptr [[i2]] +// CHECK: [[veci2:%.*]] = load <2 x i32>, ptr [[i2]] +// CHECK: [[vecb2:%.*]] = icmp ne <2 x i32> [[veci2]], zeroinitializer +// CHECK: [[vecb8:%.*]] = shufflevector <2 x i1> [[vecb2]], <2 x i1> poison, <8 x i32> <i32 0, i32 1, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison> +// CHECK: [[i8:%.*]] = bitcast <8 x i1> [[vecb8]] to i8 +// CHECK: store i8 [[i8]], ptr [[b2]] +void i2_to_b2() { + vector<int, 2> i2 = 8; + vector<bool, 2> b2 = i2; +} + +// CHECK-LABEL: d4_to_b2 +// CHECK: [[d4:%.*]] = alloca <4 x double> +// CHECK: [[b2:%.*]] = alloca i8 +// CHECK: store <4 x double> <double 9.000000e+00, double 9.000000e+00, double 9.000000e+00, double 9.000000e+00>, ptr [[d4]] +// CHECK: [[vecd4:%.*]] = load <4 x double>, ptr [[d4]] +// CHECK: [[vecd2:%.*]] = shufflevector <4 x double> [[vecd4]], <4 x double> poison, <2 x i32> zeroinitializer +// CHECK: [[vecb2:%.*]] = fcmp une <2 x double> [[vecd2]], zeroinitializer +// CHECK: [[vecb8:%.*]] = shufflevector <2 x i1> [[vecb2]], <2 x i1> poison, <8 x i32> <i32 0, i32 1, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison> +// CHECK: [[i8:%.*]] = bitcast <8 x i1> [[vecb8]] to i8 +// CHECK: store i8 [[i8]], ptr [[b2]] +void d4_to_b2() { + vector<double,4> d4 = 9.0; + vector<bool, 2> b2 = d4; +} diff --git a/clang/test/SemaHLSL/BuiltIns/vector-constructors-erros.hlsl b/clang/test/SemaHLSL/BuiltIns/vector-constructors-erros.hlsl index 73b5a192793e0cb..7f6bdc7e67836b7 100644 --- a/clang/test/SemaHLSL/BuiltIns/vector-constructors-erros.hlsl +++ b/clang/test/SemaHLSL/BuiltIns/vector-constructors-erros.hlsl @@ -18,5 +18,5 @@ void entry() { S s; float2 GettingStrange = float2(s, s); // expected-error{{no viable conversion from 'S' to 'float'}} expected-error{{no viable conversion from 'S' to 'float'}} S2 s2; - float2 EvenStranger = float2(s2); // expected-error{{no viable conversion from 'S2' to 'float'}} expected-error{{too few elements in vector initialization (expected 2 elements, have 1)}} + float2 EvenStranger = float2(s2); // expected-error{{cannot convert 'S2' to 'float2' (vector of 2 'float' values) without a conversion operator}} } diff --git a/clang/test/SemaHLSL/standard_conversion_sequences.hlsl b/clang/test/SemaHLSL/standard_conversion_sequences.hlsl new file mode 100644 index 000000000000000..ca9f2a372c02619 --- /dev/null +++ b/clang/test/SemaHLSL/standard_conversion_sequences.hlsl @@ -0,0 +1,92 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -Wconversion -verify -o - %s +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -Wno-conversion -DNO_ERR -ast-dump %s | FileCheck %s + +void test() { + + // CHECK: VarDecl {{.*}} used f3 'vector<float, 3>':'float __attribute__((ext_vector_type(3)))' cinit + // CHECK-NEXt: ImplicitCastExpr {{.*}} 'vector<float, 3>':'float __attribute__((ext_vector_type(3)))' <VectorSplat> + // CHECK-NEXt: ImplicitCastExpr {{.*}} 'float' <FloatingCast> + // CHECK-NEXt: FloatingLiteral {{.*}} 'double' 1.000000e+00 + vector<float,3> f3 = 1.0; // No warning for splatting to a vector from a literal. + + + // CHECK: VarDecl {{.*}} used d4 'vector<double, 4>':'double __attribute__((ext_vector_type(4)))' cinit + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<double, 4>':'double __attribute__((ext_vector_type(4)))' <FloatingCast> + // CHECK-NEXT: ExtVectorElementExpr {{.*}} 'float __attribute__((ext_vector_type(4)))' xyzx + // CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 3>':'float __attribute__((ext_vector_type(3)))' lvalue Var {{.*}} 'f3' 'vector<float, 3>':'float __attribute__((ext_vector_type(3)))' + vector<double,4> d4 = f3.xyzx; // No warnings for promotion or explicit extension. + + // CHECK: VarDecl {{.*}} used f2 'vector<float, 2>':'float __attribute__((ext_vector_type(2)))' cinit + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float __attribute__((ext_vector_type(2)))' <VectorTruncation> + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<float, 3>':'float __attribute__((ext_vector_type(3)))' <LValueToRValue> + // CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 3>':'float __attribute__((ext_vector_type(3)))' lvalue Var {{.*}} 'f3' 'vector<float, 3>':'float __attribute__((ext_vector_type(3)))' + // expected-warning@#f2{{implicit conversion truncates vector: 'vector<float, 3>' (vector of 3 'float' values) to 'float __attribute__((ext_vector_type(2)))' (vector of 2 'float' values)}} + vector<float,2> f2 = f3; // #f2 + + // CHECK: VarDecl {{.*}} f2_2 'vector<float, 2>':'float __attribute__((ext_vector_type(2)))' cinit + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<float, 2>':'float __attribute__((ext_vector_type(2)))' <FloatingCast> + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'double __attribute__((ext_vector_type(2)))' <VectorTruncation> + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<double, 4>':'double __attribute__((ext_vector_type(4)))' <LValueToRValue> + // CHECK-NEXT: DeclRefExpr {{.*}} 'vector<double, 4>':'double __attribute__((ext_vector_type(4)))' lvalue Var {{.*}} 'd4' 'vector<double, 4>':'double __attribute__((ext_vector_type(4)))' + // expected-warning@#f2_2{{implicit conversion truncates vector: 'vector<double, 4>' (vector of 4 'double' values) to 'vector<float, 2>' (vector of 2 'float' values)}} + // expected-warning@#f2_2{{implicit conversion loses floating-point precision: 'vector<double, 4>' (vector of 4 'double' values) to 'vector<float, 2>' (vector of 2 'float' values)}} + vector<float,2> f2_2 = d4; // #f2_2 + + // CHECK: VarDecl {{.*}} i2 'vector<int, 2>':'int __attribute__((ext_vector_type(2)))' cinit + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<int, 2>':'int __attribute__((ext_vector_type(2)))' <FloatingToIntegral> + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<float, 2>':'float __attribute__((ext_vector_type(2)))' <LValueToRValue> + // CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 2>':'float __attribute__((ext_vector_type(2)))' lvalue Var {{.*}} 'f2' 'vector<float, 2>':'float __attribute__((ext_vector_type(2)))' + // expected-warning@#i2{{mplicit conversion turns floating-point number into integer: 'vector<float, 2>' (vector of 2 'float' values) to 'vector<int, 2>' (vector of 2 'int' values)}} + vector<int,2> i2 = f2; // #i2 + + // CHECK: VarDecl {{.*}} i2_2 'vector<int, 2>':'int __attribute__((ext_vector_type(2)))' cinit + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<int, 2>':'int __attribute__((ext_vector_type(2)))' <FloatingToIntegral> + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'double __attribute__((ext_vector_type(2)))' <VectorTruncation> + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<double, 4>':'double __attribute__((ext_vector_type(4)))' <LValueToRValue> + // CHECK-NEXT: DeclRefExpr {{.*}} 'vector<double, 4>':'double __attribute__((ext_vector_type(4)))' lvalue Var {{.*}} 'd4' 'vector<double, 4>':'double __attribute__((ext_vector_type(4)))' + // expected-warning@#i2_2{{implicit conversion truncates vector: 'vector<double, 4>' (vector of 4 'double' values) to 'vector<int, 2>' (vector of 2 'int' values)}} + // expected-warning@#i2_2{{implicit conversion turns floating-point number into integer: 'vector<double, 4>' (vector of 4 'double' values) to 'vector<int, 2>' (vector of 2 'int' values)}} + vector<int,2> i2_2 = d4; // #i2_2 + + + // CHECK: VarDecl {{.*}} used i64_4 'vector<long, 4>':'long __attribute__((ext_vector_type(4)))' cinit + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<long, 4>':'long __attribute__((ext_vector_type(4)))' <FloatingToIntegral> + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<double, 4>':'double __attribute__((ext_vector_type(4)))' <LValueToRValue> + // CHECK-NEXT: DeclRefExpr {{.*}} 'vector<double, 4>':'double __attribute__((ext_vector_type(4)))' lvalue Var {{.*}} 'd4' 'vector<double, 4>':'double __attribute__((ext_vector_type(4)))' + // expected-warning@#i64_4{{implicit conversion turns floating-point number into integer: 'vector<double, 4>' (vector of 4 'double' values) to 'vector<long, 4>' (vector of 4 'long' values)}} + vector<long,4> i64_4 = d4; // #i64_4 + + // CHECK: VarDecl {{.*}} used i2_3 'vector<int, 2>':'int __attribute__((ext_vector_type(2)))' cinit + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<int, 2>':'int __attribute__((ext_vector_type(2)))' <IntegralCast> + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'long __attribute__((ext_vector_type(2)))' <VectorTruncation> + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<long, 4>':'long __attribute__((ext_vector_type(4)))' <LValueToRValue> + // CHECK-NEXT: DeclRefExpr {{.*}} 'vector<long, 4>':'long __attribute__((ext_vector_type(4)))' lvalue Var {{.*}} 'i64_4' 'vector<long, 4>':'long __attribute__((ext_vector_type(4)))' + // expected-warning@#i2_3{{implicit conversion loses integer precision: 'vector<long, 4>' (vector of 4 'long' values) to 'vector<int, 2>' (vector of 2 'int' values)}} + // expected-warning@#i2_3{{implicit conversion truncates vector: 'vector<long, 4>' (vector of 4 'long' values) to 'vector<int, 2>' (vector of 2 'int' values)}} + vector<int,2> i2_3 = i64_4; // #i2_3 + + //CHECK: VarDecl {{.*}} b2 'vector<bool, 2>':'bool __attribute__((ext_vector_type(2)))' cinit + //CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<bool, 2>':'bool __attribute__((ext_vector_type(2)))' <IntegralToBoolean> + //CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<int, 2>':'int __attribute__((ext_vector_type(2)))' <LValueToRValue> + //CHECK-NEXT: DeclRefExpr {{.*}} 'vector<int, 2>':'int __attribute__((ext_vector_type(2)))' lvalue Var {{.*}} 'i2_3' 'vector<int, 2>':'int __attribute__((ext_vector_type(2)))' + vector<bool, 2> b2 = i2_3; // No warning for integer to bool conversion. + + // CHECK: VarDecl {{.*}} b2_2 'vector<bool, 2>':'bool __attribute__((ext_vector_type(2)))' cinit + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<bool, 2>':'bool __attribute__((ext_vector_type(2)))' <FloatingToBoolean> + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'double __attribute__((ext_vector_type(2)))' <VectorTruncation> + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<double, 4>':'double __attribute__((ext_vector_type(4)))' <LValueToRValue> + // CHECK-NEXT: DeclRefExpr {{.*}} 'vector<double, 4>':'double __attribute__((ext_vector_type(4)))' lvalue Var {{.*}} 'd4' 'vector<double, 4>':'double __attribute__((ext_vector_type(4)))' + // expected-warning@#b2_2{{implicit conversion truncates vector: 'vector<double, 4>' (vector of 4 'double' values) to 'vector<bool, 2>' (vector of 2 'bool' values)}} + // expected-warning@#b2_2{{implicit conversion turns floating-point number into integer: 'vector<double, 4>' (vector of 4 'double' values) to 'vector<bool, 2>' (vector of 2 'bool' values)}} + vector<bool, 2> b2_2 = d4; // #b2_2 +} + +#ifndef NO_ERR + +void illegal() { + // vector extension is illegal + vector<float,3> f3 = 1.0; + vector<float,4> f4 = f3; // expected-error{{cannot initialize a variable of type 'vector<[...], 4>' with an lvalue of type 'vector<[...], 3>'}} +} + +#endif >From 06c7a72d8894ccca3f045d30c62e929630d07900 Mon Sep 17 00:00:00 2001 From: Chris Bieneman <chris.biene...@me.com> Date: Wed, 29 Nov 2023 11:52:47 -0600 Subject: [PATCH 2/6] Rename VectorTruncation to HLSLVectorTruncation ../clang/test/SemaHLSL/standard_conversion_sequences.hlsl ../clang/test/CodeGenHLSL/builtins/ScalarSwizzles.hlsl ../clang/test/SemaHLSL/Types/BuiltinVector/ScalarSwizzles.hlsl --- clang/include/clang/AST/OperationKinds.def | 2 +- clang/lib/AST/Expr.cpp | 2 +- clang/lib/AST/ExprConstant.cpp | 4 ++-- clang/lib/CodeGen/CGExpr.cpp | 2 +- clang/lib/CodeGen/CGExprAgg.cpp | 4 ++-- clang/lib/CodeGen/CGExprComplex.cpp | 2 +- clang/lib/CodeGen/CGExprConstant.cpp | 2 +- clang/lib/CodeGen/CGExprScalar.cpp | 2 +- clang/lib/Edit/RewriteObjCFoundationAPI.cpp | 2 +- clang/lib/Sema/SemaExprCXX.cpp | 2 +- clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp | 2 +- clang/test/SemaHLSL/standard_conversion_sequences.hlsl | 10 +++++----- 12 files changed, 18 insertions(+), 18 deletions(-) diff --git a/clang/include/clang/AST/OperationKinds.def b/clang/include/clang/AST/OperationKinds.def index e497fe4d1f93ff4..e8d934782d4482c 100644 --- a/clang/include/clang/AST/OperationKinds.def +++ b/clang/include/clang/AST/OperationKinds.def @@ -362,7 +362,7 @@ CAST_OPERATION(AddressSpaceConversion) CAST_OPERATION(IntToOCLSampler) // Truncate a vector type (HLSL only). -CAST_OPERATION(VectorTruncation) +CAST_OPERATION(HLSLVectorTruncation) //===- Binary Operations -------------------------------------------------===// // Operators listed in order of precedence. diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index bfbdb6cf0f929d4..135f04fb93c7dfb 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -1898,7 +1898,7 @@ bool CastExpr::CastConsistency() const { case CK_FixedPointToIntegral: case CK_IntegralToFixedPoint: case CK_MatrixCast: - case CK_VectorTruncation: + case CK_HLSLVectorTruncation: assert(!getType()->isBooleanType() && "unheralded conversion to bool"); goto CheckNoBasePath; diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 24c12cd0fd939d5..f737a64656a5b25 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -13875,7 +13875,7 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) { case CK_FixedPointCast: case CK_IntegralToFixedPoint: case CK_MatrixCast: - case CK_VectorTruncation: + case CK_HLSLVectorTruncation: llvm_unreachable("invalid cast kind for integral value"); case CK_BitCast: @@ -14714,7 +14714,7 @@ bool ComplexExprEvaluator::VisitCastExpr(const CastExpr *E) { case CK_FixedPointToIntegral: case CK_IntegralToFixedPoint: case CK_MatrixCast: - case CK_VectorTruncation: + case CK_HLSLVectorTruncation: llvm_unreachable("invalid cast kind for complex value"); case CK_LValueToRValue: diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 9101f81c718b711..e748af5f89d32b0 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -4933,7 +4933,7 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) { case CK_FixedPointToIntegral: case CK_IntegralToFixedPoint: case CK_MatrixCast: - case CK_VectorTruncation: + case CK_HLSLVectorTruncation: return EmitUnsupportedLValue(E, "unexpected cast lvalue"); case CK_Dependent: diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp index f9278133e5ddc6b..8949ad8a4dce46c 100644 --- a/clang/lib/CodeGen/CGExprAgg.cpp +++ b/clang/lib/CodeGen/CGExprAgg.cpp @@ -930,7 +930,7 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) { case CK_BuiltinFnToFnPtr: case CK_ZeroToOCLOpaqueType: case CK_MatrixCast: - case CK_VectorTruncation: + case CK_HLSLVectorTruncation: case CK_IntToOCLSampler: case CK_FloatingToFixedPoint: @@ -1455,7 +1455,7 @@ static bool castPreservesZero(const CastExpr *CE) { case CK_MatrixCast: case CK_NonAtomicToAtomic: case CK_AtomicToNonAtomic: - case CK_VectorTruncation: + case CK_HLSLVectorTruncation: return true; case CK_BaseToDerivedMemberPointer: diff --git a/clang/lib/CodeGen/CGExprComplex.cpp b/clang/lib/CodeGen/CGExprComplex.cpp index 45862701d59bb4a..6ffcb4186665120 100644 --- a/clang/lib/CodeGen/CGExprComplex.cpp +++ b/clang/lib/CodeGen/CGExprComplex.cpp @@ -556,7 +556,7 @@ ComplexPairTy ComplexExprEmitter::EmitCast(CastKind CK, Expr *Op, case CK_FixedPointToIntegral: case CK_IntegralToFixedPoint: case CK_MatrixCast: - case CK_VectorTruncation: + case CK_HLSLVectorTruncation: llvm_unreachable("invalid cast kind for complex value"); case CK_FloatingRealToComplex: diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp index 577eee2ee1ff0fc..f5b144a0736467a 100644 --- a/clang/lib/CodeGen/CGExprConstant.cpp +++ b/clang/lib/CodeGen/CGExprConstant.cpp @@ -1225,7 +1225,7 @@ class ConstExprEmitter : case CK_IntegralToFixedPoint: case CK_ZeroToOCLOpaqueType: case CK_MatrixCast: - case CK_VectorTruncation: + case CK_HLSLVectorTruncation: return nullptr; } llvm_unreachable("Invalid CastKind"); diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 7b57f33865c03b9..121a26a3b5df832 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -2475,7 +2475,7 @@ Value *ScalarExprEmitter::VisitCastExpr(CastExpr *CE) { case CK_IntToOCLSampler: return CGF.CGM.createOpenCLIntToSamplerConversion(E, CGF); - case CK_VectorTruncation: { + case CK_HLSLVectorTruncation: { assert(DestTy->isVectorType() && "Expected dest type to be vector type"); Value *Vec = Visit(const_cast<Expr *>(E)); SmallVector<int, 16> Mask; diff --git a/clang/lib/Edit/RewriteObjCFoundationAPI.cpp b/clang/lib/Edit/RewriteObjCFoundationAPI.cpp index d42532cc15d27e1..3c5ddcc3bb0fafa 100644 --- a/clang/lib/Edit/RewriteObjCFoundationAPI.cpp +++ b/clang/lib/Edit/RewriteObjCFoundationAPI.cpp @@ -1087,7 +1087,7 @@ static bool rewriteToNumericBoxedExpression(const ObjCMessageExpr *Msg, case CK_BooleanToSignedIntegral: llvm_unreachable("OpenCL-specific cast in Objective-C?"); - case CK_VectorTruncation: + case CK_HLSLVectorTruncation: llvm_unreachable("HLSL-specific cast in Objective-C?"); break; diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 5052af7905ca140..f628f2ff9b02c95 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -4772,7 +4772,7 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, QualType ElType = FromVec->getElementType(); QualType TruncTy = Context.getExtVectorType(ElType, ToVec->getNumElements()); - From = ImpCastExprToType(From, TruncTy, CK_VectorTruncation, + From = ImpCastExprToType(From, TruncTy, CK_HLSLVectorTruncation, From->getValueKind()) .get(); break; diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp index c90423784a3425e..c3fc56ac30ee9fd 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp @@ -521,7 +521,7 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex, case CK_ToUnion: case CK_MatrixCast: case CK_VectorSplat: - case CK_VectorTruncation: { + case CK_HLSLVectorTruncation: { QualType resultType = CastE->getType(); if (CastE->isGLValue()) resultType = getContext().getPointerType(resultType); diff --git a/clang/test/SemaHLSL/standard_conversion_sequences.hlsl b/clang/test/SemaHLSL/standard_conversion_sequences.hlsl index ca9f2a372c02619..a0d398105f15d6a 100644 --- a/clang/test/SemaHLSL/standard_conversion_sequences.hlsl +++ b/clang/test/SemaHLSL/standard_conversion_sequences.hlsl @@ -17,7 +17,7 @@ void test() { vector<double,4> d4 = f3.xyzx; // No warnings for promotion or explicit extension. // CHECK: VarDecl {{.*}} used f2 'vector<float, 2>':'float __attribute__((ext_vector_type(2)))' cinit - // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float __attribute__((ext_vector_type(2)))' <VectorTruncation> + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float __attribute__((ext_vector_type(2)))' <HLSLVectorTruncation> // CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<float, 3>':'float __attribute__((ext_vector_type(3)))' <LValueToRValue> // CHECK-NEXT: DeclRefExpr {{.*}} 'vector<float, 3>':'float __attribute__((ext_vector_type(3)))' lvalue Var {{.*}} 'f3' 'vector<float, 3>':'float __attribute__((ext_vector_type(3)))' // expected-warning@#f2{{implicit conversion truncates vector: 'vector<float, 3>' (vector of 3 'float' values) to 'float __attribute__((ext_vector_type(2)))' (vector of 2 'float' values)}} @@ -25,7 +25,7 @@ void test() { // CHECK: VarDecl {{.*}} f2_2 'vector<float, 2>':'float __attribute__((ext_vector_type(2)))' cinit // CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<float, 2>':'float __attribute__((ext_vector_type(2)))' <FloatingCast> - // CHECK-NEXT: ImplicitCastExpr {{.*}} 'double __attribute__((ext_vector_type(2)))' <VectorTruncation> + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'double __attribute__((ext_vector_type(2)))' <HLSLVectorTruncation> // CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<double, 4>':'double __attribute__((ext_vector_type(4)))' <LValueToRValue> // CHECK-NEXT: DeclRefExpr {{.*}} 'vector<double, 4>':'double __attribute__((ext_vector_type(4)))' lvalue Var {{.*}} 'd4' 'vector<double, 4>':'double __attribute__((ext_vector_type(4)))' // expected-warning@#f2_2{{implicit conversion truncates vector: 'vector<double, 4>' (vector of 4 'double' values) to 'vector<float, 2>' (vector of 2 'float' values)}} @@ -41,7 +41,7 @@ void test() { // CHECK: VarDecl {{.*}} i2_2 'vector<int, 2>':'int __attribute__((ext_vector_type(2)))' cinit // CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<int, 2>':'int __attribute__((ext_vector_type(2)))' <FloatingToIntegral> - // CHECK-NEXT: ImplicitCastExpr {{.*}} 'double __attribute__((ext_vector_type(2)))' <VectorTruncation> + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'double __attribute__((ext_vector_type(2)))' <HLSLVectorTruncation> // CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<double, 4>':'double __attribute__((ext_vector_type(4)))' <LValueToRValue> // CHECK-NEXT: DeclRefExpr {{.*}} 'vector<double, 4>':'double __attribute__((ext_vector_type(4)))' lvalue Var {{.*}} 'd4' 'vector<double, 4>':'double __attribute__((ext_vector_type(4)))' // expected-warning@#i2_2{{implicit conversion truncates vector: 'vector<double, 4>' (vector of 4 'double' values) to 'vector<int, 2>' (vector of 2 'int' values)}} @@ -58,7 +58,7 @@ void test() { // CHECK: VarDecl {{.*}} used i2_3 'vector<int, 2>':'int __attribute__((ext_vector_type(2)))' cinit // CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<int, 2>':'int __attribute__((ext_vector_type(2)))' <IntegralCast> - // CHECK-NEXT: ImplicitCastExpr {{.*}} 'long __attribute__((ext_vector_type(2)))' <VectorTruncation> + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'long __attribute__((ext_vector_type(2)))' <HLSLVectorTruncation> // CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<long, 4>':'long __attribute__((ext_vector_type(4)))' <LValueToRValue> // CHECK-NEXT: DeclRefExpr {{.*}} 'vector<long, 4>':'long __attribute__((ext_vector_type(4)))' lvalue Var {{.*}} 'i64_4' 'vector<long, 4>':'long __attribute__((ext_vector_type(4)))' // expected-warning@#i2_3{{implicit conversion loses integer precision: 'vector<long, 4>' (vector of 4 'long' values) to 'vector<int, 2>' (vector of 2 'int' values)}} @@ -73,7 +73,7 @@ void test() { // CHECK: VarDecl {{.*}} b2_2 'vector<bool, 2>':'bool __attribute__((ext_vector_type(2)))' cinit // CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<bool, 2>':'bool __attribute__((ext_vector_type(2)))' <FloatingToBoolean> - // CHECK-NEXT: ImplicitCastExpr {{.*}} 'double __attribute__((ext_vector_type(2)))' <VectorTruncation> + // CHECK-NEXT: ImplicitCastExpr {{.*}} 'double __attribute__((ext_vector_type(2)))' <HLSLVectorTruncation> // CHECK-NEXT: ImplicitCastExpr {{.*}} 'vector<double, 4>':'double __attribute__((ext_vector_type(4)))' <LValueToRValue> // CHECK-NEXT: DeclRefExpr {{.*}} 'vector<double, 4>':'double __attribute__((ext_vector_type(4)))' lvalue Var {{.*}} 'd4' 'vector<double, 4>':'double __attribute__((ext_vector_type(4)))' // expected-warning@#b2_2{{implicit conversion truncates vector: 'vector<double, 4>' (vector of 4 'double' values) to 'vector<bool, 2>' (vector of 2 'bool' values)}} >From 6cbf74c358895edb8dba02182fe5fffd38bf6bd8 Mon Sep 17 00:00:00 2001 From: Chris Bieneman <chris.biene...@me.com> Date: Wed, 29 Nov 2023 13:09:47 -0600 Subject: [PATCH 3/6] Remove clang-format comments ../clang/test/CodeGenHLSL/builtins/ScalarSwizzles.hlsl ../clang/test/SemaHLSL/Types/BuiltinVector/ScalarSwizzles.hlsl --- clang/lib/Sema/SemaOverload.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index e3509546acc0c73..39418bd9c7a3b65 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -120,7 +120,6 @@ CompareDerivedToBaseConversions(Sema &S, SourceLocation Loc, const StandardConversionSequence& SCS1, const StandardConversionSequence& SCS2); -// clang-format off - disable clang format for this block. /// GetConversionRank - Retrieve the implicit conversion rank /// corresponding to the given implicit conversion kind. ImplicitConversionRank clang::GetConversionRank(ImplicitConversionKind Kind) { @@ -165,7 +164,6 @@ ImplicitConversionRank clang::GetConversionRank(ImplicitConversionKind Kind) { static_assert(std::size(Rank) == (int)ICK_Num_Conversion_Kinds); return Rank[(int)Kind]; } -// clang-format on /// GetImplicitConversionName - Return the name of this kind of /// implicit conversion. >From 899d5298c1dd1847ac4c022f9da6d5be1cab91f8 Mon Sep 17 00:00:00 2001 From: Chris Bieneman <chris.biene...@me.com> Date: Wed, 29 Nov 2023 13:10:07 -0600 Subject: [PATCH 4/6] Update scalar swizzle tests The new "correct" implicit conversion sequences change how some of these ASTs are formed and the initial code generation. ../clang/test/CodeGenHLSL/builtins/ScalarSwizzles.hlsl ../clang/test/SemaHLSL/Types/BuiltinVector/ScalarSwizzles.hlsl --- .../CodeGenHLSL/builtins/ScalarSwizzles.hlsl | 34 +++++-------------- .../Types/BuiltinVector/ScalarSwizzles.hlsl | 25 ++------------ 2 files changed, 11 insertions(+), 48 deletions(-) diff --git a/clang/test/CodeGenHLSL/builtins/ScalarSwizzles.hlsl b/clang/test/CodeGenHLSL/builtins/ScalarSwizzles.hlsl index 2e169ef60c70c4b..73bab556b9a6dbe 100644 --- a/clang/test/CodeGenHLSL/builtins/ScalarSwizzles.hlsl +++ b/clang/test/CodeGenHLSL/builtins/ScalarSwizzles.hlsl @@ -85,7 +85,9 @@ float4 FillTwoPointFiveFloat(){ // CHECK: [[vec1Ptr:%.*]] = alloca <1 x float>, align 4 // CHECK: store <1 x float> <float 5.000000e-01>, ptr [[vec1Ptr]], align 4 // CHECK: [[vec1:%.*]] = load <1 x float>, ptr [[vec1Ptr]], align 4 -// CHECK: [[vec1Ret:%.*]] = shufflevector <1 x float> [[vec1]], <1 x float> undef, <1 x i32> zeroinitializer +// CHECK: [[el0:%.*]] = extractelement <1 x float> [[vec1]], i32 0 +// CHECK: [[vec1Splat:%.*]] = insertelement <1 x float> poison, float [[el0]], i64 0 +// CHECK: [[vec1Ret:%.*]] = shufflevector <1 x float> [[vec1Splat]], <1 x float> poison, <1 x i32> zeroinitializer // CHECK: ret <1 x float> [[vec1Ret]] vector<float, 1> FillOneHalfFloat(){ return .5f.r; @@ -113,30 +115,12 @@ float2 HowManyFloats(float V) { // up nicely too. // CHECK-LABEL: AllRighty -// CHECK: [[XTmp:%.*]] = alloca <1 x double>, align 8 -// CHECK: [[YTmp:%.*]] = alloca <1 x double>, align 8 -// CHECK: [[ZTmp:%.*]] = alloca <1 x double>, align 8 - -// CHECK: store <1 x double> <double 1.000000e+00>, ptr [[XTmp]], align 8 -// CHECK: [[XVec:%.*]] = load <1 x double>, ptr [[XTmp]], align 8 -// CHECK: [[XVec3:%.*]] = shufflevector <1 x double> [[XVec]], <1 x double> poison, <3 x i32> zeroinitializer -// CHECK: [[XVal:%.*]] = extractelement <3 x double> [[XVec3]], i32 0 -// CHECK: [[XValF:%.*]] = fptrunc double [[XVal]] to float -// CHECK: [[Vec3F1:%.*]] = insertelement <3 x float> undef, float [[XValF]], i32 0 - -// CHECK: store <1 x double> <double 1.000000e+00>, ptr [[YTmp]], align 8 -// CHECK: [[YVec:%.*]] = load <1 x double>, ptr [[YTmp]], align 8 -// CHECK: [[YVec3:%.*]] = shufflevector <1 x double> [[YVec]], <1 x double> poison, <3 x i32> zeroinitializer -// CHECK: [[YVal:%.*]] = extractelement <3 x double> [[YVec3]], i32 1 -// CHECK: [[YValF:%.*]] = fptrunc double [[YVal]] to float -// CHECK: [[Vec3F2:%.*]] = insertelement <3 x float> [[Vec3F1]], float [[YValF]], i32 1 - -// CHECK: store <1 x double> <double 1.000000e+00>, ptr [[ZTmp]], align 8 -// CHECK: [[ZVec:%.*]] = load <1 x double>, ptr [[ZTmp]], align 8 -// CHECK: [[ZVec3:%.*]] = shufflevector <1 x double> [[ZVec]], <1 x double> poison, <3 x i32> zeroinitializer -// CHECK: [[ZVal:%.*]] = extractelement <3 x double> [[ZVec3]], i32 2 -// CHECK: [[ZValF:%.*]] = fptrunc double [[ZVal]] to float -// CHECK: [[Vec3F3:%.*]] = insertelement <3 x float> [[Vec3F2]], float [[ZValF]], i32 2 +// CHECK: [[Tmp:%.*]] = alloca <1 x double>, align 8 +// CHECK: store <1 x double> <double 1.000000e+00>, ptr [[Tmp]], align 8 +// CHECK: [[vec1:%.*]] = load <1 x double>, ptr [[Tmp]], align 8 +// CHECK: [[vec3:%.*]] = shufflevector <1 x double> [[vec1]], <1 x double> poison, <3 x i32> zeroinitializer +// CHECK: [[vec3f:%.*]] = fptrunc <3 x double> [[vec3]] to <3 x float> +// ret <3 x float> [[vec3f]] // ret <3 x float> [[Vec3F3]] float3 AllRighty() { diff --git a/clang/test/SemaHLSL/Types/BuiltinVector/ScalarSwizzles.hlsl b/clang/test/SemaHLSL/Types/BuiltinVector/ScalarSwizzles.hlsl index 4ffbcacf3f30c04..a2e9a5f865ece1f 100644 --- a/clang/test/SemaHLSL/Types/BuiltinVector/ScalarSwizzles.hlsl +++ b/clang/test/SemaHLSL/Types/BuiltinVector/ScalarSwizzles.hlsl @@ -80,7 +80,7 @@ float4 FillTwoPointFiveFloat(){ // initialze the returned vector. // CHECK-LABEL: FillOneHalfFloat -// CHECK: InitListExpr {{.*}} 'vector<float, 1>':'float __attribute__((ext_vector_type(1)))' +// CHECK: ImplicitCastExpr {{.*}} 'vector<float, 1>':'float __attribute__((ext_vector_type(1)))' <VectorSplat> // CHECK-NEXT: ExtVectorElementExpr {{.*}} 'float' r // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float __attribute__((ext_vector_type(1)))' <VectorSplat> // CHECK-NEXT: FloatingLiteral {{.*}} 'float' 5.000000e-01 @@ -113,31 +113,10 @@ int64_t4 HooBoy() { // list with float truncation casts. // CHECK-LABEL: AllRighty -// CHECK: InitListExpr {{.*}} 'float3':'float __attribute__((ext_vector_type(3)))' - -// Vector element 0: -// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <FloatingCast> -// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'double' -// CHECK-NEXT: ExtVectorElementExpr {{.*}} 'double __attribute__((ext_vector_type(3)))' rrr -// CHECK-NEXT: ImplicitCastExpr {{.*}} 'double __attribute__((ext_vector_type(1)))' <VectorSplat> -// CHECK-NEXT: FloatingLiteral {{.*}} 'double' 1.000000e+00 -// CHECK-NEXT: IntegerLiteral {{.*}} 'int' 0 - -// Vector element 1: -// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <FloatingCast> -// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'double' -// CHECK-NEXT: ExtVectorElementExpr {{.*}} 'double __attribute__((ext_vector_type(3)))' rrr -// CHECK-NEXT: ImplicitCastExpr {{.*}} 'double __attribute__((ext_vector_type(1)))' <VectorSplat> -// CHECK-NEXT: FloatingLiteral {{.*}} 'double' 1.000000e+00 -// CHECK-NEXT: IntegerLiteral {{.*}} 'int' 1 - -// Vector element 2: -// CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <FloatingCast> -// CHECK-NEXT: ArraySubscriptExpr {{.*}} 'double' +// CHECK: ImplicitCastExpr {{.*}} 'float3':'float __attribute__((ext_vector_type(3)))' <FloatingCast> // CHECK-NEXT: ExtVectorElementExpr {{.*}} 'double __attribute__((ext_vector_type(3)))' rrr // CHECK-NEXT: ImplicitCastExpr {{.*}} 'double __attribute__((ext_vector_type(1)))' <VectorSplat> // CHECK-NEXT: FloatingLiteral {{.*}} 'double' 1.000000e+00 -// CHECK-NEXT: IntegerLiteral {{.*}} 'int' 2 float3 AllRighty() { return 1..rrr; >From 86c0dc0ce139dd4370523b54393133ce8f72def0 Mon Sep 17 00:00:00 2001 From: Chris B <cbiene...@microsoft.com> Date: Wed, 29 Nov 2023 13:34:54 -0600 Subject: [PATCH 5/6] Update clang/lib/Sema/SemaExprCXX.cpp Co-authored-by: Aaron Ballman <aa...@aaronballman.com> --- clang/lib/Sema/SemaExprCXX.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index f628f2ff9b02c95..0e1acf6bd5dddd7 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -4790,7 +4790,7 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType, } if (SCS.Element != ICK_Identity) { - // if SCS.Element is not ICK_Identity the To and From types must be HLSL + // If SCS.Element is not ICK_Identity the To and From types must be HLSL // vectors or matrices. HLSL matrices aren't yet supported so this code only // handles vectors for now. >From ac9711e3212b666ac4e6a2fd28c43bc7e66bf0fd Mon Sep 17 00:00:00 2001 From: Chris Bieneman <chris.biene...@me.com> Date: Wed, 29 Nov 2023 13:37:02 -0600 Subject: [PATCH 6/6] Remove spurious whitespace change --- clang/lib/CodeGen/CGExpr.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index e748af5f89d32b0..107c1c86f3c8fb7 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -5061,7 +5061,6 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) { return MakeAddrLValue(V, E->getType(), LV.getBaseInfo(), CGM.getTBAAInfoForSubobject(LV, E->getType())); } - case CK_ZeroToOCLOpaqueType: llvm_unreachable("NULL to OpenCL opaque type lvalue cast is not valid"); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits