@@ -808,6 +808,24 @@ struct SpecializationContext
808
808
return false ;
809
809
}
810
810
811
+ // / Used by `maybeSpecailizeBufferLoadCall`, this function returns a new specialized callee that
812
+ // / replaces a `specialize(.operator[], oldType)` to `specialize(.operator[], newElementType)`.
813
+ IRInst* getNewSpecializedBufferLoadCallee (
814
+ IRInst* oldSpecializedCallee,
815
+ IRType* newContainerType,
816
+ IRType* newElementType)
817
+ {
818
+ auto oldSpecialize = cast<IRSpecialize>(oldSpecializedCallee);
819
+ SLANG_ASSERT (oldSpecialize->getArgCount () == 1 );
820
+ IRBuilder builder;
821
+ builder.sharedBuilder = &sharedBuilderStorage;
822
+ builder.setInsertBefore (oldSpecializedCallee);
823
+ auto calleeType = builder.getFuncType (1 , &newContainerType, newElementType);
824
+ auto newSpecialize = builder.emitSpecializeInst (
825
+ calleeType, oldSpecialize->getBase (), 1 , (IRInst**)&newElementType);
826
+ return newSpecialize;
827
+ }
828
+
811
829
// / Transform a buffer load intrinsic call.
812
830
// / `bufferLoad(wrapExistential(bufferObj, wrapArgs), loadArgs)` should be transformed into
813
831
// / `wrapExistential(bufferLoad(bufferObj, loadArgs), wragArgs)`.
@@ -844,11 +862,18 @@ struct SpecializationContext
844
862
{
845
863
slotOperands.add (wrapExistential->getSlotOperand (ii));
846
864
}
847
- auto newCall = builder.emitCallInst (elementType, inst->getCallee (), args);
865
+ // The old callee should be in the form of `specialize(.operator[], IInterfaceType)`,
866
+ // we should update it to be `specialize(.operator[], elementType)`, so the return type
867
+ // of the load call is `elementType`.
868
+ auto oldCallee = inst->getCallee ();
869
+ auto newCallee = getNewSpecializedBufferLoadCallee (inst->getCallee (), sbType, elementType);
870
+ auto newCall = builder.emitCallInst (elementType, newCallee, args);
848
871
auto newWrapExistential = builder.emitWrapExistential (
849
872
resultType, newCall, slotOperandCount, slotOperands.getBuffer ());
850
873
inst->replaceUsesWith (newWrapExistential);
851
874
inst->removeAndDeallocate ();
875
+ SLANG_ASSERT (!oldCallee->hasUses ());
876
+ oldCallee->removeAndDeallocate ();
852
877
addUsersToWorkList (newWrapExistential);
853
878
return true ;
854
879
}
@@ -1080,7 +1105,8 @@ struct SpecializationContext
1080
1105
//
1081
1106
if (as<IRInterfaceType>(type))
1082
1107
return true ;
1083
-
1108
+ if (calcExistentialTypeParamSlotCount (type) != 0 )
1109
+ return true ;
1084
1110
// Eventually we will also want to handle arrays over
1085
1111
// existential types, but that will require careful
1086
1112
// handling in many places.
@@ -1518,6 +1544,11 @@ struct SpecializationContext
1518
1544
type = arrayType->getElementType ();
1519
1545
goto top;
1520
1546
}
1547
+ else if (auto sbType = as<IRHLSLStructuredBufferTypeBase>(type))
1548
+ {
1549
+ type = sbType->getElementType ();
1550
+ goto top;
1551
+ }
1521
1552
else if ( auto structType = as<IRStructType>(type) )
1522
1553
{
1523
1554
UInt count = 0 ;
@@ -1800,6 +1831,11 @@ struct SpecializationContext
1800
1831
type = ptrLikeType->getElementType ();
1801
1832
goto top;
1802
1833
}
1834
+ else if (auto sbType = as<IRHLSLStructuredBufferTypeBase>(type))
1835
+ {
1836
+ type = sbType->getElementType ();
1837
+ goto top;
1838
+ }
1803
1839
else if ( auto structType = as<IRStructType>(type) )
1804
1840
{
1805
1841
UInt count = 0 ;
@@ -1872,15 +1908,15 @@ struct SpecializationContext
1872
1908
baseElementType,
1873
1909
slotOperandCount,
1874
1910
type->getExistentialArgs ());
1875
- addToWorkList (wrappedElementType);
1876
1911
1877
1912
auto newPtrLikeType = builder.getType (
1878
1913
baseType->op ,
1879
1914
1 ,
1880
1915
&wrappedElementType);
1916
+ addUsersToWorkList (type);
1881
1917
addToWorkList (newPtrLikeType);
1918
+ addToWorkList (wrappedElementType);
1882
1919
1883
- addUsersToWorkList (type);
1884
1920
type->replaceUsesWith (newPtrLikeType);
1885
1921
type->removeAndDeallocate ();
1886
1922
return ;
@@ -1911,10 +1947,13 @@ struct SpecializationContext
1911
1947
}
1912
1948
1913
1949
IRStructType* newStructType = nullptr ;
1950
+ addUsersToWorkList (type);
1951
+
1914
1952
if ( !existentialSpecializedStructs.TryGetValue (key, newStructType) )
1915
1953
{
1916
1954
builder.setInsertBefore (baseStructType);
1917
1955
newStructType = builder.createStructType ();
1956
+ addToWorkList (newStructType);
1918
1957
1919
1958
auto fieldSlotArgs = type->getExistentialArgs ();
1920
1959
@@ -1939,10 +1978,8 @@ struct SpecializationContext
1939
1978
}
1940
1979
1941
1980
existentialSpecializedStructs.Add (key, newStructType);
1942
- addToWorkList (newStructType);
1943
1981
}
1944
1982
1945
- addUsersToWorkList (type);
1946
1983
type->replaceUsesWith (newStructType);
1947
1984
type->removeAndDeallocate ();
1948
1985
return ;
0 commit comments