diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -2723,8 +2723,12 @@ StringRef getFeatureStr(unsigned Index) const { return *(featuresStrs_begin() + Index); } - // 'default' is always moved to the end, so it isn't considered - // when mangling the index. + // Given an index into the 'featuresStrs' sequence, compute a unique + // ID to be used with function name mangling for the associated variant. + // This mapping is necessary due to a requirement that the mangling ID + // used for the "default" variant be the largest mangling ID in the + // variant set. Duplicate variants present in 'featuresStrs' are also + // assigned their own unique ID (the mapping is bijective). unsigned getMangledIndex(unsigned Index) const { if (getFeatureStr(Index) == "default") return std::count_if(featuresStrs_begin(), featuresStrs_end(), @@ -2734,9 +2738,10 @@ [](StringRef S) { return S != "default"; }); } - // True if this is the first of this version to appear in the config string. - // This is used to make sure we don't try to emit this function multiple - // times. + // Given an index into the 'featuresStrs' sequence, determine if the + // index corresponds to the first instance of the named variant. This + // is used to skip over duplicate variant instances when iterating over + // 'featuresStrs'. bool isFirstOfVersion(unsigned Index) const { StringRef FeatureStr(getFeatureStr(Index)); return 0 == std::count_if( diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/lib/CodeGen/CodeGenModule.h @@ -348,8 +348,9 @@ /// is defined once we get to the end of the of the translation unit. std::vector Aliases; - /// List of multiversion functions that have to be emitted. Used to make sure - /// we properly emit the iFunc. + /// List of multiversion functions to be emitted. This list is processed in + /// conjunction with other deferred symbols and is used to ensure that + /// multiversion function resolvers and ifuncs are defined and emitted. std::vector MultiVersionFuncs; typedef llvm::StringMap > ReplacementsTy; @@ -1466,9 +1467,20 @@ llvm::AttributeList ExtraAttrs = llvm::AttributeList(), ForDefinition_t IsForDefinition = NotForDefinition); + // References to multiversion functions are resolved through an implicitly + // defined resolver function. This function is responsible for creating + // the resolver symbol for the provided declaration. The value returned + // will be for an ifunc (llvm::GlobalIFunc) if the current target supports + // that feature and for a regular function (llvm::GlobalValue) otherwise. llvm::Constant *GetOrCreateMultiVersionResolver(GlobalDecl GD, llvm::Type *DeclTy, const FunctionDecl *FD); + + // In scenarios where a function is not known to be a multiversion function + // until a later declaration, it is sometimes necessary to change the + // previously created mangled name to align with requirements of whatever + // multiversion function kind the function is now known to be. This function + // is responsible for performing such mangled name updates. void UpdateMultiVersionNames(GlobalDecl GD, const FunctionDecl *FD, StringRef &CurName); @@ -1561,6 +1573,7 @@ // registered by the atexit subroutine using unatexit. void unregisterGlobalDtorsWithUnAtExit(); + /// Emit deferred multiversion function resolvers and associated variants. void emitMultiVersionFunctions(); /// Emit any vtables which we deferred and still have a use for. diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -3768,7 +3768,7 @@ } if (FD->isMultiVersion()) { - UpdateMultiVersionNames(GD, FD, MangledName); + UpdateMultiVersionNames(GD, FD, MangledName); if (!IsForDefinition) return GetOrCreateMultiVersionResolver(GD, Ty, FD); }