@@ -573,33 +573,8 @@ LoweredValInfo emitCallToDeclRef(
573
573
bool justAGetter = true ;
574
574
for (auto accessorDeclRef : getMembersOfType<AccessorDecl>(subscriptDeclRef))
575
575
{
576
- // If the subscript declares a `ref` accessor, then we can just
577
- // invoke that directly to get an l-value we can use.
578
- if (auto refAccessorDeclRef = accessorDeclRef.As <RefAccessorDecl>())
579
- {
580
- // The `ref` accessor will return a pointer to the value, so
581
- // we need to reflect that in the type of our `call` instruction.
582
- IRType* ptrType = context->irBuilder ->getPtrType (type);
583
-
584
- // Rather than call `emitCallToVal` here, we make a recursive call
585
- // to `emitCallToDeclRef` so that it can handle things like intrinsic-op
586
- // modifiers attached to the acecssor.
587
- LoweredValInfo callVal = emitCallToDeclRef (
588
- context,
589
- ptrType,
590
- refAccessorDeclRef,
591
- funcType,
592
- argCount,
593
- args);
594
-
595
- // The result from the call needs to be implicitly dereferenced,
596
- // so that it can work as an l-value of the desired result type.
597
- return LoweredValInfo::ptr (getSimpleVal (context, callVal));
598
- }
599
-
600
- // If we don't find a `ref` accessor, then we want to track whether
601
- // this subscript has any accessors other than `get` (assuming
602
- // that everything except `get` can be used for setting...).
576
+ // We want to track whether this subscript has any accessors other than
577
+ // `get` (assuming that everything except `get` can be used for setting...).
603
578
604
579
if (auto foundGetterDeclRef = accessorDeclRef.As <GetterDecl>())
605
580
{
@@ -821,6 +796,15 @@ LoweredValInfo materialize(
821
796
{
822
797
auto boundSubscriptInfo = lowered.getBoundSubscriptInfo ();
823
798
799
+ // We are being asked to extract a value from a subscript call
800
+ // (e.g., `base[index]`). We will first check if the subscript
801
+ // declared a getter and use that if possible, and then fall
802
+ // back to a `ref` accessor if one is defined.
803
+ //
804
+ // (Picking the `get` over the `ref` accessor simplifies things
805
+ // in case the `get` operation has a natural translation for
806
+ // a target, while the general `ref` case does not...)
807
+
824
808
auto getters = getMembersOfType<GetterDecl>(boundSubscriptInfo->declRef );
825
809
if (getters.Count ())
826
810
{
@@ -833,6 +817,27 @@ LoweredValInfo materialize(
833
817
goto top;
834
818
}
835
819
820
+ auto refAccessors = getMembersOfType<RefAccessorDecl>(boundSubscriptInfo->declRef );
821
+ if (refAccessors.Count ())
822
+ {
823
+ // The `ref` accessor will return a pointer to the value, so
824
+ // we need to reflect that in the type of our `call` instruction.
825
+ IRType* ptrType = context->irBuilder ->getPtrType (boundSubscriptInfo->type );
826
+
827
+ LoweredValInfo refVal = emitCallToDeclRef (
828
+ context,
829
+ ptrType,
830
+ *refAccessors.begin (),
831
+ nullptr ,
832
+ boundSubscriptInfo->args );
833
+
834
+ // The result from the call needs to be implicitly dereferenced,
835
+ // so that it can work as an l-value of the desired result type.
836
+ lowered = LoweredValInfo::ptr (getSimpleVal (context, refVal));
837
+
838
+ goto top;
839
+ }
840
+
836
841
SLANG_UNEXPECTED (" subscript had no getter" );
837
842
UNREACHABLE_RETURN (LoweredValInfo ());
838
843
}
@@ -1308,7 +1313,7 @@ static void addNameHint(
1308
1313
{
1309
1314
Name* name = getNameForNameHint (context, decl);
1310
1315
if (!name)
1311
- return ;
1316
+ return ;
1312
1317
context->irBuilder ->addDecoration <IRNameHintDecoration>(inst)->name = name;
1313
1318
}
1314
1319
@@ -2958,18 +2963,51 @@ IRInst* getAddress(
2958
2963
SourceLoc diagnosticLocation)
2959
2964
{
2960
2965
LoweredValInfo val = inVal;
2966
+
2961
2967
switch (val.flavor )
2962
2968
{
2963
2969
case LoweredValInfo::Flavor::Ptr :
2964
2970
return val.val ;
2965
2971
2966
- // TODO: are there other cases we need to handle here (e.g.,
2967
- // turning a bound subscript/property into an address)
2972
+ case LoweredValInfo::Flavor::BoundSubscript:
2973
+ {
2974
+ // If we are are trying to turn a subscript operation like `buffer[index]`
2975
+ // into a pointer, then we need to find a `ref` accessor declared
2976
+ // as part of the subscript operation being referenced.
2977
+ //
2978
+ auto subscriptInfo = val.getBoundSubscriptInfo ();
2979
+ auto refAccessors = getMembersOfType<RefAccessorDecl>(subscriptInfo->declRef );
2980
+ if (refAccessors.Count ())
2981
+ {
2982
+ // The `ref` accessor will return a pointer to the value, so
2983
+ // we need to reflect that in the type of our `call` instruction.
2984
+ IRType* ptrType = context->irBuilder ->getPtrType (subscriptInfo->type );
2985
+
2986
+ LoweredValInfo refVal = emitCallToDeclRef (
2987
+ context,
2988
+ ptrType,
2989
+ *refAccessors.begin (),
2990
+ nullptr ,
2991
+ subscriptInfo->args );
2992
+
2993
+ // The result from the call should be a pointer, and it
2994
+ // is the address that we wanted in the first place.
2995
+ return getSimpleVal (context, refVal);
2996
+ }
2997
+
2998
+ // Otherwise, there was no `ref` accessor, and so it is not possible
2999
+ // to materialize this location into a pointer for whatever purpose
3000
+ // we have in mind (e.g., passing it to an atomic operation).
3001
+ }
3002
+
3003
+ // TODO: are there other cases we need to handled here?
2968
3004
2969
3005
default :
2970
- context->getSink ()->diagnose (diagnosticLocation, Diagnostics::invalidLValueForRefParameter);
2971
- return nullptr ;
3006
+ break ;
2972
3007
}
3008
+
3009
+ context->getSink ()->diagnose (diagnosticLocation, Diagnostics::invalidLValueForRefParameter);
3010
+ return nullptr ;
2973
3011
}
2974
3012
2975
3013
void assign (
@@ -3090,15 +3128,17 @@ void assign(
3090
3128
// `someStructuredBuffer[index]`.
3091
3129
//
3092
3130
// When storing to such a value, we need to emit a call
3093
- // to the appropriate builtin "setter" accessor.
3131
+ // to the appropriate builtin "setter" accessor, if there
3132
+ // is one, and then fall back to a `ref` accessor if
3133
+ // there is no setter.
3134
+ //
3094
3135
auto subscriptInfo = left.getBoundSubscriptInfo ();
3095
3136
3096
3137
// Search for an appropriate "setter" declaration
3097
3138
auto setters = getMembersOfType<SetterDecl>(subscriptInfo->declRef );
3098
3139
if (setters.Count ())
3099
3140
{
3100
3141
auto allArgs = subscriptInfo->args ;
3101
-
3102
3142
addArgs (context, &allArgs, right);
3103
3143
3104
3144
emitCallToDeclRef (
@@ -3110,6 +3150,28 @@ void assign(
3110
3150
return ;
3111
3151
}
3112
3152
3153
+ auto refAccessors = getMembersOfType<RefAccessorDecl>(subscriptInfo->declRef );
3154
+ if (refAccessors.Count ())
3155
+ {
3156
+ // The `ref` accessor will return a pointer to the value, so
3157
+ // we need to reflect that in the type of our `call` instruction.
3158
+ IRType* ptrType = context->irBuilder ->getPtrType (subscriptInfo->type );
3159
+
3160
+ LoweredValInfo refVal = emitCallToDeclRef (
3161
+ context,
3162
+ ptrType,
3163
+ *refAccessors.begin (),
3164
+ nullptr ,
3165
+ subscriptInfo->args );
3166
+
3167
+ // The result from the call needs to be implicitly dereferenced,
3168
+ // so that it can work as an l-value of the desired result type.
3169
+ left = LoweredValInfo::ptr (getSimpleVal (context, refVal));
3170
+
3171
+ // Tail-recursively attempt assignment again on the new l-value.
3172
+ goto top;
3173
+ }
3174
+
3113
3175
// No setter found? Then we have an error!
3114
3176
SLANG_UNEXPECTED (" no setter found" );
3115
3177
break ;
0 commit comments