summaryrefslogtreecommitdiffstats
path: root/llvm/lib/IR/Globals.cpp
diff options
context:
space:
mode:
authorJames Y Knight <jyknight@google.com>2016-01-15 16:33:06 +0000
committerJames Y Knight <jyknight@google.com>2016-01-15 16:33:06 +0000
commitac03dca41245fe4cf308e7405d6e947b45341547 (patch)
tree618e6891cf0bf5d04e375a798b99cd46c101dcbd /llvm/lib/IR/Globals.cpp
parent0771b18257a6bd33ec9f9890d8cb0eed01e729d3 (diff)
downloadbcm5719-llvm-ac03dca41245fe4cf308e7405d6e947b45341547.tar.gz
bcm5719-llvm-ac03dca41245fe4cf308e7405d6e947b45341547.zip
Stop increasing alignment of externally-visible globals on ELF
platforms. With ELF, the alignment of a global variable in a shared library will get copied into an executables linked against it, if the executable even accesss the variable. So, it's not possible to implicitly increase alignment based on access patterns, or you'll break existing binaries. This happened to affect libc++'s std::cout symbol, for example. See thread: http://thread.gmane.org/gmane.comp.compilers.clang.devel/45311 (This is a re-commit of r257719, without the bug reported in PR26144. I've tweaked the code to not assert-fail in enforceKnownAlignment when computeKnownBits doesn't recurse far enough to find the underlying Alloca/GlobalObject value.) Differential Revision: http://reviews.llvm.org/D16145 llvm-svn: 257902
Diffstat (limited to 'llvm/lib/IR/Globals.cpp')
-rw-r--r--llvm/lib/IR/Globals.cpp44
1 files changed, 43 insertions, 1 deletions
diff --git a/llvm/lib/IR/Globals.cpp b/llvm/lib/IR/Globals.cpp
index 6159f93faf8..a61b62bd968 100644
--- a/llvm/lib/IR/Globals.cpp
+++ b/llvm/lib/IR/Globals.cpp
@@ -12,11 +12,12 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/IR/GlobalValue.h"
#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/Triple.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/GlobalAlias.h"
+#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Operator.h"
@@ -134,6 +135,47 @@ bool GlobalValue::isDeclaration() const {
return false;
}
+bool GlobalValue::canIncreaseAlignment() const {
+ // Firstly, can only increase the alignment of a global if it
+ // is a strong definition.
+ if (!isStrongDefinitionForLinker())
+ return false;
+
+ // It also has to either not have a section defined, or, not have
+ // alignment specified. (If it is assigned a section, the global
+ // could be densely packed with other objects in the section, and
+ // increasing the alignment could cause padding issues.)
+ if (hasSection() && getAlignment() > 0)
+ return false;
+
+ // On ELF platforms, we're further restricted in that we can't
+ // increase the alignment of any variable which might be emitted
+ // into a shared library, and which is exported. If the main
+ // executable accesses a variable found in a shared-lib, the main
+ // exe actually allocates memory for and exports the symbol ITSELF,
+ // overriding the symbol found in the library. That is, at link
+ // time, the observed alignment of the variable is copied into the
+ // executable binary. (A COPY relocation is also generated, to copy
+ // the initial data from the shadowed variable in the shared-lib
+ // into the location in the main binary, before running code.)
+ //
+ // And thus, even though you might think you are defining the
+ // global, and allocating the memory for the global in your object
+ // file, and thus should be able to set the alignment arbitrarily,
+ // that's not actually true. Doing so can cause an ABI breakage; an
+ // executable might have already been built with the previous
+ // alignment of the variable, and then assuming an increased
+ // alignment will be incorrect.
+
+ // Conservatively assume ELF if there's no parent pointer.
+ bool isELF =
+ (!Parent || Triple(Parent->getTargetTriple()).isOSBinFormatELF());
+ if (isELF && hasDefaultVisibility() && !hasLocalLinkage())
+ return false;
+
+ return true;
+}
+
//===----------------------------------------------------------------------===//
// GlobalVariable Implementation
//===----------------------------------------------------------------------===//
OpenPOWER on IntegriCloud