Skip to content

Commit 2a5ee25

Browse files
authored
[HLSL] Allow resource annotations to specify only register space (#135287)
Specifying only `space` in a `register` annotation means the compiler should implicitly assign a register slot to the resource from the provided virtual register space. Closes #133346
1 parent 2cd829f commit 2a5ee25

File tree

7 files changed

+65
-41
lines changed

7 files changed

+65
-41
lines changed

clang/include/clang/Basic/Attr.td

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4752,20 +4752,25 @@ def HLSLResourceBinding: InheritableAttr {
47524752

47534753
private:
47544754
RegisterType RegType;
4755-
unsigned SlotNumber;
4755+
std::optional<unsigned> SlotNumber;
47564756
unsigned SpaceNumber;
47574757

47584758
public:
4759-
void setBinding(RegisterType RT, unsigned SlotNum, unsigned SpaceNum) {
4759+
void setBinding(RegisterType RT, std::optional<unsigned> SlotNum, unsigned SpaceNum) {
47604760
RegType = RT;
47614761
SlotNumber = SlotNum;
47624762
SpaceNumber = SpaceNum;
47634763
}
4764+
bool isImplicit() const {
4765+
return !SlotNumber.has_value();
4766+
}
47644767
RegisterType getRegisterType() const {
4768+
assert(!isImplicit() && "binding does not have register slot");
47654769
return RegType;
47664770
}
47674771
unsigned getSlotNumber() const {
4768-
return SlotNumber;
4772+
assert(!isImplicit() && "binding does not have register slot");
4773+
return SlotNumber.value();
47694774
}
47704775
unsigned getSpaceNumber() const {
47714776
return SpaceNumber;

clang/lib/CodeGen/CGHLSLRuntime.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ void CGHLSLRuntime::addBuffer(const HLSLBufferDecl *BufDecl) {
261261
BufDecl->getAttr<HLSLResourceBindingAttr>();
262262
// FIXME: handle implicit binding if no binding attribute is found
263263
// (llvm/llvm-project#110722)
264-
if (RBA)
264+
if (RBA && !RBA->isImplicit())
265265
initializeBufferFromBinding(CGM, BufGV, RBA->getSlotNumber(),
266266
RBA->getSpaceNumber());
267267
}

clang/lib/Parse/ParseHLSL.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -163,11 +163,16 @@ void Parser::ParseHLSLAnnotations(ParsedAttributes &Attrs,
163163
SourceLocation SlotLoc = Tok.getLocation();
164164
ArgExprs.push_back(ParseIdentifierLoc());
165165

166-
// Add numeric_constant for fix-it.
167-
if (SlotStr.size() == 1 && Tok.is(tok::numeric_constant))
166+
if (SlotStr.size() == 1) {
167+
if (!Tok.is(tok::numeric_constant)) {
168+
Diag(Tok.getLocation(), diag::err_expected) << tok::numeric_constant;
169+
SkipUntil(tok::r_paren, StopAtSemi); // skip through )
170+
return;
171+
}
172+
// Add numeric_constant for fix-it.
168173
fixSeparateAttrArgAndNumber(SlotStr, SlotLoc, Tok, ArgExprs, *this,
169174
Actions.Context, PP);
170-
175+
}
171176
if (Tok.is(tok::comma)) {
172177
ConsumeToken(); // consume comma
173178
if (!Tok.is(tok::identifier)) {

clang/lib/Sema/SemaHLSL.cpp

Lines changed: 36 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1533,72 +1533,80 @@ void SemaHLSL::handleResourceBindingAttr(Decl *TheDecl, const ParsedAttr &AL) {
15331533
diag::err_incomplete_type))
15341534
return;
15351535
}
1536-
StringRef Space = "space0";
1536+
15371537
StringRef Slot = "";
1538+
StringRef Space = "";
1539+
SourceLocation SlotLoc, SpaceLoc;
15381540

15391541
if (!AL.isArgIdent(0)) {
15401542
Diag(AL.getLoc(), diag::err_attribute_argument_type)
15411543
<< AL << AANT_ArgumentIdentifier;
15421544
return;
15431545
}
1544-
15451546
IdentifierLoc *Loc = AL.getArgAsIdent(0);
1546-
StringRef Str = Loc->getIdentifierInfo()->getName();
1547-
SourceLocation ArgLoc = Loc->getLoc();
15481547

1549-
SourceLocation SpaceArgLoc;
1550-
bool SpecifiedSpace = false;
15511548
if (AL.getNumArgs() == 2) {
1552-
SpecifiedSpace = true;
1553-
Slot = Str;
1549+
Slot = Loc->getIdentifierInfo()->getName();
1550+
SlotLoc = Loc->getLoc();
15541551
if (!AL.isArgIdent(1)) {
15551552
Diag(AL.getLoc(), diag::err_attribute_argument_type)
15561553
<< AL << AANT_ArgumentIdentifier;
15571554
return;
15581555
}
1559-
1560-
IdentifierLoc *Loc = AL.getArgAsIdent(1);
1556+
Loc = AL.getArgAsIdent(1);
15611557
Space = Loc->getIdentifierInfo()->getName();
1562-
SpaceArgLoc = Loc->getLoc();
1558+
SpaceLoc = Loc->getLoc();
15631559
} else {
1564-
Slot = Str;
1560+
StringRef Str = Loc->getIdentifierInfo()->getName();
1561+
if (Str.starts_with("space")) {
1562+
Space = Str;
1563+
SpaceLoc = Loc->getLoc();
1564+
} else {
1565+
Slot = Str;
1566+
SlotLoc = Loc->getLoc();
1567+
Space = "space0";
1568+
}
15651569
}
15661570

1567-
RegisterType RegType;
1568-
unsigned SlotNum = 0;
1571+
RegisterType RegType = RegisterType::SRV;
1572+
std::optional<unsigned> SlotNum;
15691573
unsigned SpaceNum = 0;
15701574

1571-
// Validate.
1575+
// Validate slot
15721576
if (!Slot.empty()) {
15731577
if (!convertToRegisterType(Slot, &RegType)) {
1574-
Diag(ArgLoc, diag::err_hlsl_binding_type_invalid) << Slot.substr(0, 1);
1578+
Diag(SlotLoc, diag::err_hlsl_binding_type_invalid) << Slot.substr(0, 1);
15751579
return;
15761580
}
15771581
if (RegType == RegisterType::I) {
1578-
Diag(ArgLoc, diag::warn_hlsl_deprecated_register_type_i);
1582+
Diag(SlotLoc, diag::warn_hlsl_deprecated_register_type_i);
15791583
return;
15801584
}
1581-
15821585
StringRef SlotNumStr = Slot.substr(1);
1583-
if (SlotNumStr.getAsInteger(10, SlotNum)) {
1584-
Diag(ArgLoc, diag::err_hlsl_unsupported_register_number);
1586+
unsigned N;
1587+
if (SlotNumStr.getAsInteger(10, N)) {
1588+
Diag(SlotLoc, diag::err_hlsl_unsupported_register_number);
15851589
return;
15861590
}
1591+
SlotNum = N;
15871592
}
15881593

1594+
// Validate space
15891595
if (!Space.starts_with("space")) {
1590-
Diag(SpaceArgLoc, diag::err_hlsl_expected_space) << Space;
1596+
Diag(SpaceLoc, diag::err_hlsl_expected_space) << Space;
15911597
return;
15921598
}
15931599
StringRef SpaceNumStr = Space.substr(5);
15941600
if (SpaceNumStr.getAsInteger(10, SpaceNum)) {
1595-
Diag(SpaceArgLoc, diag::err_hlsl_expected_space) << Space;
1601+
Diag(SpaceLoc, diag::err_hlsl_expected_space) << Space;
15961602
return;
15971603
}
15981604

1599-
if (!DiagnoseHLSLRegisterAttribute(SemaRef, ArgLoc, TheDecl, RegType,
1600-
SpecifiedSpace))
1601-
return;
1605+
// If we have slot, diagnose it is the right register type for the decl
1606+
if (SlotNum.has_value())
1607+
if (!DiagnoseHLSLRegisterAttribute(SemaRef, SlotLoc, TheDecl, RegType,
1608+
!SpaceLoc.isInvalid()))
1609+
return;
16021610

16031611
HLSLResourceBindingAttr *NewAttr =
16041612
HLSLResourceBindingAttr::Create(getASTContext(), Slot, Space, AL);
@@ -1971,7 +1979,7 @@ void SemaHLSL::ActOnEndOfTranslationUnit(TranslationUnitDecl *TU) {
19711979
for (const Decl *VD : DefaultCBufferDecls) {
19721980
const HLSLResourceBindingAttr *RBA =
19731981
VD->getAttr<HLSLResourceBindingAttr>();
1974-
if (RBA &&
1982+
if (RBA && !RBA->isImplicit() &&
19751983
RBA->getRegisterType() == HLSLResourceBindingAttr::RegisterType::C) {
19761984
DefaultCBuffer->setHasValidPackoffset(true);
19771985
break;
@@ -3262,7 +3270,7 @@ static bool initVarDeclWithCtor(Sema &S, VarDecl *VD,
32623270

32633271
static bool initGlobalResourceDecl(Sema &S, VarDecl *VD) {
32643272
HLSLResourceBindingAttr *RBA = VD->getAttr<HLSLResourceBindingAttr>();
3265-
if (!RBA)
3273+
if (!RBA || RBA->isImplicit())
32663274
// FIXME: add support for implicit binding (llvm/llvm-project#110722)
32673275
return false;
32683276

@@ -3347,7 +3355,7 @@ void SemaHLSL::processExplicitBindingsOnDecl(VarDecl *VD) {
33473355
bool HasBinding = false;
33483356
for (Attr *A : VD->attrs()) {
33493357
HLSLResourceBindingAttr *RBA = dyn_cast<HLSLResourceBindingAttr>(A);
3350-
if (!RBA)
3358+
if (!RBA || RBA->isImplicit())
33513359
continue;
33523360
HasBinding = true;
33533361

clang/test/AST/HLSL/resource_binding_attr.hlsl

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -finclude-default-header -ast-dump -o - %s | FileCheck %s
1+
// RUN: %clang_cc1 -Wno-hlsl-implicit-binding -triple dxil-pc-shadermodel6.3-library -finclude-default-header -ast-dump -o - %s | FileCheck %s
22

33
// CHECK: HLSLBufferDecl {{.*}} line:[[# @LINE + 4]]:9 cbuffer CB
44
// CHECK-NEXT: HLSLResourceClassAttr {{.*}} Implicit CBuffer
@@ -30,6 +30,10 @@ RWBuffer<float> UAV : register(u3);
3030
// CHECK: HLSLResourceBindingAttr {{.*}} "u4" "space0"
3131
RWBuffer<float> UAV1 : register(u2), UAV2 : register(u4);
3232

33+
// CHECK: VarDecl {{.*}} UAV3 'RWBuffer<float>':'hlsl::RWBuffer<float>'
34+
// CHECK: HLSLResourceBindingAttr {{.*}} "" "space5"
35+
RWBuffer<float> UAV3 : register(space5);
36+
3337
//
3438
// Default constants ($Globals) layout annotations
3539

clang/test/SemaHLSL/resource_binding_attr_error.hlsl

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,18 @@ cbuffer c : register(bf, s2) {
2222
// expected-error@+1 {{expected identifier}}
2323
cbuffer A : register() {}
2424

25-
// expected-error@+1 {{register number should be an integer}}
26-
cbuffer B : register(space1) {}
25+
// expected-error@+1 {{invalid space specifier 'space' used; expected 'space' followed by an integer, like space1}}
26+
cbuffer B : register(space) {}
2727

2828
// expected-error@+1 {{wrong argument format for hlsl attribute, use b2 instead}}
2929
cbuffer C : register(b 2) {}
3030

3131
// expected-error@+1 {{wrong argument format for hlsl attribute, use b2 instead}}
3232
cbuffer D : register(b 2, space3) {}
3333

34+
// expected-error@+1 {{expected <numeric_constant>}}
35+
cbuffer E : register(u-1) {};
36+
3437
// expected-error@+1 {{'register' attribute only applies to cbuffer/tbuffer and external global variables}}
3538
static MyTemplatedSRV<float> U : register(u5);
3639

clang/test/SemaHLSL/resource_binding_implicit.hlsl

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,8 @@ RWBuffer<int> c;
1414
// No warning - explicit binding.
1515
RWBuffer<float> d : register(u0);
1616

17-
// TODO: Add this test once #135287 lands
18-
// TODO: ... @+1 {{resource has implicit register binding}}
19-
// TODO: RWBuffer<float> dd : register(space1);
17+
// expected-warning@+1 {{resource has implicit register binding}}
18+
RWBuffer<float> dd : register(space1);
2019

2120
// No warning - explicit binding.
2221
RWBuffer<float> ddd : register(u3, space4);

0 commit comments

Comments
 (0)