From baf194e7456ba4568dcf11249896af35b3ce18cc Mon Sep 17 00:00:00 2001 From: Tim Foley Date: Wed, 11 Apr 2018 16:18:29 -0700 Subject: Introduce an IR-level type system (#481) * Introduce an IR-level type system Up to this point, the Slang IR has used the front-end type system to represent types in the IR. As a result (but ultimately more importantly) the IR representation of generics and specialization has used AST-level concepts embedded in the IR. For example, to express the specialization of `vector` to a concrete type `float` for `T`, we needed an IR operation that could represent the specialization, with operands that somehow represented the type argument `float`. The whole thing was very complicated. The big idea of this change is to introduce a new representation in which types in the IR are just ordinary instructions, so that using them as operands makes sense. The hierarchy of IR types closely mirrors the AST-side hierarchy for now, and that will probably be something we should maintain going forward. In order to make these changes work, though, I also had to do major overhauls of things like the way substitutions are performed, how we check interface conformances, the way lookup through interface types is done, etc. etc. This is a big change, and unfortunately any attempt to summarize it in the commit message wouldn't do it justice. * Fix 64-bit build warning * Fix up some clang warnings/errors --- source/slang/syntax.h | 140 +++++++++++++++++++++++++++++--------------------- 1 file changed, 82 insertions(+), 58 deletions(-) (limited to 'source/slang/syntax.h') diff --git a/source/slang/syntax.h b/source/slang/syntax.h index 0f23492d6..ebb9d814b 100644 --- a/source/slang/syntax.h +++ b/source/slang/syntax.h @@ -400,23 +400,18 @@ namespace Slang struct SubstitutionSet { - RefPtr genericSubstitutions; - RefPtr thisTypeSubstitution; - RefPtr globalGenParamSubstitutions; - operator bool() const + RefPtr substitutions; + operator Substitutions*() const { - return genericSubstitutions || thisTypeSubstitution || globalGenParamSubstitutions; + return substitutions; } + SubstitutionSet() {} - SubstitutionSet(RefPtr genSubst, RefPtr inThisTypeSubst, - RefPtr globalSubst) + SubstitutionSet(RefPtr subst) + : substitutions(subst) { - genericSubstitutions = genSubst; - thisTypeSubstitution = inThisTypeSubst; - globalGenParamSubstitutions = globalSubst; } bool Equals(SubstitutionSet substSet) const; - SubstitutionSet substituteImpl(SubstitutionSet subst, int * ioDiff); int GetHashCode() const; }; // A reference to a declaration, which may include @@ -444,11 +439,9 @@ namespace Slang substitutions(subst) {} - DeclRefBase(Decl* decl, RefPtr genSubstitutions, - RefPtr thisTypeSubst = nullptr, - RefPtr globalSubst = nullptr) - : decl(decl), - substitutions(genSubstitutions, thisTypeSubst, globalSubst) + DeclRefBase(Decl* decl, RefPtr subst) + : decl(decl) + , substitutions(subst) {} // Apply substitutions to a type or ddeclaration @@ -492,8 +485,8 @@ namespace Slang : DeclRefBase(decl, subst) {} - DeclRef(T* decl, RefPtr genSubst) - : DeclRefBase(decl, SubstitutionSet(genSubst, nullptr, nullptr)) + DeclRef(T* decl, RefPtr subst) + : DeclRefBase(decl, SubstitutionSet(subst)) {} template @@ -1004,6 +997,67 @@ namespace Slang LookupMask mask = LookupMask::Default; }; + struct WitnessTable; + + // A value that witnesses the satisfaction of an interface + // requirement by a particular declaration or value. + struct RequirementWitness + { + RequirementWitness() + : m_flavor(Flavor::none) + {} + + RequirementWitness(DeclRef declRef) + : m_flavor(Flavor::declRef) + , m_declRef(declRef) + {} + + RequirementWitness(RefPtr val); + + RequirementWitness(RefPtr witnessTable); + + enum class Flavor + { + none, + declRef, + val, + witnessTable, + }; + + Flavor getFlavor() + { + return m_flavor; + } + + DeclRef getDeclRef() + { + SLANG_ASSERT(getFlavor() == Flavor::declRef); + return m_declRef; + } + + RefPtr getVal() + { + SLANG_ASSERT(getFlavor() == Flavor::val); + return m_obj.As(); + } + + RefPtr getWitnessTable(); + + RequirementWitness specialize(SubstitutionSet const& subst); + + Flavor m_flavor; + DeclRef m_declRef; + RefPtr m_obj; + + }; + + typedef Dictionary RequirementDictionary; + + struct WitnessTable : RefObject + { + RequirementDictionary requirementDictionary; + }; + // Generate class definition for all syntax classes #define SYNTAX_FIELD(TYPE, NAME) TYPE NAME; #define FIELD(TYPE, NAME) TYPE NAME; @@ -1096,23 +1150,6 @@ namespace Slang return FilteredMemberRefList(declRef.getDecl()->Members, declRef.substitutions); } - // TODO: change this to return a lazy list instead of constructing actual list - inline List> getMembersWithExt(DeclRef const& declRef) - { - List> rs; - for (auto d : FilteredMemberRefList(declRef.getDecl()->Members, declRef.substitutions)) - rs.Add(d); - if (auto aggDeclRef = declRef.As()) - { - for (auto ext = GetCandidateExtensions(aggDeclRef); ext; ext = ext->nextCandidateExtension) - { - for (auto mbr : getMembers(DeclRef(ext, declRef.substitutions))) - rs.Add(mbr); - } - } - return rs; - } - template inline FilteredMemberRefList getMembersOfType(DeclRef const& declRef) { @@ -1245,29 +1282,16 @@ namespace Slang Session* session, Decl* decl); - void insertSubstAtBottom(RefPtr & substHead, RefPtr substToInsert); - RefPtr getNewThisTypeSubst(DeclRefBase & declRef); - RefPtr getThisTypeSubst(DeclRefBase & declRef, bool insertSubstEntry); - void removeSubstitution(DeclRefBase & declRef, RefPtr subst); - bool hasGenericSubstitutions(RefPtr subst); - RefPtr getGenericSubstitution(RefPtr 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. - SubstitutionSet substituteSubstitutions(SubstitutionSet oldSubst, SubstitutionSet subst, int * ioDiff); + DeclRef createDefaultSubstitutionsIfNeeded( + Session* session, + DeclRef declRef); + + RefPtr createDefaultSubsitutionsForGeneric( + Session* session, + GenericDecl* genericDecl, + RefPtr outerSubst); + + RefPtr findInnerMostGenericSubstitution(Substitutions* subst); } // namespace Slang #endif \ No newline at end of file -- cgit v1.2.3