r178950 - When an internal-linkage function or variable is declared within an extern "C"

Richard Smith richard at metafoo.co.uk
Sat Apr 6 11:40:40 PDT 2013


We shouldn't claim to implement the standard rules for language linkage
until we treat language linkage as part of the function type. That said,
some mention of this in the release notes would probably be a good idea, in
case there is more fallout.
On Apr 6, 2013 5:30 AM, "Rafael EspĂ­ndola" <rafael.espindola at gmail.com>
wrote:

> Awesome! What about adding this to the release notes? Patch attached.
>
> On 6 April 2013 01:00, Richard Smith <richard-llvm at metafoo.co.uk> wrote:
> > Author: rsmith
> > Date: Sat Apr  6 00:00:46 2013
> > New Revision: 178950
> >
> > URL: http://llvm.org/viewvc/llvm-project?rev=178950&view=rev
> > Log:
> > When an internal-linkage function or variable is declared within an
> extern "C"
> > linkage specification, and is marked as __attribute__((used)), try to
> also give
> > it the unmangled name (by emitting an internal linkage alias) if nothing
> else
> > within the translation unit would use that name. This allows inline asm
> in that
> > translation unit to use the entity via its unmangled name, which people
> > apparently rely on.
> >
> > Modified:
> >     cfe/trunk/lib/CodeGen/CodeGenModule.cpp
> >     cfe/trunk/lib/CodeGen/CodeGenModule.h
> >     cfe/trunk/test/CodeGenCXX/extern-c.cpp
> >
> > Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=178950&r1=178949&r2=178950&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
> > +++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Sat Apr  6 00:00:46 2013
> > @@ -186,6 +186,7 @@ void CodeGenModule::Release() {
> >    EmitCtorList(GlobalCtors, "llvm.global_ctors");
> >    EmitCtorList(GlobalDtors, "llvm.global_dtors");
> >    EmitGlobalAnnotations();
> > +  EmitStaticExternCAliases();
> >    EmitLLVMUsed();
> >
> >    if (CodeGenOpts.ModulesAutolink) {
> > @@ -1707,6 +1708,39 @@ unsigned CodeGenModule::GetGlobalVarAddr
> >    return AddrSpace;
> >  }
> >
> > +template<typename SomeDecl>
> > +void CodeGenModule::MaybeHandleStaticInExternC(const SomeDecl *D,
> > +                                               llvm::GlobalValue *GV) {
> > +  if (!getLangOpts().CPlusPlus)
> > +    return;
> > +
> > +  // Must have 'used' attribute, or else inline assembly can't rely on
> > +  // the name existing.
> > +  if (!D->template hasAttr<UsedAttr>())
> > +    return;
> > +
> > +  // Must have internal linkage and an ordinary name.
> > +  if (!D->getIdentifier() || D->getLinkage() != InternalLinkage)
> > +    return;
> > +
> > +  // Must be in an extern "C" context. Entities declared directly within
> > +  // a record are not extern "C" even if the record is in such a
> context.
> > +  const DeclContext *DC = D->getFirstDeclaration()->getDeclContext();
> > +  if (DC->isRecord() || !DC->isExternCContext())
> > +    return;
> > +
> > +  // OK, this is an internal linkage entity inside an extern "C" linkage
> > +  // specification. Make a note of that so we can give it the "expected"
> > +  // mangled name if nothing else is using that name.
> > +  StaticExternCMap::iterator I =
> > +      StaticExternCValues.insert(std::make_pair(D->getIdentifier(),
> GV)).first;
> > +
> > +  // If we have multiple internal linkage entities with the same name
> > +  // in extern "C" regions, none of them gets that name.
> > +  if (I->second != GV)
> > +    I->second = 0;
> > +}
> > +
> >  void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) {
> >    llvm::Constant *Init = 0;
> >    QualType ASTTy = D->getType();
> > @@ -1805,6 +1839,8 @@ void CodeGenModule::EmitGlobalVarDefinit
> >      cast<llvm::GlobalValue>(Entry)->eraseFromParent();
> >    }
> >
> > +  MaybeHandleStaticInExternC(D, GV);
> > +
> >    if (D->hasAttr<AnnotateAttr>())
> >      AddGlobalAnnotations(D, GV);
> >
> > @@ -2083,6 +2119,8 @@ void CodeGenModule::EmitGlobalFunctionDe
> >    // FIXME: this is redundant with part of
> SetFunctionDefinitionAttributes
> >    setGlobalVisibility(Fn, D);
> >
> > +  MaybeHandleStaticInExternC(D, Fn);
> > +
> >    CodeGenFunction(*this).GenerateCode(D, Fn, FI);
> >
> >    SetFunctionDefinitionAttributes(D, Fn);
> > @@ -2903,6 +2941,21 @@ static void EmitGlobalDeclMetadata(CodeG
> >    GlobalMetadata->addOperand(llvm::MDNode::get(CGM.getLLVMContext(),
> Ops));
> >  }
> >
> > +/// For each function which is declared within an extern "C" region and
> marked
> > +/// as 'used', but has internal linkage, create an alias from the
> unmangled
> > +/// name to the mangled name if possible. People expect to be able to
> refer
> > +/// to such functions with an unmangled name from inline assembly
> within the
> > +/// same translation unit.
> > +void CodeGenModule::EmitStaticExternCAliases() {
> > +  for (StaticExternCMap::iterator I = StaticExternCValues.begin(),
> > +                                  E = StaticExternCValues.end();
> > +       I != E; ++I)
> > +    if (I->second && !getModule().getNamedValue(I->first->getName()))
> > +      AddUsedGlobal(
> > +        new llvm::GlobalAlias(I->second->getType(),
> I->second->getLinkage(),
> > +                              I->first->getName(), I->second,
> &getModule()));
> > +}
> > +
> >  /// Emits metadata nodes associating all the global values in the
> >  /// current module with the Decls they came from.  This is useful for
> >  /// projects using IR gen as a subroutine.
> >
> > Modified: cfe/trunk/lib/CodeGen/CodeGenModule.h
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.h?rev=178950&r1=178949&r2=178950&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/CodeGen/CodeGenModule.h (original)
> > +++ cfe/trunk/lib/CodeGen/CodeGenModule.h Sat Apr  6 00:00:46 2013
> > @@ -305,6 +305,12 @@ class CodeGenModule : public CodeGenType
> >    llvm::DenseMap<QualType, llvm::Constant *> AtomicSetterHelperFnMap;
> >    llvm::DenseMap<QualType, llvm::Constant *> AtomicGetterHelperFnMap;
> >
> > +  /// Map used to track internal linkage functions declared within
> > +  /// extern "C" regions.
> > +  typedef llvm::DenseMap<IdentifierInfo *,
> > +                         llvm::GlobalValue *> StaticExternCMap;
> > +  StaticExternCMap StaticExternCValues;
> > +
> >    /// CXXGlobalInits - Global variables with initializers that need to
> run
> >    /// before main.
> >    std::vector<llvm::Constant*> CXXGlobalInits;
> > @@ -736,6 +742,12 @@ public:
> >    // variable has been instantiated.
> >    void HandleCXXStaticMemberVarInstantiation(VarDecl *VD);
> >
> > +  /// \brief If the declaration has internal linkage but is inside an
> > +  /// extern "C" linkage specification, prepare to emit an alias for it
> > +  /// to the expected name.
> > +  template<typename SomeDecl>
> > +  void MaybeHandleStaticInExternC(const SomeDecl *D, llvm::GlobalValue
> *GV);
> > +
> >    /// AddUsedGlobal - Add a global which should be forced to be
> >    /// present in the object file; these are emitted to the llvm.used
> >    /// metadata global.
> > @@ -1048,6 +1060,10 @@ private:
> >    /// \brief Emit the link options introduced by imported modules.
> >    void EmitModuleLinkOptions();
> >
> > +  /// \brief Emit aliases for internal-linkage declarations inside "C"
> language
> > +  /// linkage specifications, giving them the "expected" name where
> possible.
> > +  void EmitStaticExternCAliases();
> > +
> >    void EmitDeclMetadata();
> >
> >    /// EmitCoverageFile - Emit the llvm.gcov metadata used to tell LLVM
> where
> >
> > Modified: cfe/trunk/test/CodeGenCXX/extern-c.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/extern-c.cpp?rev=178950&r1=178949&r2=178950&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/test/CodeGenCXX/extern-c.cpp (original)
> > +++ cfe/trunk/test/CodeGenCXX/extern-c.cpp Sat Apr  6 00:00:46 2013
> > @@ -36,3 +36,30 @@ namespace test2 {
> >    extern "C" X test2_b;
> >    X test2_b;
> >  }
> > +
> > +extern "C" {
> > +  static int unused_var;
> > +  static int unused_fn() { return 0; }
> > +
> > +  __attribute__((used)) static int internal_var;
> > +  __attribute__((used)) static int internal_fn() { return 0; }
> > +
> > +  __attribute__((used)) static int duplicate_internal_var;
> > +  __attribute__((used)) static int duplicate_internal_fn() { return 0; }
> > +
> > +  namespace N {
> > +    __attribute__((used)) static int duplicate_internal_var;
> > +    __attribute__((used)) static int duplicate_internal_fn() { return
> 0; }
> > +  }
> > +
> > +  // CHECK: @llvm.used = appending global {{.*}} @internal_var {{.*}}
> @internal_fn
> > +
> > +  // CHECK-NOT: @unused
> > +  // CHECK-NOT: @duplicate_internal
> > +  // CHECK: @internal_var = alias internal i32* @_Z12internal_var
> > +  // CHECK-NOT: @unused
> > +  // CHECK-NOT: @duplicate_internal
> > +  // CHECK: @internal_fn = alias internal i32 ()* @_Z11internal_fnv
> > +  // CHECK-NOT: @unused
> > +  // CHECK-NOT: @duplicate_internal
> > +}
> >
> >
> > _______________________________________________
> > cfe-commits mailing list
> > cfe-commits at cs.uiuc.edu
> > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130406/283005b5/attachment.html>


More information about the cfe-commits mailing list