| //===-- PPCMCInstLower.cpp - Convert PPC MachineInstr to an MCInst --------===// | 
 | // | 
 | //                     The LLVM Compiler Infrastructure | 
 | // | 
 | // This file is distributed under the University of Illinois Open Source | 
 | // License. See LICENSE.TXT for details. | 
 | // | 
 | //===----------------------------------------------------------------------===// | 
 | // | 
 | // 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 PPCSubtarget *Subtarget = &(MF->getSubtarget<PPCSubtarget>()); | 
 |   const TargetMachine &TM = Printer.TM; | 
 |   const MCExpr *Expr = MCSymbolRefExpr::create(Symbol, RefKind, Ctx); | 
 |   // -msecure-plt option works only in PIC mode. If secure plt mode | 
 |   // is on add 32768 to symbol. | 
 |   if (Subtarget->isSecurePlt() && TM.isPositionIndependent() && | 
 |       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_RegisterMask: | 
 |     return false; | 
 |   } | 
 | } |