diff --git a/lib/Target/ARM/ARMISelLowering.cpp b/lib/Target/ARM/ARMISelLowering.cpp index 1ade8f89263..5d8ee7e8542 100644 --- a/lib/Target/ARM/ARMISelLowering.cpp +++ b/lib/Target/ARM/ARMISelLowering.cpp @@ -1299,7 +1299,7 @@ SDValue ARMTargetLowering::LowerGlobalAddressDarwin(SDValue Op, Result = DAG.getNode(ARMISD::PIC_ADD, dl, PtrVT, Result, PICLabel); } - if (Subtarget->GVIsIndirectSymbol(GV, RelocM == Reloc::Static)) + if (Subtarget->GVIsIndirectSymbol(GV, RelocM)) Result = DAG.getLoad(PtrVT, dl, Chain, Result, NULL, 0); return Result; diff --git a/lib/Target/ARM/ARMSubtarget.cpp b/lib/Target/ARM/ARMSubtarget.cpp index 67669cc7b84..f5723ea5618 100644 --- a/lib/Target/ARM/ARMSubtarget.cpp +++ b/lib/Target/ARM/ARMSubtarget.cpp @@ -95,11 +95,51 @@ ARMSubtarget::ARMSubtarget(const std::string &TT, const std::string &FS, } /// GVIsIndirectSymbol - true if the GV will be accessed via an indirect symbol. -bool ARMSubtarget::GVIsIndirectSymbol(GlobalValue *GV, bool isStatic) const { - // If symbol visibility is hidden, the extra load is not needed if - // the symbol is definitely defined in the current translation unit. - bool isDecl = GV->isDeclaration() || GV->hasAvailableExternallyLinkage(); - if (GV->hasHiddenVisibility() && (!isDecl && !GV->hasCommonLinkage())) +bool +ARMSubtarget::GVIsIndirectSymbol(GlobalValue *GV, Reloc::Model RelocM) const { + if (RelocM == Reloc::Static) return false; - return !isStatic && (isDecl || GV->isWeakForLinker()); + + // GV with ghost linkage (in JIT lazy compilation mode) do not require an + // extra load from stub. + bool isDecl = GV->isDeclaration() && !GV->hasNotBeenReadFromBitcode(); + + if (!isTargetDarwin()) { + // Extra load is needed for all externally visible. + if (GV->hasLocalLinkage() || GV->hasHiddenVisibility()) + return false; + return true; + } else { + if (RelocM == Reloc::PIC_) { + // If this is a strong reference to a definition, it is definitely not + // through a stub. + if (!isDecl && !GV->isWeakForLinker()) + return false; + + // Unless we have a symbol with hidden visibility, we have to go through a + // normal $non_lazy_ptr stub because this symbol might be resolved late. + if (!GV->hasHiddenVisibility()) // Non-hidden $non_lazy_ptr reference. + return true; + + // If symbol visibility is hidden, we have a stub for common symbol + // references and external declarations. + if (isDecl || GV->hasCommonLinkage()) + // Hidden $non_lazy_ptr reference. + return true; + + return false; + } else { + // If this is a strong reference to a definition, it is definitely not + // through a stub. + if (!isDecl && !GV->isWeakForLinker()) + return false; + + // Unless we have a symbol with hidden visibility, we have to go through a + // normal $non_lazy_ptr stub because this symbol might be resolved late. + if (!GV->hasHiddenVisibility()) // Non-hidden $non_lazy_ptr reference. + return true; + } + } + + return false; } diff --git a/lib/Target/ARM/ARMSubtarget.h b/lib/Target/ARM/ARMSubtarget.h index 73f9736188d..518967b9243 100644 --- a/lib/Target/ARM/ARMSubtarget.h +++ b/lib/Target/ARM/ARMSubtarget.h @@ -15,6 +15,7 @@ #define ARMSUBTARGET_H #include "llvm/Target/TargetInstrItineraries.h" +#include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetSubtarget.h" #include @@ -133,7 +134,7 @@ protected: /// GVIsIndirectSymbol - true if the GV will be accessed via an indirect /// symbol. - bool GVIsIndirectSymbol(GlobalValue *GV, bool isStatic) const; + bool GVIsIndirectSymbol(GlobalValue *GV, Reloc::Model RelocM) const; }; } // End llvm namespace diff --git a/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp b/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp index 20af40568a7..a97302a0389 100644 --- a/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp +++ b/lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp @@ -166,8 +166,7 @@ namespace { Name = LSDAName.str(); } else if (GV) { bool isIndirect = Subtarget->isTargetDarwin() && - Subtarget->GVIsIndirectSymbol(GV, - TM.getRelocationModel() == Reloc::Static); + Subtarget->GVIsIndirectSymbol(GV, TM.getRelocationModel()); if (!isIndirect) Name = Mang->getMangledName(GV); else { diff --git a/lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.cpp b/lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.cpp index 70f6a27022f..ad91fad061a 100644 --- a/lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.cpp +++ b/lib/Target/X86/AsmPrinter/X86ATTAsmPrinter.cpp @@ -306,7 +306,6 @@ void X86ATTAsmPrinter::printSymbolOperand(const MachineOperand &MO) { Suffix = "$stub"; else if (MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY || MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY_PIC_BASE || - MO.getTargetFlags() == X86II::MO_DARWIN_HIDDEN_NONLAZY || MO.getTargetFlags() == X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE) Suffix = "$non_lazy_ptr"; @@ -321,8 +320,7 @@ void X86ATTAsmPrinter::printSymbolOperand(const MachineOperand &MO) { if (MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY || MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY_PIC_BASE) GVStubs[Name] = Mang->getMangledName(GV); - else if (MO.getTargetFlags() == X86II::MO_DARWIN_HIDDEN_NONLAZY || - MO.getTargetFlags() == X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE) + else if (MO.getTargetFlags() == X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE) HiddenGVStubs[Name] = Mang->getMangledName(GV); else if (MO.getTargetFlags() == X86II::MO_DARWIN_STUB) FnStubs[Name] = Mang->getMangledName(GV); @@ -360,7 +358,6 @@ void X86ATTAsmPrinter::printSymbolOperand(const MachineOperand &MO) { case X86II::MO_NO_FLAG: // No flag. break; case X86II::MO_DARWIN_NONLAZY: - case X86II::MO_DARWIN_HIDDEN_NONLAZY: case X86II::MO_DLLIMPORT: case X86II::MO_DARWIN_STUB: // These affect the name of the symbol, not any suffix. diff --git a/lib/Target/X86/AsmPrinter/X86MCInstLower.cpp b/lib/Target/X86/AsmPrinter/X86MCInstLower.cpp index 49c42e531ef..89fac7a29d6 100644 --- a/lib/Target/X86/AsmPrinter/X86MCInstLower.cpp +++ b/lib/Target/X86/AsmPrinter/X86MCInstLower.cpp @@ -62,7 +62,6 @@ MCSymbol *X86ATTAsmPrinter::GetGlobalAddressSymbol(const MachineOperand &MO) { Suffix = "$stub"; else if (MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY || MO.getTargetFlags() == X86II::MO_DARWIN_NONLAZY_PIC_BASE || - MO.getTargetFlags() == X86II::MO_DARWIN_HIDDEN_NONLAZY || MO.getTargetFlags() == X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE) Suffix = "$non_lazy_ptr"; @@ -84,7 +83,6 @@ MCSymbol *X86ATTAsmPrinter::GetGlobalAddressSymbol(const MachineOperand &MO) { case X86II::MO_DARWIN_NONLAZY_PIC_BASE: GVStubs[Name] = Mang->getMangledName(GV); break; - case X86II::MO_DARWIN_HIDDEN_NONLAZY: case X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE: HiddenGVStubs[Name] = Mang->getMangledName(GV); break; @@ -169,7 +167,6 @@ MCOperand X86ATTAsmPrinter::LowerSymbolOperand(const MachineOperand &MO, // These affect the name of the symbol, not any suffix. case X86II::MO_DARWIN_NONLAZY: - case X86II::MO_DARWIN_HIDDEN_NONLAZY: case X86II::MO_DLLIMPORT: case X86II::MO_DARWIN_STUB: case X86II::MO_TLSGD: diff --git a/lib/Target/X86/X86InstrInfo.h b/lib/Target/X86/X86InstrInfo.h index 2e0235af394..fd498444888 100644 --- a/lib/Target/X86/X86InstrInfo.h +++ b/lib/Target/X86/X86InstrInfo.h @@ -170,16 +170,11 @@ namespace X86II { /// a PIC-base-relative reference to a non-hidden dyld lazy pointer stub. MO_DARWIN_NONLAZY_PIC_BASE = 15, - /// MO_DARWIN_HIDDEN_NONLAZY - On a symbol operand "FOO", this indicates - /// that the reference is actually to the "FOO$non_lazy_ptr" symbol, which - /// is a non-PIC-base-relative reference to a hidden dyld lazy pointer stub. - MO_DARWIN_HIDDEN_NONLAZY = 16, - /// MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE - On a symbol operand "FOO", this /// indicates that the reference is actually to "FOO$non_lazy_ptr -PICBASE", /// which is a PIC-base-relative reference to a hidden dyld lazy pointer /// stub. - MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE = 17 + MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE = 16 }; } @@ -193,7 +188,6 @@ inline static bool isGlobalStubReference(unsigned char TargetFlag) { case X86II::MO_DARWIN_NONLAZY_PIC_BASE: // Normal $non_lazy_ptr ref. case X86II::MO_DARWIN_NONLAZY: // Normal $non_lazy_ptr ref. case X86II::MO_DARWIN_HIDDEN_NONLAZY_PIC_BASE: // Hidden $non_lazy_ptr ref. - case X86II::MO_DARWIN_HIDDEN_NONLAZY: // Hidden $non_lazy_ptr ref. return true; default: return false; diff --git a/lib/Target/X86/X86Subtarget.cpp b/lib/Target/X86/X86Subtarget.cpp index 5e4a6ba1ff4..fb76aeb0555 100644 --- a/lib/Target/X86/X86Subtarget.cpp +++ b/lib/Target/X86/X86Subtarget.cpp @@ -108,14 +108,7 @@ ClassifyGlobalReference(const GlobalValue *GV, const TargetMachine &TM) const { // normal $non_lazy_ptr stub because this symbol might be resolved late. if (!GV->hasHiddenVisibility()) // Non-hidden $non_lazy_ptr reference. return X86II::MO_DARWIN_NONLAZY; - - // If symbol visibility is hidden, we have a stub for common symbol - // references and external declarations. - if (isDecl || GV->hasCommonLinkage()) { - // Hidden $non_lazy_ptr reference. - return X86II::MO_DARWIN_HIDDEN_NONLAZY; - } - + // Otherwise, no stub. return X86II::MO_NO_FLAG; } diff --git a/test/CodeGen/ARM/hidden-vis-2.ll b/test/CodeGen/ARM/hidden-vis-2.ll index 6cf69aa486d..129d96ff5db 100644 --- a/test/CodeGen/ARM/hidden-vis-2.ll +++ b/test/CodeGen/ARM/hidden-vis-2.ll @@ -1,9 +1,12 @@ -; RUN: llvm-as < %s | llc -mtriple=arm-apple-darwin | grep ldr | count 2 +; RUN: llvm-as < %s | llc -mtriple=arm-apple-darwin | FileCheck %s @x = weak hidden global i32 0 ; [#uses=1] define i32 @t() nounwind readonly { entry: +; CHECK: t: +; CHECK: ldr +; CHECK-NEXT: ldr %0 = load i32* @x, align 4 ; [#uses=1] ret i32 %0 } diff --git a/test/CodeGen/ARM/hidden-vis-3.ll b/test/CodeGen/ARM/hidden-vis-3.ll index 4477f2a441a..1e88ce94eff 100644 --- a/test/CodeGen/ARM/hidden-vis-3.ll +++ b/test/CodeGen/ARM/hidden-vis-3.ll @@ -1,12 +1,15 @@ -; RUN: llvm-as < %s | llc -mtriple=arm-apple-darwin | grep ldr | count 6 -; RUN: llvm-as < %s | llc -mtriple=arm-apple-darwin | grep non_lazy_ptr -; RUN: llvm-as < %s | llc -mtriple=arm-apple-darwin | grep long | count 4 +; RUN: llvm-as < %s | llc -mtriple=arm-apple-darwin9 | FileCheck %s @x = external hidden global i32 ; [#uses=1] @y = extern_weak hidden global i32 ; [#uses=1] define i32 @t() nounwind readonly { entry: +; CHECK: LCPI1_0: +; CHECK-NEXT: .long _x +; CHECK: LCPI1_1: +; CHECK-NEXT: .long _y + %0 = load i32* @x, align 4 ; [#uses=1] %1 = load i32* @y, align 4 ; [#uses=1] %2 = add i32 %1, %0 ; [#uses=1] diff --git a/test/CodeGen/ARM/hidden-vis.ll b/test/CodeGen/ARM/hidden-vis.ll index 93f81ecdae0..03a0759577c 100644 --- a/test/CodeGen/ARM/hidden-vis.ll +++ b/test/CodeGen/ARM/hidden-vis.ll @@ -1,18 +1,23 @@ -; RUN: llvm-as < %s | llc -mtriple=arm-apple-darwin | \ -; RUN: grep .private_extern | count 2 +; RUN: llvm-as < %s | llc -mtriple=arm-linux | FileCheck %s -check-prefix=LINUX +; RUN: llvm-as < %s | llc -mtriple=arm-apple-darwin | FileCheck %s -check-prefix=DARWIN -%struct.Person = type { i32 } @a = hidden global i32 0 @b = external global i32 +define weak hidden void @t1() nounwind { +; LINUX: .hidden t1 +; LINUX: t1: -define weak hidden void @_ZN6Person13privateMethodEv(%struct.Person* %this) { +; DARWIN: .private_extern _t1 +; DARWIN: t1: ret void } -declare void @function(i32) +define weak void @t2() nounwind { +; LINUX: t2: +; LINUX: .hidden a -define weak void @_ZN6PersonC1Ei(%struct.Person* %this, i32 %_c) { +; DARWIN: t2: +; DARWIN: .private_extern _a ret void } - diff --git a/test/CodeGen/X86/hidden-vis-3.ll b/test/CodeGen/X86/hidden-vis-3.ll index 81dc76e1488..efa7b69fd63 100644 --- a/test/CodeGen/X86/hidden-vis-3.ll +++ b/test/CodeGen/X86/hidden-vis-3.ll @@ -1,13 +1,17 @@ -; RUN: llvm-as < %s | llc -mtriple=i386-apple-darwin9 | grep mov | count 3 -; RUN: llvm-as < %s | llc -mtriple=i386-apple-darwin9 | grep non_lazy_ptr -; RUN: llvm-as < %s | llc -mtriple=i386-apple-darwin9 | grep long | count 2 -; RUN: llvm-as < %s | llc -mtriple=x86_64-apple-darwin9 | not grep GOT +; RUN: llvm-as < %s | llc -mtriple=i386-apple-darwin9 | FileCheck %s -check-prefix=X32 +; RUN: llvm-as < %s | llc -mtriple=x86_64-apple-darwin9 | FileCheck %s -check-prefix=X64 @x = external hidden global i32 ; [#uses=1] @y = extern_weak hidden global i32 ; [#uses=1] define i32 @t() nounwind readonly { entry: +; X32: _t: +; X32: movl _y, %eax + +; X64: _t: +; X64: movl _y(%rip), %eax + %0 = load i32* @x, align 4 ; [#uses=1] %1 = load i32* @y, align 4 ; [#uses=1] %2 = add i32 %1, %0 ; [#uses=1] diff --git a/test/CodeGen/X86/hidden-vis-4.ll b/test/CodeGen/X86/hidden-vis-4.ll index e6936de1036..a744a02f0c6 100644 --- a/test/CodeGen/X86/hidden-vis-4.ll +++ b/test/CodeGen/X86/hidden-vis-4.ll @@ -1,11 +1,12 @@ -; RUN: llvm-as < %s | llc -mtriple=i386-apple-darwin9 | grep non_lazy_ptr -; RUN: llvm-as < %s | llc -mtriple=i386-apple-darwin9 | grep long -; RUN: llvm-as < %s | llc -mtriple=i386-apple-darwin9 | grep comm +; RUN: llvm-as < %s | llc -mtriple=i386-apple-darwin9 | FileCheck %s @x = common hidden global i32 0 ; [#uses=1] define i32 @t() nounwind readonly { entry: +; CHECK: t: +; CHECK: movl _x, %eax +; CHECK: .comm _x,4 %0 = load i32* @x, align 4 ; [#uses=1] ret i32 %0 } diff --git a/test/CodeGen/X86/hidden-vis.ll b/test/CodeGen/X86/hidden-vis.ll index 058850c7b75..061db11e0bb 100644 --- a/test/CodeGen/X86/hidden-vis.ll +++ b/test/CodeGen/X86/hidden-vis.ll @@ -1,20 +1,24 @@ -; RUN: llvm-as < %s | llc -mtriple=i686-pc-linux-gnu | \ -; RUN: grep .hidden | count 2 -; RUN: llvm-as < %s | llc -mtriple=i686-apple-darwin8.8.0 | \ -; RUN: grep .private_extern | count 2 +; RUN: llvm-as < %s | llc -mtriple=i686-pc-linux-gnu | FileCheck %s -check-prefix=LINUX +; RUN: llvm-as < %s | llc -mtriple=i686-apple-darwin8 | FileCheck %s -check-prefix=DARWIN -%struct.Person = type { i32 } @a = hidden global i32 0 @b = external global i32 +define weak hidden void @t1() nounwind { +; LINUX: .hidden t1 +; LINUX: t1: -define weak hidden void @_ZN6Person13privateMethodEv(%struct.Person* %this) { +; DARWIN: .private_extern _t1 +; DARWIN: t1: ret void } -declare void @function(i32) +define weak void @t2() nounwind { +; LINUX: t2: +; LINUX: .hidden a -define weak void @_ZN6PersonC1Ei(%struct.Person* %this, i32 %_c) { +; DARWIN: t2: +; DARWIN: .private_extern _a ret void }