-
Notifications
You must be signed in to change notification settings - Fork 15.5k
[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
Changes from 7 commits
b7c3836
9a57716
a09e070
28a87ff
771989c
842a52a
cbb7650
d6bed40
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, | ||||||||||||||
|
Collaborator
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'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?
Member
Author
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. Well three things First SemaHLSL is validating vectors and yet we still have Second removing } else if (DeclType->isMatrixType()) {
CheckMatrixType(Entity, IList, DeclType, Index, StructuredList,
StructuredIndex);
}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 } else if (DeclType->isMatrixType()) {
return;
}we still error with
Member
Author
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. That said the diagnostics in
Member
Author
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. @llvm-beanz the initializer list work simplifies but does not make us remove |
||||||||||||||
| 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; | ||||||||||||||
| } | ||||||||||||||
|
Collaborator
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
Member
Author
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; | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
|
|
||||||||||||||
Uh oh!
There was an error while loading. Please reload this page.