mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-18 13:34:04 +00:00
The internalize pass can be dangerous for LTO.
Consider the following program: $ cat main.c void foo(void) { } int main(int argc, char *argv[]) { foo(); return 0; } $ cat bundle.c extern void foo(void); void bar(void) { foo(); } $ clang -o main main.c $ clang -o bundle.so bundle.c -bundle -bundle_loader ./main $ nm -m bundle.so 0000000000000f40 (__TEXT,__text) external _bar (undefined) external _foo (from executable) (undefined) external dyld_stub_binder (from libSystem) $ clang -o main main.c -O4 $ clang -o bundle.so bundle.c -bundle -bundle_loader ./main Undefined symbols for architecture x86_64: "_foo", referenced from: _bar in bundle-elQN6d.o ld: symbol(s) not found for architecture x86_64 clang: error: linker command failed with exit code 1 (use -v to see invocation) The linker was told that the 'foo' in 'main' was 'internal' and had no uses, so it was dead stripped. Another situation is something like: define void @foo() { ret void } define void @bar() { call asm volatile "call _foo" ... ret void } The only use of 'foo' is inside of an inline ASM call. Since we don't look inside those for uses of functions, we don't specify this as a "use." Get around this by not invoking the 'internalize' pass by default. This is an admitted hack for LTO correctness. <rdar://problem/11185386> git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@154124 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
4e53fe8dc6
commit
97d9903236
@ -46,10 +46,13 @@
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
using namespace llvm;
|
||||
|
||||
static cl::opt<bool> DisableInline("disable-inlining",
|
||||
static cl::opt<bool> EnableInternalizing("enable-internalizing", cl::init(false),
|
||||
cl::desc("Internalize functions during LTO"));
|
||||
|
||||
static cl::opt<bool> DisableInline("disable-inlining", cl::init(false),
|
||||
cl::desc("Do not run the inliner pass"));
|
||||
|
||||
static cl::opt<bool> DisableGVNLoadPRE("disable-gvn-loadpre",
|
||||
static cl::opt<bool> DisableGVNLoadPRE("disable-gvn-loadpre", cl::init(false),
|
||||
cl::desc("Do not run the GVN load PRE pass"));
|
||||
|
||||
const char* LTOCodeGenerator::getVersionString() {
|
||||
@ -275,6 +278,14 @@ static void findUsedValues(GlobalVariable *LLVMUsed,
|
||||
}
|
||||
|
||||
void LTOCodeGenerator::applyScopeRestrictions() {
|
||||
// Internalize only if specifically asked for. Otherwise, global symbols which
|
||||
// exist in the final image, but which are used outside of that image
|
||||
// (e.g. bundling) may be removed. This also happens when a function is used
|
||||
// only in inline asm. LLVM doesn't recognize that as a "use", so it could be
|
||||
// stripped.
|
||||
if (!EnableInternalizing)
|
||||
return;
|
||||
|
||||
if (_scopeRestrictionsDone) return;
|
||||
Module *mergedModule = _linker.getModule();
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user