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

Rafael EspĂ­ndola rafael.espindola at gmail.com
Sat Apr 6 05:29:58 PDT 2013


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 --------------
A non-text attachment was scrubbed...
Name: t.patch
Type: application/octet-stream
Size: 598 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130406/ce5680af/attachment.obj>


More information about the cfe-commits mailing list