SaurabhJha created this revision. SaurabhJha added a reviewer: fhahn. Herald added a subscriber: tschuett. SaurabhJha requested review of this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits.
[Matrix] Implement explicit type conversions for MatrixType. Bugzilla ticket is here: https://bugs.llvm.org/show_bug.cgi?id=47141 Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D99037 Files: clang/include/clang/Basic/DiagnosticSemaKinds.td clang/include/clang/Sema/Sema.h clang/lib/Sema/SemaCast.cpp clang/lib/Sema/SemaExpr.cpp clang/test/Sema/matrix-cast.c clang/test/SemaCXX/matrix-casts.cpp
Index: clang/test/SemaCXX/matrix-casts.cpp =================================================================== --- /dev/null +++ clang/test/SemaCXX/matrix-casts.cpp @@ -0,0 +1,47 @@ +// RUN: %clang_cc1 -std=c++11 -fenable-matrix -fsyntax-only %s -verify + +typedef char cx4x4 __attribute__((matrix_type(4, 4))); +typedef int ix4x4 __attribute__((matrix_type(4, 4))); +typedef short sx4x4 __attribute__((matrix_type(4, 4))); +typedef int ix5x5 __attribute__((matrix_type(5, 5))); +typedef float fx5x5 __attribute__((matrix_type(5, 5))); + +void f1() { + cx4x4 m1; + ix4x4 m2; + sx4x4 m3; + ix5x5 m4; + fx5x5 m5; + + (void)reinterpret_cast<ix4x4>(m1); + (void)(ix4x4) m1; + (void)reinterpret_cast<sx4x4>(m2); + (void)(sx4x4) m1; + (void)reinterpret_cast<ix5x5>(m3); // expected-error {{reinterpret_cast from matrix 'sx4x4' (aka 'short __attribute__((matrix_type(4, 4)))') to matrix 'ix5x5' (aka 'int __attribute__((matrix_type(5, 5)))') of different size}} + (void)(ix5x5) m3; // expected-error {{-style cast from matrix 'sx4x4' (aka 'short __attribute__((matrix_type(4, 4)))') to matrix 'ix5x5' (aka 'int __attribute__((matrix_type(5, 5)))') of different size}} +} + +typedef float float2_8x8 __attribute__((matrix_type(8, 8))); +typedef double double_10x10 __attribute__((matrix_type(10, 10))); +typedef double double_8x8 __attribute__((matrix_type(8, 8))); +typedef signed int signed_int_12x12 __attribute__((matrix_type(12, 12))); +typedef unsigned int unsigned_int_12x12 __attribute__((matrix_type(12, 12))); +typedef unsigned int unsigned_int_10x10 __attribute__((matrix_type(10, 10))); + +void f2() { + float2_8x8 m1; + double_8x8 m2; + signed_int_12x12 m3; + unsigned_int_12x12 m4; + + (void)reinterpret_cast<double_10x10>(m1); // expected-error {{reinterpret_cast from matrix 'float2_8x8' (aka 'float __attribute__((matrix_type(8, 8)))') to matrix 'double_10x10' (aka 'double __attribute__((matrix_type(10, 10)))') of different size}} + (void)(double_10x10) m1; // expected-error {{C-style cast from matrix 'float2_8x8' (aka 'float __attribute__((matrix_type(8, 8)))') to matrix 'double_10x10' (aka 'double __attribute__((matrix_type(10, 10)))') of different size}} + (void)reinterpret_cast<float2_8x8>(m2); + (void)(float2_8x8) m2; + (void)reinterpret_cast<unsigned_int_12x12>(m3); + (void)(unsigned_int_12x12) m3; + (void)reinterpret_cast<signed_int_12x12>(m4); + (void)(signed_int_12x12) m4; + (void)reinterpret_cast<unsigned_int_10x10>(m3); // expected-error {{reinterpret_cast from matrix 'signed_int_12x12' (aka 'int __attribute__((matrix_type(12, 12)))') to matrix 'unsigned_int_10x10' (aka 'unsigned int __attribute__((matrix_type(10, 10)))') of different size}} + (void)(unsigned_int_10x10) m3; // expected-error {{C-style cast from matrix 'signed_int_12x12' (aka 'int __attribute__((matrix_type(12, 12)))') to matrix 'unsigned_int_10x10' (aka 'unsigned int __attribute__((matrix_type(10, 10)))') of different size}} +} \ No newline at end of file Index: clang/test/Sema/matrix-cast.c =================================================================== --- /dev/null +++ clang/test/Sema/matrix-cast.c @@ -0,0 +1,51 @@ +// RUN: %clang_cc1 -fenable-matrix -fsyntax-only %s -verify + +typedef char cx4x4 __attribute__((matrix_type(4, 4))); +typedef int ix4x4 __attribute__((matrix_type(4, 4))); +typedef short sx4x4 __attribute__((matrix_type(4, 4))); +typedef int ix5x5 __attribute__((matrix_type(5, 5))); +typedef float fx5x5 __attribute__((matrix_type(5, 5))); + +void f1() { + cx4x4 m1; + ix4x4 m2; + sx4x4 m3; + ix5x5 m4; + fx5x5 m5; + + m2 = (ix4x4)m1; + m3 = (sx4x4)m2; + m4 = (ix5x5)m3; // expected-error {{invalid conversion between matrix type \ +'ix5x5' (aka 'int __attribute__((matrix_type(5, 5)))') and 'sx4x4' \ +(aka 'short __attribute__((matrix_type(4, 4)))') of different size}} + m5 = (ix5x5)m4; // expected-error {{assigning to 'fx5x5' (aka \ +'float __attribute__((matrix_type(5, 5)))') from incompatible type 'ix5x5' (aka 'int __attribute__((matrix_type(5, 5)))')}} + m4 = (ix5x5)m5; +} + +typedef float float2_8x8 __attribute__((matrix_type(8, 8))); +typedef double double_10x10 __attribute__((matrix_type(10, 10))); +typedef double double_8x8 __attribute__((matrix_type(8, 8))); +typedef signed int signed_int_12x12 __attribute__((matrix_type(12, 12))); +typedef unsigned int unsigned_int_12x12 __attribute__((matrix_type(12, 12))); +typedef unsigned int unsigned_int_10x10 __attribute__((matrix_type(10, 10))); + +void f2() { + float2_8x8 m1; + double_10x10 m2; + double_8x8 m3; + signed_int_12x12 m4; + unsigned_int_12x12 m5; + unsigned_int_10x10 m6; + + m2 = (double_10x10)m1; // expected-error {{invalid conversion between matrix type \ +'double_10x10' (aka 'double __attribute__((matrix_type(10, 10)))') and 'float2_8x8' \ +(aka 'float __attribute__((matrix_type(8, 8)))') of different size}} + m3 = (double_8x8)m1; + + m5 = (unsigned_int_12x12)m4; + m4 = (signed_int_12x12)m5; + m6 = (unsigned_int_10x10)m4; // expected-error {{invalid conversion between matrix type \ +'unsigned_int_10x10' (aka 'unsigned int __attribute__((matrix_type(10, 10)))') and 'signed_int_12x12' \ +(aka 'int __attribute__((matrix_type(12, 12)))') of different size}} +} \ No newline at end of file Index: clang/lib/Sema/SemaExpr.cpp =================================================================== --- clang/lib/Sema/SemaExpr.cpp +++ clang/lib/Sema/SemaExpr.cpp @@ -7306,6 +7306,32 @@ ValidScalableConversion(destTy, srcTy); } +/// Are the two types compatible matrix types? That is, are they both matrices +/// and do they both have the same dimensions i.e. do they have the same number +/// of rows and the same number of columns? +/// +/// This will also return false if elements types of either of the matrices +/// is not a scalar type. +bool Sema::areCompatibleMatrixTypes(QualType srcTy, QualType destTy) { + assert(destTy->isMatrixType() && srcTy->isMatrixType()); + + const ConstantMatrixType *matSrcType = srcTy->getAs<ConstantMatrixType>(); + const ConstantMatrixType *matDestType = destTy->getAs<ConstantMatrixType>(); + + if (matSrcType->getNumRows() != matDestType->getNumRows() || + matSrcType->getNumColumns() != matDestType->getNumColumns()) { + return false; + } + + QualType elemSrcType = matSrcType->getElementType(); + QualType elemDestType = matDestType->getElementType(); + + if (!elemSrcType->isScalarType() || !elemDestType->isScalarType()) { + return false; + } + return true; +} + /// Are the two types lax-compatible vector types? That is, given /// that one of them is a vector, do they have equal storage sizes, /// where the storage size is the number of elements times the element @@ -7368,6 +7394,25 @@ return areLaxCompatibleVectorTypes(srcTy, destTy); } +bool Sema::CheckMatrixCast(SourceRange R, QualType DestMatrixTy, QualType SrcTy, + CastKind &Kind) { + assert(DestMatrixTy->isMatrixType() && "Not a matrix type!"); + + if (SrcTy->isMatrixType()) { + if (!areCompatibleMatrixTypes(SrcTy, DestMatrixTy)) { + return Diag(R.getBegin(), diag::err_invalid_conversion_between_matrices) + << DestMatrixTy << SrcTy << R; + } + } else { + return Diag(R.getBegin(), + diag::err_invalid_conversion_between_matrix_and_scalar) + << DestMatrixTy << SrcTy << R; + } + + Kind = CK_BitCast; + return false; +} + bool Sema::CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty, CastKind &Kind) { assert(VectorTy->isVectorType() && "Not a vector type!"); Index: clang/lib/Sema/SemaCast.cpp =================================================================== --- clang/lib/Sema/SemaCast.cpp +++ clang/lib/Sema/SemaCast.cpp @@ -2214,6 +2214,27 @@ return TC_Success; } + // Allow reinterpret_casts between matrices of same dimensions. + bool destIsMatrix = DestType->isMatrixType(); + bool srcIsMatrix = SrcType->isMatrixType(); + if (srcIsMatrix || destIsMatrix) { + if (srcIsMatrix && destIsMatrix) { + if (Self.areCompatibleMatrixTypes(SrcType, DestType)) { + Kind = CK_BitCast; + return TC_Success; + } else { + msg = diag::err_bad_cxx_cast_matrix_to_matrix_different_size; + return TC_Failed; + } + } else if (!destIsMatrix) { + msg = diag::err_bad_cxx_cast_matrix_to_scalar; + return TC_Failed; + } else if (!srcIsMatrix) { + msg = diag::err_bad_cxx_cast_scalar_to_matrix; + return TC_Failed; + } + } + // Allow reinterpret_casts between vectors of the same size and // between vectors and integers of the same size. bool destIsVector = DestType->isVectorType(); @@ -2765,7 +2786,8 @@ return; } - if (!DestType->isScalarType() && !DestType->isVectorType()) { + if (!DestType->isScalarType() && !DestType->isVectorType() && + !DestType->isMatrixType()) { const RecordType *DestRecordTy = DestType->getAs<RecordType>(); if (DestRecordTy && Self.Context.hasSameUnqualifiedType(DestType, SrcType)){ @@ -2816,10 +2838,11 @@ return; } - // The type we're casting to is known to be a scalar or vector. + // The type we're casting to is known to be a scalar, a vector, or a matrix. - // Require the operand to be a scalar or vector. - if (!SrcType->isScalarType() && !SrcType->isVectorType()) { + // Require the operand to be a scalar, a vector, or a matrix. + if (!SrcType->isScalarType() && !SrcType->isVectorType() && + !SrcType->isMatrixType()) { Self.Diag(SrcExpr.get()->getExprLoc(), diag::err_typecheck_expect_scalar_operand) << SrcType << SrcExpr.get()->getSourceRange(); @@ -2832,6 +2855,13 @@ return; } + if (const MatrixType *DestMatTy = DestType->getAs<MatrixType>()) { + if (Self.CheckMatrixCast(OpRange, DestType, SrcType, Kind)) { + SrcExpr = ExprError(); + } + return; + } + if (const VectorType *DestVecTy = DestType->getAs<VectorType>()) { if (DestVecTy->getVectorKind() == VectorType::AltiVecVector && (SrcType->isIntegerType() || SrcType->isFloatingType())) { Index: clang/include/clang/Sema/Sema.h =================================================================== --- clang/include/clang/Sema/Sema.h +++ clang/include/clang/Sema/Sema.h @@ -11603,6 +11603,8 @@ bool isValidSveBitcast(QualType srcType, QualType destType); + bool areCompatibleMatrixTypes(QualType srcType, QualType destType); + bool areLaxCompatibleVectorTypes(QualType srcType, QualType destType); bool isLaxVectorConversion(QualType srcType, QualType destType); @@ -11661,6 +11663,13 @@ ExprResult checkUnknownAnyArg(SourceLocation callLoc, Expr *result, QualType ¶mType); + // CheckMatrixCast - check type constraints for matrices. + // We allow casting in between matrices of the same dimensions i.e. when + // they have the same number of rows and columns. + // returns true if the cast is invalid + bool CheckMatrixCast(SourceRange R, QualType MatrixTy, QualType Tr, + CastKind &Kind); + // CheckVectorCast - check type constraints for vectors. // Since vectors are an extension, there are no C standard reference for this. // We allow casting between vectors and integer datatypes of the same size. Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -7137,6 +7137,15 @@ InGroup<CXX98CompatPedantic>, DefaultIgnore; def err_bad_reinterpret_cast_small_int : Error< "cast from pointer to smaller type %2 loses information">; +def err_bad_cxx_cast_matrix_to_matrix_different_size : Error< + "%select{||reinterpret_cast||C-style cast||}0 from matrix %1 " + "to matrix %2 of different size">; +def err_bad_cxx_cast_scalar_to_matrix : Error< + "%select{||reinterpret_cast||C-style cast||}0 from scalar %1 " + "to matrix %2">; +def err_bad_cxx_cast_matrix_to_scalar : Error< + "%select{||reinterpret_cast||C-style cast||}0 from matrix %1 " + "to scalar %2">; def err_bad_cxx_cast_vector_to_scalar_different_size : Error< "%select{||reinterpret_cast||C-style cast||}0 from vector %1 " "to scalar %2 of different size">; @@ -8568,6 +8577,13 @@ let CategoryName = "Semantic Issue" in { +def err_invalid_conversion_between_matrices : Error< + "invalid conversion between matrix type%diff{ $ and $|}0,1 of different " + "size">; + +def err_invalid_conversion_between_matrix_and_scalar : Error< + "invalid conversion between matrix type %0 and scalar type%1">; + def err_invalid_conversion_between_vectors : Error< "invalid conversion between vector type%diff{ $ and $|}0,1 of different " "size">;
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits