EmitCtorList(GlobalCtors, "llvm.global_ctors");
EmitCtorList(GlobalDtors, "llvm.global_dtors");
EmitGlobalAnnotations();
+ EmitStaticExternCAliases();
EmitLLVMUsed();
if (CodeGenOpts.ModulesAutolink) {
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();
cast<llvm::GlobalValue>(Entry)->eraseFromParent();
}
+ MaybeHandleStaticInExternC(D, GV);
+
if (D->hasAttr<AnnotateAttr>())
AddGlobalAnnotations(D, GV);
// FIXME: this is redundant with part of SetFunctionDefinitionAttributes
setGlobalVisibility(Fn, D);
+ MaybeHandleStaticInExternC(D, Fn);
+
CodeGenFunction(*this).GenerateCode(D, Fn, FI);
SetFunctionDefinitionAttributes(D, Fn);
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.
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;
// 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.
/// \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
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
+}