summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2020-09-04 10:18:44 -0700
committerGitHub <noreply@github.com>2020-09-04 10:18:44 -0700
commit8f962894fd38edb47d782d303ac9ff87b3a3bb6a (patch)
tree449d0d58ca7d90a11759372c9dc82650a565f96a /source
parent5e10f1b4f0654515af1fcb29e8d1f35e691c8aa3 (diff)
Allow mixing unspecialized and specialized existential parameters. (#1533)
* Allow mixing unspecialized and specialized existential parameters. * Fixes.
Diffstat (limited to 'source')
-rw-r--r--source/slang/core.meta.slang5
-rw-r--r--source/slang/slang-ast-builder.cpp10
-rw-r--r--source/slang/slang-ast-builder.h3
-rw-r--r--source/slang/slang-ast-type.h5
-rw-r--r--source/slang/slang-ast-val.h7
-rw-r--r--source/slang/slang-check-conformance.cpp13
-rw-r--r--source/slang/slang-emit-c-like.cpp2
-rw-r--r--source/slang/slang-emit.cpp2
-rw-r--r--source/slang/slang-ir-collect-global-uniforms.cpp16
-rw-r--r--source/slang/slang-ir-generics-lowering-context.cpp5
-rw-r--r--source/slang/slang-ir-generics-lowering-context.h2
-rw-r--r--source/slang/slang-ir-inst-defs.h6
-rw-r--r--source/slang/slang-ir-insts.h11
-rw-r--r--source/slang/slang-ir-legalize-types.cpp3
-rw-r--r--source/slang/slang-ir-lower-existential.cpp31
-rw-r--r--source/slang/slang-ir-lower-generics.cpp2
-rw-r--r--source/slang/slang-ir-lower-generics.h2
-rw-r--r--source/slang/slang-ir-specialize.cpp33
-rw-r--r--source/slang/slang-ir.cpp19
-rw-r--r--source/slang/slang-ir.h8
-rw-r--r--source/slang/slang-lower-to-ir.cpp25
-rw-r--r--source/slang/slang-type-layout.cpp18
22 files changed, 205 insertions, 23 deletions
diff --git a/source/slang/core.meta.slang b/source/slang/core.meta.slang
index 62039992e..8d0ce1d1d 100644
--- a/source/slang/core.meta.slang
+++ b/source/slang/core.meta.slang
@@ -315,6 +315,11 @@ __intrinsic_type($(kIROp_StringType))
struct String
{};
+__magic_type(DynamicType)
+__intrinsic_type($(kIROp_DynamicType))
+struct __Dynamic
+{};
+
/// An `N` component vector with elements of type `T`.
__generic<T = float, let N : int = 4>
__magic_type(Vector)
diff --git a/source/slang/slang-ast-builder.cpp b/source/slang/slang-ast-builder.cpp
index ec4fd20f1..64061549e 100644
--- a/source/slang/slang-ast-builder.cpp
+++ b/source/slang/slang-ast-builder.cpp
@@ -100,6 +100,16 @@ Type* SharedASTBuilder::getEnumTypeType()
return m_enumTypeType;
}
+Type* SharedASTBuilder::getDynamicType()
+{
+ if (!m_dynamicType)
+ {
+ auto dynamicTypeDecl = findMagicDecl("DynamicType");
+ m_dynamicType = DeclRefType::create(m_astBuilder, makeDeclRef<Decl>(dynamicTypeDecl));
+ }
+ return m_dynamicType;
+}
+
SharedASTBuilder::~SharedASTBuilder()
{
// Release built in types..
diff --git a/source/slang/slang-ast-builder.h b/source/slang/slang-ast-builder.h
index 2cc03054b..08d22f6ca 100644
--- a/source/slang/slang-ast-builder.h
+++ b/source/slang/slang-ast-builder.h
@@ -25,6 +25,8 @@ public:
Type* getStringType();
/// Get the enum type type
Type* getEnumTypeType();
+ /// Get the __Dynamic type
+ Type* getDynamicType();
const ReflectClassInfo* findClassInfo(Name* name);
SyntaxClass<NodeBase> findSyntaxClass(Name* name);
@@ -62,6 +64,7 @@ protected:
//
Type* m_stringType = nullptr;
Type* m_enumTypeType = nullptr;
+ Type* m_dynamicType = nullptr;
Type* m_builtinTypes[Index(BaseType::CountOf)];
diff --git a/source/slang/slang-ast-type.h b/source/slang/slang-ast-type.h
index 4c1c07ba3..b2e43a507 100644
--- a/source/slang/slang-ast-type.h
+++ b/source/slang/slang-ast-type.h
@@ -466,6 +466,11 @@ class StringType : public BuiltinType
SLANG_CLASS(StringType)
};
+// The built-in `__Dynamic` type
+class DynamicType : public BuiltinType
+{
+ SLANG_CLASS(DynamicType)
+};
// Type built-in `__EnumType` type
class EnumTypeType : public BuiltinType
diff --git a/source/slang/slang-ast-val.h b/source/slang/slang-ast-val.h
index 4926643d3..6bc86e805 100644
--- a/source/slang/slang-ast-val.h
+++ b/source/slang/slang-ast-val.h
@@ -206,4 +206,11 @@ class ThisTypeSubtypeWitness : public SubtypeWitness
SLANG_CLASS(ThisTypeSubtypeWitness)
};
+ /// A witness of the fact that a user provided "__Dynamic" type argument is a
+ /// subtype to the existential type parameter.
+class DynamicSubtypeWitness : public SubtypeWitness
+{
+ SLANG_CLASS(DynamicSubtypeWitness)
+};
+
} // namespace Slang
diff --git a/source/slang/slang-check-conformance.cpp b/source/slang/slang-check-conformance.cpp
index 25a7ac4ee..6a397e8b6 100644
--- a/source/slang/slang-check-conformance.cpp
+++ b/source/slang/slang-check-conformance.cpp
@@ -180,8 +180,16 @@ namespace Slang
}
return true;
}
-
- if( auto aggTypeDeclRef = declRef.as<AggTypeDecl>() )
+ if (auto dynamicType = as<DynamicType>(subType))
+ {
+ // A __Dynamic type always conforms to the interface via its witness table.
+ if (outWitness)
+ {
+ *outWitness = m_astBuilder->create<DynamicSubtypeWitness>();
+ }
+ return true;
+ }
+ else if( auto aggTypeDeclRef = declRef.as<AggTypeDecl>() )
{
ensureDecl(aggTypeDeclRef, DeclCheckState::CanEnumerateBases);
@@ -363,7 +371,6 @@ namespace Slang
}
return true;
}
-
// default is failure
return false;
}
diff --git a/source/slang/slang-emit-c-like.cpp b/source/slang/slang-emit-c-like.cpp
index 231207626..090d06f28 100644
--- a/source/slang/slang-emit-c-like.cpp
+++ b/source/slang/slang-emit-c-like.cpp
@@ -942,6 +942,7 @@ bool CLikeSourceEmitter::shouldFoldInstIntoUseSites(IRInst* inst)
case kIROp_getElementPtr:
case kIROp_Specialize:
case kIROp_lookup_interface_method:
+ case kIROp_GetValueFromExistentialBox:
return true;
}
@@ -2388,6 +2389,7 @@ void CLikeSourceEmitter::defaultEmitInstExpr(IRInst* inst, const EmitOpInfo& inO
break;
case kIROp_GlobalConstant:
+ case kIROp_GetValueFromExistentialBox:
emitOperand(inst->getOperand(0), outerPrec);
break;
diff --git a/source/slang/slang-emit.cpp b/source/slang/slang-emit.cpp
index c614a7a50..9ab42569a 100644
--- a/source/slang/slang-emit.cpp
+++ b/source/slang/slang-emit.cpp
@@ -314,7 +314,7 @@ Result linkAndOptimizeIR(
// generics / interface types to ordinary functions and types using
// function pointers.
dumpIRIfEnabled(compileRequest, irModule, "BEFORE-LOWER-GENERICS");
- lowerGenerics(irModule, sink);
+ lowerGenerics(targetRequest, irModule, sink);
dumpIRIfEnabled(compileRequest, irModule, "LOWER-GENERICS");
break;
default:
diff --git a/source/slang/slang-ir-collect-global-uniforms.cpp b/source/slang/slang-ir-collect-global-uniforms.cpp
index 306bbdfee..44f1e4ac0 100644
--- a/source/slang/slang-ir-collect-global-uniforms.cpp
+++ b/source/slang/slang-ir-collect-global-uniforms.cpp
@@ -50,6 +50,20 @@ struct CollectGlobalUniformParametersContext
IRModule* module;
IRVarLayout* globalScopeVarLayout;
+ IRGlobalParam* _getGlobalParamFromLayoutFieldKey(IRInst* key)
+ {
+ switch (key->op)
+ {
+ case kIROp_GlobalParam:
+ return cast<IRGlobalParam>(key);
+ case kIROp_MakeExistential:
+ case kIROp_WrapExistential:
+ return as<IRGlobalParam>(key->getOperand(0));
+ default:
+ return nullptr;
+ }
+ }
+
// This is a relatively simple pass, and it is all driven
// by a single subroutine.
//
@@ -158,7 +172,7 @@ struct CollectGlobalUniformParametersContext
// layout so that the "key" for the field is the corresponding
// global shader parameter.
//
- auto globalParam = as<IRGlobalParam>(fieldLayoutAttr->getFieldKey());
+ auto globalParam = _getGlobalParamFromLayoutFieldKey(fieldLayoutAttr->getFieldKey());
SLANG_ASSERT(globalParam);
auto globalParamLayout = fieldLayoutAttr->getLayout();
diff --git a/source/slang/slang-ir-generics-lowering-context.cpp b/source/slang/slang-ir-generics-lowering-context.cpp
index b7e2917d5..9c4eb7856 100644
--- a/source/slang/slang-ir-generics-lowering-context.cpp
+++ b/source/slang/slang-ir-generics-lowering-context.cpp
@@ -197,6 +197,11 @@ namespace Slang
SLANG_ASSERT(reqVal && reqVal->op == kIROp_AssociatedType);
return lowerType(builder, reqVal, typeMapping);
}
+ case kIROp_ExistentialBoxType:
+ {
+ auto existentialBoxType = static_cast<IRExistentialBoxType*>(paramType);
+ return lowerType(builder, existentialBoxType->getInterfaceType(), typeMapping);
+ }
default:
{
bool translated = false;
diff --git a/source/slang/slang-ir-generics-lowering-context.h b/source/slang/slang-ir-generics-lowering-context.h
index 8c23cad44..be56e9c84 100644
--- a/source/slang/slang-ir-generics-lowering-context.h
+++ b/source/slang/slang-ir-generics-lowering-context.h
@@ -16,6 +16,8 @@ namespace Slang
// we are processing.
IRModule* module;
+ TargetRequest* targetReq;
+
DiagnosticSink* sink;
// RTTI objects for each type used to call a generic function.
diff --git a/source/slang/slang-ir-inst-defs.h b/source/slang/slang-ir-inst-defs.h
index 4074a435f..7863b9a9c 100644
--- a/source/slang/slang-ir-inst-defs.h
+++ b/source/slang/slang-ir-inst-defs.h
@@ -26,6 +26,8 @@ INST(Nop, nop, 0, 0)
INST(StringType, String, 0, 0)
+ INST(DynamicType, DynamicType, 0, 0)
+
INST(AnyValueType, AnyValueType, 1, 0)
INST(RawPointerType, RawPointerType, 0, 0)
@@ -587,6 +589,10 @@ INST(MakeExistentialWithRTTI, makeExistentialWithRTTI, 3, 0)
//
INST(WrapExistential, wrapExistential, 2, 0)
+// A `GetValueFromExistentialBox` takes a `ExistentialBox` value and returns the value wrapped by
+// the existential box.
+INST(GetValueFromExistentialBox, getValueFromExistentialBox, 1, 0)
+
INST(ExtractExistentialValue, extractExistentialValue, 1, 0)
INST(ExtractExistentialType, extractExistentialType, 1, 0)
INST(ExtractExistentialWitnessTable, extractExistentialWitnessTable, 1, 0)
diff --git a/source/slang/slang-ir-insts.h b/source/slang/slang-ir-insts.h
index 2197456a1..dc841bb3a 100644
--- a/source/slang/slang-ir-insts.h
+++ b/source/slang/slang-ir-insts.h
@@ -1622,6 +1622,11 @@ struct IRWrapExistential : IRInst
IR_LEAF_ISA(WrapExistential)
};
+struct IRGetValueFromExistentialBox : IRInst
+{
+ IR_LEAF_ISA(GetValueFromExistentialBox);
+};
+
struct IRExtractExistentialValue : IRInst
{
IR_LEAF_ISA(ExtractExistentialValue);
@@ -1745,6 +1750,7 @@ struct IRBuilder
IRBasicType* getIntType();
IRBasicType* getUIntType();
IRStringType* getStringType();
+
IRAssociatedType* getAssociatedType(ArrayView<IRInterfaceType*> constraintTypes);
IRThisType* getThisType(IRInterfaceType* interfaceType);
IRRawPointerType* getRawPointerType();
@@ -1752,6 +1758,7 @@ struct IRBuilder
IRRTTIType* getRTTIType();
IRAnyValueType* getAnyValueType(IRIntegerValue size);
IRAnyValueType* getAnyValueType(IRInst* size);
+ IRDynamicType* getDynamicType();
IRTupleType* getTupleType(UInt count, IRType* const* types);
IRTupleType* getTupleType(IRType* type0, IRType* type1);
@@ -1770,6 +1777,7 @@ struct IRBuilder
IRInOutType* getInOutType(IRType* valueType);
IRRefType* getRefType(IRType* valueType);
IRPtrTypeBase* getPtrType(IROp op, IRType* valueType);
+ IRExistentialBoxType* getExistentialBoxType(IRType* concreteType, IRType* interfaceType);
IRArrayTypeBase* getArrayTypeBase(
IROp op,
@@ -1838,6 +1846,9 @@ struct IRBuilder
// its rate, if any.
void setDataType(IRInst* inst, IRType* dataType);
+ /// Extract the value wrapped inside an existential box.
+ IRInst* emitGetValueFromExistentialBox(IRType* type, IRInst* existentialBox);
+
/// Given an existential value, extract the underlying "real" value
IRInst* emitExtractExistentialValue(
IRType* type,
diff --git a/source/slang/slang-ir-legalize-types.cpp b/source/slang/slang-ir-legalize-types.cpp
index 3a1471f98..2161b0223 100644
--- a/source/slang/slang-ir-legalize-types.cpp
+++ b/source/slang/slang-ir-legalize-types.cpp
@@ -1210,6 +1210,9 @@ static LegalVal legalizeInst(
case kIROp_Load:
return legalizeLoad(context, args[0]);
+ case kIROp_GetValueFromExistentialBox:
+ return args[0];
+
case kIROp_FieldAddress:
return legalizeFieldAddress(context, type, args[0], args[1]);
diff --git a/source/slang/slang-ir-lower-existential.cpp b/source/slang/slang-ir-lower-existential.cpp
index a6db2b781..0dce96de2 100644
--- a/source/slang/slang-ir-lower-existential.cpp
+++ b/source/slang/slang-ir-lower-existential.cpp
@@ -7,6 +7,9 @@
namespace Slang
{
+ bool isCPUTarget(TargetRequest* targetReq);
+ bool isCUDATarget(TargetRequest* targetReq);
+
struct ExistentialLoweringContext
{
SharedGenericsLoweringContext* sharedContext;
@@ -79,12 +82,40 @@ namespace Slang
processExtractExistentialElement(inst, 0);
}
+ void processGetValueFromExistentialBox(IRGetValueFromExistentialBox* inst)
+ {
+ // Currently we do not translate on HLSL/GLSL targets,
+ // since we don't attempt to actually layout the value inside an fixed sized
+ // existential box for these targets.
+ if (isCPUTarget(sharedContext->targetReq) || isCUDATarget(sharedContext->targetReq))
+ {
+ IRBuilder builderStorage;
+ auto builder = &builderStorage;
+ builder->sharedBuilder = &sharedContext->sharedBuilderStorage;
+ builder->setInsertBefore(inst);
+
+ auto element = extractTupleElement(builder, inst->getOperand(0), 2);
+ // TODO: it is not technically sound to use `getAddress` on a temporary value.
+ // We probably need to develop a mechanism to allow a temporary value to be used
+ // in the place of a pointer.
+ auto elementAddr =
+ builder->emitGetAddress(builder->getPtrType(element->getDataType()), element);
+ auto reinterpretAddr = builder->emitBitCast(inst->getDataType(), elementAddr);
+ inst->replaceUsesWith(reinterpretAddr);
+ inst->removeAndDeallocate();
+ }
+ }
+
void processInst(IRInst* inst)
{
if (auto makeExistential = as<IRMakeExistentialWithRTTI>(inst))
{
processMakeExistential(makeExistential);
}
+ else if (auto getExistentialValue = as<IRGetValueFromExistentialBox>(inst))
+ {
+ processGetValueFromExistentialBox(getExistentialValue);
+ }
else if (auto extractExistentialVal = as<IRExtractExistentialValue>(inst))
{
processExtractExistentialValue(extractExistentialVal);
diff --git a/source/slang/slang-ir-lower-generics.cpp b/source/slang/slang-ir-lower-generics.cpp
index 63e1fdc49..a9540a87a 100644
--- a/source/slang/slang-ir-lower-generics.cpp
+++ b/source/slang/slang-ir-lower-generics.cpp
@@ -15,10 +15,12 @@
namespace Slang
{
void lowerGenerics(
+ TargetRequest* targetReq,
IRModule* module,
DiagnosticSink* sink)
{
SharedGenericsLoweringContext sharedContext;
+ sharedContext.targetReq = targetReq;
sharedContext.module = module;
sharedContext.sink = sink;
diff --git a/source/slang/slang-ir-lower-generics.h b/source/slang/slang-ir-lower-generics.h
index 76b5c1b58..ea83b35bf 100644
--- a/source/slang/slang-ir-lower-generics.h
+++ b/source/slang/slang-ir-lower-generics.h
@@ -7,10 +7,12 @@ namespace Slang
{
struct IRModule;
class DiagnosticSink;
+ class TargetRequest;
/// Lower generic and interface-based code to ordinary types and functions using
/// dynamic dispatch mechanisms.
void lowerGenerics(
+ TargetRequest* targetReq,
IRModule* module,
DiagnosticSink* sink);
diff --git a/source/slang/slang-ir-specialize.cpp b/source/slang/slang-ir-specialize.cpp
index 3acb34c87..75b2beeec 100644
--- a/source/slang/slang-ir-specialize.cpp
+++ b/source/slang/slang-ir-specialize.cpp
@@ -611,6 +611,33 @@ struct SpecializationContext
return nullptr;
}
+ void maybeInsertGetExistentialValue(IRInst* inst)
+ {
+ // If inst has `ExistentialBox` type, we need to make sure
+ // all uses are through `GetValueFromExistentialBox`.
+ if (auto existentialBoxType = as<IRExistentialBoxType>(inst->getDataType()))
+ {
+ ShortList<IRUse*> usesToReplace;
+ for (auto use = inst->firstUse; use; use = use->nextUse)
+ {
+ if (use->getUser()->op != kIROp_GetValueFromExistentialBox)
+ usesToReplace.add(use);
+ }
+ for (auto use : usesToReplace)
+ {
+ auto user = use->getUser();
+ IRBuilder builderStorage;
+ auto builder = &builderStorage;
+ builder->sharedBuilder = &sharedBuilderStorage;
+ builder->setInsertBefore(user);
+ auto getValueInst = builder->emitGetValueFromExistentialBox(
+ builder->getPtrType(existentialBoxType->getValueType()), inst);
+ use->set(getValueInst);
+ addToWorkList(getValueInst);
+ }
+ }
+ }
+
// All of the machinery for generic specialization
// has been defined above, so we will now walk
// through the flow of the overall specialization pass.
@@ -678,6 +705,10 @@ struct SpecializationContext
workListSet.Remove(inst);
cleanInsts.Add(inst);
+ // If inst represents a value of ExistentialBox type, all its uses
+ // must be through a `GetValueFromExistentialBox` inst.
+ maybeInsertGetExistentialValue(inst);
+
// For each instruction we process, we want to perform
// a few steps.
//
@@ -1640,7 +1671,7 @@ struct SpecializationContext
if(slotOperandCount <= 1) return;
auto concreteType = (IRType*) type->getExistentialArg(0);
- auto newVal = builder.getPtrType(kIROp_ExistentialBoxType, concreteType);
+ auto newVal = builder.getExistentialBoxType(concreteType, baseInterfaceType);
addUsersToWorkList(type);
type->replaceUsesWith(newVal);
diff --git a/source/slang/slang-ir.cpp b/source/slang/slang-ir.cpp
index 2f27bbebc..37841c35f 100644
--- a/source/slang/slang-ir.cpp
+++ b/source/slang/slang-ir.cpp
@@ -2232,6 +2232,8 @@ namespace Slang
return (IRStringType*)getType(kIROp_StringType);
}
+ IRDynamicType* IRBuilder::getDynamicType() { return (IRDynamicType*)getType(kIROp_DynamicType); }
+
IRAssociatedType* IRBuilder::getAssociatedType(ArrayView<IRInterfaceType*> constraintTypes)
{
return (IRAssociatedType*)getType(kIROp_AssociatedType,
@@ -2331,6 +2333,12 @@ namespace Slang
operands);
}
+ IRExistentialBoxType* IRBuilder::getExistentialBoxType(IRType* concreteType, IRType* interfaceType)
+ {
+ IRInst* operands[] = {concreteType, interfaceType};
+ return (IRExistentialBoxType*)getType(kIROp_ExistentialBoxType, 2, operands);
+ }
+
IRArrayTypeBase* IRBuilder::getArrayTypeBase(
IROp op,
IRType* elementType,
@@ -2471,7 +2479,7 @@ namespace Slang
// so we just want to return `ExistentialBox<someConcreteType>`.
//
auto concreteType = (IRType*) slotArgs[0];
- auto ptrType = getPtrType(kIROp_ExistentialBoxType, concreteType);
+ auto ptrType = getExistentialBoxType(concreteType, (IRType*)baseType);
return ptrType;
}
}
@@ -2524,6 +2532,14 @@ namespace Slang
}
}
+ IRInst* IRBuilder::emitGetValueFromExistentialBox(IRType* type, IRInst* existentialBox)
+ {
+ auto inst =
+ createInst<IRInst>(this, kIROp_GetValueFromExistentialBox, type, 1, &existentialBox);
+ addInst(inst);
+ return inst;
+ }
+
IRUndefined* IRBuilder::emitUndefined(IRType* type)
{
@@ -5273,6 +5289,7 @@ namespace Slang
case kIROp_Specialize:
case kIROp_lookup_interface_method:
case kIROp_getAddr:
+ case kIROp_GetValueFromExistentialBox:
case kIROp_Construct:
case kIROp_makeVector:
case kIROp_MakeMatrix:
diff --git a/source/slang/slang-ir.h b/source/slang/slang-ir.h
index 2c6ad244b..9a0c71cb1 100644
--- a/source/slang/slang-ir.h
+++ b/source/slang/slang-ir.h
@@ -626,6 +626,7 @@ struct IRBoolType : IRBasicType
SIMPLE_IR_TYPE(StringType, Type)
+SIMPLE_IR_TYPE(DynamicType, Type)
// True if types are equal
// Note compares nominal types by name alone
@@ -1109,7 +1110,12 @@ SIMPLE_IR_TYPE(RefType, PtrTypeBase)
SIMPLE_IR_PARENT_TYPE(OutTypeBase, PtrTypeBase)
SIMPLE_IR_TYPE(OutType, OutTypeBase)
SIMPLE_IR_TYPE(InOutType, OutTypeBase)
-SIMPLE_IR_TYPE(ExistentialBoxType, PtrTypeBase)
+
+struct IRExistentialBoxType : public IRPtrTypeBase
+{
+ IR_LEAF_ISA(ExistentialBoxType);
+ IRType* getInterfaceType() { return (IRType*)getOperand(1); }
+};
/// The base class of RawPointerType and RTTIPointerType.
struct IRRawPointerTypeBase : IRType
diff --git a/source/slang/slang-lower-to-ir.cpp b/source/slang/slang-lower-to-ir.cpp
index ee5338236..424358d3c 100644
--- a/source/slang/slang-lower-to-ir.cpp
+++ b/source/slang/slang-lower-to-ir.cpp
@@ -1420,10 +1420,14 @@ struct ValLoweringVisitor : ValVisitor<ValLoweringVisitor, LoweredValInfo, Lower
//
getBuilder()->createWitnessTableEntry(irWitnessTable, irReqKey, irSatisfyingVal);
}
-
return LoweredValInfo::simple(irWitnessTable);
}
+ LoweredValInfo visitDynamicSubtypeWitness(DynamicSubtypeWitness * /*val*/)
+ {
+ return LoweredValInfo::simple(nullptr);
+ }
+
LoweredValInfo visitThisTypeSubtypeWitness(ThisTypeSubtypeWitness* val)
{
SLANG_UNUSED(val);
@@ -7859,6 +7863,8 @@ struct SpecializedComponentTypeIRGenContext : ComponentTypeVisitor
IRInst* irParam = getSimpleVal(context, ensureDecl(context, shaderParam.paramDeclRef));
List<IRInst*> irSlotArgs;
+ // Tracks if there are any type args that is not an IRDynamicType.
+ bool hasConcreteTypeArg = false;
for( Index jj = 0; jj < specializationArgCount; ++jj )
{
auto& specializationArg = specializationInfo->existentialArgs[existentialArgOffset++];
@@ -7866,14 +7872,21 @@ struct SpecializedComponentTypeIRGenContext : ComponentTypeVisitor
auto irType = lowerSimpleVal(context, specializationArg.val);
auto irWitness = lowerSimpleVal(context, specializationArg.witness);
+ if (irType->op != kIROp_DynamicType)
+ hasConcreteTypeArg = true;
+
irSlotArgs.add(irType);
irSlotArgs.add(irWitness);
}
-
- builder->addBindExistentialSlotsDecoration(
- irParam,
- irSlotArgs.getCount(),
- irSlotArgs.getBuffer());
+ // Only insert a `BindExistentialSlots` decoration when there are at least
+ // one non-dynamic type argument.
+ if (hasConcreteTypeArg)
+ {
+ builder->addBindExistentialSlotsDecoration(
+ irParam,
+ irSlotArgs.getCount(),
+ irSlotArgs.getBuffer());
+ }
}
}
}
diff --git a/source/slang/slang-type-layout.cpp b/source/slang/slang-type-layout.cpp
index fd0b126e8..d4c6a7016 100644
--- a/source/slang/slang-type-layout.cpp
+++ b/source/slang/slang-type-layout.cpp
@@ -3662,9 +3662,10 @@ static TypeLayoutResult _createTypeLayout(
typeLayout->rules = rules;
LayoutSize fixedExistentialValueSize = 0;
- bool useFixedSizedExistentialValue =
+ bool targetSupportsPointer =
isCPUTarget(context.targetReq) || isCUDATarget(context.targetReq);
- if (useFixedSizedExistentialValue)
+
+ if (targetSupportsPointer)
{
fixedExistentialValueSize = 16;
if (auto anyValueAttr =
@@ -3672,7 +3673,9 @@ static TypeLayoutResult _createTypeLayout(
{
fixedExistentialValueSize = anyValueAttr->size;
}
- typeLayout->addResourceUsage(LayoutResourceKind::Uniform, fixedExistentialValueSize + 16);
+ // Append 16 bytes to accommodate RTTI pointer and witness table pointer.
+ auto uniformSlotSize = fixedExistentialValueSize + 16;
+ typeLayout->addResourceUsage(LayoutResourceKind::Uniform, uniformSlotSize);
}
typeLayout->addResourceUsage(LayoutResourceKind::ExistentialTypeParam, 1);
typeLayout->addResourceUsage(LayoutResourceKind::ExistentialObjectParam, 1);
@@ -3695,17 +3698,14 @@ static TypeLayoutResult _createTypeLayout(
// the existential value. We should remove this special case logic
// and always use anyValueRule once we implement the correct loading
// code gen logic for these targets.
- if (!(isCPUTarget(context.targetReq) || isCUDATarget(context.targetReq)))
+ if (!targetSupportsPointer)
anyValueRules = context.rules;
RefPtr<TypeLayout> concreteTypeLayout =
createTypeLayout(context.with(anyValueRules), concreteType);
- auto uniformLayoutInfo =
- concreteTypeLayout->FindResourceInfo(LayoutResourceKind::Uniform);
- if (!useFixedSizedExistentialValue ||
- (uniformLayoutInfo && uniformLayoutInfo->count > fixedExistentialValueSize))
+ if (!targetSupportsPointer)
{
- // TODO: for targets that supports pointers, oversized existential values
+ // For targets that supports pointers, oversized existential values
// should be placed in an overflow region and only a pointer is needed in
// the place of the fixed sized uniform slot.
// We only need the "pending layout" mechanism for targets that does not