GlobalOpt: EvaluateFunction() must not evaluate stores to weak_odr globals.

Fixes PR8389.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@116812 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Mikhail Glushenkov
2010-10-19 16:47:23 +00:00
parent d3b00539f1
commit 99fca5de96
3 changed files with 51 additions and 7 deletions

View File

@@ -80,7 +80,21 @@ public:
inline bool hasInitializer() const { return !isDeclaration(); }
/// hasDefinitiveInitializer - Whether the global variable has an initializer,
/// and this is the initializer that will be used in the final executable.
/// and any other instances of the global (this can happen due to weak
/// linkage) are guaranteed to have the same initializer.
///
/// Note that if you want to transform a global, you must use
/// hasUniqueInitializer() instead, because of the *_odr linkage type.
///
/// Example:
///
/// @a = global SomeType* null - Initializer is both definitive and unique.
///
/// @b = global weak SomeType* null - Initializer is neither definitive nor
/// unique.
///
/// @c = global weak_odr SomeType* null - Initializer is definitive, but not
/// unique.
inline bool hasDefinitiveInitializer() const {
return hasInitializer() &&
// The initializer of a global variable with weak linkage may change at
@@ -88,6 +102,19 @@ public:
!mayBeOverridden();
}
/// hasUniqueInitializer - Whether the global variable has an initializer, and
/// any changes made to the initializer will turn up in the final executable.
inline bool hasUniqueInitializer() const {
return hasInitializer() &&
// It's not safe to modify initializers of global variables with weak
// linkage, because the linker might choose to discard the initializer and
// use the initializer from another instance of the global variable
// instead. It is wrong to modify the initializer of a global variable
// with *_odr linkage because then different instances of the global may
// have different initializers, breaking the One Definition Rule.
!isWeakForLinker();
}
/// getInitializer - Return the initializer for this global variable. It is
/// illegal to call this method if the global is external, because we cannot
/// tell what the value is initialized to!