summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2024-10-09 07:35:10 -0700
committerGitHub <noreply@github.com>2024-10-09 22:35:10 +0800
commitac6f04c15995061ebe8e0ddf62ecf7eb979afb65 (patch)
treef16f0f01f1f8d0e73ecd774a22f87576f440f8e8 /source
parentbea1394ad35680940a0b69b9c67efc43764cc194 (diff)
Fix spirv lowering logic around pointer to unsized array. (#5243)
* Fix spirv lowering logic around pointer to unsized array. * Fix. --------- Co-authored-by: Ellie Hermaszewska <ellieh@nvidia.com>
Diffstat (limited to 'source')
-rw-r--r--source/slang/slang-check-decl.cpp5
-rw-r--r--source/slang/slang-diagnostic-defs.h1
-rw-r--r--source/slang/slang-ir-insts.h2
-rw-r--r--source/slang/slang-ir-lower-buffer-element-type.cpp81
-rw-r--r--source/slang/slang-ir-specialize-address-space.cpp2
-rw-r--r--source/slang/slang-ir.cpp6
6 files changed, 95 insertions, 2 deletions
diff --git a/source/slang/slang-check-decl.cpp b/source/slang/slang-check-decl.cpp
index b7f65a11a..5ca1baeec 100644
--- a/source/slang/slang-check-decl.cpp
+++ b/source/slang/slang-check-decl.cpp
@@ -8430,6 +8430,11 @@ namespace Slang
{
auto typeExpr = paramDecl->type;
+ if (!as<ArrayExpressionType>(paramDecl->type) && doesTypeHaveTag(paramDecl->type, TypeTag::Unsized))
+ {
+ getSink()->diagnose(paramDecl, Diagnostics::paramCannotBeUnsized, paramDecl);
+ }
+
// The "initializer" expression for a parameter represents
// a default argument value to use if an explicit one is
// not supplied.
diff --git a/source/slang/slang-diagnostic-defs.h b/source/slang/slang-diagnostic-defs.h
index 3f4376eb3..298c79f7e 100644
--- a/source/slang/slang-diagnostic-defs.h
+++ b/source/slang/slang-diagnostic-defs.h
@@ -329,6 +329,7 @@ DIAGNOSTIC(30068, Warning, mutatingMethodOnFunctionInputParameterWarning, "mutat
DIAGNOSTIC(30070, Error, unsizedMemberMustAppearLast, "member with unknown size at compile time can only appear as the last member in a composite type.")
DIAGNOSTIC(30071, Error, varCannotBeUnsized, "cannot instantiate a variable of unsized type.")
+DIAGNOSTIC(30072, Error, paramCannotBeUnsized, "function parameter cannot be unsized.")
DIAGNOSTIC(30075, Error, cannotSpecializeGeneric, "cannot specialize generic '$0' with the provided arguments.")
diff --git a/source/slang/slang-ir-insts.h b/source/slang/slang-ir-insts.h
index 81b916791..c2fd9da0a 100644
--- a/source/slang/slang-ir-insts.h
+++ b/source/slang/slang-ir-insts.h
@@ -4330,7 +4330,7 @@ public:
IRInst* emitUpdateElement(IRInst* base, IRInst* index, IRInst* newElement);
IRInst* emitUpdateElement(IRInst* base, IRIntegerValue index, IRInst* newElement);
IRInst* emitUpdateElement(IRInst* base, ArrayView<IRInst*> accessChain, IRInst* newElement);
-
+ IRInst* emitGetOffsetPtr(IRInst* base, IRInst* offset);
IRInst* emitGetAddress(
IRType* type,
IRInst* value);
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;
diff --git a/source/slang/slang-ir-specialize-address-space.cpp b/source/slang/slang-ir-specialize-address-space.cpp
index 60aa1f10a..836601a00 100644
--- a/source/slang/slang-ir-specialize-address-space.cpp
+++ b/source/slang/slang-ir-specialize-address-space.cpp
@@ -177,6 +177,8 @@ namespace Slang
}
case kIROp_GetElementPtr:
case kIROp_FieldAddress:
+ case kIROp_GetOffsetPtr:
+ case kIROp_BitCast:
if (!mapInstToAddrSpace.containsKey(inst))
{
auto addrSpace = getAddrSpace(inst->getOperand(0));
diff --git a/source/slang/slang-ir.cpp b/source/slang/slang-ir.cpp
index f0e7773c6..f190b3a11 100644
--- a/source/slang/slang-ir.cpp
+++ b/source/slang/slang-ir.cpp
@@ -5464,6 +5464,12 @@ namespace Slang
return inst;
}
+ IRInst* IRBuilder::emitGetOffsetPtr(IRInst* base, IRInst* offset)
+ {
+ IRInst* args[] = { base, offset };
+ return emitIntrinsicInst(base->getDataType(), kIROp_GetOffsetPtr, 2, args);
+ }
+
IRInst* IRBuilder::emitGetAddress(
IRType* type,
IRInst* value)