Skip to content

Commit 749e88e

Browse files
committed
cleanup, update comments
1 parent 56beb45 commit 749e88e

File tree

4 files changed

+100
-95
lines changed

4 files changed

+100
-95
lines changed

clang/lib/CodeGen/CGHLSLRuntime.cpp

Lines changed: 97 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,7 @@ static bool isResourceRecordType(const clang::Type *Ty) {
8989
return HLSLAttributedResourceType::findHandleTypeOnResource(Ty) != nullptr;
9090
}
9191

92-
// Returns true if the type is an HLSL resource class or an array of
93-
// HLSL resource classes
92+
// Returns true if the type is an HLSL resource class or an array of them
9493
static bool isResourceRecordTypeOrArrayOf(const clang::Type *Ty) {
9594
while (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(Ty))
9695
Ty = CAT->getArrayElementTypeNoTypeQual();
@@ -113,48 +112,56 @@ static unsigned getScalarOrVectorSize(llvm::Type *Ty) {
113112
return Ty->getScalarSizeInBits() / 8;
114113
}
115114

115+
// Returns size of a struct in constant buffer layout. The sizes are cached
116+
// in StructSizesForBuffer map. The map is also an indicator if a layout
117+
// metadata for this struct has been added to the module.
118+
// If the struct type is not in the map, this method will calculate the struct
119+
// layout, add a metadata node describing it to the module, and add the struct
120+
// size to the map.
116121
size_t
117122
CGHLSLRuntime::getOrCalculateStructSizeForBuffer(llvm::StructType *StructTy) {
118-
assert(StructTy->isStructTy());
119-
120123
// check if we already have a side for this struct
121124
auto SizeIt = StructSizesForBuffer.find(StructTy);
122125
if (SizeIt != StructSizesForBuffer.end())
123126
return SizeIt->getSecond();
124127

125-
// if not, calculate the struct layout and add it to metadata
128+
// if not, calculate the struct layout and create a metadata node
126129
LLVMContext &Ctx = CGM.getLLVMContext();
127130
SmallVector<llvm::Metadata *> LayoutItems;
131+
132+
// start metadata list with a struct name and reserve one slot for its size
128133
LayoutItems.push_back(MDString::get(Ctx, StructTy->getName()));
134+
LayoutItems.push_back(nullptr);
129135

136+
// add element offsets
130137
size_t StructSize = 0;
131-
LayoutItems.push_back(nullptr); // reserve one slot for the buffer size
132-
133138
for (llvm::Type *ElTy : StructTy->elements()) {
134139
size_t Offset = calculateBufferElementOffset(ElTy, &StructSize);
135-
// create metadata constant with the element start offset
136140
LayoutItems.push_back(getConstIntMetadata(CGM.getLLVMContext(), Offset));
137141
}
138-
139-
// set the size of the buffer
142+
// set the size of the buffer to the reserved slot
140143
LayoutItems[1] = getConstIntMetadata(Ctx, StructSize);
141144

142-
// add the struct layout info to metadata
143-
MDNode *LayoutMDNode = MDNode::get(CGM.getLLVMContext(), LayoutItems);
145+
// add the struct layout to metadata
144146
CGM.getModule()
145147
.getOrInsertNamedMetadata("hlsl.cblayouts")
146-
->addOperand(LayoutMDNode);
148+
->addOperand(MDNode::get(CGM.getLLVMContext(), LayoutItems));
147149

148150
// add struct size to list and return it
149151
StructSizesForBuffer[StructTy] = StructSize;
150152
return StructSize;
151153
}
152154

155+
// Calculates offset of a single element in constant buffer layout.
156+
// The provided LayoutEndOffset marks the end of the layout so far (end offset
157+
// of the buffer or struct). After the element offset calculations are done it
158+
// will be updated the new end of layout value.
159+
// If the PackoffsetAttrs is not nullptr the offset will be based on the
160+
// packoffset annotation.
153161
size_t CGHLSLRuntime::calculateBufferElementOffset(
154162
llvm::Type *LayoutTy, size_t *LayoutEndOffset,
155163
HLSLPackOffsetAttr *PackoffsetAttr) {
156164

157-
// calculate element offset and size
158165
size_t ElemOffset = 0;
159166
size_t ElemSize = 0;
160167
size_t ArrayCount = 1;
@@ -198,117 +205,122 @@ size_t CGHLSLRuntime::calculateBufferElementOffset(
198205
ElemOffset = PackoffsetAttr->getOffsetInBytes();
199206
} else {
200207
ElemOffset = llvm::alignTo(EndOffset, Align);
208+
// if the element does not fit, move it to the next row
201209
if (ElemOffset + ElemSize > NextRowOffset)
202210
ElemOffset = NextRowOffset;
203211
}
204212
}
205213

206214
// Update end offset of the buffer/struct layout; do not update it if
207-
// the provided EndOffset is already bigger than the new one (which may happen
208-
// with packoffset annotations)
215+
// the provided EndOffset is already bigger than the new one value
216+
// (which may happen with packoffset annotations)
209217
unsigned NewEndOffset =
210218
ElemOffset + (ArrayCount - 1) * ArrayStride + ElemSize;
211219
*LayoutEndOffset = std::max<size_t>(EndOffset, NewEndOffset);
212220

213221
return ElemOffset;
214222
}
215223

224+
// Emits constant global variables for buffer declarations, creates metadata
225+
// linking the constant globals with the buffer. Also calculates the buffer
226+
// layout and creates metadata node describing it.
216227
void CGHLSLRuntime::emitBufferGlobalsAndMetadata(const HLSLBufferDecl *BufDecl,
217228
llvm::GlobalVariable *BufGV) {
229+
LLVMContext &Ctx = CGM.getLLVMContext();
218230
llvm::StructType *LayoutStruct = cast<llvm::StructType>(
219231
cast<llvm::TargetExtType>(BufGV->getValueType())->getTypeParameter(0));
220232

221-
LLVMContext &Ctx = CGM.getLLVMContext();
222-
233+
// Start metadata list associating the buffer global variable with its
234+
// constatns
223235
SmallVector<llvm::Metadata *> BufGlobals;
224236
BufGlobals.push_back(ValueAsMetadata::get(BufGV));
225237

238+
// Start layout metadata list with a struct name and reserve one slot for
239+
// the buffer size
226240
SmallVector<llvm::Metadata *> LayoutItems;
227241
LayoutItems.push_back(MDString::get(Ctx, LayoutStruct->getName()));
242+
LayoutItems.push_back(nullptr);
228243

229244
size_t BufferSize = 0;
230-
size_t BufferSizeIndex = LayoutItems.size();
231-
LayoutItems.push_back(nullptr); // reserve one slot for the buffer size
232-
233245
bool UsePackoffset = BufDecl->hasPackoffset();
234-
235246
const auto *ElemIt = LayoutStruct->element_begin();
236247
for (Decl *D : BufDecl->decls()) {
237248
if (isa<CXXRecordDecl, EmptyDecl>(D))
238249
// Nothing to do for this declaration.
239250
continue;
240251
if (isa<FunctionDecl>(D)) {
241-
// A function within an cbuffer is effectively a top-level function,
242-
// as it only refers to globally scoped declarations.
252+
// A function within an cbuffer is effectively a top-level function.
243253
CGM.EmitTopLevelDecl(D);
244254
continue;
245255
}
246-
if (VarDecl *VD = dyn_cast<VarDecl>(D)) {
247-
QualType VDTy = VD->getType();
248-
if (VDTy.getAddressSpace() != LangAS::hlsl_constant) {
249-
if (VD->getStorageClass() == SC_Static ||
250-
isResourceRecordTypeOrArrayOf(VDTy.getTypePtr())) {
251-
// Emit static variables and resource classes inside cbuffer as
252-
// regular globals
253-
CGM.EmitGlobal(VD);
254-
}
255-
// Anything else that is not in the hlsl_constant address space must be
256-
// an empty struct or a zero-sized array and can be ignored
257-
continue;
258-
}
256+
VarDecl *VD = dyn_cast<VarDecl>(D);
257+
if (!VD)
258+
continue;
259259

260-
assert(ElemIt != LayoutStruct->element_end() &&
261-
"number of elements in layout struct does not match");
262-
llvm::Type *LayoutType = *ElemIt++;
263-
264-
assert((CGM.getTypes().ConvertTypeForMem(VDTy) == LayoutType ||
265-
(LayoutType->isStructTy() &&
266-
cast<llvm::StructType>(LayoutType)
267-
->getName()
268-
.starts_with(("struct.__cblayout_" +
269-
VDTy->getAsCXXRecordDecl()->getName())
270-
.str()))) &&
271-
"layout type does not match the converted element type");
272-
273-
// handle any resources declarations inside the struct
274-
if (VDTy->isStructureType() && VDTy->isHLSLIntangibleType())
275-
// FIXME: handle resources in cbuffer structs
276-
llvm_unreachable("resources in cbuffer are not supported yet");
277-
278-
GlobalVariable *ElemGV =
279-
cast<GlobalVariable>(CGM.GetAddrOfGlobalVar(VD, LayoutType));
280-
BufGlobals.push_back(ValueAsMetadata::get(ElemGV));
281-
282-
assert(((UsePackoffset && VD->hasAttr<HLSLPackOffsetAttr>()) ||
283-
!UsePackoffset) &&
284-
"expected packoffset attribute on every declaration");
285-
286-
size_t Offset = calculateBufferElementOffset(
287-
LayoutType, &BufferSize,
288-
UsePackoffset ? VD->getAttr<HLSLPackOffsetAttr>() : nullptr);
289-
290-
// create metadata constant with the element start offset
291-
LayoutItems.push_back(getConstIntMetadata(CGM.getLLVMContext(), Offset));
260+
QualType VDTy = VD->getType();
261+
if (VDTy.getAddressSpace() != LangAS::hlsl_constant) {
262+
if (VD->getStorageClass() == SC_Static ||
263+
VDTy.getAddressSpace() == LangAS::hlsl_groupshared ||
264+
isResourceRecordTypeOrArrayOf(VDTy.getTypePtr())) {
265+
// Emit static and groupshared variables and resource classes inside
266+
// cbuffer as regular globals
267+
CGM.EmitGlobal(VD);
268+
}
269+
// Anything else that is not in the hlsl_constant address space must be
270+
// an empty struct or a zero-sized array and can be ignored
271+
continue;
292272
}
273+
274+
assert(ElemIt != LayoutStruct->element_end() &&
275+
"number of elements in layout struct does not match");
276+
llvm::Type *LayoutType = *ElemIt++;
277+
278+
// Make sure the type of the VarDecl type matches the type of the layout
279+
// struct element, or that it is a layout struct with the same name
280+
assert((CGM.getTypes().ConvertTypeForMem(VDTy) == LayoutType ||
281+
(LayoutType->isStructTy() &&
282+
cast<llvm::StructType>(LayoutType)
283+
->getName()
284+
.starts_with(("struct.__cblayout_" +
285+
VDTy->getAsCXXRecordDecl()->getName())
286+
.str()))) &&
287+
"layout type does not match the converted element type");
288+
289+
// there might be resources inside the used defined structs
290+
if (VDTy->isStructureType() && VDTy->isHLSLIntangibleType())
291+
// FIXME: handle resources in cbuffer structs
292+
llvm_unreachable("resources in cbuffer are not supported yet");
293+
294+
// create global variable for the constant and to metadata list
295+
GlobalVariable *ElemGV =
296+
cast<GlobalVariable>(CGM.GetAddrOfGlobalVar(VD, LayoutType));
297+
BufGlobals.push_back(ValueAsMetadata::get(ElemGV));
298+
299+
// get offset of the global and and to metadata list
300+
assert(((UsePackoffset && VD->hasAttr<HLSLPackOffsetAttr>()) ||
301+
!UsePackoffset) &&
302+
"expected packoffset attribute on every declaration");
303+
size_t Offset = calculateBufferElementOffset(
304+
LayoutType, &BufferSize,
305+
UsePackoffset ? VD->getAttr<HLSLPackOffsetAttr>() : nullptr);
306+
LayoutItems.push_back(getConstIntMetadata(Ctx, Offset));
293307
}
294308
assert(ElemIt == LayoutStruct->element_end() &&
295309
"number of elements in layout struct does not match");
296-
297-
// add buffer global and a list of its constants to metadata
298-
MDNode *BufMDNode = MDNode::get(CGM.getLLVMContext(), BufGlobals);
299-
CGM.getModule().getOrInsertNamedMetadata("hlsl.cbs")->addOperand(BufMDNode);
300-
301310
// set the size of the buffer
302-
LayoutItems[BufferSizeIndex] = getConstIntMetadata(Ctx, BufferSize);
311+
LayoutItems[1] = getConstIntMetadata(Ctx, BufferSize);
312+
313+
// add buffer metadata to the module
314+
CGM.getModule()
315+
.getOrInsertNamedMetadata("hlsl.cbs")
316+
->addOperand(MDNode::get(Ctx, BufGlobals));
303317

304-
// add buffer layout to metadata
305-
MDNode *LayoutMDNode = MDNode::get(CGM.getLLVMContext(), LayoutItems);
306318
CGM.getModule()
307319
.getOrInsertNamedMetadata("hlsl.cblayouts")
308-
->addOperand(LayoutMDNode);
320+
->addOperand(MDNode::get(Ctx, LayoutItems));
309321
}
310322

311-
// Creates resource handle type for the HLSL buffer
323+
// Creates resource handle type for the HLSL buffer declaration
312324
static const clang::HLSLAttributedResourceType *
313325
createBufferHandleType(const HLSLBufferDecl *BufDecl) {
314326
ASTContext &AST = BufDecl->getASTContext();
@@ -319,26 +331,20 @@ createBufferHandleType(const HLSLBufferDecl *BufDecl) {
319331
return cast<HLSLAttributedResourceType>(QT.getTypePtr());
320332
}
321333

322-
// Creates temporary global variables for all declarations within the constant
323-
// buffer context, creates a global variable for the constant buffer and adds
324-
// it to the module.
325-
// All uses of the temporary constant globals will be replaced with buffer
326-
// access intrinsic resource.getpointer in CGHLSLRuntime::finishCodeGen.
327-
// Later on in DXILResourceAccess pass these will be transtaled
328-
// to dx.op.cbufferLoadLegacy instructions.
334+
// Codegen for HLSLBufferDecl
329335
void CGHLSLRuntime::addBuffer(const HLSLBufferDecl *BufDecl) {
330336

331337
assert(BufDecl->isCBuffer() && "tbuffer codegen is not supported yet");
332338

333-
// Create resource handle type for the buffer
339+
// create resource handle type for the buffer
334340
const clang::HLSLAttributedResourceType *ResHandleTy =
335341
createBufferHandleType(BufDecl);
336342

337-
// ignore empty constant buffer
343+
// empty constant buffer is ignored
338344
if (ResHandleTy->getContainedType()->getAsCXXRecordDecl()->isEmpty())
339345
return;
340346

341-
// Create global variable for the buffer
347+
// create global variable for the constant buffer
342348
llvm::Module &M = CGM.getModule();
343349
llvm::TargetExtType *TargetTy =
344350
cast<llvm::TargetExtType>(convertHLSLSpecificType(ResHandleTy));
@@ -350,10 +356,10 @@ void CGHLSLRuntime::addBuffer(const HLSLBufferDecl *BufDecl) {
350356
GlobalValue::NotThreadLocal);
351357
M.insertGlobalVariable(BufGV);
352358

353-
// Add globals for buffer elements and create metadata node for the buffer
359+
// Add globals for constant buffer elements and create metadata nodes
354360
emitBufferGlobalsAndMetadata(BufDecl, BufGV);
355361

356-
// Add cbuffer resource initialization
362+
// Resource initialization
357363
const HLSLResourceBindingAttr *RBA =
358364
BufDecl->getAttr<HLSLResourceBindingAttr>();
359365
// FIXME: handle implicit binding if no binding attribute is found

clang/lib/CodeGen/CGHLSLRuntime.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,6 @@ class FunctionDecl;
7171
namespace CodeGen {
7272

7373
class CodeGenModule;
74-
class CGBuilderTy;
7574

7675
class CGHLSLRuntime {
7776
public:
@@ -175,7 +174,8 @@ class CGHLSLRuntime {
175174

176175
llvm::Triple::ArchType getArch();
177176

178-
// sizes of structs that in constant buffer layout
177+
// Sizes of structs in constant buffer layout. Structs in the map
178+
// had their layout calculated and added to the module as metadata.
179179
llvm::DenseMap<llvm::StructType *, size_t> StructSizesForBuffer;
180180
};
181181

clang/lib/CodeGen/Targets/DirectX.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ llvm::Type *DirectXTargetCodeGenInfo::getHLSLType(CodeGenModule &CGM,
4444
return nullptr;
4545

4646
// convert element type
47-
// llvm::Type *ElemType = CGM.getTypes().ConvertTypeForMem(ContainedTy);
4847
llvm::Type *ElemType = CGM.getTypes().ConvertType(ContainedTy);
4948

5049
llvm::StringRef TypeName =

clang/test/CodeGenHLSL/cbuffer.hlsl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ void main() {
164164
// CHECK-NEXT: call void @_init_resource_CBArrays.cb()
165165

166166
// CHECK: !hlsl.cbs = !{![[CBSCALARS:[0-9]+]], ![[CBVECTORS:[0-9]+]], ![[CBARRAYS:[0-9]+]], ![[CBSTRUCTS:[0-9]+]], ![[CBMIX:[0-9]+]]}
167+
167168
// CHECK: !hlsl.cblayouts = !{![[CBSCALARS_LAYOUT:[0-9]+]], ![[CBVECTORS_LAYOUT:[0-9]+]], ![[CBARRAYS_LAYOUT:[0-9]+]], ![[A_LAYOUT:[0-9]+]],
168169
// CHECK-SAME: ![[B_LAYOUT:[0-9]+]], ![[C_LAYOUT:[0-9]+]], ![[D_LAYOUT:[0-9]+]], ![[CBSTRUCTS_LAYOUT:[0-9]+]], ![[TEST_LAYOUT:[0-9]+]],
169170
// CHECK-SAME: ![[ANON_LAYOUT:[0-9]+]], ![[CBMIX_LAYOUT:[0-9]+]]}
@@ -193,7 +194,6 @@ void main() {
193194
// CHECK: ![[C_LAYOUT]] = !{!"struct.C", i32 24, i32 0, i32 16}
194195
// CHECK: ![[D_LAYOUT]] = !{!"struct.__cblayout_D", i32 94, i32 0}
195196
// CHECK: ![[CBSTRUCTS_LAYOUT]] = !{!"struct.__cblayout_CBStructs", i32 262, i32 0, i32 16, i32 32, i32 64, i32 144, i32 238, i32 240, i32 256}
196-
197197
// CHECK: ![[TEST_LAYOUT]] = !{!"struct.Test", i32 8, i32 0, i32 4}
198198
// CHECK: ![[ANON_LAYOUT]] = !{!"struct.anon", i32 4, i32 0}
199199
// CHECK: ![[CBMIX_LAYOUT]] = !{!"struct.__cblayout_CBMix", i32 162, i32 0, i32 24, i32 32, i32 120, i32 128, i32 136, i32 144, i32 152, i32 160}

0 commit comments

Comments
 (0)