diff options
| author | Douglas Gregor <dgregor@apple.com> | 2010-12-06 18:36:25 +0000 | 
|---|---|---|
| committer | Douglas Gregor <dgregor@apple.com> | 2010-12-06 18:36:25 +0000 | 
| commit | bf62d647de980ba01cd2f3f47adc9bc1b7ec3d19 (patch) | |
| tree | 7829fa991010c407346a354c9e124292192f1154 /clang | |
| parent | 9bc2677b8ce6ffe8bf1de76e6293d555bcaf3f0e (diff) | |
| download | bcm5719-llvm-bf62d647de980ba01cd2f3f47adc9bc1b7ec3d19.tar.gz bcm5719-llvm-bf62d647de980ba01cd2f3f47adc9bc1b7ec3d19.zip  | |
Re-implement caching for the linkage calculation of declarations.
My previous attempt at solving the compile-time problem with many
redeclarations of the same entity cached both linkage and visibility,
while this patch only tackles linkage. There are several reasons for
this difference:
  - Linkage is a language concept, and is evaluated many times during
    semantic analysis and codegen, while visibility is only a
    code-generation concept that is evaluated only once per (unique)
    declaration. Hence, we *must* optimize linkage calculations but
    don't need to optimize visibility computation.
  - Once we know the linkage of a declaration, subsequent
    redeclarations can't change that linkage. Hence, cache
    invalidation is far simpler than for visibility, where a later
    redeclaration can completely change the visibility.
  - We have 3 spare bits in Decl to store the linkage cache, so the
    cache doesn't increase the size of declarations. With the
    visibility+linkage cache, NamedDecl got larger.
llvm-svn: 121023
Diffstat (limited to 'clang')
| -rw-r--r-- | clang/include/clang/AST/Decl.h | 44 | ||||
| -rw-r--r-- | clang/include/clang/AST/DeclBase.h | 23 | ||||
| -rw-r--r-- | clang/include/clang/AST/Redeclarable.h | 20 | ||||
| -rw-r--r-- | clang/lib/AST/Decl.cpp | 114 | ||||
| -rw-r--r-- | clang/lib/Serialization/ASTReaderDecl.cpp | 4 | 
5 files changed, 140 insertions, 65 deletions
diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index bdc91a168ee..299d5f6f4e4 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -264,7 +264,7 @@ public:    };    /// \brief Determine what kind of linkage this entity has. -  Linkage getLinkage() const { return getLinkageAndVisibility().linkage(); } +  Linkage getLinkage() const;    /// \brief Determines the visibility of this entity.    Visibility getVisibility() const { return getLinkageAndVisibility().visibility(); } @@ -272,6 +272,10 @@ public:    /// \brief Determines the linkage and visibility of this entity.    LinkageInfo getLinkageAndVisibility() const; +  /// \brief Clear the linkage cache in response to a change +  /// to the declaration.  +  void ClearLinkageCache() { HasCachedLinkage = 0; } +    /// \brief Looks through UsingDecls and ObjCCompatibleAliasDecls for    /// the underlying named decl.    NamedDecl *getUnderlyingDecl(); @@ -625,6 +629,8 @@ private:    bool NRVOVariable : 1;    friend class StmtIteratorBase; +  friend class ASTDeclReader; +    protected:    VarDecl(Kind DK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id,            QualType T, TypeSourceInfo *TInfo, StorageClass SC, @@ -660,10 +666,7 @@ public:    StorageClass getStorageClassAsWritten() const {      return (StorageClass) SClassAsWritten;    } -  void setStorageClass(StorageClass SC) { -    assert(isLegalForVariable(SC)); -    SClass = SC; -  } +  void setStorageClass(StorageClass SC);    void setStorageClassAsWritten(StorageClass SC) {      assert(isLegalForVariable(SC));      SClassAsWritten = SC; @@ -1478,10 +1481,7 @@ public:    }    StorageClass getStorageClass() const { return StorageClass(SClass); } -  void setStorageClass(StorageClass SC) { -    assert(isLegalForFunction(SC)); -    SClass = SC; -  } +  void setStorageClass(StorageClass SC);    StorageClass getStorageClassAsWritten() const {      return StorageClass(SClassAsWritten); @@ -2558,6 +2558,32 @@ inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,    return DB;  } +template<typename decl_type> +void Redeclarable<decl_type>::setPreviousDeclaration(decl_type *PrevDecl) { +  // Note: This routine is implemented here because we need both NamedDecl +  // and Redeclarable to be defined. + +  decl_type *First; +   +  if (PrevDecl) { +    // Point to previous. Make sure that this is actually the most recent +    // redeclaration, or we can build invalid chains. If the most recent +    // redeclaration is invalid, it won't be PrevDecl, but we want it anyway. +    RedeclLink = PreviousDeclLink(llvm::cast<decl_type>( +                                                        PrevDecl->getMostRecentDeclaration())); +    First = PrevDecl->getFirstDeclaration(); +    assert(First->RedeclLink.NextIsLatest() && "Expected first"); +  } else { +    // Make this first. +    First = static_cast<decl_type*>(this); +  } +   +  // First one will point to this one as latest. +  First->RedeclLink = LatestDeclLink(static_cast<decl_type*>(this)); +  if (NamedDecl *ND = dyn_cast<NamedDecl>(static_cast<decl_type*>(this))) +    ND->ClearLinkageCache(); +} +  }  // end namespace clang  #endif diff --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h index 0aa60ce9782..f091ce043ad 100644 --- a/clang/include/clang/AST/DeclBase.h +++ b/clang/include/clang/AST/DeclBase.h @@ -198,7 +198,7 @@ private:      return DeclCtx.get<DeclContext*>();    } -  /// Loc - The location that this decl. +  /// Loc - The location of this decl.    SourceLocation Loc;    /// DeclKind - This indicates which class this is. @@ -231,8 +231,19 @@ protected:    unsigned ChangedAfterLoad : 1;    /// IdentifierNamespace - This specifies what IDNS_* namespace this lives in. -  unsigned IdentifierNamespace : 15; +  unsigned IdentifierNamespace : 12; +  /// \brief Whether the \c CachedLinkage field is active. +  /// +  /// This field is only valid for NamedDecls subclasses. +  mutable unsigned HasCachedLinkage : 1; +   +  /// \brief If \c HasCachedLinkage, the linkage of this declaration. +  /// +  /// This field is only valid for NamedDecls subclasses. +  mutable unsigned CachedLinkage : 2; +   +    private:    void CheckAccessDeclContext() const; @@ -243,7 +254,9 @@ protected:        Loc(L), DeclKind(DK), InvalidDecl(0),        HasAttrs(false), Implicit(false), Used(false),        Access(AS_none), PCHLevel(0), ChangedAfterLoad(false), -      IdentifierNamespace(getIdentifierNamespaceForKind(DK)) { +      IdentifierNamespace(getIdentifierNamespaceForKind(DK)), +      HasCachedLinkage(0)  +  {      if (Decl::CollectingStats()) add(DK);    } @@ -251,7 +264,9 @@ protected:      : NextDeclInContext(0), DeclKind(DK), InvalidDecl(0),        HasAttrs(false), Implicit(false), Used(false),        Access(AS_none), PCHLevel(0), ChangedAfterLoad(false), -      IdentifierNamespace(getIdentifierNamespaceForKind(DK)) { +      IdentifierNamespace(getIdentifierNamespaceForKind(DK)), +      HasCachedLinkage(0) +  {      if (Decl::CollectingStats()) add(DK);    } diff --git a/clang/include/clang/AST/Redeclarable.h b/clang/include/clang/AST/Redeclarable.h index ba778293ba2..e87ca78d635 100644 --- a/clang/include/clang/AST/Redeclarable.h +++ b/clang/include/clang/AST/Redeclarable.h @@ -109,25 +109,7 @@ public:    /// \brief Set the previous declaration. If PrevDecl is NULL, set this as the    /// first and only declaration. -  void setPreviousDeclaration(decl_type *PrevDecl) { -    decl_type *First; - -    if (PrevDecl) { -      // Point to previous. Make sure that this is actually the most recent -      // redeclaration, or we can build invalid chains. If the most recent -      // redeclaration is invalid, it won't be PrevDecl, but we want it anyway. -      RedeclLink = PreviousDeclLink(llvm::cast<decl_type>( -                                      PrevDecl->getMostRecentDeclaration())); -      First = PrevDecl->getFirstDeclaration(); -      assert(First->RedeclLink.NextIsLatest() && "Expected first"); -    } else { -      // Make this first. -      First = static_cast<decl_type*>(this); -    } - -    // First one will point to this one as latest. -    First->RedeclLink = LatestDeclLink(static_cast<decl_type*>(this)); -  } +  void setPreviousDeclaration(decl_type *PrevDecl);    /// \brief Iterates through all the redeclarations of the same decl.    class redecl_iterator { diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 71bda4156f9..90a561e5c6e 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -85,6 +85,15 @@ struct LVFlags {                ConsiderVisibilityAttributes(true) {    } +  /// \brief Returns a set of flags that is only useful for computing the  +  /// linkage, not the visibility, of a declaration. +  static LVFlags CreateOnlyDeclLinkage() { +    LVFlags F; +    F.ConsiderGlobalVisibility = false; +    F.ConsiderVisibilityAttributes = false; +    return F; +  } +      /// Returns a set of flags, otherwise based on these, which ignores    /// off all sources of visibility except template arguments.    LVFlags onlyTemplateVisibility() const { @@ -119,10 +128,14 @@ getLVForTemplateParameterList(const TemplateParameterList *Params) {    return LV;  } +/// getLVForDecl - Get the linkage and visibility for the given declaration. +static LinkageInfo getLVForDecl(const NamedDecl *D, LVFlags F); +  /// \brief Get the most restrictive linkage for the types and  /// declarations in the given template argument list.  static LVPair getLVForTemplateArgumentList(const TemplateArgument *Args, -                                           unsigned NumArgs) { +                                           unsigned NumArgs, +                                           LVFlags &F) {    LVPair LV(ExternalLinkage, DefaultVisibility);    for (unsigned I = 0; I != NumArgs; ++I) { @@ -140,21 +153,24 @@ static LVPair getLVForTemplateArgumentList(const TemplateArgument *Args,        // The decl can validly be null as the representation of nullptr        // arguments, valid only in C++0x.        if (Decl *D = Args[I].getAsDecl()) { -        if (NamedDecl *ND = dyn_cast<NamedDecl>(D)) -          LV = merge(LV, ND->getLinkageAndVisibility()); -        if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) -          LV = merge(LV, VD->getLinkageAndVisibility()); +        if (NamedDecl *ND = dyn_cast<NamedDecl>(D)) { +          LinkageInfo LI = getLVForDecl(ND, F); +          LV = merge(LV, LVPair(LI.linkage(), LI.visibility())); +        }        }        break;      case TemplateArgument::Template: -      if (TemplateDecl *Template = Args[I].getAsTemplate().getAsTemplateDecl()) -        LV = merge(LV, Template->getLinkageAndVisibility()); +      if (TemplateDecl *Template = Args[I].getAsTemplate().getAsTemplateDecl()){ +        LinkageInfo LI = getLVForDecl(Template, F); +        LV = merge(LV, LVPair(LI.linkage(), LI.visibility())); +      }        break;      case TemplateArgument::Pack:        LV = merge(LV, getLVForTemplateArgumentList(Args[I].pack_begin(), -                                                  Args[I].pack_size())); +                                                  Args[I].pack_size(), +                                                  F));        break;      }    } @@ -163,14 +179,11 @@ static LVPair getLVForTemplateArgumentList(const TemplateArgument *Args,  }  static LVPair -getLVForTemplateArgumentList(const TemplateArgumentList &TArgs) { -  return getLVForTemplateArgumentList(TArgs.data(), TArgs.size()); +getLVForTemplateArgumentList(const TemplateArgumentList &TArgs, +                             LVFlags &F) { +  return getLVForTemplateArgumentList(TArgs.data(), TArgs.size(), F);  } -/// getLVForDecl - Get the cached linkage and visibility for the given -/// declaration. -static LinkageInfo getLVForDecl(const NamedDecl *D, LVFlags F); -  static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) {    assert(D->getDeclContext()->getRedeclContext()->isFileContext() &&           "Not a name having namespace scope"); @@ -296,7 +309,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) {        //   is visible, or if the prior declaration specifies no        //   linkage, then the identifier has external linkage.        if (const VarDecl *PrevVar = Var->getPreviousDeclaration()) { -        LinkageInfo PrevLV = PrevVar->getLinkageAndVisibility(); +        LinkageInfo PrevLV = getLVForDecl(PrevVar, F);          if (PrevLV.linkage()) LV.setLinkage(PrevLV.linkage());          LV.mergeVisibility(PrevLV);        } @@ -331,7 +344,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) {        //   is visible, or if the prior declaration specifies no        //   linkage, then the identifier has external linkage.        if (const FunctionDecl *PrevFunc = Function->getPreviousDeclaration()) { -        LinkageInfo PrevLV = PrevFunc->getLinkageAndVisibility(); +        LinkageInfo PrevLV = getLVForDecl(PrevFunc, F);          if (PrevLV.linkage()) LV.setLinkage(PrevLV.linkage());          LV.mergeVisibility(PrevLV);        } @@ -342,7 +355,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) {        LV.merge(getLVForDecl(SpecInfo->getTemplate(),                              F.onlyTemplateVisibility()));        const TemplateArgumentList &TemplateArgs = *SpecInfo->TemplateArguments; -      LV.merge(getLVForTemplateArgumentList(TemplateArgs)); +      LV.merge(getLVForTemplateArgumentList(TemplateArgs, F));      }    //     - a named class (Clause 9), or an unnamed class defined in a @@ -366,7 +379,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) {        // The arguments at which the template was instantiated.        const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs(); -      LV.merge(getLVForTemplateArgumentList(TemplateArgs)); +      LV.merge(getLVForTemplateArgumentList(TemplateArgs, F));      }      // Consider -fvisibility unless the type has C linkage. @@ -377,8 +390,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) {    //     - an enumerator belonging to an enumeration with external linkage;    } else if (isa<EnumConstantDecl>(D)) { -    LinkageInfo EnumLV = -      cast<NamedDecl>(D->getDeclContext())->getLinkageAndVisibility(); +    LinkageInfo EnumLV = getLVForDecl(cast<NamedDecl>(D->getDeclContext()), F);      if (!isExternalLinkage(EnumLV.linkage()))        return LinkageInfo::none();      LV.merge(EnumLV); @@ -464,7 +476,7 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, LVFlags F) {      // the template parameters and arguments.      if (FunctionTemplateSpecializationInfo *Spec             = MD->getTemplateSpecializationInfo()) { -      LV.merge(getLVForTemplateArgumentList(*Spec->TemplateArguments)); +      LV.merge(getLVForTemplateArgumentList(*Spec->TemplateArguments, F));        LV.merge(getLVForTemplateParameterList(                                Spec->getTemplate()->getTemplateParameters())); @@ -499,7 +511,7 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, LVFlags F) {          = dyn_cast<ClassTemplateSpecializationDecl>(RD)) {        // Merge template argument/parameter information for member        // class template specializations. -      LV.merge(getLVForTemplateArgumentList(Spec->getTemplateArgs())); +      LV.merge(getLVForTemplateArgumentList(Spec->getTemplateArgs(), F));        LV.merge(getLVForTemplateParameterList(                      Spec->getSpecializedTemplate()->getTemplateParameters()));      } @@ -525,8 +537,27 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, LVFlags F) {    return LV;  } +Linkage NamedDecl::getLinkage() const { +  if (HasCachedLinkage) { +#ifndef NDEBUG +    assert(CachedLinkage == getLVForDecl(this,  +                                  LVFlags::CreateOnlyDeclLinkage()).linkage()); +#endif +    return Linkage(CachedLinkage); +  } + +  CachedLinkage = getLVForDecl(this,  +                               LVFlags::CreateOnlyDeclLinkage()).linkage(); +  HasCachedLinkage = 1; +  return Linkage(CachedLinkage); +} +  LinkageInfo NamedDecl::getLinkageAndVisibility() const { -  return getLVForDecl(this, LVFlags()); +  LinkageInfo LI = getLVForDecl(this, LVFlags()); +  assert(!HasCachedLinkage || (CachedLinkage == LI.linkage())); +  HasCachedLinkage = 1; +  CachedLinkage = LI.linkage(); +  return LI;  }  static LinkageInfo getLVForDecl(const NamedDecl *D, LVFlags Flags) { @@ -581,11 +612,13 @@ static LinkageInfo getLVForDecl(const NamedDecl *D, LVFlags Flags) {          return LinkageInfo::uniqueExternal();        LinkageInfo LV; -      if (const VisibilityAttr *VA = GetExplicitVisibility(Function)) -        LV.setVisibility(GetVisibilityFromAttr(VA)); - +      if (Flags.ConsiderVisibilityAttributes) { +        if (const VisibilityAttr *VA = GetExplicitVisibility(Function)) +          LV.setVisibility(GetVisibilityFromAttr(VA)); +      } +              if (const FunctionDecl *Prev = Function->getPreviousDeclaration()) { -        LinkageInfo PrevLV = Prev->getLinkageAndVisibility(); +        LinkageInfo PrevLV = getLVForDecl(Prev, Flags);          if (PrevLV.linkage()) LV.setLinkage(PrevLV.linkage());          LV.mergeVisibility(PrevLV);        } @@ -602,11 +635,13 @@ static LinkageInfo getLVForDecl(const NamedDecl *D, LVFlags Flags) {          LinkageInfo LV;          if (Var->getStorageClass() == SC_PrivateExtern)            LV.setVisibility(HiddenVisibility); -        else if (const VisibilityAttr *VA = GetExplicitVisibility(Var)) -          LV.setVisibility(GetVisibilityFromAttr(VA)); - +        else if (Flags.ConsiderVisibilityAttributes) { +          if (const VisibilityAttr *VA = GetExplicitVisibility(Var)) +            LV.setVisibility(GetVisibilityFromAttr(VA)); +        } +                  if (const VarDecl *Prev = Var->getPreviousDeclaration()) { -          LinkageInfo PrevLV = Prev->getLinkageAndVisibility(); +          LinkageInfo PrevLV = getLVForDecl(Prev, Flags);            if (PrevLV.linkage()) LV.setLinkage(PrevLV.linkage());            LV.mergeVisibility(PrevLV);          } @@ -878,6 +913,14 @@ VarDecl *VarDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,    return new (C) VarDecl(Var, DC, L, Id, T, TInfo, S, SCAsWritten);  } +void VarDecl::setStorageClass(StorageClass SC) { +  assert(isLegalForVariable(SC)); +  if (getStorageClass() != SC) +    ClearLinkageCache(); +   +  SClass = SC; +} +  SourceLocation VarDecl::getInnerLocStart() const {    SourceLocation Start = getTypeSpecStartLoc();    if (Start.isInvalid()) @@ -1277,6 +1320,14 @@ FunctionDecl *FunctionDecl::getCanonicalDecl() {    return getFirstDeclaration();  } +void FunctionDecl::setStorageClass(StorageClass SC) { +  assert(isLegalForFunction(SC)); +  if (getStorageClass() != SC) +    ClearLinkageCache(); +   +  SClass = SC; +} +  /// \brief Returns a value indicating whether this function  /// corresponds to a builtin function.  /// @@ -1787,6 +1838,7 @@ void TagDecl::setTypedefForAnonDecl(TypedefDecl *TDD) {    TypedefDeclOrQualifier = TDD;     if (TypeForDecl)      TypeForDecl->ClearLinkageCache(); +  ClearLinkageCache();  }  void TagDecl::startDefinition() { diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index adbf3bff3c3..7053f404e43 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -384,7 +384,7 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) {    // FunctionDecl's body is handled last at ASTDeclReader::Visit,    // after everything else is read. -  FD->setStorageClass((StorageClass)Record[Idx++]); +  FD->SClass = (StorageClass)Record[Idx++];    FD->setStorageClassAsWritten((StorageClass)Record[Idx++]);    FD->setInlineSpecified(Record[Idx++]);    FD->setVirtualAsWritten(Record[Idx++]); @@ -651,7 +651,7 @@ void ASTDeclReader::VisitIndirectFieldDecl(IndirectFieldDecl *FD) {  void ASTDeclReader::VisitVarDecl(VarDecl *VD) {    VisitDeclaratorDecl(VD);    VisitRedeclarable(VD); -  VD->setStorageClass((StorageClass)Record[Idx++]); +  VD->SClass = (StorageClass)Record[Idx++];    VD->setStorageClassAsWritten((StorageClass)Record[Idx++]);    VD->setThreadSpecified(Record[Idx++]);    VD->setCXXDirectInitializer(Record[Idx++]);  | 

