diff options
| author | Sarah Spall <sarahspall@microsoft.com> | 2025-02-06 14:38:01 -0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-02-06 14:38:01 -0800 |
| commit | 01072e546fd6243b889c6cfc109e9ad761e1b17c (patch) | |
| tree | c41cd0cd22a49fe9d135d98521e5b83d3cd411f7 /clang/lib/CodeGen/CGExpr.cpp | |
| parent | fe58eee60200c91b5b4131e9dc73a5e870b3cf4d (diff) | |
[HLSL] Implement HLSL Flat casting (excluding splat cases) (#118842)
Implement HLSLElementwiseCast excluding support for splat cases
Do not support casting types that contain bitfields.
Partly closes #100609 and partly closes #100619
Diffstat (limited to 'clang/lib/CodeGen/CGExpr.cpp')
| -rw-r--r-- | clang/lib/CodeGen/CGExpr.cpp | 73 |
1 files changed, 73 insertions, 0 deletions
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index bf8df2789f58..1e233c42c878 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -5338,6 +5338,7 @@ LValue CodeGenFunction::EmitCastLValue(const CastExpr *E) { case CK_MatrixCast: case CK_HLSLVectorTruncation: case CK_HLSLArrayRValue: + case CK_HLSLElementwiseCast: return EmitUnsupportedLValue(E, "unexpected cast lvalue"); case CK_Dependent: @@ -6376,3 +6377,75 @@ RValue CodeGenFunction::EmitPseudoObjectRValue(const PseudoObjectExpr *E, LValue CodeGenFunction::EmitPseudoObjectLValue(const PseudoObjectExpr *E) { return emitPseudoObjectExpr(*this, E, true, AggValueSlot::ignored()).LV; } + +void CodeGenFunction::FlattenAccessAndType( + Address Addr, QualType AddrType, + SmallVectorImpl<std::pair<Address, llvm::Value *>> &AccessList, + SmallVectorImpl<QualType> &FlatTypes) { + // WorkList is list of type we are processing + the Index List to access + // the field of that type in Addr for use in a GEP + llvm::SmallVector<std::pair<QualType, llvm::SmallVector<llvm::Value *, 4>>, + 16> + WorkList; + llvm::IntegerType *IdxTy = llvm::IntegerType::get(getLLVMContext(), 32); + // Addr should be a pointer so we need to 'dereference' it + WorkList.push_back({AddrType, {llvm::ConstantInt::get(IdxTy, 0)}}); + + while (!WorkList.empty()) { + auto [T, IdxList] = WorkList.pop_back_val(); + T = T.getCanonicalType().getUnqualifiedType(); + assert(!isa<MatrixType>(T) && "Matrix types not yet supported in HLSL"); + if (const auto *CAT = dyn_cast<ConstantArrayType>(T)) { + uint64_t Size = CAT->getZExtSize(); + for (int64_t I = Size - 1; I > -1; I--) { + llvm::SmallVector<llvm::Value *, 4> IdxListCopy = IdxList; + IdxListCopy.push_back(llvm::ConstantInt::get(IdxTy, I)); + WorkList.emplace_back(CAT->getElementType(), IdxListCopy); + } + } else if (const auto *RT = dyn_cast<RecordType>(T)) { + const RecordDecl *Record = RT->getDecl(); + assert(!Record->isUnion() && "Union types not supported in flat cast."); + + const CXXRecordDecl *CXXD = dyn_cast<CXXRecordDecl>(Record); + + llvm::SmallVector<QualType, 16> FieldTypes; + if (CXXD && CXXD->isStandardLayout()) + Record = CXXD->getStandardLayoutBaseWithFields(); + + // deal with potential base classes + if (CXXD && !CXXD->isStandardLayout()) { + for (auto &Base : CXXD->bases()) + FieldTypes.push_back(Base.getType()); + } + + for (auto *FD : Record->fields()) + FieldTypes.push_back(FD->getType()); + + for (int64_t I = FieldTypes.size() - 1; I > -1; I--) { + llvm::SmallVector<llvm::Value *, 4> IdxListCopy = IdxList; + IdxListCopy.push_back(llvm::ConstantInt::get(IdxTy, I)); + WorkList.insert(WorkList.end(), {FieldTypes[I], IdxListCopy}); + } + } else if (const auto *VT = dyn_cast<VectorType>(T)) { + llvm::Type *LLVMT = ConvertTypeForMem(T); + CharUnits Align = getContext().getTypeAlignInChars(T); + Address GEP = + Builder.CreateInBoundsGEP(Addr, IdxList, LLVMT, Align, "vector.gep"); + for (unsigned I = 0, E = VT->getNumElements(); I < E; I++) { + llvm::Value *Idx = llvm::ConstantInt::get(IdxTy, I); + // gep on vector fields is not recommended so combine gep with + // extract/insert + AccessList.emplace_back(GEP, Idx); + FlatTypes.push_back(VT->getElementType()); + } + } else { + // a scalar/builtin type + llvm::Type *LLVMT = ConvertTypeForMem(T); + CharUnits Align = getContext().getTypeAlignInChars(T); + Address GEP = + Builder.CreateInBoundsGEP(Addr, IdxList, LLVMT, Align, "gep"); + AccessList.emplace_back(GEP, nullptr); + FlatTypes.push_back(T); + } + } +} |
