Skip to content

Commit 99ed882

Browse files
authored
[HLSL] Wrap offset info into a dedicated type. NFC (#167396)
Rather than using a nullable SmallVector, use a wrapper class for offset info. This simplifies places that need to handle whether or not there's any offset information.
1 parent 5b72096 commit 99ed882

File tree

7 files changed

+88
-64
lines changed

7 files changed

+88
-64
lines changed

clang/lib/CodeGen/CGHLSLRuntime.cpp

Lines changed: 16 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -261,12 +261,12 @@ static std::optional<llvm::Value *> initializeLocalResourceArray(
261261

262262
llvm::Type *
263263
CGHLSLRuntime::convertHLSLSpecificType(const Type *T,
264-
SmallVector<int32_t> *Packoffsets) {
264+
const CGHLSLOffsetInfo &OffsetInfo) {
265265
assert(T->isHLSLSpecificType() && "Not an HLSL specific type!");
266266

267267
// Check if the target has a specific translation for this type first.
268268
if (llvm::Type *TargetTy =
269-
CGM.getTargetCodeGenInfo().getHLSLType(CGM, T, Packoffsets))
269+
CGM.getTargetCodeGenInfo().getHLSLType(CGM, T, OffsetInfo))
270270
return TargetTy;
271271

272272
llvm_unreachable("Generic handling of HLSL types is not supported.");
@@ -357,25 +357,14 @@ createBufferHandleType(const HLSLBufferDecl *BufDecl) {
357357
return cast<HLSLAttributedResourceType>(QT.getTypePtr());
358358
}
359359

360-
// Iterates over all declarations in the HLSL buffer and based on the
361-
// packoffset or register(c#) annotations it fills outs the Layout
362-
// vector with the user-specified layout offsets.
363-
// The buffer offsets can be specified 2 ways:
364-
// 1. declarations in cbuffer {} block can have a packoffset annotation
365-
// (translates to HLSLPackOffsetAttr)
366-
// 2. default constant buffer declarations at global scope can have
367-
// register(c#) annotations (translates to HLSLResourceBindingAttr with
368-
// RegisterType::C)
369-
// It is not guaranteed that all declarations in a buffer have an annotation.
370-
// For those where it is not specified a -1 value is added to the Layout
371-
// vector. In the final layout these declarations will be placed at the end
372-
// of the HLSL buffer after all of the elements with specified offset.
373-
static void fillPackoffsetLayout(const HLSLBufferDecl *BufDecl,
374-
SmallVector<int32_t> &Layout) {
375-
assert(Layout.empty() && "expected empty vector for layout");
376-
assert(BufDecl->hasValidPackoffset());
360+
CGHLSLOffsetInfo CGHLSLOffsetInfo::fromDecl(const HLSLBufferDecl &BufDecl) {
361+
CGHLSLOffsetInfo Result;
377362

378-
for (Decl *D : BufDecl->buffer_decls()) {
363+
// If we don't have packoffset info, just return an empty result.
364+
if (!BufDecl.hasValidPackoffset())
365+
return Result;
366+
367+
for (Decl *D : BufDecl.buffer_decls()) {
379368
if (isa<CXXRecordDecl, EmptyDecl>(D) || isa<FunctionDecl>(D)) {
380369
continue;
381370
}
@@ -384,11 +373,11 @@ static void fillPackoffsetLayout(const HLSLBufferDecl *BufDecl,
384373
continue;
385374

386375
if (!VD->hasAttrs()) {
387-
Layout.push_back(-1);
376+
Result.Offsets.push_back(Unspecified);
388377
continue;
389378
}
390379

391-
int32_t Offset = -1;
380+
uint32_t Offset = Unspecified;
392381
for (auto *Attr : VD->getAttrs()) {
393382
if (auto *POA = dyn_cast<HLSLPackOffsetAttr>(Attr)) {
394383
Offset = POA->getOffsetInBytes();
@@ -401,8 +390,9 @@ static void fillPackoffsetLayout(const HLSLBufferDecl *BufDecl,
401390
break;
402391
}
403392
}
404-
Layout.push_back(Offset);
393+
Result.Offsets.push_back(Offset);
405394
}
395+
return Result;
406396
}
407397

408398
// Codegen for HLSLBufferDecl
@@ -419,13 +409,9 @@ void CGHLSLRuntime::addBuffer(const HLSLBufferDecl *BufDecl) {
419409
return;
420410

421411
// create global variable for the constant buffer
422-
SmallVector<int32_t> Layout;
423-
if (BufDecl->hasValidPackoffset())
424-
fillPackoffsetLayout(BufDecl, Layout);
425-
426-
llvm::TargetExtType *TargetTy =
427-
cast<llvm::TargetExtType>(convertHLSLSpecificType(
428-
ResHandleTy, BufDecl->hasValidPackoffset() ? &Layout : nullptr));
412+
CGHLSLOffsetInfo OffsetInfo = CGHLSLOffsetInfo::fromDecl(*BufDecl);
413+
llvm::TargetExtType *TargetTy = cast<llvm::TargetExtType>(
414+
convertHLSLSpecificType(ResHandleTy, OffsetInfo));
429415
llvm::GlobalVariable *BufGV = new GlobalVariable(
430416
TargetTy, /*isConstant*/ false,
431417
GlobalValue::LinkageTypes::ExternalLinkage, PoisonValue::get(TargetTy),

clang/lib/CodeGen/CGHLSLRuntime.h

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,33 @@ class CodeGenModule;
8181
class CodeGenFunction;
8282
class LValue;
8383

84+
class CGHLSLOffsetInfo {
85+
SmallVector<uint32_t> Offsets;
86+
87+
public:
88+
static const uint32_t Unspecified = ~0U;
89+
90+
/// Iterates over all declarations in the HLSL buffer and based on the
91+
/// packoffset or register(c#) annotations it fills outs the Offsets vector
92+
/// with the user-specified layout offsets. The buffer offsets can be
93+
/// specified 2 ways: 1. declarations in cbuffer {} block can have a
94+
/// packoffset annotation (translates to HLSLPackOffsetAttr) 2. default
95+
/// constant buffer declarations at global scope can have register(c#)
96+
/// annotations (translates to HLSLResourceBindingAttr with RegisterType::C)
97+
/// It is not guaranteed that all declarations in a buffer have an annotation.
98+
/// For those where it is not specified a `~0U` value is added to the Offsets
99+
/// vector. In the final layout these declarations will be placed at the end
100+
/// of the HLSL buffer after all of the elements with specified offset.
101+
static CGHLSLOffsetInfo fromDecl(const HLSLBufferDecl &BufDecl);
102+
103+
/// Get the given offset, or `~0U` if there is no offset for the member.
104+
uint32_t operator[](size_t I) const {
105+
if (Offsets.empty())
106+
return Unspecified;
107+
return Offsets[I];
108+
}
109+
};
110+
84111
class CGHLSLRuntime {
85112
public:
86113
//===----------------------------------------------------------------------===//
@@ -167,9 +194,11 @@ class CGHLSLRuntime {
167194
CGHLSLRuntime(CodeGenModule &CGM) : CGM(CGM) {}
168195
virtual ~CGHLSLRuntime() {}
169196

170-
llvm::Type *
171-
convertHLSLSpecificType(const Type *T,
172-
SmallVector<int32_t> *Packoffsets = nullptr);
197+
llvm::Type *convertHLSLSpecificType(const Type *T,
198+
const CGHLSLOffsetInfo &OffsetInfo);
199+
llvm::Type *convertHLSLSpecificType(const Type *T) {
200+
return convertHLSLSpecificType(T, CGHLSLOffsetInfo());
201+
}
173202

174203
void generateGlobalCtorDtorCalls();
175204

clang/lib/CodeGen/HLSLBufferLayoutBuilder.cpp

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,9 @@ namespace CodeGen {
6666
// annotation though. For those that don't, the PackOffsets array will contain
6767
// -1 value instead. These elements must be placed at the end of the layout
6868
// after all of the elements with specific offset.
69-
llvm::TargetExtType *HLSLBufferLayoutBuilder::createLayoutType(
70-
const RecordType *RT, const llvm::SmallVector<int32_t> *PackOffsets) {
69+
llvm::TargetExtType *
70+
HLSLBufferLayoutBuilder::createLayoutType(const RecordType *RT,
71+
const CGHLSLOffsetInfo &OffsetInfo) {
7172

7273
// check if we already have the layout type for this struct
7374
if (llvm::TargetExtType *Ty =
@@ -101,14 +102,10 @@ llvm::TargetExtType *HLSLBufferLayoutBuilder::createLayoutType(
101102
const CXXRecordDecl *RD = RecordDecls.pop_back_val();
102103

103104
for (const auto *FD : RD->fields()) {
104-
assert((!PackOffsets || Index < PackOffsets->size()) &&
105-
"number of elements in layout struct does not match number of "
106-
"packoffset annotations");
107-
108105
// No PackOffset info at all, or have a valid packoffset/register(c#)
109106
// annotations value -> layout the field.
110-
const int PO = PackOffsets ? (*PackOffsets)[Index++] : -1;
111-
if (!PackOffsets || PO != -1) {
107+
const uint32_t PO = OffsetInfo[Index++];
108+
if (PO != CGHLSLOffsetInfo::Unspecified) {
112109
if (!layoutField(FD, EndOffset, FieldOffset, FieldType, PO))
113110
return nullptr;
114111
Layout.push_back(FieldOffset);
@@ -175,7 +172,7 @@ bool HLSLBufferLayoutBuilder::layoutField(const FieldDecl *FD,
175172
unsigned &EndOffset,
176173
unsigned &FieldOffset,
177174
llvm::Type *&FieldType,
178-
int Packoffset) {
175+
uint32_t Packoffset) {
179176

180177
// Size of element; for arrays this is a size of a single element in the
181178
// array. Total array size of calculated as (ArrayCount-1) * ArrayStride +
@@ -201,8 +198,9 @@ bool HLSLBufferLayoutBuilder::layoutField(const FieldDecl *FD,
201198
// For array of structures, create a new array with a layout type
202199
// instead of the structure type.
203200
if (Ty->isStructureOrClassType()) {
201+
CGHLSLOffsetInfo EmptyOffsets;
204202
llvm::Type *NewTy = cast<llvm::TargetExtType>(
205-
createLayoutType(Ty->getAsCanonical<RecordType>()));
203+
createLayoutType(Ty->getAsCanonical<RecordType>(), EmptyOffsets));
206204
if (!NewTy)
207205
return false;
208206
assert(isa<llvm::TargetExtType>(NewTy) && "expected target type");
@@ -216,17 +214,20 @@ bool HLSLBufferLayoutBuilder::layoutField(const FieldDecl *FD,
216214
ElemLayoutTy = CGM.getTypes().ConvertTypeForMem(FieldTy);
217215
}
218216
ArrayStride = llvm::alignTo(ElemSize, CBufferRowSizeInBytes);
219-
ElemOffset = (Packoffset != -1) ? Packoffset : NextRowOffset;
217+
ElemOffset = (Packoffset != CGHLSLOffsetInfo::Unspecified) ? Packoffset
218+
: NextRowOffset;
220219

221220
} else if (FieldTy->isStructureOrClassType()) {
222221
// Create a layout type for the structure
222+
CGHLSLOffsetInfo EmptyOffsets;
223223
ElemLayoutTy = createLayoutType(
224-
cast<RecordType>(FieldTy->getAsCanonical<RecordType>()));
224+
cast<RecordType>(FieldTy->getAsCanonical<RecordType>()), EmptyOffsets);
225225
if (!ElemLayoutTy)
226226
return false;
227227
assert(isa<llvm::TargetExtType>(ElemLayoutTy) && "expected target type");
228228
ElemSize = cast<llvm::TargetExtType>(ElemLayoutTy)->getIntParameter(0);
229-
ElemOffset = (Packoffset != -1) ? Packoffset : NextRowOffset;
229+
ElemOffset = (Packoffset != CGHLSLOffsetInfo::Unspecified) ? Packoffset
230+
: NextRowOffset;
230231

231232
} else {
232233
// scalar or vector - find element size and alignment
@@ -246,7 +247,7 @@ bool HLSLBufferLayoutBuilder::layoutField(const FieldDecl *FD,
246247
}
247248

248249
// calculate or get element offset for the vector or scalar
249-
if (Packoffset != -1) {
250+
if (Packoffset != CGHLSLOffsetInfo::Unspecified) {
250251
ElemOffset = Packoffset;
251252
} else {
252253
ElemOffset = llvm::alignTo(EndOffset, Align);
@@ -269,5 +270,13 @@ bool HLSLBufferLayoutBuilder::layoutField(const FieldDecl *FD,
269270
return true;
270271
}
271272

273+
bool HLSLBufferLayoutBuilder::layoutField(const FieldDecl *FD,
274+
unsigned &EndOffset,
275+
unsigned &FieldOffset,
276+
llvm::Type *&FieldType) {
277+
return layoutField(FD, EndOffset, FieldOffset, FieldType,
278+
CGHLSLOffsetInfo::Unspecified);
279+
}
280+
272281
} // namespace CodeGen
273282
} // namespace clang

clang/lib/CodeGen/HLSLBufferLayoutBuilder.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ class RecordType;
1414
class FieldDecl;
1515

1616
namespace CodeGen {
17+
class CGHLSLOffsetInfo;
1718
class CodeGenModule;
1819

1920
//===----------------------------------------------------------------------===//
@@ -33,14 +34,15 @@ class HLSLBufferLayoutBuilder {
3334
// Returns LLVM target extension type with the name LayoutTypeName
3435
// for given structure type and layout data. The first number in
3536
// the Layout is the size followed by offsets for each struct element.
36-
llvm::TargetExtType *
37-
createLayoutType(const RecordType *StructType,
38-
const llvm::SmallVector<int32_t> *Packoffsets = nullptr);
37+
llvm::TargetExtType *createLayoutType(const RecordType *StructType,
38+
const CGHLSLOffsetInfo &OffsetInfo);
3939

4040
private:
4141
bool layoutField(const clang::FieldDecl *FD, unsigned &EndOffset,
4242
unsigned &FieldOffset, llvm::Type *&FieldType,
43-
int Packoffset = -1);
43+
uint32_t Packoffset);
44+
bool layoutField(const clang::FieldDecl *FD, unsigned &EndOffset,
45+
unsigned &FieldOffset, llvm::Type *&FieldType);
4446
};
4547

4648
} // namespace CodeGen

clang/lib/CodeGen/TargetInfo.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ class ABIInfo;
3939
class CallArgList;
4040
class CodeGenFunction;
4141
class CGBlockInfo;
42+
class CGHLSLOffsetInfo;
4243
class SwiftABIInfo;
4344

4445
/// TargetCodeGenInfo - This class organizes various target-specific
@@ -442,9 +443,8 @@ class TargetCodeGenInfo {
442443
}
443444

444445
/// Return an LLVM type that corresponds to a HLSL type
445-
virtual llvm::Type *
446-
getHLSLType(CodeGenModule &CGM, const Type *T,
447-
const SmallVector<int32_t> *Packoffsets = nullptr) const {
446+
virtual llvm::Type *getHLSLType(CodeGenModule &CGM, const Type *T,
447+
const CGHLSLOffsetInfo &OffsetInfo) const {
448448
return nullptr;
449449
}
450450

clang/lib/CodeGen/Targets/DirectX.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,13 @@ class DirectXTargetCodeGenInfo : public TargetCodeGenInfo {
2929
DirectXTargetCodeGenInfo(CodeGen::CodeGenTypes &CGT)
3030
: TargetCodeGenInfo(std::make_unique<DefaultABIInfo>(CGT)) {}
3131

32-
llvm::Type *
33-
getHLSLType(CodeGenModule &CGM, const Type *T,
34-
const SmallVector<int32_t> *Packoffsets = nullptr) const override;
32+
llvm::Type *getHLSLType(CodeGenModule &CGM, const Type *T,
33+
const CGHLSLOffsetInfo &OffsetInfo) const override;
3534
};
3635

3736
llvm::Type *DirectXTargetCodeGenInfo::getHLSLType(
3837
CodeGenModule &CGM, const Type *Ty,
39-
const SmallVector<int32_t> *Packoffsets) const {
38+
const CGHLSLOffsetInfo &OffsetInfo) const {
4039
auto *ResType = dyn_cast<HLSLAttributedResourceType>(Ty);
4140
if (!ResType)
4241
return nullptr;
@@ -78,7 +77,7 @@ llvm::Type *DirectXTargetCodeGenInfo::getHLSLType(
7877
llvm::Type *BufferLayoutTy =
7978
HLSLBufferLayoutBuilder(CGM, "dx.Layout")
8079
.createLayoutType(ContainedTy->castAsCanonical<RecordType>(),
81-
Packoffsets);
80+
OffsetInfo);
8281
if (!BufferLayoutTy)
8382
return nullptr;
8483

clang/lib/CodeGen/Targets/SPIR.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,8 @@ class CommonSPIRTargetCodeGenInfo : public TargetCodeGenInfo {
5353

5454
unsigned getDeviceKernelCallingConv() const override;
5555
llvm::Type *getOpenCLType(CodeGenModule &CGM, const Type *T) const override;
56-
llvm::Type *
57-
getHLSLType(CodeGenModule &CGM, const Type *Ty,
58-
const SmallVector<int32_t> *Packoffsets = nullptr) const override;
56+
llvm::Type *getHLSLType(CodeGenModule &CGM, const Type *Ty,
57+
const CGHLSLOffsetInfo &OffsetInfo) const override;
5958
llvm::Type *getSPIRVImageTypeFromHLSLResource(
6059
const HLSLAttributedResourceType::Attributes &attributes,
6160
QualType SampledType, CodeGenModule &CGM) const;
@@ -518,7 +517,7 @@ static llvm::Type *getInlineSpirvType(CodeGenModule &CGM,
518517

519518
llvm::Type *CommonSPIRTargetCodeGenInfo::getHLSLType(
520519
CodeGenModule &CGM, const Type *Ty,
521-
const SmallVector<int32_t> *Packoffsets) const {
520+
const CGHLSLOffsetInfo &OffsetInfo) const {
522521
llvm::LLVMContext &Ctx = CGM.getLLVMContext();
523522

524523
if (auto *SpirvType = dyn_cast<HLSLInlineSpirvType>(Ty))
@@ -567,7 +566,7 @@ llvm::Type *CommonSPIRTargetCodeGenInfo::getHLSLType(
567566
llvm::Type *BufferLayoutTy =
568567
HLSLBufferLayoutBuilder(CGM, "spirv.Layout")
569568
.createLayoutType(ContainedTy->castAsCanonical<RecordType>(),
570-
Packoffsets);
569+
OffsetInfo);
571570
uint32_t StorageClass = /* Uniform storage class */ 2;
572571
return llvm::TargetExtType::get(Ctx, "spirv.VulkanBuffer", {BufferLayoutTy},
573572
{StorageClass, false});

0 commit comments

Comments
 (0)