diff --git a/lib/Target/PowerPC/PPCAsmPrinter.cpp b/lib/Target/PowerPC/PPCAsmPrinter.cpp index 3f1e67bf526..f7a64f86caa 100644 --- a/lib/Target/PowerPC/PPCAsmPrinter.cpp +++ b/lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -55,6 +55,7 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/MapVector.h" +#include "llvm/ADT/VariadicFunction.h" using namespace llvm; namespace { @@ -558,6 +559,21 @@ static MCSymbol *GetAnonSym(MCSymbol *Sym, MCContext &Ctx) { return Ctx.GetOrCreateSymbol(Sym->getName() + "$tmp"); } +namespace { + // Helper function to emit a custom MCInst. + void emitMCInstImpl(MCStreamer &OutStreamer, unsigned Opcode, + ArrayRef Ops) { + MCInst TmpInst; + TmpInst.setOpcode(Opcode); + for (unsigned I = 0, E = Ops.size(); I != E; ++I) + TmpInst.addOperand(*Ops[I]); + OutStreamer.EmitInstruction(TmpInst); + } + + const VariadicFunction2 emitMCInst = {}; +} + void PPCDarwinAsmPrinter:: EmitFunctionStubs(const MachineModuleInfoMachO::SymbolListTy &Stubs) { bool isPPC64 = TM.getDataLayout()->getPointerSizeInBits() == 64; @@ -586,32 +602,52 @@ EmitFunctionStubs(const MachineModuleInfoMachO::SymbolListTy &Stubs) { OutStreamer.EmitLabel(Stub); OutStreamer.EmitSymbolAttribute(RawSym, MCSA_IndirectSymbol); + + // mflr r0 + emitMCInst(OutStreamer, PPC::MFLR, MCOperand::CreateReg(PPC::R0)); // FIXME: MCize this. - OutStreamer.EmitRawText(StringRef("\tmflr r0")); - OutStreamer.EmitRawText("\tbcl 20,31," + Twine(AnonSymbol->getName())); + OutStreamer.EmitRawText("\tbcl 20, 31, " + Twine(AnonSymbol->getName())); OutStreamer.EmitLabel(AnonSymbol); - OutStreamer.EmitRawText(StringRef("\tmflr r11")); - OutStreamer.EmitRawText("\taddis r11,r11,ha16("+Twine(LazyPtr->getName())+ - "-" + AnonSymbol->getName() + ")"); - OutStreamer.EmitRawText(StringRef("\tmtlr r0")); - - if (isPPC64) - OutStreamer.EmitRawText("\tldu r12,lo16(" + Twine(LazyPtr->getName()) + - "-" + AnonSymbol->getName() + ")(r11)"); - else - OutStreamer.EmitRawText("\tlwzu r12,lo16(" + Twine(LazyPtr->getName()) + - "-" + AnonSymbol->getName() + ")(r11)"); - OutStreamer.EmitRawText(StringRef("\tmtctr r12")); - OutStreamer.EmitRawText(StringRef("\tbctr")); - + // mflr r11 + emitMCInst(OutStreamer, PPC::MFLR, MCOperand::CreateReg(PPC::R11)); + // addis r11, r11, ha16(LazyPtr - AnonSymbol) + MCOperand Sub = MCOperand::CreateExpr( + MCBinaryExpr::CreateSub( + MCSymbolRefExpr::Create(LazyPtr, OutContext), + MCSymbolRefExpr::Create(AnonSymbol, OutContext), + OutContext)); + emitMCInst(OutStreamer, PPC::ADDIS, MCOperand::CreateReg(PPC::R11), + MCOperand::CreateReg(PPC::R11), Sub); + // mtlr r0 + emitMCInst(OutStreamer, PPC::MTLR, MCOperand::CreateReg(PPC::R0)); + + if (isPPC64) { + // ldu r12, lo16(LazyPtr - AnonSymbol)(r11) + emitMCInst(OutStreamer, PPC::LDU, MCOperand::CreateReg(PPC::R12), + Sub, Sub, MCOperand::CreateReg(PPC::R11)); + } else { + // lwzu r12, lo16(LazyPtr - AnonSymbol)(r11) + emitMCInst(OutStreamer, PPC::LWZU, MCOperand::CreateReg(PPC::R12), + Sub, Sub, MCOperand::CreateReg(PPC::R11)); + } + // mtctr r12 + emitMCInst(OutStreamer, PPC::MTCTR, MCOperand::CreateReg(PPC::R12)); + // bctr + emitMCInst(OutStreamer, PPC::BCTR); + OutStreamer.SwitchSection(LSPSection); OutStreamer.EmitLabel(LazyPtr); OutStreamer.EmitSymbolAttribute(RawSym, MCSA_IndirectSymbol); - - if (isPPC64) - OutStreamer.EmitRawText(StringRef("\t.quad dyld_stub_binding_helper")); - else - OutStreamer.EmitRawText(StringRef("\t.long dyld_stub_binding_helper")); + + MCSymbol *DyldStubBindingHelper = + OutContext.GetOrCreateSymbol(StringRef("dyld_stub_binding_helper")); + if (isPPC64) { + // .quad dyld_stub_binding_helper + OutStreamer.EmitSymbolValue(DyldStubBindingHelper, 8); + } else { + // .long dyld_stub_binding_helper + OutStreamer.EmitSymbolValue(DyldStubBindingHelper, 4); + } } OutStreamer.AddBlankLine(); return; @@ -631,23 +667,44 @@ EmitFunctionStubs(const MachineModuleInfoMachO::SymbolListTy &Stubs) { EmitAlignment(4); OutStreamer.EmitLabel(Stub); OutStreamer.EmitSymbolAttribute(RawSym, MCSA_IndirectSymbol); - OutStreamer.EmitRawText("\tlis r11,ha16(" + Twine(LazyPtr->getName()) +")"); - if (isPPC64) - OutStreamer.EmitRawText("\tldu r12,lo16(" + Twine(LazyPtr->getName()) + - ")(r11)"); - else - OutStreamer.EmitRawText("\tlwzu r12,lo16(" + Twine(LazyPtr->getName()) + - ")(r11)"); - OutStreamer.EmitRawText(StringRef("\tmtctr r12")); - OutStreamer.EmitRawText(StringRef("\tbctr")); + // lis r11, ha16(LazyPtr) + MCOperand LazyPtrHa16 = + MCOperand::CreateExpr( + MCSymbolRefExpr::Create(LazyPtr, MCSymbolRefExpr::VK_PPC_DARWIN_HA16, + OutContext)); + emitMCInst(OutStreamer, PPC::LIS, MCOperand::CreateReg(PPC::R11), + LazyPtrHa16); + + MCOperand LazyPtrLo16 = + MCOperand::CreateExpr( + MCSymbolRefExpr::Create(LazyPtr, MCSymbolRefExpr::VK_PPC_DARWIN_LO16, + OutContext)); + if (isPPC64) { + // ldu r12, lo16(LazyPtr)(r11) + emitMCInst(OutStreamer, PPC::LDU, MCOperand::CreateReg(PPC::R12), + LazyPtrLo16, LazyPtrLo16, MCOperand::CreateReg(PPC::R11)); + } else { + // lwzu r12, lo16(LazyPtr)(r11) + emitMCInst(OutStreamer, PPC::LWZU, MCOperand::CreateReg(PPC::R12), + LazyPtrLo16, LazyPtrLo16, MCOperand::CreateReg(PPC::R11)); + } + // mtctr r12 + emitMCInst(OutStreamer, PPC::MTCTR, MCOperand::CreateReg(PPC::R12)); + // bctr + emitMCInst(OutStreamer, PPC::BCTR); OutStreamer.SwitchSection(LSPSection); OutStreamer.EmitLabel(LazyPtr); OutStreamer.EmitSymbolAttribute(RawSym, MCSA_IndirectSymbol); - - if (isPPC64) - OutStreamer.EmitRawText(StringRef("\t.quad dyld_stub_binding_helper")); - else - OutStreamer.EmitRawText(StringRef("\t.long dyld_stub_binding_helper")); + + MCSymbol *DyldStubBindingHelper = + OutContext.GetOrCreateSymbol(StringRef("dyld_stub_binding_helper")); + if (isPPC64) { + // .quad dyld_stub_binding_helper + OutStreamer.EmitSymbolValue(DyldStubBindingHelper, 8); + } else { + // .long dyld_stub_binding_helper + OutStreamer.EmitSymbolValue(DyldStubBindingHelper, 4); + } } OutStreamer.AddBlankLine(); diff --git a/test/CodeGen/PowerPC/available-externally.ll b/test/CodeGen/PowerPC/available-externally.ll index fdead7dd8b3..abed0de80b8 100644 --- a/test/CodeGen/PowerPC/available-externally.ll +++ b/test/CodeGen/PowerPC/available-externally.ll @@ -1,6 +1,8 @@ ; RUN: llc < %s -relocation-model=static | FileCheck %s -check-prefix=STATIC ; RUN: llc < %s -relocation-model=pic | FileCheck %s -check-prefix=PIC +; RUN: llc < %s -relocation-model=pic -mtriple=powerpc64-apple-darwin8 | FileCheck %s -check-prefix=PIC64 ; RUN: llc < %s -relocation-model=dynamic-no-pic | FileCheck %s -check-prefix=DYNAMIC +; RUN: llc < %s -relocation-model=dynamic-no-pic -mtriple=powerpc64-apple-darwin8 | FileCheck %s -check-prefix=DYNAMIC64 ; PR4482 target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" target triple = "powerpc-apple-darwin8" @@ -16,10 +18,18 @@ entry: ; PIC: bl L_exact_log2$stub ; PIC: blr +; PIC64: _foo: +; PIC64: bl L_exact_log2$stub +; PIC64: blr + ; DYNAMIC: _foo: ; DYNAMIC: bl L_exact_log2$stub ; DYNAMIC: blr +; DYNAMIC64: _foo: +; DYNAMIC64: bl L_exact_log2$stub +; DYNAMIC64: blr + %A = call i32 @exact_log2(i64 %x) nounwind ret i32 %A } @@ -34,13 +44,13 @@ entry: ; PIC: L_exact_log2$stub: ; PIC: .indirect_symbol _exact_log2 ; PIC: mflr r0 -; PIC: bcl 20,31,L_exact_log2$stub$tmp +; PIC: bcl 20, 31, L_exact_log2$stub$tmp ; PIC: L_exact_log2$stub$tmp: ; PIC: mflr r11 -; PIC: addis r11,r11,ha16(L_exact_log2$lazy_ptr-L_exact_log2$stub$tmp) +; PIC: addis r11, r11, ha16(L_exact_log2$lazy_ptr-L_exact_log2$stub$tmp) ; PIC: mtlr r0 -; PIC: lwzu r12,lo16(L_exact_log2$lazy_ptr-L_exact_log2$stub$tmp)(r11) +; PIC: lwzu r12, lo16(L_exact_log2$lazy_ptr-L_exact_log2$stub$tmp)(r11) ; PIC: mtctr r12 ; PIC: bctr @@ -51,12 +61,32 @@ entry: ; PIC: .subsections_via_symbols +; PIC64: .section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32 +; PIC64: L_exact_log2$stub: +; PIC64: .indirect_symbol _exact_log2 +; PIC64: mflr r0 +; PIC64: bcl 20, 31, L_exact_log2$stub$tmp + +; PIC64: L_exact_log2$stub$tmp: +; PIC64: mflr r11 +; PIC64: addis r11, r11, ha16(L_exact_log2$lazy_ptr-L_exact_log2$stub$tmp) +; PIC64: mtlr r0 +; PIC64: ldu r12, lo16(L_exact_log2$lazy_ptr-L_exact_log2$stub$tmp)(r11) +; PIC64: mtctr r12 +; PIC64: bctr + +; PIC64: .section __DATA,__la_symbol_ptr,lazy_symbol_pointers +; PIC64: L_exact_log2$lazy_ptr: +; PIC64: .indirect_symbol _exact_log2 +; PIC64: .quad dyld_stub_binding_helper + +; PIC64: .subsections_via_symbols ; DYNAMIC: .section __TEXT,__symbol_stub1,symbol_stubs,pure_instructions,16 ; DYNAMIC: L_exact_log2$stub: ; DYNAMIC: .indirect_symbol _exact_log2 -; DYNAMIC: lis r11,ha16(L_exact_log2$lazy_ptr) -; DYNAMIC: lwzu r12,lo16(L_exact_log2$lazy_ptr)(r11) +; DYNAMIC: lis r11, ha16(L_exact_log2$lazy_ptr) +; DYNAMIC: lwzu r12, lo16(L_exact_log2$lazy_ptr)(r11) ; DYNAMIC: mtctr r12 ; DYNAMIC: bctr @@ -65,7 +95,15 @@ entry: ; DYNAMIC: .indirect_symbol _exact_log2 ; DYNAMIC: .long dyld_stub_binding_helper +; DYNAMIC64: .section __TEXT,__symbol_stub1,symbol_stubs,pure_instructions,16 +; DYNAMIC64: L_exact_log2$stub: +; DYNAMIC64: .indirect_symbol _exact_log2 +; DYNAMIC64: lis r11, ha16(L_exact_log2$lazy_ptr) +; DYNAMIC64: ldu r12, lo16(L_exact_log2$lazy_ptr)(r11) +; DYNAMIC64: mtctr r12 +; DYNAMIC64: bctr - - - +; DYNAMIC64: .section __DATA,__la_symbol_ptr,lazy_symbol_pointers +; DYNAMIC64: L_exact_log2$lazy_ptr: +; DYNAMIC64: .indirect_symbol _exact_log2 +; DYNAMIC64: .quad dyld_stub_binding_helper diff --git a/test/CodeGen/PowerPC/stubs.ll b/test/CodeGen/PowerPC/stubs.ll index 4889263b4c4..cfcc50b7a87 100644 --- a/test/CodeGen/PowerPC/stubs.ll +++ b/test/CodeGen/PowerPC/stubs.ll @@ -10,8 +10,8 @@ entry: ; CHECK: .section __TEXT,__symbol_stub1,symbol_stubs,pure_instructions,16 ; CHECK: ___floatditf$stub: ; CHECK: .indirect_symbol ___floatditf -; CHECK: lis r11,ha16(___floatditf$lazy_ptr) -; CHECK: lwzu r12,lo16(___floatditf$lazy_ptr)(r11) +; CHECK: lis r11, ha16(___floatditf$lazy_ptr) +; CHECK: lwzu r12, lo16(___floatditf$lazy_ptr)(r11) ; CHECK: mtctr r12 ; CHECK: bctr ; CHECK: .section __DATA,__la_symbol_ptr,lazy_symbol_pointers