22using llvm::hlsl::CBufferRowSizeInBytes;
31 llvm::Type *NewElemType) {
34 NewElemType = createArrayWithNewElementType(
35 CGM, cast<const ConstantArrayType>(ArrayElemType), NewElemType);
36 return llvm::ArrayType::get(NewElemType,
ArrayType->getSExtSize());
40static unsigned getScalarOrVectorSizeInBytes(llvm::Type *Ty) {
41 assert(Ty->isVectorTy() || Ty->isIntegerTy() || Ty->isFloatingPointTy());
42 if (Ty->isVectorTy()) {
43 llvm::FixedVectorType *FVT = cast<llvm::FixedVectorType>(Ty);
44 return FVT->getNumElements() *
45 (FVT->getElementType()->getScalarSizeInBits() / 8);
47 return Ty->getScalarSizeInBits() / 8;
73 if (llvm::TargetExtType *Ty =
80 unsigned EndOffset = 0;
90 while (RecordDecls.back()->getNumBases()) {
92 assert(
D->getNumBases() == 1 &&
93 "HLSL doesn't support multiple inheritance");
94 RecordDecls.push_back(
D->bases_begin()->getType()->castAsCXXRecordDecl());
98 llvm::Type *FieldType;
100 while (!RecordDecls.empty()) {
103 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");
110 const int PO = PackOffsets ? (*PackOffsets)[Index++] : -1;
111 if (!PackOffsets || PO != -1) {
112 if (!layoutField(FD, EndOffset, FieldOffset, FieldType, PO))
114 Layout.push_back(FieldOffset);
115 LayoutElements.push_back(FieldType);
121 DelayLayoutFields.emplace_back(FD, LayoutElements.size());
124 LayoutElements.push_back(
nullptr);
129 for (
auto I : DelayLayoutFields) {
131 const unsigned IndexInLayoutElements = I.second;
134 const unsigned IndexInLayout = IndexInLayoutElements + 1;
135 assert(Layout[IndexInLayout] ==
UINT_MAX &&
136 LayoutElements[IndexInLayoutElements] ==
nullptr);
138 if (!layoutField(FD, EndOffset, FieldOffset, FieldType))
140 Layout[IndexInLayout] = FieldOffset;
141 LayoutElements[IndexInLayoutElements] = FieldType;
145 Layout[0] = EndOffset;
151 Decl->getName().empty() ?
"anon" :
Decl->getQualifiedNameAsString();
152 llvm::StructType *StructTy =
153 llvm::StructType::create(LayoutElements, Name,
true);
156 llvm::TargetExtType *NewLayoutTy = llvm::TargetExtType::get(
174bool HLSLBufferLayoutBuilder::layoutField(
const FieldDecl *FD,
176 unsigned &FieldOffset,
177 llvm::Type *&FieldType,
183 unsigned ElemSize = 0;
184 unsigned ElemOffset = 0;
185 unsigned ArrayCount = 1;
186 unsigned ArrayStride = 0;
188 unsigned NextRowOffset = llvm::alignTo(EndOffset, CBufferRowSizeInBytes);
190 llvm::Type *ElemLayoutTy =
nullptr;
198 ArrayCount *= ArrayTy->getSExtSize();
199 Ty = ArrayTy->getElementType();
204 llvm::Type *NewTy = cast<llvm::TargetExtType>(
208 assert(isa<llvm::TargetExtType>(NewTy) &&
"expected target type");
209 ElemSize = cast<llvm::TargetExtType>(NewTy)->getIntParameter(0);
210 ElemLayoutTy = createArrayWithNewElementType(
211 CGM, cast<ConstantArrayType>(FieldTy.
getTypePtr()), NewTy);
218 ArrayStride = llvm::alignTo(ElemSize, CBufferRowSizeInBytes);
219 ElemOffset = (Packoffset != -1) ? Packoffset : NextRowOffset;
227 assert(isa<llvm::TargetExtType>(ElemLayoutTy) &&
"expected target type");
228 ElemSize = cast<llvm::TargetExtType>(ElemLayoutTy)->getIntParameter(0);
229 ElemOffset = (Packoffset != -1) ? Packoffset : NextRowOffset;
235 if (ElemLayoutTy->isVectorTy()) {
237 const llvm::FixedVectorType *FVT =
238 cast<llvm::FixedVectorType>(ElemLayoutTy);
239 unsigned SubElemSize = FVT->getElementType()->getScalarSizeInBits() / 8;
240 ElemSize = FVT->getNumElements() * SubElemSize;
243 assert(ElemLayoutTy->isIntegerTy() || ElemLayoutTy->isFloatingPointTy());
244 ElemSize = ElemLayoutTy->getScalarSizeInBits() / 8;
249 if (Packoffset != -1) {
250 ElemOffset = Packoffset;
252 ElemOffset = llvm::alignTo(EndOffset, Align);
254 if (ElemOffset + ElemSize > NextRowOffset)
255 ElemOffset = NextRowOffset;
262 unsigned NewEndOffset =
263 ElemOffset + (ArrayCount - 1) * ArrayStride + ElemSize;
264 EndOffset = std::max<unsigned>(EndOffset, NewEndOffset);
267 FieldOffset = ElemOffset;
268 FieldType = ElemLayoutTy;
C Language Family Type Representation.
const ConstantArrayType * getAsConstantArrayType(QualType T) const
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Represents a C++ struct/union/class.
void addHLSLBufferLayoutType(const RecordType *LayoutStructTy, llvm::TargetExtType *LayoutTy)
llvm::TargetExtType * getHLSLBufferLayoutType(const RecordType *LayoutStructTy)
This class organizes the cross-function state that is used while generating LLVM code.
CGHLSLRuntime & getHLSLRuntime()
Return a reference to the configured HLSL runtime.
CodeGenTypes & getTypes()
ASTContext & getContext() const
llvm::LLVMContext & getLLVMContext()
llvm::Type * ConvertTypeForMem(QualType T)
ConvertTypeForMem - Convert type T into a llvm::Type.
llvm::TargetExtType * createLayoutType(const RecordType *StructType, const llvm::SmallVector< int32_t > *Packoffsets=nullptr)
Represents the canonical version of C arrays with a specified constant size.
Decl - This represents one declaration (or definition), e.g.
Represents a member of a struct/union/class.
A (possibly-)qualified type.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
field_range fields() const
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
The base class of the type hierarchy.
bool isConstantArrayType() const
CXXRecordDecl * castAsCXXRecordDecl() const
const Type * getArrayElementTypeNoTypeQual() const
If this is an array type, return the element type of the array, potentially with type qualifiers miss...
bool isStructureOrClassType() const
const T * getAsCanonical() const
If this type is canonically the specified type, return its canonical type cast to that specified type...
The JSON file list parser is used to communicate input to InstallAPI.