summaryrefslogtreecommitdiff
path: root/lib/Target/PowerPC/PPCAsmPrinter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Target/PowerPC/PPCAsmPrinter.cpp')
-rw-r--r--lib/Target/PowerPC/PPCAsmPrinter.cpp127
1 files changed, 91 insertions, 36 deletions
diff --git a/lib/Target/PowerPC/PPCAsmPrinter.cpp b/lib/Target/PowerPC/PPCAsmPrinter.cpp
index 17451900840a..a9da64cc216f 100644
--- a/lib/Target/PowerPC/PPCAsmPrinter.cpp
+++ b/lib/Target/PowerPC/PPCAsmPrinter.cpp
@@ -510,6 +510,32 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
const Module *M = MF->getFunction().getParent();
PICLevel::Level PL = M->getPICLevel();
+#ifndef NDEBUG
+ // Validate that SPE and FPU are mutually exclusive in codegen
+ if (!MI->isInlineAsm()) {
+ for (const MachineOperand &MO: MI->operands()) {
+ if (MO.isReg()) {
+ unsigned Reg = MO.getReg();
+ if (Subtarget->hasSPE()) {
+ if (PPC::F4RCRegClass.contains(Reg) ||
+ PPC::F8RCRegClass.contains(Reg) ||
+ PPC::QBRCRegClass.contains(Reg) ||
+ PPC::QFRCRegClass.contains(Reg) ||
+ PPC::QSRCRegClass.contains(Reg) ||
+ PPC::VFRCRegClass.contains(Reg) ||
+ PPC::VRRCRegClass.contains(Reg) ||
+ PPC::VSFRCRegClass.contains(Reg) ||
+ PPC::VSSRCRegClass.contains(Reg)
+ )
+ llvm_unreachable("SPE targets cannot have FPRegs!");
+ } else {
+ if (PPC::SPERCRegClass.contains(Reg))
+ llvm_unreachable("SPE register found in FPU-targeted code!");
+ }
+ }
+ }
+ }
+#endif
// Lower multi-instruction pseudo operations.
switch (MI->getOpcode()) {
default: break;
@@ -563,33 +589,63 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
// Transform %rd = UpdateGBR(%rt, %ri)
// Into: lwz %rt, .L0$poff - .L0$pb(%ri)
// add %rd, %rt, %ri
+ // or into (if secure plt mode is on):
+ // addis r30, r30, .LTOC - .L0$pb@ha
+ // addi r30, r30, .LTOC - .L0$pb@l
// Get the offset from the GOT Base Register to the GOT
LowerPPCMachineInstrToMCInst(MI, TmpInst, *this, isDarwin);
- MCSymbol *PICOffset =
- MF->getInfo<PPCFunctionInfo>()->getPICOffsetSymbol();
- TmpInst.setOpcode(PPC::LWZ);
- const MCExpr *Exp =
- MCSymbolRefExpr::create(PICOffset, MCSymbolRefExpr::VK_None, OutContext);
- const MCExpr *PB =
- MCSymbolRefExpr::create(MF->getPICBaseSymbol(),
- MCSymbolRefExpr::VK_None,
- OutContext);
- const MCOperand TR = TmpInst.getOperand(1);
- const MCOperand PICR = TmpInst.getOperand(0);
-
- // Step 1: lwz %rt, .L$poff - .L$pb(%ri)
- TmpInst.getOperand(1) =
- MCOperand::createExpr(MCBinaryExpr::createSub(Exp, PB, OutContext));
- TmpInst.getOperand(0) = TR;
- TmpInst.getOperand(2) = PICR;
- EmitToStreamer(*OutStreamer, TmpInst);
+ if (Subtarget->isSecurePlt() && isPositionIndependent() ) {
+ unsigned PICR = TmpInst.getOperand(0).getReg();
+ MCSymbol *LTOCSymbol = OutContext.getOrCreateSymbol(StringRef(".LTOC"));
+ const MCExpr *PB =
+ MCSymbolRefExpr::create(MF->getPICBaseSymbol(),
+ OutContext);
- TmpInst.setOpcode(PPC::ADD4);
- TmpInst.getOperand(0) = PICR;
- TmpInst.getOperand(1) = TR;
- TmpInst.getOperand(2) = PICR;
- EmitToStreamer(*OutStreamer, TmpInst);
- return;
+ const MCExpr *LTOCDeltaExpr =
+ MCBinaryExpr::createSub(MCSymbolRefExpr::create(LTOCSymbol, OutContext),
+ PB, OutContext);
+
+ const MCExpr *LTOCDeltaHi =
+ PPCMCExpr::createHa(LTOCDeltaExpr, false, OutContext);
+ EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDIS)
+ .addReg(PICR)
+ .addReg(PICR)
+ .addExpr(LTOCDeltaHi));
+
+ const MCExpr *LTOCDeltaLo =
+ PPCMCExpr::createLo(LTOCDeltaExpr, false, OutContext);
+ EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDI)
+ .addReg(PICR)
+ .addReg(PICR)
+ .addExpr(LTOCDeltaLo));
+ return;
+ } else {
+ MCSymbol *PICOffset =
+ MF->getInfo<PPCFunctionInfo>()->getPICOffsetSymbol();
+ TmpInst.setOpcode(PPC::LWZ);
+ const MCExpr *Exp =
+ MCSymbolRefExpr::create(PICOffset, MCSymbolRefExpr::VK_None, OutContext);
+ const MCExpr *PB =
+ MCSymbolRefExpr::create(MF->getPICBaseSymbol(),
+ MCSymbolRefExpr::VK_None,
+ OutContext);
+ const MCOperand TR = TmpInst.getOperand(1);
+ const MCOperand PICR = TmpInst.getOperand(0);
+
+ // Step 1: lwz %rt, .L$poff - .L$pb(%ri)
+ TmpInst.getOperand(1) =
+ MCOperand::createExpr(MCBinaryExpr::createSub(Exp, PB, OutContext));
+ TmpInst.getOperand(0) = TR;
+ TmpInst.getOperand(2) = PICR;
+ EmitToStreamer(*OutStreamer, TmpInst);
+
+ TmpInst.setOpcode(PPC::ADD4);
+ TmpInst.getOperand(0) = PICR;
+ TmpInst.getOperand(1) = TR;
+ TmpInst.getOperand(2) = PICR;
+ EmitToStreamer(*OutStreamer, TmpInst);
+ return;
+ }
}
case PPC::LWZtoc: {
// Transform %r3 = LWZtoc @min1, %r2
@@ -741,11 +797,11 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
else if (MO.isGlobal()) {
const GlobalValue *GV = MO.getGlobal();
MOSymbol = getSymbol(GV);
- DEBUG(
- unsigned char GVFlags = Subtarget->classifyGlobalReference(GV);
- assert((GVFlags & PPCII::MO_NLP_FLAG) &&
- "LDtocL used on symbol that could be accessed directly is "
- "invalid. Must match ADDIStocHA."));
+ LLVM_DEBUG(
+ unsigned char GVFlags = Subtarget->classifyGlobalReference(GV);
+ assert((GVFlags & PPCII::MO_NLP_FLAG) &&
+ "LDtocL used on symbol that could be accessed directly is "
+ "invalid. Must match ADDIStocHA."));
MOSymbol = lookUpOrCreateTOCEntry(MOSymbol);
}
@@ -770,11 +826,9 @@ void PPCAsmPrinter::EmitInstruction(const MachineInstr *MI) {
if (MO.isGlobal()) {
const GlobalValue *GV = MO.getGlobal();
- DEBUG(
- unsigned char GVFlags = Subtarget->classifyGlobalReference(GV);
- assert (
- !(GVFlags & PPCII::MO_NLP_FLAG) &&
- "Interposable definitions must use indirect access."));
+ LLVM_DEBUG(unsigned char GVFlags = Subtarget->classifyGlobalReference(GV);
+ assert(!(GVFlags & PPCII::MO_NLP_FLAG) &&
+ "Interposable definitions must use indirect access."));
MOSymbol = getSymbol(GV);
} else if (MO.isCPI()) {
MOSymbol = GetCPISymbol(MO.getIndex());
@@ -1233,7 +1287,7 @@ void PPCLinuxAsmPrinter::EmitFunctionEntryLabel() {
if (!Subtarget->isPPC64()) {
const PPCFunctionInfo *PPCFI = MF->getInfo<PPCFunctionInfo>();
- if (PPCFI->usesPICBase()) {
+ if (PPCFI->usesPICBase() && !Subtarget->isSecurePlt()) {
MCSymbol *RelocSymbol = PPCFI->getPICOffsetSymbol();
MCSymbol *PICBase = MF->getPICBaseSymbol();
OutStreamer->EmitLabel(RelocSymbol);
@@ -1255,7 +1309,7 @@ void PPCLinuxAsmPrinter::EmitFunctionEntryLabel() {
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
+ // full 8-byte offset to the TOC in memory immediately preceding
// the function global entry point.
if (TM.getCodeModel() == CodeModel::Large
&& !MF->getRegInfo().use_empty(PPC::X2)) {
@@ -1458,6 +1512,7 @@ void PPCDarwinAsmPrinter::EmitStartOfAsmFile(Module &M) {
"ppc750",
"ppc970",
"ppcA2",
+ "ppce500",
"ppce500mc",
"ppce5500",
"power3",