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