aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/CodeGen/CGExprAgg.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/CodeGen/CGExprAgg.cpp')
-rw-r--r--clang/lib/CodeGen/CGExprAgg.cpp94
1 files changed, 93 insertions, 1 deletions
diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp
index 2ad6587..c3f1cbe 100644
--- a/clang/lib/CodeGen/CGExprAgg.cpp
+++ b/clang/lib/CodeGen/CGExprAgg.cpp
@@ -491,6 +491,79 @@ static bool isTrivialFiller(Expr *E) {
return false;
}
+// emit a flat cast where the RHS is a scalar, including vector
+static void EmitHLSLScalarFlatCast(CodeGenFunction &CGF, Address DestVal,
+ QualType DestTy, llvm::Value *SrcVal,
+ QualType SrcTy, SourceLocation Loc) {
+ // Flatten our destination
+ SmallVector<QualType, 16> DestTypes; // Flattened type
+ SmallVector<std::pair<Address, llvm::Value *>, 16> StoreGEPList;
+ // ^^ Flattened accesses to DestVal we want to store into
+ CGF.FlattenAccessAndType(DestVal, DestTy, StoreGEPList, DestTypes);
+
+ assert(SrcTy->isVectorType() && "HLSL Flat cast doesn't handle splatting.");
+ const VectorType *VT = SrcTy->getAs<VectorType>();
+ SrcTy = VT->getElementType();
+ assert(StoreGEPList.size() <= VT->getNumElements() &&
+ "Cannot perform HLSL flat cast when vector source \
+ object has less elements than flattened destination \
+ object.");
+ for (unsigned I = 0, Size = StoreGEPList.size(); I < Size; I++) {
+ llvm::Value *Load = CGF.Builder.CreateExtractElement(SrcVal, I, "vec.load");
+ llvm::Value *Cast =
+ CGF.EmitScalarConversion(Load, SrcTy, DestTypes[I], Loc);
+
+ // store back
+ llvm::Value *Idx = StoreGEPList[I].second;
+ if (Idx) {
+ llvm::Value *V =
+ CGF.Builder.CreateLoad(StoreGEPList[I].first, "load.for.insert");
+ Cast = CGF.Builder.CreateInsertElement(V, Cast, Idx);
+ }
+ CGF.Builder.CreateStore(Cast, StoreGEPList[I].first);
+ }
+ return;
+}
+
+// emit a flat cast where the RHS is an aggregate
+static void EmitHLSLElementwiseCast(CodeGenFunction &CGF, Address DestVal,
+ QualType DestTy, Address SrcVal,
+ QualType SrcTy, SourceLocation Loc) {
+ // Flatten our destination
+ SmallVector<QualType, 16> DestTypes; // Flattened type
+ SmallVector<std::pair<Address, llvm::Value *>, 16> StoreGEPList;
+ // ^^ Flattened accesses to DestVal we want to store into
+ CGF.FlattenAccessAndType(DestVal, DestTy, StoreGEPList, DestTypes);
+ // Flatten our src
+ SmallVector<QualType, 16> SrcTypes; // Flattened type
+ SmallVector<std::pair<Address, llvm::Value *>, 16> LoadGEPList;
+ // ^^ Flattened accesses to SrcVal we want to load from
+ CGF.FlattenAccessAndType(SrcVal, SrcTy, LoadGEPList, SrcTypes);
+
+ assert(StoreGEPList.size() <= LoadGEPList.size() &&
+ "Cannot perform HLSL flat cast when flattened source object \
+ has less elements than flattened destination object.");
+ // apply casts to what we load from LoadGEPList
+ // and store result in Dest
+ for (unsigned I = 0, E = StoreGEPList.size(); I < E; I++) {
+ llvm::Value *Idx = LoadGEPList[I].second;
+ llvm::Value *Load = CGF.Builder.CreateLoad(LoadGEPList[I].first, "load");
+ Load =
+ Idx ? CGF.Builder.CreateExtractElement(Load, Idx, "vec.extract") : Load;
+ llvm::Value *Cast =
+ CGF.EmitScalarConversion(Load, SrcTypes[I], DestTypes[I], Loc);
+
+ // store back
+ Idx = StoreGEPList[I].second;
+ if (Idx) {
+ llvm::Value *V =
+ CGF.Builder.CreateLoad(StoreGEPList[I].first, "load.for.insert");
+ Cast = CGF.Builder.CreateInsertElement(V, Cast, Idx);
+ }
+ CGF.Builder.CreateStore(Cast, StoreGEPList[I].first);
+ }
+}
+
/// Emit initialization of an array from an initializer list. ExprToVisit must
/// be either an InitListEpxr a CXXParenInitListExpr.
void AggExprEmitter::EmitArrayInit(Address DestPtr, llvm::ArrayType *AType,
@@ -890,7 +963,25 @@ void AggExprEmitter::VisitCastExpr(CastExpr *E) {
case CK_HLSLArrayRValue:
Visit(E->getSubExpr());
break;
-
+ case CK_HLSLElementwiseCast: {
+ Expr *Src = E->getSubExpr();
+ QualType SrcTy = Src->getType();
+ RValue RV = CGF.EmitAnyExpr(Src);
+ QualType DestTy = E->getType();
+ Address DestVal = Dest.getAddress();
+ SourceLocation Loc = E->getExprLoc();
+
+ if (RV.isScalar()) {
+ llvm::Value *SrcVal = RV.getScalarVal();
+ EmitHLSLScalarFlatCast(CGF, DestVal, DestTy, SrcVal, SrcTy, Loc);
+ } else {
+ assert(RV.isAggregate() &&
+ "Can't perform HLSL Aggregate cast on a complex type.");
+ Address SrcVal = RV.getAggregateAddress();
+ EmitHLSLElementwiseCast(CGF, DestVal, DestTy, SrcVal, SrcTy, Loc);
+ }
+ break;
+ }
case CK_NoOp:
case CK_UserDefinedConversion:
case CK_ConstructorConversion:
@@ -1461,6 +1552,7 @@ static bool castPreservesZero(const CastExpr *CE) {
case CK_NonAtomicToAtomic:
case CK_AtomicToNonAtomic:
case CK_HLSLVectorTruncation:
+ case CK_HLSLElementwiseCast:
return true;
case CK_BaseToDerivedMemberPointer: