summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2020-08-18 13:08:45 -0700
committerGitHub <noreply@github.com>2020-08-18 13:08:45 -0700
commitb820f34a1b6336af184458c5b1dfe2273c99f1ff (patch)
treeca9986891127cfe07eda18bfbdb5094eef5677cc
parent9abcb6ea24dbc7184c3a2ad9f4458f63f8901928 (diff)
Support initializing an existential value from a generic value. (#1503)
* Support initializing an existential value from a generic value. * Remove trailing spaces and clean up debugging code.
-rw-r--r--.gitignore1
-rw-r--r--source/slang/slang-ir-any-value-marshalling.cpp20
-rw-r--r--source/slang/slang-ir-augment-make-existential.cpp84
-rw-r--r--source/slang/slang-ir-augment-make-existential.h16
-rw-r--r--source/slang/slang-ir-generics-lowering-context.cpp3
-rw-r--r--source/slang/slang-ir-hoist-local-types.cpp111
-rw-r--r--source/slang/slang-ir-hoist-local-types.h18
-rw-r--r--source/slang/slang-ir-inst-defs.h4
-rw-r--r--source/slang/slang-ir-insts.h16
-rw-r--r--source/slang/slang-ir-lower-existential.cpp37
-rw-r--r--source/slang/slang-ir-lower-generic-call.cpp19
-rw-r--r--source/slang/slang-ir-lower-generic-function.cpp19
-rw-r--r--source/slang/slang-ir-lower-generic-type.cpp19
-rw-r--r--source/slang/slang-ir-lower-generics.cpp17
-rw-r--r--source/slang/slang-ir-lower-tuple-types.cpp19
-rw-r--r--source/slang/slang-ir-witness-table-wrapper.cpp19
-rw-r--r--source/slang/slang-ir.cpp10
-rw-r--r--source/slang/slang.vcxproj6
-rw-r--r--source/slang/slang.vcxproj.filters12
-rw-r--r--tests/compute/dynamic-dispatch-9.slang50
-rw-r--r--tests/compute/dynamic-dispatch-9.slang.expected.txt4
21 files changed, 402 insertions, 102 deletions
diff --git a/.gitignore b/.gitignore
index 1471d0b6e..0ee4e49e4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,6 +7,7 @@
*.sdf
*.ilk
*.obj
+.clang-format
bin/
intermediate/
build.*/
diff --git a/source/slang/slang-ir-any-value-marshalling.cpp b/source/slang/slang-ir-any-value-marshalling.cpp
index 26a9fca58..f732ffbe7 100644
--- a/source/slang/slang-ir-any-value-marshalling.cpp
+++ b/source/slang/slang-ir-any-value-marshalling.cpp
@@ -448,24 +448,18 @@ namespace Slang
sharedContext->addToWorkList(sharedContext->module->getModuleInst());
- // Process all instructions and translate all `IRPackAnyValue` and `IRUnpackAnyValue`.
while (sharedContext->workList.getCount() != 0)
{
- // We will then iterate until our work list goes dry.
- //
- while (sharedContext->workList.getCount() != 0)
- {
- IRInst* inst = sharedContext->workList.getLast();
+ IRInst* inst = sharedContext->workList.getLast();
- sharedContext->workList.removeLast();
- sharedContext->workListSet.Remove(inst);
+ sharedContext->workList.removeLast();
+ sharedContext->workListSet.Remove(inst);
- processInst(inst);
+ processInst(inst);
- for (auto child = inst->getLastChild(); child; child = child->getPrevInst())
- {
- sharedContext->addToWorkList(child);
- }
+ for (auto child = inst->getLastChild(); child; child = child->getPrevInst())
+ {
+ sharedContext->addToWorkList(child);
}
}
diff --git a/source/slang/slang-ir-augment-make-existential.cpp b/source/slang/slang-ir-augment-make-existential.cpp
new file mode 100644
index 000000000..18d061276
--- /dev/null
+++ b/source/slang/slang-ir-augment-make-existential.cpp
@@ -0,0 +1,84 @@
+#include "slang-ir-augment-make-existential.h"
+#include "slang-ir-insts.h"
+#include "slang-ir.h"
+
+namespace Slang
+{
+struct AugmentMakeExistentialContext
+{
+ IRModule* module;
+
+ SharedIRBuilder sharedBuilderStorage;
+
+ List<IRInst*> workList;
+ HashSet<IRInst*> workListSet;
+
+ void addToWorkList(IRInst* inst)
+ {
+ if (workListSet.Contains(inst))
+ return;
+
+ workList.add(inst);
+ workListSet.Add(inst);
+ }
+
+ void processMakeExistential(IRMakeExistential* inst)
+ {
+ IRBuilder builderStorage;
+ auto builder = &builderStorage;
+ builder->sharedBuilder = &sharedBuilderStorage;
+ builder->setInsertBefore(inst);
+
+ auto augInst = builder->emitMakeExistentialWithRTTI(
+ inst->getFullType(),
+ inst->getWrappedValue(),
+ inst->getWitnessTable(),
+ inst->getWrappedValue()->getDataType());
+ inst->replaceUsesWith(augInst);
+ inst->removeAndDeallocate();
+ }
+
+ void processInst(IRInst* inst)
+ {
+ switch (inst->op)
+ {
+ case kIROp_MakeExistential:
+ processMakeExistential((IRMakeExistential*)inst);
+ break;
+ default:
+ break;
+ }
+ }
+
+ void processModule()
+ {
+ SharedIRBuilder* sharedBuilder = &sharedBuilderStorage;
+ sharedBuilder->module = module;
+ sharedBuilder->session = module->session;
+
+ addToWorkList(module->getModuleInst());
+
+ while (workList.getCount() != 0)
+ {
+ IRInst* inst = workList.getLast();
+
+ workList.removeLast();
+ workListSet.Remove(inst);
+
+ processInst(inst);
+
+ for (auto child = inst->getLastChild(); child; child = child->getPrevInst())
+ {
+ addToWorkList(child);
+ }
+ }
+ }
+};
+
+void augmentMakeExistentialInsts(IRModule* module)
+{
+ AugmentMakeExistentialContext context;
+ context.module = module;
+ context.processModule();
+}
+} // namespace Slang
diff --git a/source/slang/slang-ir-augment-make-existential.h b/source/slang/slang-ir-augment-make-existential.h
new file mode 100644
index 000000000..75f2183b4
--- /dev/null
+++ b/source/slang/slang-ir-augment-make-existential.h
@@ -0,0 +1,16 @@
+// slang-ir-augment-make-existential.h
+#pragma once
+
+#include "slang-ir.h"
+
+namespace Slang
+{
+struct IRModule;
+class DiagnosticSink;
+
+/// Augment `MakeExistential(v, w)` insts to `MakeExistentialWithRTTI(v, w, t)`,
+/// where v is a concrete typed value, w is a witness table, and t is the type of
+/// v.
+void augmentMakeExistentialInsts(IRModule* module);
+
+} // namespace Slang
diff --git a/source/slang/slang-ir-generics-lowering-context.cpp b/source/slang/slang-ir-generics-lowering-context.cpp
index 55e18ebbb..67f376153 100644
--- a/source/slang/slang-ir-generics-lowering-context.cpp
+++ b/source/slang/slang-ir-generics-lowering-context.cpp
@@ -135,7 +135,8 @@ namespace Slang
switch (paramType->op)
{
case kIROp_WitnessTableType:
- // Do not translate witness table type.
+ case kIROp_ExtractExistentialType:
+ // Do not translate these types.
return (IRType*)paramType;
case kIROp_Param:
{
diff --git a/source/slang/slang-ir-hoist-local-types.cpp b/source/slang/slang-ir-hoist-local-types.cpp
new file mode 100644
index 000000000..864daa680
--- /dev/null
+++ b/source/slang/slang-ir-hoist-local-types.cpp
@@ -0,0 +1,111 @@
+#include "slang-ir-hoist-local-types.h"
+
+#include "slang-ir-insts.h"
+#include "slang-ir.h"
+
+namespace Slang
+{
+struct HoistLocalTypesContext
+{
+ IRModule* module;
+ DiagnosticSink* sink;
+
+ SharedIRBuilder sharedBuilderStorage;
+
+ List<IRInst*> workList;
+ HashSet<IRInst*> workListSet;
+
+ void addToWorkList(IRInst* inst)
+ {
+ for (auto ii = inst->getParent(); ii; ii = ii->getParent())
+ {
+ if (as<IRGeneric>(ii))
+ return;
+ }
+
+ if (workListSet.Contains(inst))
+ return;
+
+ workList.add(inst);
+ workListSet.Add(inst);
+ }
+
+ void processInst(IRInst* inst)
+ {
+ auto sharedBuilder = &sharedBuilderStorage;
+ if (!as<IRType>(inst))
+ return;
+ if (inst->getParent() == module->getModuleInst())
+ return;
+ IRInstKey key = {inst};
+ if (auto value = sharedBuilder->globalValueNumberingMap.TryGetValue(key))
+ {
+ inst->replaceUsesWith(*value);
+ inst->removeAndDeallocate();
+ return;
+ }
+ IRBuilder builder;
+ builder.sharedBuilder = sharedBuilder;
+ builder.setInsertInto(module->getModuleInst());
+ bool hoistable = true;
+ ShortList<IRInst*> mappedOperands;
+ for (UInt i = 0; i < inst->getOperandCount(); i++)
+ {
+ IRInstKey opKey = {inst->getOperand(i)};
+ if (auto value = sharedBuilder->globalValueNumberingMap.TryGetValue(opKey))
+ {
+ mappedOperands.add(*value);
+ }
+ else
+ {
+ hoistable = false;
+ break;
+ }
+ }
+ if (hoistable)
+ {
+ auto newType = builder.getType(
+ inst->op, mappedOperands.getCount(), mappedOperands.getArrayView().getBuffer());
+ inst->transferDecorationsTo(newType);
+ inst->replaceUsesWith(newType);
+ inst->removeAndDeallocate();
+ }
+ }
+
+ void processModule()
+ {
+ SharedIRBuilder* sharedBuilder = &sharedBuilderStorage;
+ sharedBuilder->module = module;
+ sharedBuilder->session = module->session;
+
+ // Deduplicate equivalent types and build numbering map for global types.
+ sharedBuilder->deduplicateAndRebuildGlobalNumberingMap();
+
+ addToWorkList(module->getModuleInst());
+
+ while (workList.getCount() != 0)
+ {
+ IRInst* inst = workList.getLast();
+
+ workList.removeLast();
+ workListSet.Remove(inst);
+
+ processInst(inst);
+
+ for (auto child = inst->getLastChild(); child; child = child->getPrevInst())
+ {
+ addToWorkList(child);
+ }
+ }
+ }
+};
+
+void hoistLocalTypes(IRModule* module, DiagnosticSink* sink)
+{
+ HoistLocalTypesContext context;
+ context.module = module;
+ context.sink = sink;
+ context.processModule();
+}
+
+} // namespace Slang
diff --git a/source/slang/slang-ir-hoist-local-types.h b/source/slang/slang-ir-hoist-local-types.h
new file mode 100644
index 000000000..6b742746f
--- /dev/null
+++ b/source/slang/slang-ir-hoist-local-types.h
@@ -0,0 +1,18 @@
+// slang-ir-hoist-local-types.h
+#pragma once
+
+#include "slang-ir.h"
+
+namespace Slang
+{
+struct IRModule;
+class DiagnosticSink;
+
+/// Hoist local types to global scope if possible.
+/// Some transformation passes may leave behind local type definitons that
+/// can be hoisted to global scope. This pass examines all local type defintions
+// and try to hoist them to global scope if the definition is no longer dependent on
+// the local context.
+void hoistLocalTypes(IRModule* module, DiagnosticSink* sink);
+
+} // namespace Slang
diff --git a/source/slang/slang-ir-inst-defs.h b/source/slang/slang-ir-inst-defs.h
index f60f84a9e..05ad07668 100644
--- a/source/slang/slang-ir-inst-defs.h
+++ b/source/slang/slang-ir-inst-defs.h
@@ -573,6 +573,10 @@ INST(HighLevelDeclDecoration, highLevelDecl, 1, 0)
// shows that `C` conforms to `I`.
//
INST(MakeExistential, makeExistential, 2, 0)
+// A `MakeExistentialWithRTTI(v, w, t)` is the same with `MakeExistential`,
+// but with the type of `v` being an explict operand.
+INST(MakeExistentialWithRTTI, makeExistentialWithRTTI, 3, 0)
+
// A `wrapExistential(v, T0,w0, T1,w0) : T` instruction is similar to `makeExistential`.
// but applies to a value `v` that is of type `BindExistentials(T, T0,w0, ...)`. The
diff --git a/source/slang/slang-ir-insts.h b/source/slang/slang-ir-insts.h
index a66ca8f7a..65a2dd4a6 100644
--- a/source/slang/slang-ir-insts.h
+++ b/source/slang/slang-ir-insts.h
@@ -1590,6 +1590,16 @@ struct IRMakeExistential : IRInst
IR_LEAF_ISA(MakeExistential)
};
+struct IRMakeExistentialWithRTTI : IRInst
+{
+ IRInst* getWrappedValue() { return getOperand(0); }
+ IRInst* getWitnessTable() { return getOperand(1); }
+ IRInst* getRTTI() { return getOperand(2); }
+
+
+ IR_LEAF_ISA(MakeExistentialWithRTTI)
+};
+
/// Generalizes `IRMakeExistential` by allowing a type with existential sub-fields to be boxed
struct IRWrapExistential : IRInst
{
@@ -1927,6 +1937,12 @@ struct IRBuilder
IRInst* value,
IRInst* witnessTable);
+ IRInst* emitMakeExistentialWithRTTI(
+ IRType* type,
+ IRInst* value,
+ IRInst* witnessTable,
+ IRInst* rtti);
+
IRInst* emitWrapExistential(
IRType* type,
IRInst* value,
diff --git a/source/slang/slang-ir-lower-existential.cpp b/source/slang/slang-ir-lower-existential.cpp
index af47a1dfe..4078ad884 100644
--- a/source/slang/slang-ir-lower-existential.cpp
+++ b/source/slang/slang-ir-lower-existential.cpp
@@ -11,7 +11,7 @@ namespace Slang
{
SharedGenericsLoweringContext* sharedContext;
- void processMakeExistential(IRMakeExistential* inst)
+ void processMakeExistential(IRMakeExistentialWithRTTI* inst)
{
IRBuilder builderStorage;
auto builder = &builderStorage;
@@ -27,17 +27,11 @@ namespace Slang
auto rttiType = builder->getPtrType(builder->getRTTIType());
auto tupleType = builder->getTupleType(anyValueType, witnessTableType, rttiType);
- IRInst* rttiObject = nullptr;
- if (valueType->op != kIROp_AnyValueType)
- {
- rttiObject = sharedContext->maybeEmitRTTIObject(valueType);
- rttiObject = builder->emitGetAddress(
- builder->getPtrType(builder->getRTTIType()),
- rttiObject);
- }
- else
+ IRInst* rttiObject = inst->getRTTI();
+ if (auto type = as<IRType>(rttiObject))
{
- rttiObject = valueType;
+ rttiObject = sharedContext->maybeEmitRTTIObject(type);
+ rttiObject = builder->emitGetAddress(rttiType, rttiObject);
}
IRInst* packedValue = value;
if (valueType->op != kIROp_AnyValueType)
@@ -87,7 +81,7 @@ namespace Slang
void processInst(IRInst* inst)
{
- if (auto makeExistential = as<IRMakeExistential>(inst))
+ if (auto makeExistential = as<IRMakeExistentialWithRTTI>(inst))
{
processMakeExistential(makeExistential);
}
@@ -119,21 +113,16 @@ namespace Slang
while (sharedContext->workList.getCount() != 0)
{
- // We will then iterate until our work list goes dry.
- //
- while (sharedContext->workList.getCount() != 0)
- {
- IRInst* inst = sharedContext->workList.getLast();
+ IRInst* inst = sharedContext->workList.getLast();
- sharedContext->workList.removeLast();
- sharedContext->workListSet.Remove(inst);
+ sharedContext->workList.removeLast();
+ sharedContext->workListSet.Remove(inst);
- processInst(inst);
+ processInst(inst);
- for (auto child = inst->getLastChild(); child; child = child->getPrevInst())
- {
- sharedContext->addToWorkList(child);
- }
+ for (auto child = inst->getLastChild(); child; child = child->getPrevInst())
+ {
+ sharedContext->addToWorkList(child);
}
}
}
diff --git a/source/slang/slang-ir-lower-generic-call.cpp b/source/slang/slang-ir-lower-generic-call.cpp
index 1bc6d6705..90216b915 100644
--- a/source/slang/slang-ir-lower-generic-call.cpp
+++ b/source/slang/slang-ir-lower-generic-call.cpp
@@ -226,21 +226,16 @@ namespace Slang
while (sharedContext->workList.getCount() != 0)
{
- // We will then iterate until our work list goes dry.
- //
- while (sharedContext->workList.getCount() != 0)
- {
- IRInst* inst = sharedContext->workList.getLast();
+ IRInst* inst = sharedContext->workList.getLast();
- sharedContext->workList.removeLast();
- sharedContext->workListSet.Remove(inst);
+ sharedContext->workList.removeLast();
+ sharedContext->workListSet.Remove(inst);
- processInst(inst);
+ processInst(inst);
- for (auto child = inst->getLastChild(); child; child = child->getPrevInst())
- {
- sharedContext->addToWorkList(child);
- }
+ for (auto child = inst->getLastChild(); child; child = child->getPrevInst())
+ {
+ sharedContext->addToWorkList(child);
}
}
}
diff --git a/source/slang/slang-ir-lower-generic-function.cpp b/source/slang/slang-ir-lower-generic-function.cpp
index 360e3cdbb..f9a7e0a24 100644
--- a/source/slang/slang-ir-lower-generic-function.cpp
+++ b/source/slang/slang-ir-lower-generic-function.cpp
@@ -297,21 +297,16 @@ namespace Slang
while (sharedContext->workList.getCount() != 0)
{
- // We will then iterate until our work list goes dry.
- //
- while (sharedContext->workList.getCount() != 0)
- {
- IRInst* inst = sharedContext->workList.getLast();
+ IRInst* inst = sharedContext->workList.getLast();
- sharedContext->workList.removeLast();
- sharedContext->workListSet.Remove(inst);
+ sharedContext->workList.removeLast();
+ sharedContext->workListSet.Remove(inst);
- processInst(inst);
+ processInst(inst);
- for (auto child = inst->getLastChild(); child; child = child->getPrevInst())
- {
- sharedContext->addToWorkList(child);
- }
+ for (auto child = inst->getLastChild(); child; child = child->getPrevInst())
+ {
+ sharedContext->addToWorkList(child);
}
}
diff --git a/source/slang/slang-ir-lower-generic-type.cpp b/source/slang/slang-ir-lower-generic-type.cpp
index 4ea47a4b2..0b0973274 100644
--- a/source/slang/slang-ir-lower-generic-type.cpp
+++ b/source/slang/slang-ir-lower-generic-type.cpp
@@ -44,21 +44,16 @@ namespace Slang
while (sharedContext->workList.getCount() != 0)
{
- // We will then iterate until our work list goes dry.
- //
- while (sharedContext->workList.getCount() != 0)
- {
- IRInst* inst = sharedContext->workList.getLast();
+ IRInst* inst = sharedContext->workList.getLast();
- sharedContext->workList.removeLast();
- sharedContext->workListSet.Remove(inst);
+ sharedContext->workList.removeLast();
+ sharedContext->workListSet.Remove(inst);
- processInst(inst);
+ processInst(inst);
- for (auto child = inst->getLastChild(); child; child = child->getPrevInst())
- {
- sharedContext->addToWorkList(child);
- }
+ for (auto child = inst->getLastChild(); child; child = child->getPrevInst())
+ {
+ sharedContext->addToWorkList(child);
}
}
sharedContext->sharedBuilderStorage.deduplicateAndRebuildGlobalNumberingMap();
diff --git a/source/slang/slang-ir-lower-generics.cpp b/source/slang/slang-ir-lower-generics.cpp
index b00e36ef1..63e1fdc49 100644
--- a/source/slang/slang-ir-lower-generics.cpp
+++ b/source/slang/slang-ir-lower-generics.cpp
@@ -2,6 +2,7 @@
#include "slang-ir-lower-generics.h"
#include "slang-ir-any-value-marshalling.h"
+#include "slang-ir-augment-make-existential.h"
#include "slang-ir-generics-lowering-context.h"
#include "slang-ir-lower-existential.h"
#include "slang-ir-lower-generic-function.h"
@@ -21,9 +22,15 @@ namespace Slang
sharedContext.module = module;
sharedContext.sink = sink;
- lowerExistentials(&sharedContext);
- if (sink->getErrorCount() != 0)
- return;
+ // Replace all `makeExistential` insts with `makeExistentialWithRTTI`
+ // before making any other changes. This is necessary because a parameter of
+ // generic type will be lowered into `AnyValueType`, and after that we can no longer
+ // access the original generic type parameter from the lowered parameter value.
+ // This steps ensures that the generic type parameter is available via an
+ // explicit operand in `makeExistentialWithRTTI`, so that type parameter
+ // can be translated into an RTTI object during `lower-generic-type`,
+ // and used to create a tuple representing the existential value.
+ augmentMakeExistentialInsts(module);
lowerGenericFunctions(&sharedContext);
if (sink->getErrorCount() != 0)
@@ -33,6 +40,10 @@ namespace Slang
if (sink->getErrorCount() != 0)
return;
+ lowerExistentials(&sharedContext);
+ if (sink->getErrorCount() != 0)
+ return;
+
lowerGenericCalls(&sharedContext);
if (sink->getErrorCount() != 0)
return;
diff --git a/source/slang/slang-ir-lower-tuple-types.cpp b/source/slang/slang-ir-lower-tuple-types.cpp
index cadf77253..d9fd91d3d 100644
--- a/source/slang/slang-ir-lower-tuple-types.cpp
+++ b/source/slang/slang-ir-lower-tuple-types.cpp
@@ -149,21 +149,16 @@ namespace Slang
while (workList.getCount() != 0)
{
- // We will then iterate until our work list goes dry.
- //
- while (workList.getCount() != 0)
- {
- IRInst* inst = workList.getLast();
+ IRInst* inst = workList.getLast();
- workList.removeLast();
- workListSet.Remove(inst);
+ workList.removeLast();
+ workListSet.Remove(inst);
- processInst(inst);
+ processInst(inst);
- for (auto child = inst->getLastChild(); child; child = child->getPrevInst())
- {
- addToWorkList(child);
- }
+ for (auto child = inst->getLastChild(); child; child = child->getPrevInst())
+ {
+ addToWorkList(child);
}
}
diff --git a/source/slang/slang-ir-witness-table-wrapper.cpp b/source/slang/slang-ir-witness-table-wrapper.cpp
index 8dda95563..084571642 100644
--- a/source/slang/slang-ir-witness-table-wrapper.cpp
+++ b/source/slang/slang-ir-witness-table-wrapper.cpp
@@ -211,21 +211,16 @@ namespace Slang
while (sharedContext->workList.getCount() != 0)
{
- // We will then iterate until our work list goes dry.
- //
- while (sharedContext->workList.getCount() != 0)
- {
- IRInst* inst = sharedContext->workList.getLast();
+ IRInst* inst = sharedContext->workList.getLast();
- sharedContext->workList.removeLast();
- sharedContext->workListSet.Remove(inst);
+ sharedContext->workList.removeLast();
+ sharedContext->workListSet.Remove(inst);
- processInst(inst);
+ processInst(inst);
- for (auto child = inst->getLastChild(); child; child = child->getPrevInst())
- {
- sharedContext->addToWorkList(child);
- }
+ for (auto child = inst->getLastChild(); child; child = child->getPrevInst())
+ {
+ sharedContext->addToWorkList(child);
}
}
}
diff --git a/source/slang/slang-ir.cpp b/source/slang/slang-ir.cpp
index 2a1db6310..c5943da3c 100644
--- a/source/slang/slang-ir.cpp
+++ b/source/slang/slang-ir.cpp
@@ -2790,6 +2790,16 @@ namespace Slang
return emitIntrinsicInst(type, kIROp_MakeExistential, SLANG_COUNT_OF(args), args);
}
+ IRInst* IRBuilder::emitMakeExistentialWithRTTI(
+ IRType* type,
+ IRInst* value,
+ IRInst* witnessTable,
+ IRInst* rtti)
+ {
+ IRInst* args[] = { value, witnessTable, rtti };
+ return emitIntrinsicInst(type, kIROp_MakeExistentialWithRTTI, SLANG_COUNT_OF(args), args);
+ }
+
IRInst* IRBuilder::emitWrapExistential(
IRType* type,
IRInst* value,
diff --git a/source/slang/slang.vcxproj b/source/slang/slang.vcxproj
index 82e575ef9..563014c5b 100644
--- a/source/slang/slang.vcxproj
+++ b/source/slang/slang.vcxproj
@@ -223,6 +223,7 @@
<ClInclude Include="slang-image-format-defs.h" />
<ClInclude Include="slang-include-system.h" />
<ClInclude Include="slang-ir-any-value-marshalling.h" />
+ <ClInclude Include="slang-ir-augment-make-existential.h" />
<ClInclude Include="slang-ir-bind-existentials.h" />
<ClInclude Include="slang-ir-byte-address-legalize.h" />
<ClInclude Include="slang-ir-clone.h" />
@@ -236,6 +237,7 @@
<ClInclude Include="slang-ir-explicit-global-init.h" />
<ClInclude Include="slang-ir-generics-lowering-context.h" />
<ClInclude Include="slang-ir-glsl-legalize.h" />
+ <ClInclude Include="slang-ir-hoist-local-types.h" />
<ClInclude Include="slang-ir-inline.h" />
<ClInclude Include="slang-ir-inst-defs.h" />
<ClInclude Include="slang-ir-insts.h" />
@@ -329,6 +331,7 @@
<ClCompile Include="slang-hlsl-intrinsic-set.cpp" />
<ClCompile Include="slang-include-system.cpp" />
<ClCompile Include="slang-ir-any-value-marshalling.cpp" />
+ <ClCompile Include="slang-ir-augment-make-existential.cpp" />
<ClCompile Include="slang-ir-bind-existentials.cpp" />
<ClCompile Include="slang-ir-byte-address-legalize.cpp" />
<ClCompile Include="slang-ir-clone.cpp" />
@@ -343,6 +346,7 @@
<ClCompile Include="slang-ir-explicit-global-init.cpp" />
<ClCompile Include="slang-ir-generics-lowering-context.cpp" />
<ClCompile Include="slang-ir-glsl-legalize.cpp" />
+ <ClCompile Include="slang-ir-hoist-local-types.cpp" />
<ClCompile Include="slang-ir-inline.cpp" />
<ClCompile Include="slang-ir-layout.cpp" />
<ClCompile Include="slang-ir-legalize-types.cpp" />
@@ -413,4 +417,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
-</Project> \ No newline at end of file
+</Project> \ No newline at end of file
diff --git a/source/slang/slang.vcxproj.filters b/source/slang/slang.vcxproj.filters
index 3484a1638..1fff5d01f 100644
--- a/source/slang/slang.vcxproj.filters
+++ b/source/slang/slang.vcxproj.filters
@@ -120,6 +120,9 @@
<ClInclude Include="slang-ir-any-value-marshalling.h">
<Filter>Header Files</Filter>
</ClInclude>
+ <ClInclude Include="slang-ir-augment-make-existential.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
<ClInclude Include="slang-ir-bind-existentials.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -159,6 +162,9 @@
<ClInclude Include="slang-ir-glsl-legalize.h">
<Filter>Header Files</Filter>
</ClInclude>
+ <ClInclude Include="slang-ir-hoist-local-types.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
<ClInclude Include="slang-ir-inline.h">
<Filter>Header Files</Filter>
</ClInclude>
@@ -434,6 +440,9 @@
<ClCompile Include="slang-ir-any-value-marshalling.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="slang-ir-augment-make-existential.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
<ClCompile Include="slang-ir-bind-existentials.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@@ -476,6 +485,9 @@
<ClCompile Include="slang-ir-glsl-legalize.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="slang-ir-hoist-local-types.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
<ClCompile Include="slang-ir-inline.cpp">
<Filter>Source Files</Filter>
</ClCompile>
diff --git a/tests/compute/dynamic-dispatch-9.slang b/tests/compute/dynamic-dispatch-9.slang
new file mode 100644
index 000000000..4fb45edc9
--- /dev/null
+++ b/tests/compute/dynamic-dispatch-9.slang
@@ -0,0 +1,50 @@
+//TEST(compute):COMPARE_COMPUTE:-cpu -xslang -allow-dynamic-code
+//DISABLE_TEST(compute):COMPARE_COMPUTE:-cuda -xslang -allow-dynamic-code
+
+// Test dynamic dispatch code gen for initializing an extential value
+// from a generic value.
+
+[anyValueSize(16)]
+interface IInterface
+{
+ int Compute(int inVal);
+};
+
+int GenericCompute0(IInterface obj, int inVal)
+{
+ return obj.Compute(inVal);
+}
+
+int GenericCompute1<T:IInterface>(T obj, int inVal)
+{
+ IInterface iobj = obj;
+ return iobj.Compute(inVal) +
+ GenericCompute0(obj, inVal) -
+ GenericCompute0(iobj, inVal);
+}
+
+
+struct Impl : IInterface
+{
+ int base;
+ int Compute(int inVal) { return base + inVal * inVal; }
+};
+
+int test(int inVal)
+{
+ Impl obj;
+ obj.base = 1;
+ return GenericCompute1(obj, inVal);
+}
+
+//TEST_INPUT:ubuffer(data=[0 1 2 3], stride=4):out,name=outputBuffer
+RWStructuredBuffer<int> outputBuffer : register(u0);
+
+[numthreads(4, 1, 1)]
+void computeMain(uint3 dispatchThreadID : SV_DispatchThreadID)
+{
+ uint tid = dispatchThreadID.x;
+ int inVal = outputBuffer[tid];
+ int outVal = test(inVal);
+ outputBuffer[tid] = outVal;
+}
diff --git a/tests/compute/dynamic-dispatch-9.slang.expected.txt b/tests/compute/dynamic-dispatch-9.slang.expected.txt
new file mode 100644
index 000000000..146ab3c8c
--- /dev/null
+++ b/tests/compute/dynamic-dispatch-9.slang.expected.txt
@@ -0,0 +1,4 @@
+1
+2
+5
+A