SaurabhJha updated this revision to Diff 335677. SaurabhJha added a comment.
I reverted the int <-> float conversion to previous code to make the tests pass. That way, we atleast have something working and we can go from there. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D99037/new/ https://reviews.llvm.org/D99037 Files: clang/include/clang/AST/OperationKinds.def clang/include/clang/Basic/DiagnosticSemaKinds.td clang/include/clang/Sema/Sema.h clang/lib/AST/Expr.cpp clang/lib/AST/ExprConstant.cpp clang/lib/CodeGen/CGExpr.cpp clang/lib/CodeGen/CGExprAgg.cpp clang/lib/CodeGen/CGExprComplex.cpp clang/lib/CodeGen/CGExprConstant.cpp clang/lib/CodeGen/CGExprScalar.cpp clang/lib/Edit/RewriteObjCFoundationAPI.cpp clang/lib/Sema/SemaCast.cpp clang/lib/Sema/SemaExpr.cpp clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp clang/test/CodeGen/matrix-cast.c 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,67 @@ +// RUN: %clang_cc1 -std=c++11 -fenable-matrix -fsyntax-only -verify %s + +template <typename X> + +using matrix_4_4 = X __attribute__((matrix_type(4, 4))); + +template <typename Y> + +using matrix_5_5 = Y __attribute__((matrix_type(5, 5))); + +typedef struct test_struct { +} test_struct; + +typedef int vec __attribute__((vector_size(4))); + +void f1() { + // TODO: Update this test once the support of C-style casts for C++ is implemented. + matrix_4_4<char> m1; + matrix_4_4<int> m2; + matrix_4_4<short> m3; + matrix_5_5<int> m4; + int i; + vec v; + test_struct *s; + + (matrix_4_4<int>)m1; // expected-error {{C-style cast from 'matrix_4_4<char>' (aka 'char __attribute__((matrix_type(4, \ +4)))') to 'matrix_4_4<int>' (aka 'int __attribute__((matrix_type(4, 4)))') is not allowed}} + (matrix_4_4<short>)m2; // expected-error {{C-style cast from 'matrix_4_4<int>' (aka 'int __attribute__((matrix_type(4, \ +4)))') to 'matrix_4_4<short>' (aka 'short __attribute__((matrix_type(4, 4)))') is not allowed}} + (matrix_5_5<int>)m3; // expected-error {{C-style cast from 'matrix_4_4<short>' (aka 'short __attribute__((matrix_type(4, \ +4)))') to 'matrix_5_5<int>' (aka 'int __attribute__((matrix_type(5, 5)))') is not allowed}} + + (int)m3; // expected-error {{C-style cast from 'matrix_4_4<short>' (aka 'short __attribute__((matrix_type(4, \ +4)))') to 'int'}} + (matrix_4_4<int>)i; // expected-error {{C-style cast from 'int' to 'matrix_4_4<int>' (aka 'int __attribute__((\ +matrix_type(4, 4)))') is not allowed}} + + (vec)m2; // expected-error {{C-style cast from 'matrix_4_4<int>' (aka 'int __attribute__((matrix_type(4, 4)))') \ +to 'vec' (vector of 1 'int' value) is not allowed}} + (matrix_4_4<char>)v; // expected-error {{C-style cast from 'vec' (vector of 1 'int' value) to 'matrix_4_4<char>' \ +(aka 'char __attribute__((matrix_type(4, 4)))') is not allowed}} + + (test_struct *)m1; // expected-error {{cannot cast from type 'matrix_4_4<char>' (aka 'char __attribute__\ +((matrix_type(4, 4)))') to pointer type 'test_struct *}}' + (matrix_5_5<float>)s; // expected-error {{C-style cast from 'test_struct *' to 'matrix_5_5<float>' (aka 'float __attribute__\ +((matrix_type(5, 5)))') is not allowed}}' +} + +void f2() { + // TODO: Update this test once the support of C-style casts for C++ is implemented. + matrix_4_4<float> m1; + matrix_5_5<double> m2; + matrix_5_5<signed int> m3; + matrix_4_4<unsigned int> m4; + float f; + + (matrix_4_4<double>)m1; // expected-error {{C-style cast from 'matrix_4_4<float>' (aka 'float __attribute__\ +((matrix_type(4, 4)))') to 'matrix_4_4<double>' (aka 'double __attribute__((matrix_type(4, 4)))') is not allowed}} + (matrix_5_5<float>)m2; // expected-error {{C-style cast from 'matrix_5_5<double>' (aka 'double __attribute__\ +((matrix_type(5, 5)))') to 'matrix_5_5<float>' (aka 'float __attribute__((matrix_type(5, 5)))') is not allowed}} + (matrix_5_5<unsigned int>)m3; // expected-error {{C-style cast from 'matrix_5_5<int>' (aka 'int __attribute__\ +((matrix_type(5, 5)))') to 'matrix_5_5<unsigned int>' (aka 'unsigned int __attribute__((matrix_type(5, 5)))') \ +is not allowed}} + (matrix_4_4<int>)m4; // expected-error {{C-style cast from 'matrix_4_4<unsigned int>' (aka 'unsigned int \ +__attribute__((matrix_type(4, 4)))') to 'matrix_4_4<int>' (aka 'int __attribute__((matrix_type(4, 4)))') is not \ +allowed}} +} Index: clang/test/Sema/matrix-cast.c =================================================================== --- /dev/null +++ clang/test/Sema/matrix-cast.c @@ -0,0 +1,75 @@ +// 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))); +typedef int vec __attribute__((vector_size(4))); +typedef struct test_struct { +} test_struct; + +void f1() { + cx4x4 m1; + ix4x4 m2; + sx4x4 m3; + ix5x5 m4; + fx5x5 m5; + int i; + vec v; + test_struct *s; + + m2 = (ix4x4)m1; + m3 = (sx4x4)m2; + m4 = (ix5x5)m3; // expected-error {{conversion between matrix type 'ix5x5' (aka 'int __attribute__\ +((matrix_type(5, 5)))') and 'sx4x4' (aka 'short __attribute__((matrix_type(4, 4)))') of different size \ +is not allowed}} + 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)))')}} + i = (int)m4; // expected-error {{conversion between matrix type 'ix5x5' (aka 'int __attribute__\ +((matrix_type(5, 5)))') and type 'int' is not allowed}} + m4 = (ix5x5)i; // expected-error {{conversion between matrix type 'ix5x5' (aka 'int __attribute__\ +((matrix_type(5, 5)))') and type 'int' is not allowed}} + v = (vec)m4; // expected-error {{conversion between matrix type 'ix5x5' (aka 'int __attribute__\ +((matrix_type(5, 5)))') and type 'vec' (vector of 1 'int' value) is not allowed}} + m4 = (ix5x5)v; // expected-error {{conversion between matrix type 'ix5x5' (aka 'int __attribute__\ +((matrix_type(5, 5)))') and type 'vec' (vector of 1 'int' value) is not allowed}} + s = (test_struct *)m3; // expected-error {{conversion between matrix type 'sx4x4' (aka 'short \ +__attribute__((matrix_type(4, 4)))') and type 'test_struct *' (aka 'struct test_struct *') is not allowed}} + m3 = (sx4x4)s; // expected-error {{conversion between matrix type 'sx4x4' (aka 'short \ +__attribute__((matrix_type(4, 4)))') and type 'test_struct *' (aka 'struct test_struct *') is not allowed}} + + 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; + float f; + + m2 = (double_10x10)m1; // expected-error {{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 is not allowed}} + m3 = (double_8x8)m1; + + m5 = (unsigned_int_12x12)m4; + m4 = (signed_int_12x12)m5; + m6 = (unsigned_int_10x10)m4; // expected-error {{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 is not allowed}} + f = (float)m4; // expected-error {{conversion between matrix type 'signed_int_12x12' \ +(aka 'int __attribute__((matrix_type(12, 12)))') and type 'float' is not allowed}} + m4 = (signed_int_12x12)f; // expected-error {{conversion between matrix type 'signed_int_12x12' \ +(aka 'int __attribute__((matrix_type(12, 12)))') and type 'float' is not allowed}} +} \ No newline at end of file Index: clang/test/CodeGen/matrix-cast.c =================================================================== --- /dev/null +++ clang/test/CodeGen/matrix-cast.c @@ -0,0 +1,100 @@ +// RUN: %clang_cc1 -fenable-matrix -triple x86_64-apple-darwin %s -emit-llvm -disable-llvm-passes -o - | FileCheck %s + +typedef char cx5x5 __attribute__((matrix_type(5, 5))); +typedef int ix5x5 __attribute__((matrix_type(5, 5))); +typedef short sx5x5 __attribute__((matrix_type(5, 5))); +typedef float fx5x5 __attribute__((matrix_type(5, 5))); +typedef double dx5x5 __attribute__((matrix_type(5, 5))); +typedef unsigned short unsigned_short_int_5x5 __attribute__((matrix_type(5, 5))); +typedef unsigned int unsigned_int_5x5 __attribute__((matrix_type(5, 5))); +typedef unsigned long unsigned_long_int_5x5 __attribute__((matrix_type(5, 5))); + +void cast_char_matrix_to_int(cx5x5 c, ix5x5 i) { + // CHECK-LABEL: define{{.*}} void @cast_char_matrix_to_int(<25 x i8> %c, <25 x i32> %i) + // CHECK: [[C:%.*]] = load <25 x i8>, <25 x i8>* {{.*}}, align 1 + // CHECK-NEXT: [[CONV:%.*]] = sext <25 x i8> [[C]] to <25 x i32> + // CHECK-NEXT: store <25 x i32> [[CONV]], <25 x i32>* {{.*}}, align 4 + // CHECK-NEXT: ret void + + i = (ix5x5)c; +} + +void cast_char_matrix_to_unsigned_int(cx5x5 c, unsigned_int_5x5 u) { + // CHECK-LABEL: define{{.*}} void @cast_char_matrix_to_unsigned_int(<25 x i8> %c, <25 x i32> %u) + // CHECK: [[C:%.*]] = load <25 x i8>, <25 x i8>* {{.*}}, align 1 + // CHECK-NEXT: [[CONV:%.*]] = sext <25 x i8> [[C]] to <25 x i32> + // CHECK-NEXT: store <25 x i32> [[CONV]], <25 x i32>* {{.*}}, align 4 + // CHECK-NEXT: ret void + + u = (unsigned_int_5x5)c; +} + +void cast_int_matrix_to_short(ix5x5 i, sx5x5 s) { + // CHECK-LABEL: define{{.*}} void @cast_int_matrix_to_short(<25 x i32> %i, <25 x i16> %s) + // CHECK: [[I:%.*]] = load <25 x i32>, <25 x i32>* {{.*}}, align 4 + // CHECK-NEXT: [[CONV:%.*]] = trunc <25 x i32> [[I]] to <25 x i16> + // CHECK-NEXT: store <25 x i16> [[CONV]], <25 x i16>* {{.*}}, align 2 + // CHECK-NEXT: ret void + + s = (sx5x5)i; +} + +void cast_int_matrix_to_float(ix5x5 i, fx5x5 f) { + // CHECK-LABEL: define{{.*}} void @cast_int_matrix_to_float(<25 x i32> %i, <25 x float> %f) + // CHECK: [[I:%.*]] = load <25 x i32>, <25 x i32>* {{.*}}, align 4 + // CHECK-NEXT: [[CONV:%.*]] = bitcast <25 x i32> [[I]] to <25 x float> + // CHECK-NEXT: store <25 x float> [[CONV]], <25 x float>* {{.*}}, align 4 + // CHECK-NEXT: ret void + + f = (fx5x5)i; +} + +void cast_double_matrix_to_int(dx5x5 d, ix5x5 i) { + // CHECK-LABEL: define{{.*}} void @cast_double_matrix_to_int(<25 x double> %d, <25 x i32> %i) + // CHECK: [[D:%.*]] = load <25 x double>, <25 x double>* {{.*}}, align 8 + // CHECK-NEXT: [[CONV:%.*]] = fptosi <25 x double> [[D]] to <25 x i32> + // CHECK-NEXT: store <25 x i32> [[CONV]], <25 x i32>* {{.*}}, align 4 + // CHECK-NEXT: ret void + + i = (ix5x5)d; +} + +void cast_float_matrix_to_unsigned_short_int(fx5x5 f, unsigned_short_int_5x5 i) { + // CHECK-LABEL: define{{.*}} void @cast_float_matrix_to_unsigned_short_int(<25 x float> %f, <25 x i16> %i) + // CHECK: [[F:%.*]] = load <25 x float>, <25 x float>* {{.*}}, align 4 + // CHECK-NEXT: [[CONV:%.*]] = fptoui <25 x float> [[F]] to <25 x i16> + // CHECK-NEXT: store <25 x i16> [[CONV]], <25 x i16>* %1, align 2 + // CHECK-NEXT: ret void + + i = (unsigned_short_int_5x5)f; +} + +void cast_double_matrix_to_float(dx5x5 d, fx5x5 f) { + // CHECK-LABEL: define{{.*}} void @cast_double_matrix_to_float(<25 x double> %d, <25 x float> %f) + // CHECK: [[D:%.*]] = load <25 x double>, <25 x double>* {{.*}}, align 8 + // CHECK-NEXT: [[CONV:%.*]] = fptrunc <25 x double> [[D]] to <25 x float> + // CHECK-NEXT: store <25 x float> [[CONV]], <25 x float>* {{.*}}, align 4 + // CHECK-NEXT: ret void + + f = (fx5x5)d; +} + +void cast_unsigned_short_int_to_unsigned_int(unsigned_short_int_5x5 s, unsigned_int_5x5 i) { + // CHECK-LABEL: define{{.*}} void @cast_unsigned_short_int_to_unsigned_int(<25 x i16> %s, <25 x i32> %i) + // CHECK: [[S:%.*]] = load <25 x i16>, <25 x i16>* {{.*}}, align 2 + // CHECK-NEXT: [[CONV:%.*]] = zext <25 x i16> [[S]] to <25 x i32> + // CHECK-NEXT: store <25 x i32> [[CONV]], <25 x i32>* {{.*}}, align 4 + // CHECK-NEXT: ret void + + i = (unsigned_int_5x5)s; +} + +void cast_unsigned_long_int_to_unsigned_short_int(unsigned_long_int_5x5 l, unsigned_short_int_5x5 s) { + // CHECK-LABEL: define{{.*}} void @cast_unsigned_long_int_to_unsigned_short_int(<25 x i64> %l, <25 x i16> %s) + // CHECK: [[L:%.*]] = load <25 x i64>, <25 x i64>* %0, align 8 + // CHECK-NEXT: [[CONV:%.*]] = trunc <25 x i64> [[L]] to <25 x i16> + // CHECK-NEXT: store <25 x i16> [[CONV]], <25 x i16>* {{.*}}, align 2 + // CHECK-NEXT: ret void + + s = (unsigned_short_int_5x5)l; +} Index: clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp =================================================================== --- clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp +++ clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp @@ -543,6 +543,10 @@ state = handleLVectorSplat(state, LCtx, CastE, Bldr, Pred); continue; } + case CK_MatrixCast: { + // TODO: Handle MatrixCast here. + continue; + } } } } Index: clang/lib/Sema/SemaExpr.cpp =================================================================== --- clang/lib/Sema/SemaExpr.cpp +++ clang/lib/Sema/SemaExpr.cpp @@ -7345,6 +7345,19 @@ ValidScalableConversion(destTy, srcTy); } +/// Are the two types matrix types and do they have the same dimensions i.e. +/// do they have the same number of rows and the same number of columns? +bool Sema::areMatrixTypesOfTheSameDimension(QualType srcTy, QualType destTy) { + if (!destTy->isMatrixType() || !srcTy->isMatrixType()) + return false; + + const ConstantMatrixType *matSrcType = srcTy->getAs<ConstantMatrixType>(); + const ConstantMatrixType *matDestType = destTy->getAs<ConstantMatrixType>(); + + return (matSrcType->getNumRows() == matDestType->getNumRows() && + matSrcType->getNumColumns() == matDestType->getNumColumns()); +} + /// 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 @@ -7407,6 +7420,27 @@ return areLaxCompatibleVectorTypes(srcTy, destTy); } +bool Sema::CheckMatrixCast(SourceRange R, QualType DestTy, QualType SrcTy, + CastKind &Kind) { + if (SrcTy->isMatrixType() && DestTy->isMatrixType()) { + if (!areMatrixTypesOfTheSameDimension(SrcTy, DestTy)) { + return Diag(R.getBegin(), diag::err_invalid_conversion_between_matrixes) + << DestTy << SrcTy << R; + } + } else if (SrcTy->isMatrixType()) { + return Diag(R.getBegin(), + diag::err_invalid_conversion_between_matrix_and_type) + << SrcTy << DestTy << R; + } else if (DestTy->isMatrixType()) { + return Diag(R.getBegin(), + diag::err_invalid_conversion_between_matrix_and_type) + << DestTy << SrcTy << R; + } + + Kind = CK_MatrixCast; + 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 @@ -2859,7 +2859,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)){ @@ -2910,10 +2911,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(); @@ -2926,6 +2928,13 @@ return; } + if (DestType->getAs<MatrixType>() || SrcType->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/lib/Edit/RewriteObjCFoundationAPI.cpp =================================================================== --- clang/lib/Edit/RewriteObjCFoundationAPI.cpp +++ clang/lib/Edit/RewriteObjCFoundationAPI.cpp @@ -1080,6 +1080,7 @@ case CK_BuiltinFnToFnPtr: case CK_ZeroToOCLOpaqueType: case CK_IntToOCLSampler: + case CK_MatrixCast: return false; case CK_BooleanToSignedIntegral: Index: clang/lib/CodeGen/CGExprScalar.cpp =================================================================== --- clang/lib/CodeGen/CGExprScalar.cpp +++ clang/lib/CodeGen/CGExprScalar.cpp @@ -348,6 +348,10 @@ EmitImplicitIntegerSignChangeChecks( SanOpts.has(SanitizerKind::ImplicitIntegerSignChange)) {} }; + Value * + EmitCastBetweenScalarTypes(Value *Src, QualType SrcType, QualType DstType, + ScalarConversionOpts Opts); + Value * EmitScalarConversion(Value *Src, QualType SrcTy, QualType DstTy, SourceLocation Loc, @@ -1191,6 +1195,71 @@ {Src, Dst}); } +Value *ScalarExprEmitter::EmitCastBetweenScalarTypes(Value *Src, + QualType SrcType, + QualType DstType, + ScalarConversionOpts Opts) { + + llvm::Type *SrcTy = Src->getType(); + llvm::Type *DstTy = ConvertType(DstType); + + // If the types are non-matrix, the element types and the types are the same. + // The assignments in this condition is used in the code following this + // condition where we use element types to determine the kind of cast and + // original types for actual casting. + llvm::Type *SrcElementTy; + llvm::Type *DstElementTy; + QualType SrcElementType; + QualType DstElementType; + if (SrcType->isMatrixType() && DstType->isMatrixType()) { + // Allow bitcast between matrices of the same size. + if (SrcTy->getPrimitiveSizeInBits() == DstTy->getPrimitiveSizeInBits()) + return Builder.CreateBitCast(Src, DstTy, "conv"); + + SrcElementTy = cast<llvm::VectorType>(SrcTy)->getElementType(); + DstElementTy = cast<llvm::VectorType>(DstTy)->getElementType(); + SrcElementType = SrcType->castAs<MatrixType>()->getElementType(); + DstElementType = DstType->castAs<MatrixType>()->getElementType(); + } else { + SrcElementTy = SrcTy; + DstElementTy = DstTy; + SrcElementType = SrcType; + DstElementType = DstType; + } + + Value *Res = nullptr; + if (isa<llvm::IntegerType>(SrcElementTy)) { + bool InputSigned = SrcElementType->isSignedIntegerOrEnumerationType(); + if (SrcElementType->isBooleanType() && Opts.TreatBooleanAsSigned) { + InputSigned = true; + } + if (isa<llvm::IntegerType>(DstElementTy)) + Res = Builder.CreateIntCast(Src, DstTy, InputSigned, "conv"); + else if (InputSigned) + Res = Builder.CreateSIToFP(Src, DstTy, "conv"); + else + Res = Builder.CreateUIToFP(Src, DstTy, "conv"); + } else if (isa<llvm::IntegerType>(DstElementTy)) { + assert(SrcElementTy->isFloatingPointTy() && "Unknown real conversion"); + if (DstElementType->isSignedIntegerOrEnumerationType()) + Res = Builder.CreateFPToSI(Src, DstTy, "conv"); + else + Res = Builder.CreateFPToUI(Src, DstTy, "conv"); + } else { + if (!SrcType->isMatrixType() || !DstType->isMatrixType()) { + // Not applicable for matrix types. + assert(SrcTy->isFloatingPointTy() && DstTy->isFloatingPointTy() && + "Unknown real conversion"); + } + if (DstElementTy->getTypeID() < SrcElementTy->getTypeID()) + Res = Builder.CreateFPTrunc(Src, DstTy, "conv"); + else + Res = Builder.CreateFPExt(Src, DstTy, "conv"); + } + + return Res; +} + /// Emit a conversion from the specified type to the specified destination type, /// both of which are LLVM scalar types. Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType, @@ -1318,6 +1387,10 @@ return Builder.CreateVectorSplat(NumElements, Src, "splat"); } + if (SrcType->isMatrixType() && DstType->isMatrixType()) { + return EmitCastBetweenScalarTypes(Src, SrcType, DstType, Opts); + } + if (isa<llvm::VectorType>(SrcTy) || isa<llvm::VectorType>(DstTy)) { // Allow bitcast from vector to integer/fp of the same size. unsigned SrcSize = SrcTy->getPrimitiveSizeInBits(); @@ -1403,7 +1476,7 @@ Res = Builder.CreateFPToUI(Src, DstTy, "conv"); } else { assert(SrcTy->isFloatingPointTy() && DstTy->isFloatingPointTy() && - "Unknown real conversion"); + "Unknown real conversion"); if (DstTy->getTypeID() < SrcTy->getTypeID()) Res = Builder.CreateFPTrunc(Src, DstTy, "conv"); else @@ -1414,8 +1487,8 @@ if (CGF.getContext().getTargetInfo().useFP16ConversionIntrinsics()) { assert(ResTy->isIntegerTy(16) && "Only half FP requires extra conversion"); Res = Builder.CreateCall( - CGF.CGM.getIntrinsic(llvm::Intrinsic::convert_to_fp16, CGF.CGM.FloatTy), - Res); + CGF.CGM.getIntrinsic(llvm::Intrinsic::convert_to_fp16, CGF.CGM.FloatTy), + Res); } else { Res = Builder.CreateFPTrunc(Res, ResTy, "conv"); } @@ -2230,6 +2303,10 @@ CGF.EmitIgnoredExpr(E); return nullptr; } + case CK_MatrixCast: { + return EmitScalarConversion(Visit(E), E->getType(), DestTy, + CE->getExprLoc()); + } case CK_VectorSplat: { llvm::Type *DstTy = ConvertType(DestTy); Value *Elt = Visit(const_cast<Expr*>(E)); Index: clang/lib/CodeGen/CGExprConstant.cpp =================================================================== --- clang/lib/CodeGen/CGExprConstant.cpp +++ clang/lib/CodeGen/CGExprConstant.cpp @@ -1170,6 +1170,7 @@ case CK_FixedPointToIntegral: case CK_IntegralToFixedPoint: case CK_ZeroToOCLOpaqueType: + case CK_MatrixCast: return nullptr; } llvm_unreachable("Invalid CastKind"); Index: clang/lib/CodeGen/CGExprComplex.cpp =================================================================== --- clang/lib/CodeGen/CGExprComplex.cpp +++ clang/lib/CodeGen/CGExprComplex.cpp @@ -533,6 +533,7 @@ case CK_FixedPointToBoolean: case CK_FixedPointToIntegral: case CK_IntegralToFixedPoint: + case CK_MatrixCast: llvm_unreachable("invalid cast kind for complex value"); case CK_FloatingRealToComplex: Index: clang/lib/CodeGen/CGExprAgg.cpp =================================================================== --- clang/lib/CodeGen/CGExprAgg.cpp +++ clang/lib/CodeGen/CGExprAgg.cpp @@ -901,6 +901,7 @@ case CK_CopyAndAutoreleaseBlockObject: case CK_BuiltinFnToFnPtr: case CK_ZeroToOCLOpaqueType: + case CK_MatrixCast: case CK_IntToOCLSampler: case CK_FloatingToFixedPoint: @@ -1422,6 +1423,7 @@ case CK_PointerToIntegral: // Language extensions. case CK_VectorSplat: + case CK_MatrixCast: case CK_NonAtomicToAtomic: case CK_AtomicToNonAtomic: return true; Index: clang/lib/CodeGen/CGExpr.cpp =================================================================== --- clang/lib/CodeGen/CGExpr.cpp +++ clang/lib/CodeGen/CGExpr.cpp @@ -4645,6 +4645,7 @@ case CK_FixedPointToBoolean: case CK_FixedPointToIntegral: case CK_IntegralToFixedPoint: + case CK_MatrixCast: return EmitUnsupportedLValue(E, "unexpected cast lvalue"); case CK_Dependent: Index: clang/lib/AST/ExprConstant.cpp =================================================================== --- clang/lib/AST/ExprConstant.cpp +++ clang/lib/AST/ExprConstant.cpp @@ -13183,6 +13183,7 @@ case CK_FixedPointToFloating: case CK_FixedPointCast: case CK_IntegralToFixedPoint: + case CK_MatrixCast: llvm_unreachable("invalid cast kind for integral value"); case CK_BitCast: @@ -13923,6 +13924,7 @@ case CK_FixedPointToBoolean: case CK_FixedPointToIntegral: case CK_IntegralToFixedPoint: + case CK_MatrixCast: llvm_unreachable("invalid cast kind for complex value"); case CK_LValueToRValue: Index: clang/lib/AST/Expr.cpp =================================================================== --- clang/lib/AST/Expr.cpp +++ clang/lib/AST/Expr.cpp @@ -1708,6 +1708,7 @@ case CK_FixedPointCast: case CK_FixedPointToIntegral: case CK_IntegralToFixedPoint: + case CK_MatrixCast: assert(!getType()->isBooleanType() && "unheralded conversion to bool"); goto CheckNoBasePath; Index: clang/include/clang/Sema/Sema.h =================================================================== --- clang/include/clang/Sema/Sema.h +++ clang/include/clang/Sema/Sema.h @@ -11644,6 +11644,8 @@ bool isValidSveBitcast(QualType srcType, QualType destType); + bool areMatrixTypesOfTheSameDimension(QualType srcTy, QualType destTy); + bool areLaxCompatibleVectorTypes(QualType srcType, QualType destType); bool isLaxVectorConversion(QualType srcType, QualType destType); @@ -11702,6 +11704,13 @@ ExprResult checkUnknownAnyArg(SourceLocation callLoc, Expr *result, QualType ¶mType); + // CheckMatrixCast - Check type constraints for matrix casts. + // We allow casting between matrices of the same dimensions i.e. when they + // have the same number of rows and column. 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 @@ -8577,6 +8577,12 @@ let CategoryName = "Semantic Issue" in { +def err_invalid_conversion_between_matrixes : Error< + "conversion between matrix type%diff{ $ and $|}0,1 of different size is not allowed">; + +def err_invalid_conversion_between_matrix_and_type : Error< + "conversion between matrix type %0 and type %1 is not allowed">; + def err_invalid_conversion_between_vectors : Error< "invalid conversion between vector type%diff{ $ and $|}0,1 of different " "size">; Index: clang/include/clang/AST/OperationKinds.def =================================================================== --- clang/include/clang/AST/OperationKinds.def +++ clang/include/clang/AST/OperationKinds.def @@ -181,6 +181,9 @@ /// (void) malloc(2048) CAST_OPERATION(ToVoid) +/// CK_MatrixCast - A cast between matrix types of the same dimensions. +CAST_OPERATION(MatrixCast) + /// CK_VectorSplat - A conversion from an arithmetic type to a /// vector of that element type. Fills all elements ("splats") with /// the source value.
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits