@@ -491,6 +491,70 @@ static bool isTrivialFiller(Expr *E) {
491491 return false ;
492492}
493493
494+
495+
496+ // emit a flat cast where the RHS is a scalar, including vector
497+ static void EmitHLSLScalarFlatCast (CodeGenFunction &CGF, Address DestVal,
498+ QualType DestTy, llvm::Value *SrcVal,
499+ QualType SrcTy, SourceLocation Loc) {
500+ // Flatten our destination
501+ SmallVector<QualType> DestTypes; // Flattened type
502+ SmallVector<llvm::Value *, 4 > IdxList;
503+ SmallVector<std::pair<Address, llvm::Value *>, 16 > StoreGEPList;
504+ // ^^ Flattened accesses to DestVal we want to store into
505+ CGF.FlattenAccessAndType (DestVal, DestTy, IdxList, StoreGEPList,
506+ DestTypes);
507+
508+ if (const VectorType *VT = SrcTy->getAs <VectorType>()) {
509+ SrcTy = VT->getElementType ();
510+ assert (StoreGEPList.size () <= VT->getNumElements () &&
511+ " Cannot perform HLSL flat cast when vector source \
512+ object has less elements than flattened destination \
513+ object." );
514+ for (unsigned i = 0 ; i < StoreGEPList.size (); i ++) {
515+ llvm::Value *Load = CGF.Builder .CreateExtractElement (SrcVal, i,
516+ " vec.load" );
517+ llvm::Value *Cast = CGF.EmitScalarConversion (Load, SrcTy,
518+ DestTypes[i],
519+ Loc);
520+ CGF.PerformStore (StoreGEPList[i], Cast);
521+ }
522+ return ;
523+ }
524+ llvm_unreachable (" HLSL Flat cast doesn't handle splatting." );
525+ }
526+
527+ // emit a flat cast where the RHS is an aggregate
528+ static void EmitHLSLAggregateFlatCast (CodeGenFunction &CGF, Address DestVal,
529+ QualType DestTy, Address SrcVal,
530+ QualType SrcTy, SourceLocation Loc) {
531+ // Flatten our destination
532+ SmallVector<QualType> DestTypes; // Flattened type
533+ SmallVector<llvm::Value *, 4 > IdxList;
534+ SmallVector<std::pair<Address, llvm::Value *>, 16 > StoreGEPList;
535+ // ^^ Flattened accesses to DestVal we want to store into
536+ CGF.FlattenAccessAndType (DestVal, DestTy, IdxList, StoreGEPList,
537+ DestTypes);
538+ // Flatten our src
539+ SmallVector<QualType> SrcTypes; // Flattened type
540+ SmallVector<std::pair<Address, llvm::Value *>, 16 > LoadGEPList;
541+ // ^^ Flattened accesses to SrcVal we want to load from
542+ IdxList.clear ();
543+ CGF.FlattenAccessAndType (SrcVal, SrcTy, IdxList, LoadGEPList, SrcTypes);
544+
545+ assert (StoreGEPList.size () <= LoadGEPList.size () &&
546+ " Cannot perform HLSL flat cast when flattened source object \
547+ has less elements than flattened destination object." );
548+ // apply casts to what we load from LoadGEPList
549+ // and store result in Dest
550+ for (unsigned i = 0 ; i < StoreGEPList.size (); i ++) {
551+ llvm::Value *Load = CGF.PerformLoad (LoadGEPList[i]);
552+ llvm::Value *Cast = CGF.EmitScalarConversion (Load, SrcTypes[i],
553+ DestTypes[i], Loc);
554+ CGF.PerformStore (StoreGEPList[i], Cast);
555+ }
556+ }
557+
494558// / Emit initialization of an array from an initializer list. ExprToVisit must
495559// / be either an InitListEpxr a CXXParenInitListExpr.
496560void AggExprEmitter::EmitArrayInit (Address DestPtr, llvm::ArrayType *AType,
@@ -890,7 +954,24 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) {
890954 case CK_HLSLArrayRValue:
891955 Visit (E->getSubExpr ());
892956 break ;
893-
957+ case CK_HLSLAggregateCast: {
958+ Expr *Src = E->getSubExpr ();
959+ QualType SrcTy = Src->getType ();
960+ RValue RV = CGF.EmitAnyExpr (Src);
961+ QualType DestTy = E->getType ();
962+ Address DestVal = Dest.getAddress ();
963+ SourceLocation Loc = E->getExprLoc ();
964+
965+ if (RV.isScalar ()) {
966+ llvm::Value *SrcVal = RV.getScalarVal ();
967+ EmitHLSLScalarFlatCast (CGF, DestVal, DestTy, SrcVal, SrcTy, Loc);
968+ } else { // RHS is an aggregate
969+ assert (RV.isAggregate () &&
970+ " Can't perform HLSL Aggregate cast on a complex type." );
971+ Address SrcVal = RV.getAggregateAddress ();
972+ EmitHLSLAggregateFlatCast (CGF, DestVal, DestTy, SrcVal, SrcTy, Loc);
973+ }
974+ break ; }
894975 case CK_NoOp:
895976 case CK_UserDefinedConversion:
896977 case CK_ConstructorConversion:
0 commit comments