summaryrefslogtreecommitdiffstats
path: root/source/slang
diff options
context:
space:
mode:
Diffstat (limited to 'source/slang')
-rw-r--r--source/slang/ir.cpp19
-rw-r--r--source/slang/syntax.cpp57
-rw-r--r--source/slang/syntax.h17
3 files changed, 64 insertions, 29 deletions
diff --git a/source/slang/ir.cpp b/source/slang/ir.cpp
index 598445fcd..eb78d144e 100644
--- a/source/slang/ir.cpp
+++ b/source/slang/ir.cpp
@@ -3109,24 +3109,7 @@ namespace Slang
RefPtr<Type> IRSpecContext::maybeCloneType(Type* originalType)
{
- auto rsType = originalType->GetCanonicalType()->Substitute(subst).As<Type>();
- if (auto declRefType = rsType.As<DeclRefType>())
- {
- if (subst)
- {
- auto newSubst = cloneSubstitutions(this, subst);
- insertSubstAtBottom(declRefType->declRef.substitutions, newSubst);
- }
- }
- else if (auto funcType = rsType.As<FuncType>())
- {
- RefPtr<FuncType> newFuncType = new FuncType();
- newFuncType->setSession(funcType->getSession());
- newFuncType->resultType = maybeCloneType(funcType->resultType);
- for (auto paramType : funcType->paramTypes)
- newFuncType->paramTypes.Add(maybeCloneType(paramType));
- }
- return rsType;
+ return originalType->Substitute(subst).As<Type>();
}
IRValue* IRSpecContext::maybeCloneValue(IRValue* originalValue)
diff --git a/source/slang/syntax.cpp b/source/slang/syntax.cpp
index 2c214a332..f8237359d 100644
--- a/source/slang/syntax.cpp
+++ b/source/slang/syntax.cpp
@@ -489,7 +489,7 @@ void Type::accept(IValVisitor* visitor, void* extra)
bool restore = false;
if (thisSubst && thisSubst->sourceType.Ptr() == dynamic_cast<Val*>(this))
thisSubst->sourceType = nullptr;
- auto newSubst = declRef.substitutions->SubstituteImpl(subst, ioDiff);
+ auto newSubst = substituteSubstitutions(declRef.substitutions, subst, ioDiff);
if (restore)
thisSubst->sourceType = oldSubstSrc;
if (auto thisTypeSubst = newSubst.As<ThisTypeSubstitution>())
@@ -1205,9 +1205,7 @@ void Type::accept(IValVisitor* visitor, void* extra)
if (!this) return nullptr;
int diff = 0;
- RefPtr<Substitutions> outerSubst;
- if (outer)
- outerSubst = outer->SubstituteImpl(subst, &diff);
+ RefPtr<Substitutions> outerSubst = outer ? outer->SubstituteImpl(subst, &diff) : nullptr;
RefPtr<Val> newSourceType;
if (sourceType)
newSourceType = sourceType->SubstituteImpl(subst, &diff);
@@ -1244,9 +1242,36 @@ void Type::accept(IValVisitor* visitor, void* extra)
return false;
}
- RefPtr<Substitutions> GlobalGenericParamSubstitution::SubstituteImpl(Substitutions* /*subst*/, int* /*ioDiff*/)
+ RefPtr<Substitutions> GlobalGenericParamSubstitution::SubstituteImpl(Substitutions* subst, int* ioDiff)
{
- // we will never replace values for this type of substitution
+ // if we find a GlobalGenericParamSubstitution in subst that references the same __generic_param decl
+ // return a copy of that GlobalGenericParamSubstitution
+ int diff = 0;
+ RefPtr<Substitutions> outerSubst = outer ? outer->SubstituteImpl(subst, &diff) : nullptr;
+ while (subst)
+ {
+ if (auto gSubst = dynamic_cast<GlobalGenericParamSubstitution*>(subst))
+ {
+ if (gSubst->paramDecl == paramDecl)
+ {
+ // substitute only if we are really different
+ if (!gSubst->actualType->EqualsVal(actualType))
+ {
+ RefPtr<GlobalGenericParamSubstitution> rs = new GlobalGenericParamSubstitution(*gSubst);
+ rs->outer = outerSubst;
+ return rs;
+ }
+ }
+ }
+ subst = subst->outer;
+ }
+ if (diff)
+ {
+ *ioDiff++;
+ RefPtr<GlobalGenericParamSubstitution> rs = new GlobalGenericParamSubstitution(*this);
+ rs->outer = outerSubst;
+ return rs;
+ }
return this;
}
@@ -1322,8 +1347,9 @@ void Type::accept(IValVisitor* visitor, void* extra)
}
return false;
}
- void insertGlobalGenericSubstitutions(RefPtr<Substitutions> & destSubst, Substitutions * srcSubst)
+ void insertGlobalGenericSubstitutions(RefPtr<Substitutions> & destSubst, Substitutions * srcSubst, int * ioDiff)
{
+ int diff = 0;
while (srcSubst)
{
if (auto globalGenSubst = dynamic_cast<GlobalGenericParamSubstitution*>(srcSubst))
@@ -1333,19 +1359,18 @@ void Type::accept(IValVisitor* visitor, void* extra)
RefPtr<GlobalGenericParamSubstitution> cpyGlobalGenSubst = new GlobalGenericParamSubstitution(*globalGenSubst);
cpyGlobalGenSubst->outer = nullptr;
insertSubstAtBottom(destSubst, cpyGlobalGenSubst);
+ diff = 1;
}
}
srcSubst = srcSubst->outer;
}
+ *ioDiff += diff;
}
DeclRefBase DeclRefBase::SubstituteImpl(Substitutions* subst, int* ioDiff)
{
- insertGlobalGenericSubstitutions(substitutions, subst);
- if (!substitutions) return *this;
-
int diff = 0;
- RefPtr<Substitutions> substSubst = substitutions->SubstituteImpl(subst, &diff);
+ RefPtr<Substitutions> substSubst = substituteSubstitutions(substitutions, subst, &diff);
if (!diff)
return *this;
@@ -1841,6 +1866,16 @@ void Type::accept(IValVisitor* visitor, void* extra)
return nullptr;
}
+ RefPtr<Substitutions> substituteSubstitutions(RefPtr<Substitutions> oldSubst, Substitutions * subst, int * ioDiff)
+ {
+ if (oldSubst)
+ oldSubst = oldSubst->SubstituteImpl(subst, ioDiff);
+
+ RefPtr<Substitutions> newSubst = oldSubst;
+ insertGlobalGenericSubstitutions(newSubst, subst, ioDiff);
+ return newSubst;
+ }
+
// FilteredTupleType
String FilteredTupleType::ToString()
diff --git a/source/slang/syntax.h b/source/slang/syntax.h
index f3690d9ae..e6a010a4a 100644
--- a/source/slang/syntax.h
+++ b/source/slang/syntax.h
@@ -1162,6 +1162,23 @@ namespace Slang
void removeSubstitution(DeclRefBase & declRef, RefPtr<Substitutions> subst);
bool hasGenericSubstitutions(RefPtr<Substitutions> subst);
RefPtr<GenericSubstitution> getGenericSubstitution(RefPtr<Substitutions> subst);
+
+ // This function substitutes the type arguments referenced in a linked list of substitutions
+ // which head is at `substHead` using the substitutions specified by `subst`. If the linked
+ // list `substHead` does not contain `GlobalGenericParamSubstitution` entries, they will be
+ // added to the bottom(outter most) of the linked list.
+ // Note that this function should be called when `substHead` is known to be the head of
+ // substitution linked list because the existance of `GlobalGenericPaaramSubstitution` is
+ // detected assuming the linked lists starts at `substHead`. If a substitution that is not
+ // the head of a substitution linked list is passed in, duplicate
+ // `GlobalGenericParamSubstitution`s could be appended to the linked list.
+ // This means that this function should * not* be called in places like
+ // `GenericSubstitution::SubstitutionImpl()` for its outer substitutions, because `outer` is
+ // obviously not the head of the linked list. Instead, use this function to substitution the
+ // substitution lists of `DeclRef` etc. to replace the call of
+ // `declRef.substitutions->SubstituteImpl()`, because the head to the linked list is known as a
+ // member of that class there.
+ RefPtr<Substitutions> substituteSubstitutions(RefPtr<Substitutions> oldSubst, Substitutions * subst, int * ioDiff);
} // namespace Slang
#endif \ No newline at end of file