Awesome! What about adding this to the release notes? Patch attached.
On 6 April 2013 01:00, Richard Smith <[email protected]> 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 > [email protected] > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
t.patch
Description: Binary data
_______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
