summaryrefslogtreecommitdiff
path: root/lib/CodeGen/CGCXX.cpp
diff options
context:
space:
mode:
authorEvgeniy Stepanov <eugeni.stepanov@gmail.com>2015-09-11 20:29:07 +0000
committerEvgeniy Stepanov <eugeni.stepanov@gmail.com>2015-09-11 20:29:07 +0000
commitbfffdd3dff15236e9cbed4f97015ea394031306b (patch)
treec3ab5bc90db492bdf27169928d48c003a9c2680b /lib/CodeGen/CGCXX.cpp
parentf78dda92f5038f2bcb4aad369c9f07669a107613 (diff)
downloadclang-bfffdd3dff15236e9cbed4f97015ea394031306b.tar.gz
Always_inline codegen rewrite.
Current implementation may end up emitting an undefined reference for an "inline __attribute__((always_inline))" function by generating an "available_externally alwaysinline" IR function for it and then failing to inline all the calls. This happens when a call to such function is in dead code. As the inliner is an SCC pass, it does not process dead code. Libc++ relies on the compiler never emitting such undefined reference. With this patch, we emit a pair of 1. internal alwaysinline definition (called F.alwaysinline) 2a. A stub F() { musttail call F.alwaysinline } -- or, depending on the linkage -- 2b. A declaration of F. The frontend ensures that F.inlinefunction is only used for direct calls, and the stub is used for everything else (taking the address of the function, really). Declaration (2b) is emitted in the case when "inline" is meant for inlining only (like __gnu_inline__ and some other cases). This approach, among other nice properties, ensures that alwaysinline functions are always internal, making it impossible for a direct call to such function to produce an undefined symbol reference. This patch is based on ideas by Chandler Carruth and Richard Smith. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@247465 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGCXX.cpp')
-rw-r--r--lib/CodeGen/CGCXX.cpp12
1 files changed, 4 insertions, 8 deletions
diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp
index ad30364986..07eb91582a 100644
--- a/lib/CodeGen/CGCXX.cpp
+++ b/lib/CodeGen/CGCXX.cpp
@@ -109,6 +109,9 @@ bool CodeGenModule::TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D) {
D->getType()->getAs<FunctionType>()->getCallConv())
return true;
+ if (BaseD->hasAttr<AlwaysInlineAttr>())
+ return true;
+
return TryEmitDefinitionAsAlias(GlobalDecl(D, Dtor_Base),
GlobalDecl(BaseD, Dtor_Base),
false);
@@ -161,14 +164,7 @@ bool CodeGenModule::TryEmitDefinitionAsAlias(GlobalDecl AliasDecl,
// Instead of creating as alias to a linkonce_odr, replace all of the uses
// of the aliasee.
- if (llvm::GlobalValue::isDiscardableIfUnused(Linkage) &&
- (TargetLinkage != llvm::GlobalValue::AvailableExternallyLinkage ||
- !TargetDecl.getDecl()->hasAttr<AlwaysInlineAttr>())) {
- // FIXME: An extern template instantiation will create functions with
- // linkage "AvailableExternally". In libc++, some classes also define
- // members with attribute "AlwaysInline" and expect no reference to
- // be generated. It is desirable to reenable this optimisation after
- // corresponding LLVM changes.
+ if (llvm::GlobalValue::isDiscardableIfUnused(Linkage)) {
Replacements[MangledName] = Aliasee;
return false;
}