llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-backend-spir-v Author: Helena Kotas (hekota) <details> <summary>Changes</summary> Changes line endings in files related to HLSL to LF (`\n`). --- Patch is 550.08 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/156930.diff 92 Files Affected: - (modified) clang/lib/CodeGen/HLSLBufferLayoutBuilder.cpp (+273-273) - (modified) clang/lib/CodeGen/HLSLBufferLayoutBuilder.h (+47-47) - (modified) clang/test/AST/HLSL/is_structured_resource_element_compatible_concept.hlsl (+15-15) - (modified) clang/test/AST/HLSL/is_typed_resource_element_compatible_concept.hlsl (+9-9) - (modified) clang/test/CodeGenHLSL/builtins/asint16.hlsl (+60-60) - (modified) clang/test/CodeGenHLSL/builtins/asuint16.hlsl (+60-60) - (modified) clang/test/CodeGenHLSL/builtins/atan2-overloads.hlsl (+123-123) - (modified) clang/test/CodeGenHLSL/builtins/atan2.hlsl (+59-59) - (modified) clang/test/CodeGenHLSL/builtins/cross.hlsl (+37-37) - (modified) clang/test/CodeGenHLSL/builtins/dot2add.hlsl (+175-175) - (modified) clang/test/CodeGenHLSL/builtins/dst.hlsl (+51-51) - (modified) clang/test/CodeGenHLSL/builtins/normalize-overloads.hlsl (+156-156) - (modified) clang/test/CodeGenHLSL/builtins/normalize.hlsl (+85-85) - (modified) clang/test/CodeGenHLSL/builtins/or.hlsl (+80-80) - (modified) clang/test/CodeGenHLSL/builtins/step-overloads.hlsl (+153-153) - (modified) clang/test/CodeGenHLSL/builtins/step.hlsl (+84-84) - (modified) clang/test/CodeGenHLSL/resources/AppendStructuredBuffer-elementtype.hlsl (+54-54) - (modified) clang/test/CodeGenHLSL/resources/ConsumeStructuredBuffer-elementtype.hlsl (+54-54) - (modified) clang/test/CodeGenHLSL/resources/RWStructuredBuffer-elementtype.hlsl (+61-61) - (modified) clang/test/CodeGenHLSL/resources/RasterizerOrderedStructuredBuffer-elementtype.hlsl (+60-60) - (modified) clang/test/CodeGenHLSL/resources/StructuredBuffer-elementtype.hlsl (+61-61) - (modified) clang/test/CodeGenHLSL/resources/StructuredBuffers-subscripts.hlsl (+51-51) - (modified) clang/test/CodeGenHLSL/resources/cbuffer_and_namespaces.hlsl (+54-54) - (modified) clang/test/CodeGenHLSL/resources/cbuffer_with_static_global_and_function.hlsl (+29-29) - (modified) clang/test/CodeGenHLSL/resources/res-array-global-dyn-index.hlsl (+29-29) - (modified) clang/test/CodeGenHLSL/resources/res-array-global-multi-dim.hlsl (+46-46) - (modified) clang/test/CodeGenHLSL/resources/res-array-global-subarray-many.hlsl (+109-109) - (modified) clang/test/CodeGenHLSL/resources/res-array-global-subarray-one.hlsl (+62-62) - (modified) clang/test/CodeGenHLSL/resources/res-array-global.hlsl (+75-75) - (modified) clang/test/CodeGenHLSL/resources/res-array-local-multi-dim.hlsl (+49-49) - (modified) clang/test/CodeGenHLSL/resources/res-array-local1.hlsl (+64-64) - (modified) clang/test/CodeGenHLSL/resources/res-array-local2.hlsl (+37-37) - (modified) clang/test/CodeGenHLSL/resources/res-array-local3.hlsl (+62-62) - (modified) clang/test/Options/Gis.hlsl (+13-13) - (modified) clang/test/ParserHLSL/bitfields.hlsl (+31-31) - (modified) clang/test/ParserHLSL/hlsl_annotations_on_struct_members.hlsl (+21-21) - (modified) clang/test/ParserHLSL/hlsl_contained_type_attr.hlsl (+25-25) - (modified) clang/test/ParserHLSL/hlsl_contained_type_attr_error.hlsl (+28-28) - (modified) clang/test/ParserHLSL/hlsl_is_rov_attr.hlsl (+22-22) - (modified) clang/test/ParserHLSL/hlsl_is_rov_attr_error.hlsl (+20-20) - (modified) clang/test/ParserHLSL/hlsl_raw_buffer_attr.hlsl (+22-22) - (modified) clang/test/ParserHLSL/hlsl_raw_buffer_attr_error.hlsl (+17-17) - (modified) clang/test/ParserHLSL/hlsl_resource_class_attr.hlsl (+37-37) - (modified) clang/test/ParserHLSL/hlsl_resource_class_attr_error.hlsl (+22-22) - (modified) clang/test/ParserHLSL/hlsl_resource_handle_attrs.hlsl (+19-19) - (modified) clang/test/SemaHLSL/Availability/avail-diag-default-compute.hlsl (+119-119) - (modified) clang/test/SemaHLSL/Availability/avail-diag-default-lib.hlsl (+180-180) - (modified) clang/test/SemaHLSL/Availability/avail-diag-relaxed-compute.hlsl (+119-119) - (modified) clang/test/SemaHLSL/Availability/avail-diag-relaxed-lib.hlsl (+162-162) - (modified) clang/test/SemaHLSL/Availability/avail-diag-strict-compute.hlsl (+129-129) - (modified) clang/test/SemaHLSL/Availability/avail-diag-strict-lib.hlsl (+192-192) - (modified) clang/test/SemaHLSL/Availability/avail-lib-multiple-stages.hlsl (+57-57) - (modified) clang/test/SemaHLSL/BuiltIns/StructuredBuffers.hlsl (+31-31) - (modified) clang/test/SemaHLSL/BuiltIns/asint16-errors.hlsl (+43-43) - (modified) clang/test/SemaHLSL/BuiltIns/asuint16-errors.hlsl (+52-52) - (modified) clang/test/SemaHLSL/BuiltIns/cross-errors.hlsl (+61-61) - (modified) clang/test/SemaHLSL/BuiltIns/dot2add-errors.hlsl (+13-13) - (modified) clang/test/SemaHLSL/BuiltIns/half-float-only-errors2.hlsl (+13-13) - (modified) clang/test/SemaHLSL/BuiltIns/length-errors.hlsl (+81-81) - (modified) clang/test/SemaHLSL/BuiltIns/logical-operator-errors.hlsl (+33-33) - (modified) clang/test/SemaHLSL/BuiltIns/normalize-errors.hlsl (+31-31) - (modified) clang/test/SemaHLSL/BuiltIns/step-errors.hlsl (+31-31) - (modified) clang/test/SemaHLSL/Types/Traits/IsIntangibleType.hlsl (+81-81) - (modified) clang/test/SemaHLSL/Types/Traits/IsIntangibleTypeErrors.hlsl (+12-12) - (modified) clang/test/SemaHLSL/Types/Traits/IsTypedResourceElementCompatible.hlsl (+58-58) - (modified) clang/test/SemaHLSL/resource_binding_attr_error_basic.hlsl (+42-42) - (modified) clang/test/SemaHLSL/resource_binding_attr_error_other.hlsl (+9-9) - (modified) clang/test/SemaHLSL/resource_binding_attr_error_resource.hlsl (+49-49) - (modified) clang/test/SemaHLSL/resource_binding_attr_error_silence_diags.hlsl (+27-27) - (modified) clang/test/SemaHLSL/resource_binding_attr_error_space.hlsl (+62-62) - (modified) clang/test/SemaHLSL/resource_binding_attr_error_udt.hlsl (+135-135) - (modified) llvm/test/CodeGen/DirectX/Metadata/cbuffer_metadata.ll (+79-79) - (modified) llvm/test/CodeGen/DirectX/atan2.ll (+87-87) - (modified) llvm/test/CodeGen/DirectX/atan2_error.ll (+11-11) - (modified) llvm/test/CodeGen/DirectX/cross.ll (+56-56) - (modified) llvm/test/CodeGen/DirectX/dot2add.ll (+13-13) - (modified) llvm/test/CodeGen/DirectX/dot2add_error.ll (+15-15) - (modified) llvm/test/CodeGen/DirectX/legalize-fneg.ll (+23-23) - (modified) llvm/test/CodeGen/DirectX/legalize-load-store-array-alloca.ll (+41-41) - (modified) llvm/test/CodeGen/DirectX/metadata-stripping.ll (+32-32) - (modified) llvm/test/CodeGen/DirectX/noop_bitcast_global_array_type.ll (+53-53) - (modified) llvm/test/CodeGen/DirectX/normalize.ll (+112-112) - (modified) llvm/test/CodeGen/DirectX/normalize_error.ll (+10-10) - (modified) llvm/test/CodeGen/DirectX/step.ll (+78-78) - (modified) llvm/test/CodeGen/SPIRV/hlsl-intrinsics/atan2.ll (+49-49) - (modified) llvm/test/CodeGen/SPIRV/hlsl-intrinsics/cross.ll (+33-33) - (modified) llvm/test/CodeGen/SPIRV/hlsl-intrinsics/faceforward.ll (+62-62) - (modified) llvm/test/CodeGen/SPIRV/hlsl-intrinsics/length.ll (+31-31) - (modified) llvm/test/CodeGen/SPIRV/hlsl-intrinsics/normalize.ll (+31-31) - (modified) llvm/test/CodeGen/SPIRV/hlsl-intrinsics/reflect.ll (+33-33) - (modified) llvm/test/CodeGen/SPIRV/hlsl-intrinsics/smoothstep.ll (+68-68) - (modified) llvm/test/CodeGen/SPIRV/hlsl-intrinsics/step.ll (+33-33) ``````````diff diff --git a/clang/lib/CodeGen/HLSLBufferLayoutBuilder.cpp b/clang/lib/CodeGen/HLSLBufferLayoutBuilder.cpp index a21feaa1120c6..838903cdcd1ee 100644 --- a/clang/lib/CodeGen/HLSLBufferLayoutBuilder.cpp +++ b/clang/lib/CodeGen/HLSLBufferLayoutBuilder.cpp @@ -1,273 +1,273 @@ -//===- HLSLBufferLayoutBuilder.cpp ----------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "HLSLBufferLayoutBuilder.h" -#include "CGHLSLRuntime.h" -#include "CodeGenModule.h" -#include "clang/AST/Type.h" -#include <climits> - -//===----------------------------------------------------------------------===// -// Implementation of constant buffer layout common between DirectX and -// SPIR/SPIR-V. -//===----------------------------------------------------------------------===// - -using namespace clang; -using namespace clang::CodeGen; -using llvm::hlsl::CBufferRowSizeInBytes; - -namespace { - -// Creates a new array type with the same dimentions but with the new -// element type. -static llvm::Type * -createArrayWithNewElementType(CodeGenModule &CGM, - const ConstantArrayType *ArrayType, - llvm::Type *NewElemType) { - const clang::Type *ArrayElemType = ArrayType->getArrayElementTypeNoTypeQual(); - if (ArrayElemType->isConstantArrayType()) - NewElemType = createArrayWithNewElementType( - CGM, cast<const ConstantArrayType>(ArrayElemType), NewElemType); - return llvm::ArrayType::get(NewElemType, ArrayType->getSExtSize()); -} - -// Returns the size of a scalar or vector in bytes -static unsigned getScalarOrVectorSizeInBytes(llvm::Type *Ty) { - assert(Ty->isVectorTy() || Ty->isIntegerTy() || Ty->isFloatingPointTy()); - if (Ty->isVectorTy()) { - llvm::FixedVectorType *FVT = cast<llvm::FixedVectorType>(Ty); - return FVT->getNumElements() * - (FVT->getElementType()->getScalarSizeInBits() / 8); - } - return Ty->getScalarSizeInBits() / 8; -} - -} // namespace - -namespace clang { -namespace CodeGen { - -// Creates a layout type for given struct or class with HLSL constant buffer -// layout taking into account PackOffsets, if provided. -// Previously created layout types are cached by CGHLSLRuntime. -// -// The function iterates over all fields of the record type (including base -// classes) and calls layoutField to converts each field to its corresponding -// LLVM type and to calculate its HLSL constant buffer layout. Any embedded -// structs (or arrays of structs) are converted to target layout types as well. -// -// When PackOffsets are specified the elements will be placed based on the -// user-specified offsets. Not all elements must have a packoffset/register(c#) -// annotation though. For those that don't, the PackOffsets array will contain -// -1 value instead. These elements must be placed at the end of the layout -// after all of the elements with specific offset. -llvm::TargetExtType *HLSLBufferLayoutBuilder::createLayoutType( - const RecordType *RT, const llvm::SmallVector<int32_t> *PackOffsets) { - - // check if we already have the layout type for this struct - if (llvm::TargetExtType *Ty = - CGM.getHLSLRuntime().getHLSLBufferLayoutType(RT)) - return Ty; - - SmallVector<unsigned> Layout; - SmallVector<llvm::Type *> LayoutElements; - unsigned Index = 0; // packoffset index - unsigned EndOffset = 0; - - SmallVector<std::pair<const FieldDecl *, unsigned>> DelayLayoutFields; - - // reserve first spot in the layout vector for buffer size - Layout.push_back(0); - - // iterate over all fields of the record, including fields on base classes - llvm::SmallVector<CXXRecordDecl *> RecordDecls; - RecordDecls.push_back(RT->castAsCXXRecordDecl()); - while (RecordDecls.back()->getNumBases()) { - CXXRecordDecl *D = RecordDecls.back(); - assert(D->getNumBases() == 1 && - "HLSL doesn't support multiple inheritance"); - RecordDecls.push_back(D->bases_begin()->getType()->castAsCXXRecordDecl()); - } - - unsigned FieldOffset; - llvm::Type *FieldType; - - while (!RecordDecls.empty()) { - const CXXRecordDecl *RD = RecordDecls.pop_back_val(); - - for (const auto *FD : RD->fields()) { - assert((!PackOffsets || Index < PackOffsets->size()) && - "number of elements in layout struct does not match number of " - "packoffset annotations"); - - // No PackOffset info at all, or have a valid packoffset/register(c#) - // annotations value -> layout the field. - const int PO = PackOffsets ? (*PackOffsets)[Index++] : -1; - if (!PackOffsets || PO != -1) { - if (!layoutField(FD, EndOffset, FieldOffset, FieldType, PO)) - return nullptr; - Layout.push_back(FieldOffset); - LayoutElements.push_back(FieldType); - continue; - } - // Have PackOffset info, but there is no packoffset/register(cX) - // annotation on this field. Delay the layout until after all of the - // other elements with packoffsets/register(cX) are processed. - DelayLayoutFields.emplace_back(FD, LayoutElements.size()); - // reserve space for this field in the layout vector and elements list - Layout.push_back(UINT_MAX); - LayoutElements.push_back(nullptr); - } - } - - // process delayed layouts - for (auto I : DelayLayoutFields) { - const FieldDecl *FD = I.first; - const unsigned IndexInLayoutElements = I.second; - // the first item in layout vector is size, so we need to offset the index - // by 1 - const unsigned IndexInLayout = IndexInLayoutElements + 1; - assert(Layout[IndexInLayout] == UINT_MAX && - LayoutElements[IndexInLayoutElements] == nullptr); - - if (!layoutField(FD, EndOffset, FieldOffset, FieldType)) - return nullptr; - Layout[IndexInLayout] = FieldOffset; - LayoutElements[IndexInLayoutElements] = FieldType; - } - - // set the size of the buffer - Layout[0] = EndOffset; - - // create the layout struct type; anonymous struct have empty name but - // non-empty qualified name - const auto *Decl = RT->castAsCXXRecordDecl(); - std::string Name = - Decl->getName().empty() ? "anon" : Decl->getQualifiedNameAsString(); - llvm::StructType *StructTy = - llvm::StructType::create(LayoutElements, Name, true); - - // create target layout type - llvm::TargetExtType *NewLayoutTy = llvm::TargetExtType::get( - CGM.getLLVMContext(), LayoutTypeName, {StructTy}, Layout); - if (NewLayoutTy) - CGM.getHLSLRuntime().addHLSLBufferLayoutType(RT, NewLayoutTy); - return NewLayoutTy; -} - -// The function converts a single field of HLSL Buffer to its corresponding -// LLVM type and calculates it's layout. Any embedded structs (or -// arrays of structs) are converted to target layout types as well. -// The converted type is set to the FieldType parameter, the element -// offset is set to the FieldOffset parameter. The EndOffset (=size of the -// buffer) is also updated accordingly to the offset just after the placed -// element, unless the incoming EndOffset already larger (may happen in case -// of unsorted packoffset annotations). -// Returns true if the conversion was successful. -// The packoffset parameter contains the field's layout offset provided by the -// user or -1 if there was no packoffset (or register(cX)) annotation. -bool HLSLBufferLayoutBuilder::layoutField(const FieldDecl *FD, - unsigned &EndOffset, - unsigned &FieldOffset, - llvm::Type *&FieldType, - int Packoffset) { - - // Size of element; for arrays this is a size of a single element in the - // array. Total array size of calculated as (ArrayCount-1) * ArrayStride + - // ElemSize. - unsigned ElemSize = 0; - unsigned ElemOffset = 0; - unsigned ArrayCount = 1; - unsigned ArrayStride = 0; - - unsigned NextRowOffset = llvm::alignTo(EndOffset, CBufferRowSizeInBytes); - - llvm::Type *ElemLayoutTy = nullptr; - QualType FieldTy = FD->getType(); - - if (FieldTy->isConstantArrayType()) { - // Unwrap array to find the element type and get combined array size. - QualType Ty = FieldTy; - while (Ty->isConstantArrayType()) { - auto *ArrayTy = CGM.getContext().getAsConstantArrayType(Ty); - ArrayCount *= ArrayTy->getSExtSize(); - Ty = ArrayTy->getElementType(); - } - // For array of structures, create a new array with a layout type - // instead of the structure type. - if (Ty->isStructureOrClassType()) { - llvm::Type *NewTy = cast<llvm::TargetExtType>( - createLayoutType(Ty->getAsCanonical<RecordType>())); - if (!NewTy) - return false; - assert(isa<llvm::TargetExtType>(NewTy) && "expected target type"); - ElemSize = cast<llvm::TargetExtType>(NewTy)->getIntParameter(0); - ElemLayoutTy = createArrayWithNewElementType( - CGM, cast<ConstantArrayType>(FieldTy.getTypePtr()), NewTy); - } else { - // Array of vectors or scalars - ElemSize = - getScalarOrVectorSizeInBytes(CGM.getTypes().ConvertTypeForMem(Ty)); - ElemLayoutTy = CGM.getTypes().ConvertTypeForMem(FieldTy); - } - ArrayStride = llvm::alignTo(ElemSize, CBufferRowSizeInBytes); - ElemOffset = (Packoffset != -1) ? Packoffset : NextRowOffset; - - } else if (FieldTy->isStructureOrClassType()) { - // Create a layout type for the structure - ElemLayoutTy = createLayoutType( - cast<RecordType>(FieldTy->getAsCanonical<RecordType>())); - if (!ElemLayoutTy) - return false; - assert(isa<llvm::TargetExtType>(ElemLayoutTy) && "expected target type"); - ElemSize = cast<llvm::TargetExtType>(ElemLayoutTy)->getIntParameter(0); - ElemOffset = (Packoffset != -1) ? Packoffset : NextRowOffset; - - } else { - // scalar or vector - find element size and alignment - unsigned Align = 0; - ElemLayoutTy = CGM.getTypes().ConvertTypeForMem(FieldTy); - if (ElemLayoutTy->isVectorTy()) { - // align vectors by sub element size - const llvm::FixedVectorType *FVT = - cast<llvm::FixedVectorType>(ElemLayoutTy); - unsigned SubElemSize = FVT->getElementType()->getScalarSizeInBits() / 8; - ElemSize = FVT->getNumElements() * SubElemSize; - Align = SubElemSize; - } else { - assert(ElemLayoutTy->isIntegerTy() || ElemLayoutTy->isFloatingPointTy()); - ElemSize = ElemLayoutTy->getScalarSizeInBits() / 8; - Align = ElemSize; - } - - // calculate or get element offset for the vector or scalar - if (Packoffset != -1) { - ElemOffset = Packoffset; - } else { - ElemOffset = llvm::alignTo(EndOffset, Align); - // if the element does not fit, move it to the next row - if (ElemOffset + ElemSize > NextRowOffset) - ElemOffset = NextRowOffset; - } - } - - // Update end offset of the layout; do not update it if the EndOffset - // is already bigger than the new value (which may happen with unordered - // packoffset annotations) - unsigned NewEndOffset = - ElemOffset + (ArrayCount - 1) * ArrayStride + ElemSize; - EndOffset = std::max<unsigned>(EndOffset, NewEndOffset); - - // add the layout element and offset to the lists - FieldOffset = ElemOffset; - FieldType = ElemLayoutTy; - return true; -} - -} // namespace CodeGen -} // namespace clang +//===- HLSLBufferLayoutBuilder.cpp ----------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "HLSLBufferLayoutBuilder.h" +#include "CGHLSLRuntime.h" +#include "CodeGenModule.h" +#include "clang/AST/Type.h" +#include <climits> + +//===----------------------------------------------------------------------===// +// Implementation of constant buffer layout common between DirectX and +// SPIR/SPIR-V. +//===----------------------------------------------------------------------===// + +using namespace clang; +using namespace clang::CodeGen; +using llvm::hlsl::CBufferRowSizeInBytes; + +namespace { + +// Creates a new array type with the same dimentions but with the new +// element type. +static llvm::Type * +createArrayWithNewElementType(CodeGenModule &CGM, + const ConstantArrayType *ArrayType, + llvm::Type *NewElemType) { + const clang::Type *ArrayElemType = ArrayType->getArrayElementTypeNoTypeQual(); + if (ArrayElemType->isConstantArrayType()) + NewElemType = createArrayWithNewElementType( + CGM, cast<const ConstantArrayType>(ArrayElemType), NewElemType); + return llvm::ArrayType::get(NewElemType, ArrayType->getSExtSize()); +} + +// Returns the size of a scalar or vector in bytes +static unsigned getScalarOrVectorSizeInBytes(llvm::Type *Ty) { + assert(Ty->isVectorTy() || Ty->isIntegerTy() || Ty->isFloatingPointTy()); + if (Ty->isVectorTy()) { + llvm::FixedVectorType *FVT = cast<llvm::FixedVectorType>(Ty); + return FVT->getNumElements() * + (FVT->getElementType()->getScalarSizeInBits() / 8); + } + return Ty->getScalarSizeInBits() / 8; +} + +} // namespace + +namespace clang { +namespace CodeGen { + +// Creates a layout type for given struct or class with HLSL constant buffer +// layout taking into account PackOffsets, if provided. +// Previously created layout types are cached by CGHLSLRuntime. +// +// The function iterates over all fields of the record type (including base +// classes) and calls layoutField to converts each field to its corresponding +// LLVM type and to calculate its HLSL constant buffer layout. Any embedded +// structs (or arrays of structs) are converted to target layout types as well. +// +// When PackOffsets are specified the elements will be placed based on the +// user-specified offsets. Not all elements must have a packoffset/register(c#) +// annotation though. For those that don't, the PackOffsets array will contain +// -1 value instead. These elements must be placed at the end of the layout +// after all of the elements with specific offset. +llvm::TargetExtType *HLSLBufferLayoutBuilder::createLayoutType( + const RecordType *RT, const llvm::SmallVector<int32_t> *PackOffsets) { + + // check if we already have the layout type for this struct + if (llvm::TargetExtType *Ty = + CGM.getHLSLRuntime().getHLSLBufferLayoutType(RT)) + return Ty; + + SmallVector<unsigned> Layout; + SmallVector<llvm::Type *> LayoutElements; + unsigned Index = 0; // packoffset index + unsigned EndOffset = 0; + + SmallVector<std::pair<const FieldDecl *, unsigned>> DelayLayoutFields; + + // reserve first spot in the layout vector for buffer size + Layout.push_back(0); + + // iterate over all fields of the record, including fields on base classes + llvm::SmallVector<CXXRecordDecl *> RecordDecls; + RecordDecls.push_back(RT->castAsCXXRecordDecl()); + while (RecordDecls.back()->getNumBases()) { + CXXRecordDecl *D = RecordDecls.back(); + assert(D->getNumBases() == 1 && + "HLSL doesn't support multiple inheritance"); + RecordDecls.push_back(D->bases_begin()->getType()->castAsCXXRecordDecl()); + } + + unsigned FieldOffset; + llvm::Type *FieldType; + + while (!RecordDecls.empty()) { + const CXXRecordDecl *RD = RecordDecls.pop_back_val(); + + for (const auto *FD : RD->fields()) { + assert((!PackOffsets || Index < PackOffsets->size()) && + "number of elements in layout struct does not match number of " + "packoffset annotations"); + + // No PackOffset info at all, or have a valid packoffset/register(c#) + // annotations value -> layout the field. + const int PO = PackOffsets ? (*PackOffsets)[Index++] : -1; + if (!PackOffsets || PO != -1) { + if (!layoutField(FD, EndOffset, FieldOffset, FieldType, PO)) + return nullptr; + Layout.push_back(FieldOffset); + LayoutElements.push_back(FieldType); + continue; + } + // Have PackOffset info, but there is no packoffset/register(cX) + // annotation on this field. Delay the layout until after all of the + // other elements with packoffsets/register(cX) are processed. + DelayLayoutFields.emplace_back(FD, LayoutElements.size()); + // reserve space for this field in the layout vector and elements list + Layout.push_back(UINT_MAX); + LayoutElements.push_back(nullptr); + } + } + + // process delayed layouts + for (auto I : DelayLayoutFields) { + const FieldDecl *FD = I.first; + const unsigned IndexInLayoutElements = I.second; + // the first item in layout vector is size, so we need to offset the index + // by 1 + const unsigned IndexInLayout = IndexInLayoutElements + 1; + assert(Layout[IndexInLayout] == UINT_MAX && + LayoutElements[IndexInLayoutElements] == nullptr); + + if (!layoutField(FD, EndOffset, FieldOffset, FieldType)) + return nullptr; + Layout[IndexInLayout] = FieldOffset; + LayoutElements[IndexInLayoutElements] = FieldType; + } + + // set the size of the buffer + Layout[0] = EndOffset; + + // create the layout struct type; anonymous struct have empty name but + // non-empty qualified name + const auto *Decl = RT->castAsCXXRecordDecl(); + std::string Name = + Decl->getName().empty() ? "anon" : Decl->getQualifiedNameAsString(); + llvm::StructType *StructTy = + llvm::StructType::create(LayoutElements, Name, true); + + // create target layout type + llvm::TargetExtType *NewLayoutTy = llvm::TargetExtType::get( + CGM.getLLVMContext(), LayoutTypeName, {StructTy}, Layout); + if (NewLayoutTy) + CGM.getHLSLRuntime().addHLSLBufferLayoutType(RT, NewLayoutTy); + return NewLayoutTy; +} + +// The function converts a single field of HLSL Buffer to its corresponding +// LLVM type and calculates it's layout. Any embedded structs (or +// arrays of structs) are converted to target layout types as well. +// The converted type is set to the FieldType parameter, the element +// offset is set to the FieldOffset parameter. The EndOffset (=size of the +// buffer) is also updated accordingly to the offset just after the placed +// element, unless the incoming EndOffset already larger (may happen in case +// of unsorted packoffset annotations). +// Returns true if the conversion was successful. +// The packoffset parameter contains the field's layout offset provided by the +// user or -1 if there was no packoffset (or register(cX)) annotation. +bool HLSLBufferLayoutBuilder::layoutField(const FieldDecl *FD, + unsigned &EndOffset, + unsigned &FieldOffset, + llvm::Type *&FieldType, + int Packoffset) { + + // Size of element; for arrays this is a size of a single element in the + // array. Total array size of calculated as (ArrayCount-1) * ArrayStride + + // ElemSize. + unsigned ElemSize = 0; + unsigned ElemOffset = 0; + unsigned ArrayCount = 1; + unsigned ArrayStride = 0; + + unsigned NextRowOffset = llvm::alignTo(EndOffset, CBufferRowSizeInBytes); + + llvm::Type *ElemLayoutTy = nullptr; + QualType FieldTy = FD->getType(); + + if (FieldTy->isConstantArrayType()) { + // Unwrap array to find the element type and get combined array size. + QualType Ty = FieldTy; + while (Ty->isConstantArrayType()) { + auto *ArrayTy = CGM.getContext().getAsConstantArrayType(Ty); + ArrayCount *= ArrayTy->getSExtSize(); + Ty = ArrayTy->getElementType(); + } + // For array of structures, create a new array with a layout type + // instead of the structure type. + if (Ty->isStruc... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/156930 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits