1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-19 11:02:59 +02:00
llvm-mirror/lib/Target/PowerPC/PPCMCInstLower.cpp
Sean Fertile 2fb8946c5f [PowerPC][AIX]Add lowering of MCSymbol MachineOperand.
Adds machine operand lowering for MCSymbolSDNodes to the PowerPC
backend. This is needed to produce call instructions in assembly for AIX
because the callee operand is a MCSymbolSDNode. The test is XFAIL'ed for
asserts due to a (valid) assertion in PEI that the AIX ABI isn't supported yet.

Differential Revision: https://reviews.llvm.org/D63738

llvm-svn: 367133
2019-07-26 17:25:27 +00:00

203 lines
6.9 KiB
C++

//===-- PPCMCInstLower.cpp - Convert PPC MachineInstr to an MCInst --------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file contains code to lower PPC MachineInstrs to their corresponding
// MCInst records.
//
//===----------------------------------------------------------------------===//
#include "MCTargetDesc/PPCMCExpr.h"
#include "PPC.h"
#include "PPCSubtarget.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/Twine.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineModuleInfoImpls.h"
#include "llvm/CodeGen/TargetLowering.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/Mangler.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
using namespace llvm;
static MachineModuleInfoMachO &getMachOMMI(AsmPrinter &AP) {
return AP.MMI->getObjFileInfo<MachineModuleInfoMachO>();
}
static MCSymbol *GetSymbolFromOperand(const MachineOperand &MO,
AsmPrinter &AP) {
const TargetMachine &TM = AP.TM;
Mangler &Mang = TM.getObjFileLowering()->getMangler();
const DataLayout &DL = AP.getDataLayout();
MCContext &Ctx = AP.OutContext;
SmallString<128> Name;
StringRef Suffix;
if (MO.getTargetFlags() & PPCII::MO_NLP_FLAG)
Suffix = "$non_lazy_ptr";
if (!Suffix.empty())
Name += DL.getPrivateGlobalPrefix();
if (!MO.isGlobal()) {
assert(MO.isSymbol() && "Isn't a symbol reference");
Mangler::getNameWithPrefix(Name, MO.getSymbolName(), DL);
} else {
const GlobalValue *GV = MO.getGlobal();
TM.getNameWithPrefix(Name, GV, Mang);
}
Name += Suffix;
MCSymbol *Sym = Ctx.getOrCreateSymbol(Name);
// If the symbol reference is actually to a non_lazy_ptr, not to the symbol,
// then add the suffix.
if (MO.getTargetFlags() & PPCII::MO_NLP_FLAG) {
MachineModuleInfoMachO &MachO = getMachOMMI(AP);
MachineModuleInfoImpl::StubValueTy &StubSym = MachO.getGVStubEntry(Sym);
if (!StubSym.getPointer()) {
assert(MO.isGlobal() && "Extern symbol not handled yet");
StubSym = MachineModuleInfoImpl::
StubValueTy(AP.getSymbol(MO.getGlobal()),
!MO.getGlobal()->hasInternalLinkage());
}
return Sym;
}
return Sym;
}
static MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol,
AsmPrinter &Printer, bool isDarwin) {
MCContext &Ctx = Printer.OutContext;
MCSymbolRefExpr::VariantKind RefKind = MCSymbolRefExpr::VK_None;
unsigned access = MO.getTargetFlags() & PPCII::MO_ACCESS_MASK;
switch (access) {
case PPCII::MO_TPREL_LO:
RefKind = MCSymbolRefExpr::VK_PPC_TPREL_LO;
break;
case PPCII::MO_TPREL_HA:
RefKind = MCSymbolRefExpr::VK_PPC_TPREL_HA;
break;
case PPCII::MO_DTPREL_LO:
RefKind = MCSymbolRefExpr::VK_PPC_DTPREL_LO;
break;
case PPCII::MO_TLSLD_LO:
RefKind = MCSymbolRefExpr::VK_PPC_GOT_TLSLD_LO;
break;
case PPCII::MO_TOC_LO:
RefKind = MCSymbolRefExpr::VK_PPC_TOC_LO;
break;
case PPCII::MO_TLS:
RefKind = MCSymbolRefExpr::VK_PPC_TLS;
break;
}
if (MO.getTargetFlags() == PPCII::MO_PLT)
RefKind = MCSymbolRefExpr::VK_PLT;
const MachineFunction *MF = MO.getParent()->getParent()->getParent();
const Module *M = MF->getFunction().getParent();
const PPCSubtarget *Subtarget = &(MF->getSubtarget<PPCSubtarget>());
const TargetMachine &TM = Printer.TM;
const MCExpr *Expr = MCSymbolRefExpr::create(Symbol, RefKind, Ctx);
// If -msecure-plt -fPIC, add 32768 to symbol.
if (Subtarget->isSecurePlt() && TM.isPositionIndependent() &&
M->getPICLevel() == PICLevel::BigPIC &&
MO.getTargetFlags() == PPCII::MO_PLT)
Expr =
MCBinaryExpr::createAdd(Expr, MCConstantExpr::create(32768, Ctx), Ctx);
if (!MO.isJTI() && MO.getOffset())
Expr = MCBinaryExpr::createAdd(Expr,
MCConstantExpr::create(MO.getOffset(), Ctx),
Ctx);
// Subtract off the PIC base if required.
if (MO.getTargetFlags() & PPCII::MO_PIC_FLAG) {
const MachineFunction *MF = MO.getParent()->getParent()->getParent();
const MCExpr *PB = MCSymbolRefExpr::create(MF->getPICBaseSymbol(), Ctx);
Expr = MCBinaryExpr::createSub(Expr, PB, Ctx);
}
// Add ha16() / lo16() markers if required.
switch (access) {
case PPCII::MO_LO:
Expr = PPCMCExpr::createLo(Expr, isDarwin, Ctx);
break;
case PPCII::MO_HA:
Expr = PPCMCExpr::createHa(Expr, isDarwin, Ctx);
break;
}
return MCOperand::createExpr(Expr);
}
void llvm::LowerPPCMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI,
AsmPrinter &AP, bool isDarwin) {
OutMI.setOpcode(MI->getOpcode());
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
MCOperand MCOp;
if (LowerPPCMachineOperandToMCOperand(MI->getOperand(i), MCOp, AP,
isDarwin))
OutMI.addOperand(MCOp);
}
}
bool llvm::LowerPPCMachineOperandToMCOperand(const MachineOperand &MO,
MCOperand &OutMO, AsmPrinter &AP,
bool isDarwin) {
switch (MO.getType()) {
default:
llvm_unreachable("unknown operand type");
case MachineOperand::MO_Register:
assert(!MO.getSubReg() && "Subregs should be eliminated!");
assert(MO.getReg() > PPC::NoRegister &&
MO.getReg() < PPC::NUM_TARGET_REGS &&
"Invalid register for this target!");
OutMO = MCOperand::createReg(MO.getReg());
return true;
case MachineOperand::MO_Immediate:
OutMO = MCOperand::createImm(MO.getImm());
return true;
case MachineOperand::MO_MachineBasicBlock:
OutMO = MCOperand::createExpr(
MCSymbolRefExpr::create(MO.getMBB()->getSymbol(), AP.OutContext));
return true;
case MachineOperand::MO_GlobalAddress:
case MachineOperand::MO_ExternalSymbol:
OutMO = GetSymbolRef(MO, GetSymbolFromOperand(MO, AP), AP, isDarwin);
return true;
case MachineOperand::MO_JumpTableIndex:
OutMO = GetSymbolRef(MO, AP.GetJTISymbol(MO.getIndex()), AP, isDarwin);
return true;
case MachineOperand::MO_ConstantPoolIndex:
OutMO = GetSymbolRef(MO, AP.GetCPISymbol(MO.getIndex()), AP, isDarwin);
return true;
case MachineOperand::MO_BlockAddress:
OutMO = GetSymbolRef(MO, AP.GetBlockAddressSymbol(MO.getBlockAddress()), AP,
isDarwin);
return true;
case MachineOperand::MO_MCSymbol:
OutMO = GetSymbolRef(MO, MO.getMCSymbol(), AP, isDarwin);
return true;
case MachineOperand::MO_RegisterMask:
return false;
}
}