-
Notifications
You must be signed in to change notification settings - Fork 14.9k
[HLSL] Add matrix constructors using initalizer lists #162743
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
b7c3836
9a57716
a09e070
28a87ff
771989c
842a52a
cbb7650
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -17,6 +17,7 @@ | |
| #include "clang/AST/ExprCXX.h" | ||
| #include "clang/AST/ExprObjC.h" | ||
| #include "clang/AST/IgnoreExpr.h" | ||
| #include "clang/AST/TypeBase.h" | ||
| #include "clang/AST/TypeLoc.h" | ||
| #include "clang/Basic/SourceManager.h" | ||
| #include "clang/Basic/Specifiers.h" | ||
|
|
@@ -403,6 +404,9 @@ class InitListChecker { | |
| unsigned &Index, | ||
| InitListExpr *StructuredList, | ||
| unsigned &StructuredIndex); | ||
| void CheckMatrixType(const InitializedEntity &Entity, InitListExpr *IList, | ||
| QualType DeclType, unsigned &Index, | ||
| InitListExpr *StructuredList, unsigned &StructuredIndex); | ||
| void CheckVectorType(const InitializedEntity &Entity, | ||
| InitListExpr *IList, QualType DeclType, unsigned &Index, | ||
| InitListExpr *StructuredList, | ||
|
|
@@ -1003,7 +1007,8 @@ InitListChecker::FillInEmptyInitializations(const InitializedEntity &Entity, | |
| return; | ||
|
|
||
| if (ElementEntity.getKind() == InitializedEntity::EK_ArrayElement || | ||
| ElementEntity.getKind() == InitializedEntity::EK_VectorElement) | ||
| ElementEntity.getKind() == InitializedEntity::EK_VectorElement || | ||
| ElementEntity.getKind() == InitializedEntity::EK_MatrixElement) | ||
| ElementEntity.setElementIndex(Init); | ||
|
|
||
| if (Init >= NumInits && (ILE->hasArrayFiller() || SkipEmptyInitChecks)) | ||
|
|
@@ -1273,6 +1278,7 @@ static void warnBracedScalarInit(Sema &S, const InitializedEntity &Entity, | |
|
|
||
| switch (Entity.getKind()) { | ||
| case InitializedEntity::EK_VectorElement: | ||
| case InitializedEntity::EK_MatrixElement: | ||
| case InitializedEntity::EK_ComplexElement: | ||
| case InitializedEntity::EK_ArrayElement: | ||
| case InitializedEntity::EK_Parameter: | ||
|
|
@@ -1372,11 +1378,12 @@ void InitListChecker::CheckExplicitInitList(const InitializedEntity &Entity, | |
| SemaRef.Diag(IList->getInit(Index)->getBeginLoc(), DK) | ||
| << T << IList->getInit(Index)->getSourceRange(); | ||
| } else { | ||
| int initKind = T->isArrayType() ? 0 : | ||
| T->isVectorType() ? 1 : | ||
| T->isScalarType() ? 2 : | ||
| T->isUnionType() ? 3 : | ||
| 4; | ||
| int initKind = T->isArrayType() ? 0 | ||
| : T->isVectorType() ? 1 | ||
| : T->isMatrixType() ? 2 | ||
| : T->isScalarType() ? 3 | ||
| : T->isUnionType() ? 4 | ||
| : 5; | ||
|
|
||
| unsigned DK = ExtraInitsIsError ? diag::err_excess_initializers | ||
| : diag::ext_excess_initializers; | ||
|
|
@@ -1430,6 +1437,9 @@ void InitListChecker::CheckListElementTypes(const InitializedEntity &Entity, | |
| } else if (DeclType->isVectorType()) { | ||
| CheckVectorType(Entity, IList, DeclType, Index, | ||
| StructuredList, StructuredIndex); | ||
| } else if (DeclType->isMatrixType()) { | ||
| CheckMatrixType(Entity, IList, DeclType, Index, StructuredList, | ||
| StructuredIndex); | ||
| } else if (const RecordDecl *RD = DeclType->getAsRecordDecl()) { | ||
| auto Bases = | ||
| CXXRecordDecl::base_class_const_range(CXXRecordDecl::base_class_const_iterator(), | ||
|
|
@@ -1877,6 +1887,34 @@ void InitListChecker::CheckReferenceType(const InitializedEntity &Entity, | |
| AggrDeductionCandidateParamTypes->push_back(DeclType); | ||
| } | ||
|
|
||
| void InitListChecker::CheckMatrixType(const InitializedEntity &Entity, | ||
| InitListExpr *IList, QualType DeclType, | ||
| unsigned &Index, | ||
| InitListExpr *StructuredList, | ||
| unsigned &StructuredIndex) { | ||
| if (!SemaRef.getLangOpts().HLSL) | ||
| return; | ||
|
|
||
| const ConstantMatrixType *MT = DeclType->castAs<ConstantMatrixType>(); | ||
| QualType ElemTy = MT->getElementType(); | ||
| const unsigned MaxElts = MT->getNumElementsFlattened(); | ||
|
|
||
| unsigned NumEltsInit = 0; | ||
| InitializedEntity ElemEnt = | ||
| InitializedEntity::InitializeElement(SemaRef.Context, 0, Entity); | ||
|
|
||
| while (NumEltsInit < MaxElts && Index < IList->getNumInits()) { | ||
| // Not a sublist: just consume directly. | ||
| ElemEnt.setElementIndex(Index); | ||
| CheckSubElementType(ElemEnt, IList, ElemTy, Index, StructuredList, | ||
| StructuredIndex); | ||
| ++NumEltsInit; | ||
| } | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I looked at this and I understand what is going on. We need the code up to here. We'll never get this far if we have the wrong number of initializers because this happens after initializer flattening. We should add an assert There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yep did this already. Originally was thinking if |
||
|
|
||
| // HLSL requires exactly NumEltsInit to equal Max initializers. | ||
| assert(NumEltsInit == MaxElts && "NumEltsInit must equal MaxElts"); | ||
| } | ||
|
|
||
| void InitListChecker::CheckVectorType(const InitializedEntity &Entity, | ||
| InitListExpr *IList, QualType DeclType, | ||
| unsigned &Index, | ||
|
|
@@ -3639,6 +3677,9 @@ InitializedEntity::InitializedEntity(ASTContext &Context, unsigned Index, | |
| } else if (const VectorType *VT = Parent.getType()->getAs<VectorType>()) { | ||
| Kind = EK_VectorElement; | ||
| Type = VT->getElementType(); | ||
| } else if (const MatrixType *MT = Parent.getType()->getAs<MatrixType>()) { | ||
| Kind = EK_MatrixElement; | ||
| Type = MT->getElementType(); | ||
| } else { | ||
| const ComplexType *CT = Parent.getType()->getAs<ComplexType>(); | ||
| assert(CT && "Unexpected type"); | ||
|
|
@@ -3687,6 +3728,7 @@ DeclarationName InitializedEntity::getName() const { | |
| case EK_Delegating: | ||
| case EK_ArrayElement: | ||
| case EK_VectorElement: | ||
| case EK_MatrixElement: | ||
| case EK_ComplexElement: | ||
| case EK_BlockElement: | ||
| case EK_LambdaToBlockConversionBlockElement: | ||
|
|
@@ -3720,6 +3762,7 @@ ValueDecl *InitializedEntity::getDecl() const { | |
| case EK_Delegating: | ||
| case EK_ArrayElement: | ||
| case EK_VectorElement: | ||
| case EK_MatrixElement: | ||
| case EK_ComplexElement: | ||
| case EK_BlockElement: | ||
| case EK_LambdaToBlockConversionBlockElement: | ||
|
|
@@ -3753,6 +3796,7 @@ bool InitializedEntity::allowsNRVO() const { | |
| case EK_Delegating: | ||
| case EK_ArrayElement: | ||
| case EK_VectorElement: | ||
| case EK_MatrixElement: | ||
| case EK_ComplexElement: | ||
| case EK_BlockElement: | ||
| case EK_LambdaToBlockConversionBlockElement: | ||
|
|
@@ -3792,6 +3836,9 @@ unsigned InitializedEntity::dumpImpl(raw_ostream &OS) const { | |
| case EK_Delegating: OS << "Delegating"; break; | ||
| case EK_ArrayElement: OS << "ArrayElement " << Index; break; | ||
| case EK_VectorElement: OS << "VectorElement " << Index; break; | ||
| case EK_MatrixElement: | ||
| OS << "MatrixElement " << Index; | ||
| break; | ||
| case EK_ComplexElement: OS << "ComplexElement " << Index; break; | ||
| case EK_BlockElement: OS << "Block"; break; | ||
| case EK_LambdaToBlockConversionBlockElement: | ||
|
|
@@ -6029,7 +6076,7 @@ static void TryOrBuildParenListInitialization( | |
| Sequence.SetFailed(InitializationSequence::FK_ParenthesizedListInitFailed); | ||
| if (!VerifyOnly) { | ||
| QualType T = Entity.getType(); | ||
| int InitKind = T->isArrayType() ? 0 : T->isUnionType() ? 3 : 4; | ||
| int InitKind = T->isArrayType() ? 0 : T->isUnionType() ? 4 : 5; | ||
| SourceRange ExcessInitSR(Args[EntityIndexToProcess]->getBeginLoc(), | ||
| Args.back()->getEndLoc()); | ||
| S.Diag(Kind.getLocation(), diag::err_excess_initializers) | ||
|
|
@@ -6822,7 +6869,8 @@ void InitializationSequence::InitializeFrom(Sema &S, | |
| // For HLSL ext vector types we allow list initialization behavior for C++ | ||
| // functional cast expressions which look like constructor syntax. This is | ||
| // accomplished by converting initialization arguments to InitListExpr. | ||
| if (S.getLangOpts().HLSL && Args.size() > 1 && DestType->isExtVectorType() && | ||
| if (S.getLangOpts().HLSL && Args.size() > 1 && | ||
| (DestType->isExtVectorType() || DestType->isConstantMatrixType()) && | ||
| (SourceType.isNull() || | ||
| !Context.hasSameUnqualifiedType(SourceType, DestType))) { | ||
| InitListExpr *ILE = new (Context) | ||
|
|
@@ -6987,6 +7035,7 @@ static AssignmentAction getAssignmentAction(const InitializedEntity &Entity, | |
| case InitializedEntity::EK_Binding: | ||
| case InitializedEntity::EK_ArrayElement: | ||
| case InitializedEntity::EK_VectorElement: | ||
| case InitializedEntity::EK_MatrixElement: | ||
| case InitializedEntity::EK_ComplexElement: | ||
| case InitializedEntity::EK_BlockElement: | ||
| case InitializedEntity::EK_LambdaToBlockConversionBlockElement: | ||
|
|
@@ -7012,6 +7061,7 @@ static bool shouldBindAsTemporary(const InitializedEntity &Entity) { | |
| case InitializedEntity::EK_Base: | ||
| case InitializedEntity::EK_Delegating: | ||
| case InitializedEntity::EK_VectorElement: | ||
| case InitializedEntity::EK_MatrixElement: | ||
| case InitializedEntity::EK_ComplexElement: | ||
| case InitializedEntity::EK_Exception: | ||
| case InitializedEntity::EK_BlockElement: | ||
|
|
@@ -7042,6 +7092,7 @@ static bool shouldDestroyEntity(const InitializedEntity &Entity) { | |
| case InitializedEntity::EK_Base: | ||
| case InitializedEntity::EK_Delegating: | ||
| case InitializedEntity::EK_VectorElement: | ||
| case InitializedEntity::EK_MatrixElement: | ||
| case InitializedEntity::EK_ComplexElement: | ||
| case InitializedEntity::EK_BlockElement: | ||
| case InitializedEntity::EK_LambdaToBlockConversionBlockElement: | ||
|
|
@@ -7095,6 +7146,7 @@ static SourceLocation getInitializationLoc(const InitializedEntity &Entity, | |
| case InitializedEntity::EK_Base: | ||
| case InitializedEntity::EK_Delegating: | ||
| case InitializedEntity::EK_VectorElement: | ||
| case InitializedEntity::EK_MatrixElement: | ||
| case InitializedEntity::EK_ComplexElement: | ||
| case InitializedEntity::EK_BlockElement: | ||
| case InitializedEntity::EK_LambdaToBlockConversionBlockElement: | ||
|
|
@@ -7844,11 +7896,13 @@ ExprResult InitializationSequence::Perform(Sema &S, | |
| ExprResult CurInit((Expr *)nullptr); | ||
| SmallVector<Expr*, 4> ArrayLoopCommonExprs; | ||
|
|
||
| // HLSL allows vector initialization to function like list initialization, but | ||
| // use the syntax of a C++-like constructor. | ||
| bool IsHLSLVectorInit = S.getLangOpts().HLSL && DestType->isExtVectorType() && | ||
| isa<InitListExpr>(Args[0]); | ||
| (void)IsHLSLVectorInit; | ||
| // HLSL allows vector/matrix initialization to function like list | ||
| // initialization, but use the syntax of a C++-like constructor. | ||
| bool IsHLSLVectorOrMatrixInit = | ||
| S.getLangOpts().HLSL && | ||
| (DestType->isExtVectorType() || DestType->isConstantMatrixType()) && | ||
| isa<InitListExpr>(Args[0]); | ||
| (void)IsHLSLVectorOrMatrixInit; | ||
|
|
||
| // For initialization steps that start with a single initializer, | ||
| // grab the only argument out the Args and place it into the "current" | ||
|
|
@@ -7887,7 +7941,7 @@ ExprResult InitializationSequence::Perform(Sema &S, | |
| case SK_StdInitializerList: | ||
| case SK_OCLSamplerInit: | ||
| case SK_OCLZeroOpaqueType: { | ||
| assert(Args.size() == 1 || IsHLSLVectorInit); | ||
| assert(Args.size() == 1 || IsHLSLVectorOrMatrixInit); | ||
| CurInit = Args[0]; | ||
| if (!CurInit.get()) return ExprError(); | ||
| break; | ||
|
|
@@ -9104,7 +9158,7 @@ bool InitializationSequence::Diagnose(Sema &S, | |
| << R; | ||
| else | ||
| S.Diag(Kind.getLocation(), diag::err_excess_initializers) | ||
| << /*scalar=*/2 << R; | ||
| << /*scalar=*/3 << R; | ||
| break; | ||
| } | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure why we need to do this checking. Shouldn't this all be done in the SemaHLSL code that validates the initializer list and transforms it to per-element initializers?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well three things First SemaHLSL is validating vectors and yet we still have
CheckVectorTypewhich even has HLSL copy initalization.Second removing
causes us to hit this else case:
llvm-project/clang/lib/Sema/SemaInit.cpp
Lines 1481 to 1486 in 0c2913a
Third even if we do something like below to avoid the err_illegal_initializer_type diag message
we still error with
excess elements in matrix initializer. SoCheckMatrixTypeis necessary.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That said the diagnostics in
CheckMatrixTypenever trigger and are now preceded by the ones in SemaHLSL and the flatten mixed vector/matrix/scalar elements is also done in SemaHLSL so I will investigate to see if we can reduce the scope of whatCheckMatrixTypeis doing.Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@llvm-beanz the initializer list work simplifies but does not make us remove
CheckMatrixType. It simplifies it so that all we have to do is support the scalar case by looping over the number of inits and callingCheckSubElementType. So I deleted all the vector and matrix type handeling