[clang] [HLSL] Add support for elementwise and aggregate splat casting struct types with bitfields (PR #161263)
Sarah Spall via cfe-commits
cfe-commits at lists.llvm.org
Wed Oct 1 09:55:58 PDT 2025
================
@@ -6784,74 +6784,104 @@ 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>
+void CodeGenFunction::FlattenAccessAndTypeLValue(
+ LValue Val, SmallVectorImpl<LValue> &AccessList) {
+
+ llvm::SmallVector<
+ std::tuple<LValue, 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)}});
+ WorkList.push_back({Val, Val.getType(), {llvm::ConstantInt::get(IdxTy, 0)}});
while (!WorkList.empty()) {
- auto [T, IdxList] = WorkList.pop_back_val();
+ auto [LVal, 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);
+ WorkList.push_back({LVal, CAT->getElementType(), IdxListCopy});
}
} else if (const auto *RT = dyn_cast<RecordType>(T)) {
const RecordDecl *Record = RT->getOriginalDecl()->getDefinitionOrSelf();
assert(!Record->isUnion() && "Union types not supported in flat cast.");
const CXXRecordDecl *CXXD = dyn_cast<CXXRecordDecl>(Record);
- llvm::SmallVector<QualType, 16> FieldTypes;
+ llvm::SmallVector<
+ std::tuple<LValue, QualType, llvm::SmallVector<llvm::Value *, 4>>, 16>
+ ReverseList;
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());
+ if (CXXD->getNumBases() > 0) {
+ assert(CXXD->getNumBases() == 1 &&
+ "HLSL doesn't support multiple inheritance.");
+ auto Base = CXXD->bases_begin();
+ llvm::SmallVector<llvm::Value *, 4> IdxListCopy = IdxList;
+ IdxListCopy.push_back(llvm::ConstantInt::get(
+ IdxTy, 0)); // base struct should be at index zero
+ ReverseList.insert(ReverseList.end(),
+ {LVal, Base->getType(), IdxListCopy});
+ }
}
- for (auto *FD : Record->fields())
- FieldTypes.push_back(FD->getType());
+ const CGRecordLayout &Layout = CGM.getTypes().getCGRecordLayout(Record);
- 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});
+ llvm::Type *LLVMT = ConvertTypeForMem(T);
+ CharUnits Align = getContext().getTypeAlignInChars(T);
+ LValue RLValue;
+ bool createdGEP = false;
+ for (auto *FD : Record->fields()) {
+ if (FD->isBitField()) {
+ if (FD->isUnnamedBitField())
+ continue;
+ if (!createdGEP) {
+ createdGEP = true;
+ Address GEP = Builder.CreateInBoundsGEP(LVal.getAddress(), IdxList,
+ LLVMT, Align, "gep");
----------------
spall wrote:
The gep should be skipped if it is a regular field and not a bitfield. EmitLValueForField should only be used if it is a bitfield and we need to construct a special LValue for it; this requires the GEP for the struct itself. Otherwise we wait as long as possible to generate the gep to access a 'scalar' field, because we want to generate as few geps as possible.
https://github.com/llvm/llvm-project/pull/161263
More information about the cfe-commits
mailing list