summaryrefslogtreecommitdiffstats
path: root/source/slang/slang-ir-lower-buffer-element-type.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/slang/slang-ir-lower-buffer-element-type.cpp')
-rw-r--r--source/slang/slang-ir-lower-buffer-element-type.cpp81
1 files changed, 80 insertions, 1 deletions
diff --git a/source/slang/slang-ir-lower-buffer-element-type.cpp b/source/slang/slang-ir-lower-buffer-element-type.cpp
index d0ad7483a..29999017a 100644
--- a/source/slang/slang-ir-lower-buffer-element-type.cpp
+++ b/source/slang/slang-ir-lower-buffer-element-type.cpp
@@ -361,7 +361,11 @@ namespace Slang
info.loweredInnerStructKey = structKey;
info.convertLoweredToOriginal = createArrayUnpackFunc(arrayType, loweredType, structKey, innerArrayType, loweredInnerTypeInfo);
info.convertOriginalToLowered = createArrayPackFunc(arrayType, loweredType, innerArrayType, loweredInnerTypeInfo);
-
+ return info;
+ }
+ else if (as<IRArrayTypeBase>(type))
+ {
+ info.loweredType = builder.getVoidType();
return info;
}
else if (auto structType = as<IRStructType>(type))
@@ -399,6 +403,11 @@ namespace Slang
Index fieldId = 0;
for (auto field : structType->getFields())
{
+ if (as<IRVoidType>(fieldLoweredTypeInfo[fieldId].loweredType))
+ {
+ fieldId++;
+ continue;
+ }
auto loweredFieldTypeInfo = fieldLoweredTypeInfo[fieldId];
builder.createStructField(loweredType, field->getKey(), loweredFieldTypeInfo.loweredType);
fieldId++;
@@ -418,6 +427,11 @@ namespace Slang
Index fieldId = 0;
for (auto field : structType->getFields())
{
+ if (as<IRVoidType>(fieldLoweredTypeInfo[fieldId].loweredType))
+ {
+ fieldId++;
+ continue;
+ }
auto storageField = builder.emitFieldExtract(fieldLoweredTypeInfo[fieldId].loweredType, loweredParam, field->getKey());
auto unpackedField = fieldLoweredTypeInfo[fieldId].convertLoweredToOriginal
? builder.emitCallInst(field->getFieldType(), fieldLoweredTypeInfo[fieldId].convertLoweredToOriginal, 1, &storageField)
@@ -442,6 +456,11 @@ namespace Slang
Index fieldId = 0;
for (auto field : structType->getFields())
{
+ if (as<IRVoidType>(fieldLoweredTypeInfo[fieldId].loweredType))
+ {
+ fieldId++;
+ continue;
+ }
auto fieldVal = builder.emitFieldExtract(field->getFieldType(), param, field->getKey());
auto packedField = fieldLoweredTypeInfo[fieldId].convertOriginalToLowered
? builder.emitCallInst(fieldLoweredTypeInfo[fieldId].loweredType, fieldLoweredTypeInfo[fieldId].convertOriginalToLowered, 1, &fieldVal)
@@ -641,6 +660,66 @@ namespace Slang
auto ptrVal = ptrValsWorkList[i];
auto oldPtrType = ptrVal->getFullType();
auto originalElementType = oldPtrType->getOperand(0);
+
+ // If we are accessing an unsized array element from a pointer, we need to compute
+ // the trailing ptr that points to the first element of the array.
+ // And then replace all getElementPtr(arrayPtr, index) with getOffsetPtr(trailingPtr, index).
+ if (auto fieldAddr = as<IRFieldAddress>(ptrVal))
+ {
+ if (auto ptrType = as<IRPtrType>(ptrVal->getDataType()))
+ {
+ if (auto unsizedArrayType = as<IRUnsizedArrayType>(ptrType->getValueType()))
+ {
+ builder.setInsertBefore(ptrVal);
+ auto newArrayPtrVal = builder.emitGetOffsetPtr(fieldAddr->getBase(), builder.getIntValue(builder.getIntType(), 1));
+ auto loweredInnerType = getLoweredTypeInfo(unsizedArrayType->getElementType(), layoutRules);
+
+ IRSizeAndAlignment arrayElementSizeAlignment;
+ getSizeAndAlignment(
+ target->getOptionSet(), layoutRules, loweredInnerType.loweredType, &arrayElementSizeAlignment);
+ IRSizeAndAlignment baseSizeAlignment;
+ getSizeAndAlignment(
+ target->getOptionSet(),
+ layoutRules,
+ tryGetPointedToType(&builder, fieldAddr->getBase()->getDataType()),
+ &baseSizeAlignment);
+
+ // Convert pointer to uint64 and adjust offset.
+ auto rawPtr = builder.emitBitCast(builder.getUInt64Type(), newArrayPtrVal);
+ IRIntegerValue offset = baseSizeAlignment.size;
+ offset = align(offset, arrayElementSizeAlignment.alignment);
+ newArrayPtrVal = builder.emitAdd(rawPtr->getFullType(), rawPtr,
+ builder.getIntValue(builder.getUInt64Type(), offset));
+
+ newArrayPtrVal = builder.emitBitCast(
+ builder.getPtrType(loweredInnerType.loweredType,
+ ptrType->getAddressSpace()), newArrayPtrVal);
+ traverseUses(ptrVal, [&](IRUse* use)
+ {
+ auto user = use->getUser();
+ if (user->getOp() == kIROp_GetElementPtr)
+ {
+ builder.setInsertBefore(user);
+ auto newElementPtr = builder.emitGetOffsetPtr(newArrayPtrVal, user->getOperand(1));
+ user->replaceUsesWith(newElementPtr);
+ user->removeAndDeallocate();
+ ptrValsWorkList.add(newElementPtr);
+ }
+ else if (user->getOp() == kIROp_GetOffsetPtr)
+ {
+ }
+ else
+ {
+ SLANG_UNEXPECTED("unknown use of pointer to unsized array.");
+ }
+ });
+ SLANG_ASSERT(!ptrVal->hasUses());
+ ptrVal->removeAndDeallocate();
+ continue;
+ }
+ }
+ }
+
auto loweredElementTypeInfo = getLoweredTypeInfo((IRType*)originalElementType, layoutRules);
if (!loweredElementTypeInfo.convertLoweredToOriginal)
continue;