diff options
| author | Yong He <yonghe@outlook.com> | 2023-08-04 15:47:39 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-08-04 15:47:39 -0700 |
| commit | a2d90fb275962da84611160f8ddd74d934a68dbd (patch) | |
| tree | 066084537b9f4fe1f367de100ed6638a88a028c1 /source/slang/slang-ast-decl-ref.cpp | |
| parent | 17da4f0dec2b86ba3a4bdaf8a2ae112047d23623 (diff) | |
Redesign `DeclRef` and systematic `Val` deduplication (#3049)
* Redesign DeclRef + Deduplicate Val.
* Update project files
* Fix warning.
* Fix.
* Fix.
* Remove `Val::_equalsImplOverride`.
* Rmove `Val::_getHashCodeOverride`.
* Remove `semanticVisitor` param from `resolve`.
* Cleanups.
---------
Co-authored-by: Yong He <yhe@nvidia.com>
Diffstat (limited to 'source/slang/slang-ast-decl-ref.cpp')
| -rw-r--r-- | source/slang/slang-ast-decl-ref.cpp | 461 |
1 files changed, 461 insertions, 0 deletions
diff --git a/source/slang/slang-ast-decl-ref.cpp b/source/slang/slang-ast-decl-ref.cpp new file mode 100644 index 000000000..4384a6df9 --- /dev/null +++ b/source/slang/slang-ast-decl-ref.cpp @@ -0,0 +1,461 @@ +#include "slang-ast-builder.h" +#include "slang-ast-reflect.h" +#include "slang-generated-ast.h" +#include "slang-generated-ast-macro.h" +#include "slang-check-impl.h" + +namespace Slang +{ + +DeclRefBase* DirectDeclRef::_substituteImplOverride(ASTBuilder* astBuilder, SubstitutionSet subst, int* ioDiff) +{ + SLANG_UNUSED(astBuilder); + SLANG_UNUSED(subst); + SLANG_UNUSED(ioDiff); + return this; +} + +void DirectDeclRef::_toTextOverride(StringBuilder& out) +{ + if (getDecl()->getName() && getDecl()->getName()->text.getLength() != 0) + { + out << getDecl()->getName()->text; + } +} + +Val* DirectDeclRef::_resolveImplOverride() +{ + return this; +} + +DeclRefBase* DirectDeclRef::_getBaseOverride() +{ + return nullptr; +} + +DeclRefBase* _getDeclRefFromVal(Val* val) +{ + if (auto declRefType = as<DeclRefType>(val)) + return declRefType->getDeclRef(); + else if (auto genParamIntVal = as<GenericParamIntVal>(val)) + return genParamIntVal->getDeclRef(); + else if (auto declaredSubtypeWitness = as<DeclaredSubtypeWitness>(val)) + return declaredSubtypeWitness->getDeclRef(); + else if (auto declRef = as<DeclRefBase>(val)) + return declRef; + return nullptr; +} + +DeclRefBase* _resolveAsDeclRef(DeclRefBase* declRefToResolve) +{ + if (auto rs = _getDeclRefFromVal(declRefToResolve->resolve())) + return rs; + return declRefToResolve; +} + +DeclRefBase* MemberDeclRef::_substituteImplOverride(ASTBuilder* astBuilder, SubstitutionSet subst, int* ioDiff) +{ + int diff = 0; + auto substParent = getParentOperand()->substituteImpl(astBuilder, subst, &diff); + if (diff) + { + (*ioDiff)++; + return astBuilder->getMemberDeclRef(substParent, getDecl()); + } + return this; +} + +void MemberDeclRef::_toTextOverride(StringBuilder& out) +{ + getParentOperand()->toText(out); + if (out.getLength() && !out.endsWith(".")) + out << "."; + if (getDecl()->getName() && getDecl()->getName()->text.getLength() != 0) + { + out << getDecl()->getName()->text; + } +} + +Val* MemberDeclRef::_resolveImplOverride() +{ + auto resolvedParent = _resolveAsDeclRef(getParentOperand()); + if (resolvedParent != getParentOperand()) + { + return getCurrentASTBuilder()->getMemberDeclRef(resolvedParent, getDecl()); + } + return this; +} + +DeclRefBase* MemberDeclRef::_getBaseOverride() +{ + return getParentOperand(); +} + +Decl* LookupDeclRef::getSupDecl() +{ + if (auto supType = as<DeclRefType>(getWitness()->getSup())) + { + return supType->getDeclRef().getDecl(); + } + // If we reach here, something is wrong. + SLANG_UNEXPECTED("Invalid lookup declref"); +} + +DeclRefBase* LookupDeclRef::_substituteImplOverride(ASTBuilder* astBuilder, SubstitutionSet subst, int* ioDiff) +{ + int diff = 0; + + auto substWitness = as<SubtypeWitness>(getWitness()->substituteImpl(astBuilder, subst, &diff)); + if (diff == 0) + return this; + (*ioDiff)++; + + auto substSource = as<Type>(getLookupSource()->substituteImpl(astBuilder, subst, &diff)); + SLANG_ASSERT(substSource); + + if (auto resolved = _getDeclRefFromVal(tryResolve(substWitness, substSource))) + return resolved; + + return astBuilder->getLookupDeclRef(substSource, substWitness, getDecl()); +} + +void LookupDeclRef::_toTextOverride(StringBuilder& out) +{ + getLookupSource()->toText(out); + if (out.getLength() && !out.endsWith(".")) + out << "."; + if (getDecl()->getName() && getDecl()->getName()->text.getLength() != 0) + { + out << getDecl()->getName()->text; + } +} + +Val* LookupDeclRef::_resolveImplOverride() +{ + auto astBuilder = getCurrentASTBuilder(); + Val* resolved = this; + + auto newLookupSource = as<Type>(getLookupSource()->resolve()); + SLANG_ASSERT(newLookupSource); + + auto newWitness = as<SubtypeWitness>(getWitness()->resolve()); + SLANG_ASSERT(newWitness); + + if (auto resolvedVal = tryResolve(newWitness, newLookupSource)) + return resolvedVal; + if (newLookupSource != getLookupSource() || newWitness != getWitness()) + resolved = astBuilder->getLookupDeclRef(newLookupSource, newWitness, getDecl()); + return resolved; +} + +DeclRefBase* LookupDeclRef::_getBaseOverride() +{ + return nullptr; +} + +Val* LookupDeclRef::tryResolve(SubtypeWitness* newWitness, Type* newLookupSource) +{ + auto astBuilder = getCurrentASTBuilder(); + Decl* requirementKey = getDecl(); + RequirementWitness requirementWitness = tryLookUpRequirementWitness(astBuilder, newWitness, requirementKey); + switch (requirementWitness.getFlavor()) + { + default: + // No usable value was found, so there is nothing we can do. + break; + + case RequirementWitness::Flavor::val: + { + auto satisfyingVal = requirementWitness.getVal(); + return satisfyingVal; + } + break; + } + + // Hard code implementation of T.Differential.Differential == T.Differential rule. + auto builtinReq = requirementKey->findModifier<BuiltinRequirementModifier>(); + bool isConstraint = false; + if (!builtinReq) + { + if (auto parentAssocType = as<AssocTypeDecl>(requirementKey->parentDecl)) + { + builtinReq = parentAssocType->findModifier<BuiltinRequirementModifier>(); + isConstraint = true; + } + if (!builtinReq) + return nullptr; + } + if (builtinReq->kind != BuiltinRequirementKind::DifferentialType) + return nullptr; + // Is the concrete type a Differential associated type? + auto innerDeclRefType = as<DeclRefType>(newLookupSource); + if (!innerDeclRefType) + return nullptr; + auto innerBuiltinReq = innerDeclRefType->getDeclRef().getDecl()->findModifier<BuiltinRequirementModifier>(); + if (!innerBuiltinReq) + return nullptr; + if (innerBuiltinReq->kind != BuiltinRequirementKind::DifferentialType) + return nullptr; + if (isConstraint) + return newWitness; + if (innerDeclRefType->getDeclRef() != this) + { + auto result = innerDeclRefType->getDeclRef().declRefBase->resolve(); + if (result) + return result; + } + return innerDeclRefType; +} + +DeclRefBase* GenericAppDeclRef::_substituteImplOverride(ASTBuilder* astBuilder, SubstitutionSet subst, int* ioDiff) +{ + int diff = 0; + auto substGenericDeclRef = getGenericDeclRef()->substituteImpl(astBuilder, subst, &diff); + List<Val*> substArgs; + for (auto arg : getArgs()) + { + substArgs.add(arg->substituteImpl(astBuilder, subst, &diff)); + } + if (diff == 0) + return this; + (*ioDiff)++; + return astBuilder->getGenericAppDeclRef(substGenericDeclRef, substArgs.getArrayView(), getDecl()); +} + +GenericDecl* GenericAppDeclRef::getGenericDecl() { return as<GenericDecl>(getGenericDeclRef()->getDecl()); } + + +void GenericAppDeclRef::_toTextOverride(StringBuilder& out) +{ + auto genericDecl = as<GenericDecl>(getGenericDeclRef()->getDecl()); + Index paramCount = 0; + for (auto member : genericDecl->members) + if (as<GenericTypeParamDecl>(member) || as<GenericValueParamDecl>(member)) + paramCount++; + getGenericDeclRef()->toText(out); + out << "<"; + auto args = getArgs(); + Index argCount = args.getCount(); + for (Index aa = 0; aa < Math::Min(paramCount, argCount); ++aa) + { + if (aa != 0) out << ", "; + args[aa]->toText(out); + } + out << ">"; +} + +Val* GenericAppDeclRef::_resolveImplOverride() +{ + auto astBuilder = getCurrentASTBuilder(); + Val* resolvedVal = this; + auto resolvedGenericDeclRef = _resolveAsDeclRef(getGenericDeclRef()); + bool diff = false; + if (resolvedGenericDeclRef != getGenericDeclRef()) + diff = true; + List<Val*> resolvedArgs; + for (auto arg : getArgs()) + { + auto resolvedArg = arg->resolve(); + resolvedArgs.add(resolvedArg); + if (resolvedArg != arg) + diff = true; + } + if (diff) + resolvedVal = astBuilder->getGenericAppDeclRef(resolvedGenericDeclRef, resolvedArgs.getArrayView(), getDecl()); + return resolvedVal; +} + +DeclRefBase* GenericAppDeclRef::_getBaseOverride() +{ + return getGenericDeclRef(); +} + +// Convenience accessors for common properties of declarations + +DeclRefBase* DeclRefBase::substituteImpl(ASTBuilder* astBuilder, SubstitutionSet subst, int* ioDiff) +{ + SLANG_AST_NODE_VIRTUAL_CALL(DeclRefBase, substituteImpl, (astBuilder, subst, ioDiff)); +} + +DeclRefBase* DeclRefBase::getBase() { SLANG_AST_NODE_VIRTUAL_CALL(DeclRefBase, getBase, ()); } +void DeclRefBase::toText(StringBuilder& out) { SLANG_AST_NODE_VIRTUAL_CALL(DeclRefBase, toText, (out)); } + +Name* DeclRefBase::getName() const +{ + return getDecl()->nameAndLoc.name; +} + +SourceLoc DeclRefBase::getNameLoc() const +{ + return getDecl()->nameAndLoc.loc; +} + +SourceLoc DeclRefBase::getLoc() const +{ + return getDecl()->loc; +} + +DeclRefBase* DeclRefBase::getParent() +{ + auto astBuilder = getCurrentASTBuilder(); + if (!getDecl()->parentDecl) + return nullptr; + auto parentDecl = getDecl()->parentDecl; + for (auto base = getBase(); base; base = base->getBase()) + { + if (base->getDecl() == parentDecl) + return base; + bool parentIsChildOfBase = false; + for (auto dd = parentDecl->parentDecl; dd; dd = dd->parentDecl) + { + if (dd == base->getDecl()) + { + parentIsChildOfBase = true; + break; + } + } + if (parentIsChildOfBase) + return astBuilder->getMemberDeclRef(base, parentDecl); + } + return astBuilder->getDirectDeclRef(parentDecl); +} + +SubstitutionSet::operator bool() const +{ + return declRef != nullptr && !as<DirectDeclRef>(declRef); +} + +Val::OperandView<Val> tryGetGenericArguments(SubstitutionSet substSet, Decl* genericDecl) +{ + if (!substSet.declRef) + return Val::OperandView<Val>(); + + DeclRefBase* currentDeclRef = substSet.declRef; + // search for a substitution that might apply to us + for (auto s = currentDeclRef; s; s = s->getBase()) + { + auto genericAppDeclRef = as<GenericAppDeclRef>(s); + if (!genericAppDeclRef) + continue; + + // the generic decl associated with the substitution list must be + // the generic decl that declared this parameter + auto parentGeneric = genericAppDeclRef->getGenericDecl(); + if (parentGeneric != genericDecl) + continue; + + return genericAppDeclRef->getArgs(); + } + return Val::OperandView<Val>(); +} + +Type* SubstitutionSet::applyToType(ASTBuilder* astBuilder, Type* type) const +{ + if (!type) + return nullptr; + int diff = 0; + auto newType = as<Type>(type->substituteImpl(astBuilder, *this, &diff)); + if (diff && newType) + return newType; + return type; +} + +SubstExpr<Expr> applySubstitutionToExpr(SubstitutionSet substSet, Expr* expr) +{ + return SubstExpr<Expr>(expr, substSet); +} + + +DeclRefBase* SubstitutionSet::applyToDeclRef(ASTBuilder* astBuilder, DeclRefBase* otherDeclRef) const +{ + int diff = 0; + return otherDeclRef->substituteImpl(astBuilder, *this, &diff); +} + +LookupDeclRef* SubstitutionSet::findLookupDeclRef() const +{ + for (auto s = declRef; s; s = s->getBase()) + { + if (auto lookupDeclRef = as<LookupDeclRef>(s)) + return lookupDeclRef; + } + return nullptr; +} + +DeclRefBase* SubstitutionSet::getInnerMostNodeWithSubstInfo() const +{ + for (auto s = declRef; s; s = s->getBase()) + { + if (as<LookupDeclRef>(s) || as<GenericAppDeclRef>(s)) + return s; + } + return nullptr; +} + + +GenericAppDeclRef* SubstitutionSet::findGenericAppDeclRef(GenericDecl* genericDecl) const +{ + for (auto s = declRef; s; s = s->getBase()) + { + if (auto genApp = as<GenericAppDeclRef>(s)) + { + if (genApp->getGenericDecl() == genericDecl) + return genApp; + } + } + return nullptr; +} + +GenericAppDeclRef* SubstitutionSet::findGenericAppDeclRef() const +{ + for (auto s = declRef; s; s = s->getBase()) + { + if (auto genApp = as<GenericAppDeclRef>(s)) + { + return genApp; + } + } + return nullptr; +} + +DeclRef<Decl> createDefaultSubstitutionsIfNeeded( + ASTBuilder* astBuilder, + SemanticsVisitor* semantics, + DeclRef<Decl> declRef) +{ + if (declRef.as<GenericTypeParamDecl>()) + return declRef; + if (declRef.as<GenericValueParamDecl>()) + return declRef; + if (declRef.as<GenericTypeConstraintDecl>()) + return declRef; + ShortList<GenericDecl*> genericParentDecls; + auto lastSubstNode = SubstitutionSet(declRef).getInnerMostNodeWithSubstInfo(); + auto lastGenApp = as<GenericAppDeclRef>(lastSubstNode); + for (auto dd = declRef.getDecl()->parentDecl; dd; dd = dd->parentDecl) + { + if (lastGenApp && dd == lastGenApp->getGenericDecl()) + break; + if (auto gen = as<GenericDecl>(dd)) + genericParentDecls.add(gen); + } + DeclRef<Decl> parentDeclRef = lastSubstNode; + for (auto i = genericParentDecls.getCount() - 1; i >= 0; i--) + { + auto current = genericParentDecls[i]; + auto args = getDefaultSubstitutionArgs(astBuilder, semantics, current); + if (parentDeclRef) + { + parentDeclRef = astBuilder->getMemberDeclRef(parentDeclRef, current); + } + else + { + parentDeclRef = astBuilder->getDirectDeclRef(current); + } + parentDeclRef = astBuilder->getGenericAppDeclRef(parentDeclRef.as<GenericDecl>(), args.getArrayView()); + } + if (parentDeclRef.getDecl() == declRef.getDecl()) + return parentDeclRef; + return astBuilder->getMemberDeclRef(parentDeclRef, declRef.getDecl()); +} +} |
