-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[HLSL] Implement default constant buffer $Globals
#125807
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
- create structs with public fields instead of classes with private fields - add Packed attribute to prevent struct padding - use __cblayout_ prefix in name - filter out arrays of resources (bug fix) - don't create implicit initializer for constant buffer decls - update tests
…-project into cbuffer-codegen5
…-project into cbuffer-codegen5
All variable declarations in the global scope that are not resources, static or empty are implicitly added to implicit constant buffer `$Globals`. Fixes llvm#123801
✅ With the latest revision this PR passed the C/C++ code formatter. |
@llvm/pr-subscribers-clang @llvm/pr-subscribers-hlsl Author: Helena Kotas (hekota) ChangesAll variable declarations in the global scope that are not resources, static or empty are implicitly added to implicit constant buffer Fixes #123801 Depends on #124886. Patch is 20.87 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/125807.diff 10 Files Affected:
diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h
index 05e56978977f2b1..f86ddaf89bd9cfa 100644
--- a/clang/include/clang/AST/Decl.h
+++ b/clang/include/clang/AST/Decl.h
@@ -5038,6 +5038,11 @@ class HLSLBufferDecl final : public NamedDecl, public DeclContext {
// LayoutStruct - Layout struct for the buffer
CXXRecordDecl *LayoutStruct;
+ // For default (implicit) constant buffer, a lisf of references of global
+ // decls that belong to the buffer. The decls are already parented by the
+ // translation unit context.
+ SmallVector<Decl *> DefaultBufferDecls;
+
HLSLBufferDecl(DeclContext *DC, bool CBuffer, SourceLocation KwLoc,
IdentifierInfo *ID, SourceLocation IDLoc,
SourceLocation LBrace);
@@ -5047,6 +5052,8 @@ class HLSLBufferDecl final : public NamedDecl, public DeclContext {
bool CBuffer, SourceLocation KwLoc,
IdentifierInfo *ID, SourceLocation IDLoc,
SourceLocation LBrace);
+ static HLSLBufferDecl *CreateDefaultCBuffer(ASTContext &C,
+ DeclContext *LexicalParent);
static HLSLBufferDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID);
SourceRange getSourceRange() const override LLVM_READONLY {
@@ -5061,6 +5068,7 @@ class HLSLBufferDecl final : public NamedDecl, public DeclContext {
bool hasPackoffset() const { return HasPackoffset; }
const CXXRecordDecl *getLayoutStruct() const { return LayoutStruct; }
void addLayoutStruct(CXXRecordDecl *LS);
+ void addDefaultBufferDecl(Decl *D);
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
@@ -5072,6 +5080,20 @@ class HLSLBufferDecl final : public NamedDecl, public DeclContext {
return static_cast<HLSLBufferDecl *>(const_cast<DeclContext *>(DC));
}
+ // Iterator for the buffer decls. Concatenates the list of decls parented
+ // by this HLSLBufferDecl with the list of default buffer decls.
+ using buffer_decl_iterator =
+ llvm::concat_iterator<Decl *const, SmallVector<Decl *>::const_iterator,
+ decl_iterator>;
+ using buffer_decl_range = llvm::iterator_range<buffer_decl_iterator>;
+
+ buffer_decl_range buffer_decls() const {
+ return buffer_decl_range(buffer_decls_begin(), buffer_decls_end());
+ }
+ buffer_decl_iterator buffer_decls_begin() const;
+ buffer_decl_iterator buffer_decls_end() const;
+ bool buffer_decls_empty();
+
friend class ASTDeclReader;
friend class ASTDeclWriter;
};
diff --git a/clang/include/clang/Sema/SemaHLSL.h b/clang/include/clang/Sema/SemaHLSL.h
index f4cd11f423a84a0..b1cc856975532fa 100644
--- a/clang/include/clang/Sema/SemaHLSL.h
+++ b/clang/include/clang/Sema/SemaHLSL.h
@@ -103,13 +103,13 @@ class SemaHLSL : public SemaBase {
HLSLParamModifierAttr::Spelling Spelling);
void ActOnTopLevelFunction(FunctionDecl *FD);
void ActOnVariableDeclarator(VarDecl *VD);
+ void ActOnEndOfTranslationUnit(TranslationUnitDecl *TU);
void CheckEntryPoint(FunctionDecl *FD);
void CheckSemanticAnnotation(FunctionDecl *EntryPoint, const Decl *Param,
const HLSLAnnotationAttr *AnnotationAttr);
void DiagnoseAttrStageMismatch(
const Attr *A, llvm::Triple::EnvironmentType Stage,
std::initializer_list<llvm::Triple::EnvironmentType> AllowedStages);
- void DiagnoseAvailabilityViolations(TranslationUnitDecl *TU);
QualType handleVectorBinOpConversion(ExprResult &LHS, ExprResult &RHS,
QualType LHSType, QualType RHSType,
@@ -159,11 +159,16 @@ class SemaHLSL : public SemaBase {
// List of all resource bindings
ResourceBindings Bindings;
+ // default constant buffer $Globals
+ HLSLBufferDecl *DefaultCBuffer;
+
private:
void collectResourcesOnVarDecl(VarDecl *D);
void collectResourcesOnUserRecordDecl(const VarDecl *VD,
const RecordType *RT);
void processExplicitBindingsOnDecl(VarDecl *D);
+
+ void diagnoseAvailabilityViolations(TranslationUnitDecl *TU);
};
} // namespace clang
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index 4c5201d0ba2ee90..eede936577f0962 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -57,6 +57,7 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
@@ -5741,10 +5742,22 @@ HLSLBufferDecl *HLSLBufferDecl::Create(ASTContext &C,
return Result;
}
+HLSLBufferDecl *
+HLSLBufferDecl::CreateDefaultCBuffer(ASTContext &C,
+ DeclContext *LexicalParent) {
+ DeclContext *DC = LexicalParent;
+ IdentifierInfo *II = &C.Idents.get("$Globals", tok::TokenKind::identifier);
+ HLSLBufferDecl *Result = new (C, DC) HLSLBufferDecl(
+ DC, true, SourceLocation(), II, SourceLocation(), SourceLocation());
+ Result->setImplicit(true);
+ return Result;
+}
+
HLSLBufferDecl *HLSLBufferDecl::CreateDeserialized(ASTContext &C,
GlobalDeclID ID) {
- return new (C, ID) HLSLBufferDecl(nullptr, false, SourceLocation(), nullptr,
- SourceLocation(), SourceLocation());
+ return new (C, ID)
+ HLSLBufferDecl(nullptr, false, SourceLocation(), nullptr,
+ SourceLocation(), SourceLocation());
}
void HLSLBufferDecl::addLayoutStruct(CXXRecordDecl *LS) {
@@ -5753,6 +5766,30 @@ void HLSLBufferDecl::addLayoutStruct(CXXRecordDecl *LS) {
addDecl(LS);
}
+void HLSLBufferDecl::addDefaultBufferDecl(Decl *D) {
+ assert(isImplicit() &&
+ "default decls can only be added to the implicit/default constant "
+ "buffer $Globals");
+ DefaultBufferDecls.push_back(D);
+}
+
+HLSLBufferDecl::buffer_decl_iterator
+HLSLBufferDecl::buffer_decls_begin() const {
+ return buffer_decl_iterator(llvm::iterator_range(DefaultBufferDecls.begin(),
+ DefaultBufferDecls.end()),
+ decl_range(decls_begin(), decls_end()));
+}
+
+HLSLBufferDecl::buffer_decl_iterator HLSLBufferDecl::buffer_decls_end() const {
+ return buffer_decl_iterator(
+ llvm::iterator_range(DefaultBufferDecls.end(), DefaultBufferDecls.end()),
+ decl_range(decls_end(), decls_end()));
+}
+
+bool HLSLBufferDecl::buffer_decls_empty() {
+ return DefaultBufferDecls.empty() && decls_empty();
+}
+
//===----------------------------------------------------------------------===//
// ImportDecl Implementation
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp
index 52247173b69901b..a24f5ac87866770 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.cpp
+++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp
@@ -244,7 +244,7 @@ void CGHLSLRuntime::emitBufferGlobalsAndMetadata(const HLSLBufferDecl *BufDecl,
size_t BufferSize = 0;
bool UsePackoffset = BufDecl->hasPackoffset();
const auto *ElemIt = LayoutStruct->element_begin();
- for (Decl *D : BufDecl->decls()) {
+ for (Decl *D : BufDecl->buffer_decls()) {
if (isa<CXXRecordDecl, EmptyDecl>(D))
// Nothing to do for this declaration.
continue;
@@ -286,10 +286,7 @@ void CGHLSLRuntime::emitBufferGlobalsAndMetadata(const HLSLBufferDecl *BufDecl,
.str()))) &&
"layout type does not match the converted element type");
- // there might be resources inside the used defined structs
- if (VDTy->isStructureType() && VDTy->isHLSLIntangibleType())
- // FIXME: handle resources in cbuffer structs
- llvm_unreachable("resources in cbuffer are not supported yet");
+ // FIXME: handle resources in cbuffer user-defined structs
// create global variable for the constant and to metadata list
GlobalVariable *ElemGV =
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index eb8d3ceeeba4c0d..65ec9c06b9ee5ac 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -5503,6 +5503,11 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D,
if (getLangOpts().OpenCL && ASTTy->isSamplerT())
return;
+ // HLSL default buffer constants will be emitted during HLSLBufferDecl codegen
+ if (getLangOpts().HLSL &&
+ D->getType().getAddressSpace() == LangAS::hlsl_constant)
+ return;
+
// If this is OpenMP device, check if it is legal to emit this global
// normally.
if (LangOpts.OpenMPIsTargetDevice && OpenMPRuntime &&
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index abb46d3a84e74e2..d3c350b58da1a09 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -1416,8 +1416,7 @@ void Sema::ActOnEndOfTranslationUnit() {
}
if (LangOpts.HLSL)
- HLSL().DiagnoseAvailabilityViolations(
- getASTContext().getTranslationUnitDecl());
+ HLSL().ActOnEndOfTranslationUnit(getASTContext().getTranslationUnitDecl());
// If there were errors, disable 'unused' warnings since they will mostly be
// noise. Don't warn for a use from a module: either we should warn on all
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 1537a887318920f..977185fcf9997b7 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -9,6 +9,7 @@
//===----------------------------------------------------------------------===//
#include "clang/Sema/SemaHLSL.h"
+#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Attr.h"
#include "clang/AST/Attrs.inc"
@@ -147,7 +148,7 @@ bool ResourceBindings::hasBindingInfoForDecl(const VarDecl *VD) const {
return DeclToBindingListIndex.contains(VD);
}
-SemaHLSL::SemaHLSL(Sema &S) : SemaBase(S) {}
+SemaHLSL::SemaHLSL(Sema &S) : SemaBase(S), DefaultCBuffer(nullptr) {}
Decl *SemaHLSL::ActOnStartBuffer(Scope *BufferScope, bool CBuffer,
SourceLocation KwLoc, IdentifierInfo *Ident,
@@ -219,7 +220,7 @@ static void validatePackoffset(Sema &S, HLSLBufferDecl *BufDecl) {
// or on none.
bool HasPackOffset = false;
bool HasNonPackOffset = false;
- for (auto *Field : BufDecl->decls()) {
+ for (auto *Field : BufDecl->buffer_decls()) {
VarDecl *Var = dyn_cast<VarDecl>(Field);
if (!Var)
continue;
@@ -486,7 +487,7 @@ void createHostLayoutStructForBuffer(Sema &S, HLSLBufferDecl *BufDecl) {
LS->setImplicit(true);
LS->startDefinition();
- for (Decl *D : BufDecl->decls()) {
+ for (Decl *D : BufDecl->buffer_decls()) {
VarDecl *VD = dyn_cast<VarDecl>(D);
if (!VD || VD->getStorageClass() == SC_Static ||
VD->getType().getAddressSpace() == LangAS::hlsl_groupshared)
@@ -1922,7 +1923,21 @@ void DiagnoseHLSLAvailability::CheckDeclAvailability(NamedDecl *D,
} // namespace
-void SemaHLSL::DiagnoseAvailabilityViolations(TranslationUnitDecl *TU) {
+void SemaHLSL::ActOnEndOfTranslationUnit(TranslationUnitDecl *TU) {
+
+ // process default CBuffer - create buffer layout struct and invoke codegenCGH
+ if (DefaultCBuffer) {
+ SemaRef.getCurLexicalContext()->addDecl(DefaultCBuffer);
+ createHostLayoutStructForBuffer(SemaRef, DefaultCBuffer);
+
+ DeclGroupRef DG(DefaultCBuffer);
+ SemaRef.Consumer.HandleTopLevelDecl(DG);
+ }
+
+ diagnoseAvailabilityViolations(TU);
+}
+
+void SemaHLSL::diagnoseAvailabilityViolations(TranslationUnitDecl *TU) {
// Skip running the diagnostics scan if the diagnostic mode is
// strict (-fhlsl-strict-availability) and the target shader stage is known
// because all relevant diagnostics were already emitted in the
@@ -2784,6 +2799,14 @@ QualType SemaHLSL::getInoutParameterType(QualType Ty) {
return Ty;
}
+static bool IsDefaultBufferConstantDecl(VarDecl *VD) {
+ QualType QT = VD->getType();
+ return VD->getDeclContext()->isTranslationUnit() &&
+ QT.getAddressSpace() == LangAS::Default &&
+ VD->getStorageClass() != SC_Static &&
+ !isInvalidConstantBufferLeafElementType(QT.getTypePtr());
+}
+
void SemaHLSL::ActOnVariableDeclarator(VarDecl *VD) {
if (VD->hasGlobalStorage()) {
// make sure the declaration has a complete type
@@ -2795,7 +2818,21 @@ void SemaHLSL::ActOnVariableDeclarator(VarDecl *VD) {
return;
}
- // find all resources on decl
+ // Global variables outside a cbuffer block that are not a resource, static,
+ // groupshared, or an empty array or struct belong to the default constant
+ // buffer $Globals
+ if (IsDefaultBufferConstantDecl(VD)) {
+ if (DefaultCBuffer == nullptr)
+ DefaultCBuffer = HLSLBufferDecl::CreateDefaultCBuffer(
+ SemaRef.getASTContext(), SemaRef.getCurLexicalContext());
+ // update address space to hlsl_constant
+ QualType NewTy = getASTContext().getAddrSpaceQualType(
+ VD->getType(), LangAS::hlsl_constant);
+ VD->setType(NewTy);
+ DefaultCBuffer->addDefaultBufferDecl(VD);
+ }
+
+ // find all resources bindings on decl
if (VD->getType()->isHLSLIntangibleType())
collectResourcesOnVarDecl(VD);
diff --git a/clang/test/AST/HLSL/default_cbuffer.hlsl b/clang/test/AST/HLSL/default_cbuffer.hlsl
new file mode 100644
index 000000000000000..9e0fce7cc53cfad
--- /dev/null
+++ b/clang/test/AST/HLSL/default_cbuffer.hlsl
@@ -0,0 +1,50 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -ast-dump -o - %s | FileCheck %s
+
+struct EmptyStruct {
+};
+
+struct S {
+ RWBuffer<float> buf;
+ EmptyStruct es;
+ float ea[0];
+ float b;
+};
+
+// CHECK: VarDecl {{.*}} used a 'hlsl_constant float'
+float a;
+
+// CHECK: VarDecl {{.*}} b 'RWBuffer<float>':'hlsl::RWBuffer<float>'
+RWBuffer<float> b;
+
+// CHECK: VarDecl {{.*}} c 'EmptyStruct'
+EmptyStruct c;
+
+// CHECK: VarDecl {{.*}} d 'float[0]'
+float d[0];
+
+// CHECK: VarDecl {{.*}} e 'RWBuffer<float>[2]'
+RWBuffer<float> e[2];
+
+// CHECK: VarDecl {{.*}} f 'groupshared float'
+groupshared float f;
+
+// CHECK: VarDecl {{.*}} g 'hlsl_constant float'
+float g;
+
+// CHECK: VarDecl {{.*}} h 'hlsl_constant S'
+S h;
+
+// CHECK: HLSLBufferDecl {{.*}} implicit cbuffer $Globals
+// CHECK: CXXRecordDecl {{.*}} implicit struct __cblayout_$Globals definition
+// CHECK: PackedAttr
+// CHECK-NEXT: FieldDecl {{.*}} a 'float'
+// CHECK-NEXT: FieldDecl {{.*}} g 'float'
+// CHECK-NEXT: FieldDecl {{.*}} h '__cblayout_S'
+
+// CHECK: CXXRecordDecl {{.*}} implicit struct __cblayout_S definition
+// CHECK: PackedAttr {{.*}} Implicit
+// CHECK-NEXT: FieldDecl {{.*}} b 'float'
+
+export float foo() {
+ return a;
+}
diff --git a/clang/test/CodeGenHLSL/basic_types.hlsl b/clang/test/CodeGenHLSL/basic_types.hlsl
index d987af45a649fb5..362042654ea8c4d 100644
--- a/clang/test/CodeGenHLSL/basic_types.hlsl
+++ b/clang/test/CodeGenHLSL/basic_types.hlsl
@@ -6,38 +6,38 @@
// RUN: -emit-llvm -disable-llvm-passes -o - -DNAMESPACED| FileCheck %s
-// CHECK: @uint16_t_Val = global i16 0, align 2
-// CHECK: @int16_t_Val = global i16 0, align 2
-// CHECK: @uint_Val = global i32 0, align 4
-// CHECK: @uint64_t_Val = global i64 0, align 8
-// CHECK: @int64_t_Val = global i64 0, align 8
-// CHECK: @int16_t2_Val = global <2 x i16> zeroinitializer, align 4
-// CHECK: @int16_t3_Val = global <3 x i16> zeroinitializer, align 8
-// CHECK: @int16_t4_Val = global <4 x i16> zeroinitializer, align 8
-// CHECK: @uint16_t2_Val = global <2 x i16> zeroinitializer, align 4
-// CHECK: @uint16_t3_Val = global <3 x i16> zeroinitializer, align 8
-// CHECK: @uint16_t4_Val = global <4 x i16> zeroinitializer, align 8
-// CHECK: @int2_Val = global <2 x i32> zeroinitializer, align 8
-// CHECK: @int3_Val = global <3 x i32> zeroinitializer, align 16
-// CHECK: @int4_Val = global <4 x i32> zeroinitializer, align 16
-// CHECK: @uint2_Val = global <2 x i32> zeroinitializer, align 8
-// CHECK: @uint3_Val = global <3 x i32> zeroinitializer, align 16
-// CHECK: @uint4_Val = global <4 x i32> zeroinitializer, align 16
-// CHECK: @int64_t2_Val = global <2 x i64> zeroinitializer, align 16
-// CHECK: @int64_t3_Val = global <3 x i64> zeroinitializer, align 32
-// CHECK: @int64_t4_Val = global <4 x i64> zeroinitializer, align 32
-// CHECK: @uint64_t2_Val = global <2 x i64> zeroinitializer, align 16
-// CHECK: @uint64_t3_Val = global <3 x i64> zeroinitializer, align 32
-// CHECK: @uint64_t4_Val = global <4 x i64> zeroinitializer, align 32
-// CHECK: @half2_Val = global <2 x half> zeroinitializer, align 4
-// CHECK: @half3_Val = global <3 x half> zeroinitializer, align 8
-// CHECK: @half4_Val = global <4 x half> zeroinitializer, align 8
-// CHECK: @float2_Val = global <2 x float> zeroinitializer, align 8
-// CHECK: @float3_Val = global <3 x float> zeroinitializer, align 16
-// CHECK: @float4_Val = global <4 x float> zeroinitializer, align 16
-// CHECK: @double2_Val = global <2 x double> zeroinitializer, align 16
-// CHECK: @double3_Val = global <3 x double> zeroinitializer, align 32
-// CHECK: @double4_Val = global <4 x double> zeroinitializer, align 32
+// CHECK: @uint16_t_Val = external addrspace(2) global i16, align 2
+// CHECK: @int16_t_Val = external addrspace(2) global i16, align 2
+// CHECK: @uint_Val = external addrspace(2) global i32, align 4
+// CHECK: @uint64_t_Val = external addrspace(2) global i64, align 8
+// CHECK: @int64_t_Val = external addrspace(2) global i64, align 8
+// CHECK: @int16_t2_Val = external addrspace(2) global <2 x i16>, align 4
+// CHECK: @int16_t3_Val = external addrspace(2) global <3 x i16>, align 8
+// CHECK: @int16_t4_Val = external addrspace(2) global <4 x i16>, align 8
+// CHECK: @uint16_t2_Val = external addrspace(2) global <2 x i16>, align 4
+// CHECK: @uint16_t3_Val = external addrspace(2) global <3 x i16>, align 8
+// CHECK: @uint16_t4_Val = external addrspace(2) global <4 x i16>, align 8
+// CHECK: @int2_Val = external addrspace(2) global <2 x i32>, align 8
+// CHECK: @int3_Val = external addrspace(2) global <3 x i32>, align 16
+// CHECK: @int4_Val = external addrspace(2) global <4 x i32>, align 16
+// CHECK: @uint2_Val = external addrspace(2) global <2 x i32>, align 8
+// CHECK: @uint3_Val = external addrspace(2) global <3 x i32>, align 16
+// CHECK: @uint4_Val = external addrspace(2) global <4 x i32>, align 16
+// CHECK: @int64_t2_Val = external addrspace(2) global <2 x i64>, align 16
+// CHECK: @int64_t3_Val = external addrspace(2) global <3 x i64>, align 32
+// CHECK: @int64_t4_Val = external addrspace(2) global <4 x i64>, align 32
+// CHECK: @uint64_t2_Val = external addrspace(2) global <2 x i64>, align 16
+// CHECK: @uint64_t3_Val = external addrspace(2) global <3 x i64>, align 32
+// CHECK: @uint64_t4_Val = external addrspace(2) global <4 x i64>, align 32
+// CHECK: @half2_Val = external addrspace(2) global <2 x half>, align 4
+// CHECK: @half3_Val = external addrspace(2) global <3 x half>, align 8
+// CHECK: @half4_Val = external addrspace(2) global <4 x half>, align 8
+// CHECK: @float2_Val = external addrspace(2) global <2 x float>, align 8
+// CHECK: @float3_Val = external addrspace(2) global <3 x float>, align 16
+// CHECK: @float4_Val = external addrspace(2) global <4 x float>, align 16
+// CHECK: @double2_Val = external addrspace(2) global <2 x double>, align 16
+// CHECK: @double3_Val = external addrspace(2) global <3 x double>, align 32
+// CHECK: @double4_Val = external addrspace(2) global <4 x double>, align 32
#ifdef NAMESPACED
#define TYPE_DECL(T) hlsl::T T##_Val
diff --git a/clang/test/CodeGenHLSL/default_cbuffer.hlsl b/clang/test/CodeGenHLSL/default_cbuffer.hlsl
new file mode 100644
index 000000000000000..7368997b51ac9ec
--- /dev/null
+++ b/clang/test/CodeGenHLSL/default_cbuffer.hlsl
@@ -0,0 +1,43 @@
+// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.3-compute \
+// RUN: -fnative-half-type -emit-llvm -disable-llvm-passes -o - %s | FileCheck %s
+
+// CHECK: %"struct.__cblayout_$Globals" = type { float, float, %struct.__cblayout_S }
+// CHECK: %struct.__cblayout_S = type { float }
+
+// CHECK-DAG: @"$Globals.cb" = external constant target("dx.CBuffer", %"struct.__cblayout_$Globals")
+// CHECK-DAG:...
[truncated]
|
clang/include/clang/AST/Decl.h
Outdated
@@ -5072,6 +5080,20 @@ class HLSLBufferDecl final : public NamedDecl, public DeclContext { | |||
return static_cast<HLSLBufferDecl *>(const_cast<DeclContext *>(DC)); | |||
} | |||
|
|||
// Iterator for the buffer decls. Concatenates the list of decls parented |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just want to clarify what this comment says. The children decls of this hlslbufferdecl are concatenated with the list of default buffer decls? Does the order of this matter?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is correct. We are not depending on the order, but I like to put default buffer decls first and the children decls second because the children decls will include an implicit buffer layout struct decl that is created last. I will update the comment to make it clearer.
private: | ||
void collectResourcesOnVarDecl(VarDecl *D); | ||
void collectResourcesOnUserRecordDecl(const VarDecl *VD, | ||
const RecordType *RT); | ||
void processExplicitBindingsOnDecl(VarDecl *D); | ||
|
||
void diagnoseAvailabilityViolations(TranslationUnitDecl *TU); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do you want this to be private now?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It used to be called directly from clang Sema. Now clang Sema calls HLSL Sema's ActOnEndOfTranslationUnit
because we need to do more work at the end of translation unit. The diagnoseAvailabilityViolations
is called from SemaHLSL::ActOnEndOfTranslationUnit
so it can be private now.
|
||
HLSLBufferDecl::buffer_decl_iterator HLSLBufferDecl::buffer_decls_end() const { | ||
return buffer_decl_iterator( | ||
llvm::iterator_range(DefaultBufferDecls.end(), DefaultBufferDecls.end()), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is supposed to say end, end?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it signifies the end of the list. buffer_decl_iterator
is a llvm::concat_iterator
and it takes a list of ranges.
clang/lib/CodeGen/CGHLSLRuntime.cpp
Outdated
if (VDTy->isStructureType() && VDTy->isHLSLIntangibleType()) | ||
// FIXME: handle resources in cbuffer structs | ||
llvm_unreachable("resources in cbuffer are not supported yet"); | ||
// FIXME: handle resources in cbuffer user-defined structs |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is future work? not a reminder for this pr?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, this is a future work (llvm/wg-hlsl#175). I've removed the llvm_unreachable
because we use it in existing tests.
…m-project into default-cbuffer
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/55/builds/7360 Here is the relevant piece of the build log for the reference
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/24/builds/5528 Here is the relevant piece of the build log for the reference
|
…`" (#128112) Reverts llvm/llvm-project#125807 Reverting this change because of failing tests.
All variable declarations in the global scope that are not resources, static or empty are implicitly added to implicit constant buffer `$Globals`. They are created in `hlsl_constant` address space and collected in an implicit `HLSLBufferDecl` node that is added to the AST at the end of the translation unit. Codegen is the same as for explicit constant buffers. Fixes llvm#123801
All variable declarations in the global scope that are not resources, static or empty are implicitly added to implicit constant buffer
$Globals
. They are created inhlsl_constant
address space and collected in an implicitHLSLBufferDecl
node that is added to the AST at the end of the translation unit. Codegen is the same as for explicit constant buffers.Fixes #123801