Skip to content

Commit 6f68127

Browse files
author
Tim Foley
authored
IR: fixes for subscript accessors (shader-slang#322)
* IR: fixes for subscript accessors Fixes shader-slang#320 This is a bunch of fixes for handling of `__subscript` operations on builtin types (notably `RWStructuredBuffer` and `StructuredBuffer` at this point). - Automatically add a `GetterDecl` to any subscript decalratio was declithout any accessors. This avoids hitting a null- dereference in the emit logic. - Add a notion of a `RefAccessor` (declared with `ref`) as a peer to getters and setters. The idea is that a `ref` accessor returns a pointer to the element data, so that it can be used for both getting and setting values. This is closer to the behavior of `RWStructuredBuffer` element access in HLSL. - Fixes for dealing with "access chains" where there might be a combination of a subscript (where the is a `get` and `set` but no `ref`) and member access, so that we have to read the base value into a temp, modify it, and then write it back. - This logic is still a bit of a mess, so we will eventually want to take a more consistent pass over this to deal with how we "materialize" values for setters. - Update `RWStructuredBuffer` to have a `ref` accessor, and then fix up the IR tests to handle the new opcode that I added for it. - Note: I didn't handle this as an intrinsic simply because the `tests/ir/*` tests aren't really set up to handle builtins with ugly mangled names. * Fixup: type error in VM for buffer element ref I was using the result type of the op as the element type for computing the element address, but the result type is a pointer to the real element type. This caused test failures on 64-bit platforms, where the stride of the buffer in the `ir/factorial` test needs to be 4. The fix is to assume the result type is a pointer, and extract the pointed-to type out of that.
1 parent 35318fb commit 6f68127

12 files changed

+347
-59
lines changed

source/slang/check.cpp

+30
Original file line numberDiff line numberDiff line change
@@ -3575,6 +3575,32 @@ namespace Slang
35753575

35763576
decl->SetCheckState(DeclCheckState::CheckedHeader);
35773577

3578+
// If we have a subscript declaration with no accessor declarations,
3579+
// then we should create a single `GetterDecl` to represent
3580+
// the implicit meaning of their declaration, so:
3581+
//
3582+
// subscript(uint index) -> T;
3583+
//
3584+
// becomes:
3585+
//
3586+
// subscript(uint index) -> T { get; }
3587+
//
3588+
3589+
bool anyAccessors = false;
3590+
for(auto accessorDecl : decl->getMembersOfType<AccessorDecl>())
3591+
{
3592+
anyAccessors = true;
3593+
}
3594+
3595+
if(!anyAccessors)
3596+
{
3597+
RefPtr<GetterDecl> getterDecl = new GetterDecl();
3598+
getterDecl->loc = decl->loc;
3599+
3600+
getterDecl->ParentDecl = decl;
3601+
decl->Members.Add(getterDecl);
3602+
}
3603+
35783604
for(auto mm : decl->Members)
35793605
{
35803606
checkDecl(mm);
@@ -4662,6 +4688,10 @@ namespace Slang
46624688
{
46634689
callExpr->type.IsLeftValue = true;
46644690
}
4691+
for(auto refAccessor : subscriptDeclRef.getDecl()->getMembersOfType<RefAccessorDecl>())
4692+
{
4693+
callExpr->type.IsLeftValue = true;
4694+
}
46654695
}
46664696

46674697
// TODO: there may be other cases that confer l-value-ness

source/slang/decl-defs.h

+1
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ SIMPLE_SYNTAX_CLASS(AccessorDecl, FunctionDeclBase)
179179

180180
SIMPLE_SYNTAX_CLASS(GetterDecl, AccessorDecl)
181181
SIMPLE_SYNTAX_CLASS(SetterDecl, AccessorDecl)
182+
SIMPLE_SYNTAX_CLASS(RefAccessorDecl, AccessorDecl)
182183

183184
SIMPLE_SYNTAX_CLASS(FuncDecl, FunctionDeclBase)
184185

source/slang/emit.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -4875,6 +4875,7 @@ emitDeclImpl(decl, nullptr);
48754875
case kIROp_FieldAddress:
48764876
case kIROp_getElementPtr:
48774877
case kIROp_specialize:
4878+
case kIROp_BufferElementRef:
48784879
return true;
48794880
}
48804881

@@ -5516,6 +5517,7 @@ emitDeclImpl(decl, nullptr);
55165517
break;
55175518

55185519
case kIROp_BufferLoad:
5520+
case kIROp_BufferElementRef:
55195521
emitIROperand(ctx, inst->getArg(0));
55205522
emit("[");
55215523
emitIROperand(ctx, inst->getArg(1));

source/slang/hlsl.meta.slang

+3-7
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,7 @@ struct StructuredBuffer
4444
T Load(int location);
4545
T Load(int location, out uint status);
4646

47-
__intrinsic_op(bufferLoad)
48-
__subscript(uint index) -> T;
47+
__subscript(uint index) -> T { __intrinsic_op(bufferLoad) get; };
4948
};
5049

5150
__generic<T> __magic_type(HLSLConsumeStructuredBufferType) struct ConsumeStructuredBuffer
@@ -201,11 +200,8 @@ struct RWStructuredBuffer
201200

202201
__subscript(uint index) -> T
203202
{
204-
__intrinsic_op(bufferLoad)
205-
get;
206-
207-
__intrinsic_op(bufferStore)
208-
set;
203+
__intrinsic_op(bufferElementRef)
204+
ref;
209205
}
210206
};
211207

source/slang/hlsl.meta.slang.h

+3-7
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,7 @@ sb << "\n";
4545
sb << " T Load(int location);\n";
4646
sb << " T Load(int location, out uint status);\n";
4747
sb << "\n";
48-
sb << " __intrinsic_op(bufferLoad)\n";
49-
sb << " __subscript(uint index) -> T;\n";
48+
sb << " __subscript(uint index) -> T { __intrinsic_op(bufferLoad) get; };\n";
5049
sb << "};\n";
5150
sb << "\n";
5251
sb << "__generic<T> __magic_type(HLSLConsumeStructuredBufferType) struct ConsumeStructuredBuffer\n";
@@ -203,11 +202,8 @@ sb << " T Load(int location, out uint status);\n";
203202
sb << "\n";
204203
sb << "\t__subscript(uint index) -> T\n";
205204
sb << "\t{\n";
206-
sb << "\t\t__intrinsic_op(bufferLoad)\n";
207-
sb << "\t\tget;\n";
208-
sb << "\n";
209-
sb << "\t\t__intrinsic_op(bufferStore)\n";
210-
sb << "\t\tset;\n";
205+
sb << " __intrinsic_op(bufferElementRef)\n";
206+
sb << " ref;\n";
211207
sb << "\t}\n";
212208
sb << "};\n";
213209
sb << "\n";

source/slang/ir-inst-defs.h

+1
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ INST(Store, store, 2, 0)
119119

120120
INST(BufferLoad, bufferLoad, 2, 0)
121121
INST(BufferStore, bufferStore, 3, 0)
122+
INST(BufferElementRef, bufferElementRef, 2, 0)
122123

123124
INST(FieldExtract, get_field, 2, 0)
124125
INST(FieldAddress, get_field_addr, 2, 0)

0 commit comments

Comments
 (0)