Index: lib/Target/PowerPC/PPCAsmPrinter.cpp =================================================================== --- lib/Target/PowerPC/PPCAsmPrinter.cpp +++ lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -1096,8 +1096,28 @@ } // ELFv2 ABI - Normal entry label. - if (Subtarget->isELFv2ABI()) + if (Subtarget->isELFv2ABI()) { + // In the Large code model, we allow arbitrary displacements between + // the text section and its associated TOC section. We place the + // full 8-byte offset to the TOC in memory immediatedly preceding + // the function global entry point. + if (TM.getCodeModel() == CodeModel::Large + && !MF->getRegInfo().use_empty(PPC::X2)) { + const PPCFunctionInfo *PPCFI = MF->getInfo(); + + MCSymbol *TOCSymbol = OutContext.getOrCreateSymbol(StringRef(".TOC.")); + MCSymbol *GlobalEPSymbol = PPCFI->getGlobalEPSymbol(); + const MCExpr *TOCDeltaExpr = + MCBinaryExpr::createSub(MCSymbolRefExpr::create(TOCSymbol, OutContext), + MCSymbolRefExpr::create(GlobalEPSymbol, + OutContext), + OutContext); + + OutStreamer->EmitLabel(PPCFI->getTOCOffsetSymbol()); + OutStreamer->EmitValue(TOCDeltaExpr, 8); + } return AsmPrinter::EmitFunctionEntryLabel(); + } // Emit an official procedure descriptor. MCSectionSubPair Current = OutStreamer->getCurrentSection(); @@ -1164,10 +1184,25 @@ // thus emit a prefix sequence along the following lines: // // func: + // .Lfunc_gepNN: // # global entry point - // addis r2,r12,(.TOC.-func)@ha - // addi r2,r2,(.TOC.-func)@l - // .localentry func, .-func + // addis r2,r12,(.TOC.-.Lfunc_gepNN)@ha + // addi r2,r2,(.TOC.-.Lfunc_gepNN)@l + // .Lfunc_lepNN: + // .localentry func, .Lfunc_lepNN-.Lfunc_gepNN + // # local entry point, followed by function body + // + // For the Large code model, we create + // + // .Lfunc_tocNN: + // .quad .TOC.-.Lfunc_gepNN # done by EmitFunctionEntryLabel + // func: + // .Lfunc_gepNN: + // # global entry point + // ld r2,.Lfunc_tocNN-.Lfunc_gepNN(r12) + // add r2,r2,r12 + // .Lfunc_lepNN: + // .localentry func, .Lfunc_lepNN-.Lfunc_gepNN // # local entry point, followed by function body // // This ensures we have r2 set up correctly while executing the function @@ -1175,32 +1210,49 @@ if (Subtarget->isELFv2ABI() // Only do all that if the function uses r2 in the first place. && !MF->getRegInfo().use_empty(PPC::X2)) { + const PPCFunctionInfo *PPCFI = MF->getInfo(); - MCSymbol *GlobalEntryLabel = OutContext.createTempSymbol(); + MCSymbol *GlobalEntryLabel = PPCFI->getGlobalEPSymbol(); OutStreamer->EmitLabel(GlobalEntryLabel); const MCSymbolRefExpr *GlobalEntryLabelExp = MCSymbolRefExpr::create(GlobalEntryLabel, OutContext); - MCSymbol *TOCSymbol = OutContext.getOrCreateSymbol(StringRef(".TOC.")); - const MCExpr *TOCDeltaExpr = - MCBinaryExpr::createSub(MCSymbolRefExpr::create(TOCSymbol, OutContext), - GlobalEntryLabelExp, OutContext); + if (TM.getCodeModel() != CodeModel::Large) { + MCSymbol *TOCSymbol = OutContext.getOrCreateSymbol(StringRef(".TOC.")); + const MCExpr *TOCDeltaExpr = + MCBinaryExpr::createSub(MCSymbolRefExpr::create(TOCSymbol, OutContext), + GlobalEntryLabelExp, OutContext); - const MCExpr *TOCDeltaHi = - PPCMCExpr::createHa(TOCDeltaExpr, false, OutContext); - EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDIS) - .addReg(PPC::X2) - .addReg(PPC::X12) - .addExpr(TOCDeltaHi)); - - const MCExpr *TOCDeltaLo = - PPCMCExpr::createLo(TOCDeltaExpr, false, OutContext); - EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDI) - .addReg(PPC::X2) - .addReg(PPC::X2) - .addExpr(TOCDeltaLo)); + const MCExpr *TOCDeltaHi = + PPCMCExpr::createHa(TOCDeltaExpr, false, OutContext); + EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDIS) + .addReg(PPC::X2) + .addReg(PPC::X12) + .addExpr(TOCDeltaHi)); + + const MCExpr *TOCDeltaLo = + PPCMCExpr::createLo(TOCDeltaExpr, false, OutContext); + EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDI) + .addReg(PPC::X2) + .addReg(PPC::X2) + .addExpr(TOCDeltaLo)); + } else { + MCSymbol *TOCOffset = PPCFI->getTOCOffsetSymbol(); + const MCExpr *TOCOffsetDeltaExpr = + MCBinaryExpr::createSub(MCSymbolRefExpr::create(TOCOffset, OutContext), + GlobalEntryLabelExp, OutContext); + + EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LD) + .addReg(PPC::X2) + .addExpr(TOCOffsetDeltaExpr) + .addReg(PPC::X12)); + EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADD8) + .addReg(PPC::X2) + .addReg(PPC::X2) + .addReg(PPC::X12)); + } - MCSymbol *LocalEntryLabel = OutContext.createTempSymbol(); + MCSymbol *LocalEntryLabel = PPCFI->getLocalEPSymbol(); OutStreamer->EmitLabel(LocalEntryLabel); const MCSymbolRefExpr *LocalEntryLabelExp = MCSymbolRefExpr::create(LocalEntryLabel, OutContext); Index: lib/Target/PowerPC/PPCMachineFunctionInfo.h =================================================================== --- lib/Target/PowerPC/PPCMachineFunctionInfo.h +++ lib/Target/PowerPC/PPCMachineFunctionInfo.h @@ -197,6 +197,10 @@ bool usesPICBase() const { return UsesPICBase; } MCSymbol *getPICOffsetSymbol() const; + + MCSymbol *getGlobalEPSymbol() const; + MCSymbol *getLocalEPSymbol() const; + MCSymbol *getTOCOffsetSymbol() const; }; } // end of namespace llvm Index: lib/Target/PowerPC/PPCMachineFunctionInfo.cpp =================================================================== --- lib/Target/PowerPC/PPCMachineFunctionInfo.cpp +++ lib/Target/PowerPC/PPCMachineFunctionInfo.cpp @@ -23,3 +23,24 @@ Twine(MF.getFunctionNumber()) + "$poff"); } + +MCSymbol *PPCFunctionInfo::getGlobalEPSymbol() const { + const DataLayout &DL = MF.getDataLayout(); + return MF.getContext().getOrCreateSymbol(Twine(DL.getPrivateGlobalPrefix()) + + "func_gep" + + Twine(MF.getFunctionNumber())); +} + +MCSymbol *PPCFunctionInfo::getLocalEPSymbol() const { + const DataLayout &DL = MF.getDataLayout(); + return MF.getContext().getOrCreateSymbol(Twine(DL.getPrivateGlobalPrefix()) + + "func_lep" + + Twine(MF.getFunctionNumber())); +} + +MCSymbol *PPCFunctionInfo::getTOCOffsetSymbol() const { + const DataLayout &DL = MF.getDataLayout(); + return MF.getContext().getOrCreateSymbol(Twine(DL.getPrivateGlobalPrefix()) + + "func_toc" + + Twine(MF.getFunctionNumber())); +} Index: test/CodeGen/PowerPC/ppc64le-localentry-large.ll =================================================================== --- test/CodeGen/PowerPC/ppc64le-localentry-large.ll +++ test/CodeGen/PowerPC/ppc64le-localentry-large.ll @@ -0,0 +1,27 @@ +; RUN: llc -march=ppc64le -code-model=large < %s | FileCheck %s + +target datalayout = "e-m:e-i64:64-n32:64" +target triple = "powerpc64le-unknown-linux-gnu" + +@number64 = global i64 10, align 8 + +; CHECK: .abiversion 2 + +define i64 @use_toc(i64 %a) nounwind { +entry: +; CHECK: .Lfunc_toc[[FN:[0-9]+]]: +; CHECK-NEXT: .quad .TOC.-.Lfunc_gep[[FN]] +; CHECK: use_toc: +; CHECK-NEXT: .L{{.*}}: +; CHECK-NEXT: .Lfunc_gep[[FN]]: +; CHECK-NEXT: ld 2, .Lfunc_toc[[FN]]-.Lfunc_gep[[FN]](12) +; CHECK-NEXT: add 2, 2, 12 +; CHECK-NEXT: .Lfunc_lep[[FN]]: +; CHECK-NEXT: .localentry use_toc, .Lfunc_lep[[FN]]-.Lfunc_gep[[FN]] +; CHECK-NEXT: %entry + %0 = load i64, i64* @number64, align 8 + %cmp = icmp eq i64 %0, %a + %conv1 = zext i1 %cmp to i64 + ret i64 %conv1 +} + Index: test/CodeGen/PowerPC/ppc64le-localentry.ll =================================================================== --- test/CodeGen/PowerPC/ppc64le-localentry.ll +++ test/CodeGen/PowerPC/ppc64le-localentry.ll @@ -17,11 +17,11 @@ entry: ; CHECK-LABEL: @use_toc ; CHECK-NEXT: .L{{.*}}: -; CHECK-NEXT: .Ltmp[[TMP1:[0-9]+]]: -; CHECK-NEXT: addis 2, 12, .TOC.-.Ltmp[[TMP1]]@ha -; CHECK-NEXT: addi 2, 2, .TOC.-.Ltmp[[TMP1]]@l -; CHECK-NEXT: .Ltmp[[TMP2:[0-9]+]]: -; CHECK-NEXT: .localentry use_toc, .Ltmp[[TMP2]]-.Ltmp[[TMP1]] +; CHECK-NEXT: .Lfunc_gep[[FN:[0-9]+]]: +; CHECK-NEXT: addis 2, 12, .TOC.-.Lfunc_gep[[FN]]@ha +; CHECK-NEXT: addi 2, 2, .TOC.-.Lfunc_gep[[FN]]@l +; CHECK-NEXT: .Lfunc_lep[[FN]]: +; CHECK-NEXT: .localentry use_toc, .Lfunc_lep[[FN]]-.Lfunc_gep[[FN]] ; CHECK-NEXT: %entry %0 = load i64, i64* @number64, align 8 %cmp = icmp eq i64 %0, %a @@ -34,11 +34,11 @@ entry: ; CHECK-LABEL: @use_toc_implicit ; CHECK-NEXT: .L{{.*}}: -; CHECK-NEXT: .Ltmp[[TMP1:[0-9]+]]: -; CHECK-NEXT: addis 2, 12, .TOC.-.Ltmp[[TMP1]]@ha -; CHECK-NEXT: addi 2, 2, .TOC.-.Ltmp[[TMP1]]@l -; CHECK-NEXT: .Ltmp[[TMP2:[0-9]+]]: -; CHECK-NEXT: .localentry use_toc_implicit, .Ltmp[[TMP2]]-.Ltmp[[TMP1]] +; CHECK-NEXT: .Lfunc_gep[[FN:[0-9]+]]: +; CHECK-NEXT: addis 2, 12, .TOC.-.Lfunc_gep[[FN]]@ha +; CHECK-NEXT: addi 2, 2, .TOC.-.Lfunc_gep[[FN]]@l +; CHECK-NEXT: .Lfunc_lep[[FN]]: +; CHECK-NEXT: .localentry use_toc_implicit, .Lfunc_lep[[FN]]-.Lfunc_gep[[FN]] ; CHECK-NEXT: %entry call void @callee() ret void