PPCMCInstLower.cpp revision 263508
1359575Sdim//===-- PPCMCInstLower.cpp - Convert PPC MachineInstr to an MCInst --------===//
2359575Sdim//
3359575Sdim//                     The LLVM Compiler Infrastructure
4359575Sdim//
5359575Sdim// This file is distributed under the University of Illinois Open Source
6359575Sdim// License. See LICENSE.TXT for details.
7359575Sdim//
8359575Sdim//===----------------------------------------------------------------------===//
9359575Sdim//
10359575Sdim// This file contains code to lower PPC MachineInstrs to their corresponding
11359575Sdim// MCInst records.
12359575Sdim//
13359575Sdim//===----------------------------------------------------------------------===//
14359575Sdim
15359575Sdim#include "PPC.h"
16359575Sdim#include "MCTargetDesc/PPCMCExpr.h"
17359575Sdim#include "llvm/ADT/SmallString.h"
18359575Sdim#include "llvm/ADT/Twine.h"
19359575Sdim#include "llvm/CodeGen/AsmPrinter.h"
20359575Sdim#include "llvm/CodeGen/MachineFunction.h"
21359575Sdim#include "llvm/CodeGen/MachineModuleInfoImpls.h"
22359575Sdim#include "llvm/IR/GlobalValue.h"
23359575Sdim#include "llvm/MC/MCAsmInfo.h"
24359575Sdim#include "llvm/MC/MCExpr.h"
25359575Sdim#include "llvm/MC/MCInst.h"
26359575Sdim#include "llvm/Target/Mangler.h"
27359575Sdimusing namespace llvm;
28359575Sdim
29359575Sdimstatic MachineModuleInfoMachO &getMachOMMI(AsmPrinter &AP) {
30359575Sdim  return AP.MMI->getObjFileInfo<MachineModuleInfoMachO>();
31359575Sdim}
32359575Sdim
33359575Sdim
34359575Sdimstatic MCSymbol *GetSymbolFromOperand(const MachineOperand &MO, AsmPrinter &AP){
35359575Sdim  MCContext &Ctx = AP.OutContext;
36359575Sdim
37359575Sdim  SmallString<128> Name;
38359575Sdim  if (!MO.isGlobal()) {
39359575Sdim    assert(MO.isSymbol() && "Isn't a symbol reference");
40359575Sdim    Name += AP.MAI->getGlobalPrefix();
41359575Sdim    Name += MO.getSymbolName();
42359575Sdim  } else {
43359575Sdim    const GlobalValue *GV = MO.getGlobal();
44359575Sdim    bool isImplicitlyPrivate = false;
45359575Sdim    if (MO.getTargetFlags() == PPCII::MO_DARWIN_STUB ||
46359575Sdim        (MO.getTargetFlags() & PPCII::MO_NLP_FLAG))
47359575Sdim      isImplicitlyPrivate = true;
48359575Sdim
49359575Sdim    AP.Mang->getNameWithPrefix(Name, GV, isImplicitlyPrivate);
50359575Sdim  }
51359575Sdim
52359575Sdim  // If the target flags on the operand changes the name of the symbol, do that
53359575Sdim  // before we return the symbol.
54359575Sdim  if (MO.getTargetFlags() == PPCII::MO_DARWIN_STUB) {
55359575Sdim    Name += "$stub";
56359575Sdim    const char *PGP = AP.MAI->getPrivateGlobalPrefix();
57359575Sdim    const char *Prefix = "";
58359575Sdim    if (!Name.startswith(PGP)) {
59359575Sdim      // http://llvm.org/bugs/show_bug.cgi?id=15763
60359575Sdim      // all stubs and lazy_ptrs should be local symbols, which need leading 'L'
61359575Sdim      Prefix = PGP;
62359575Sdim    }
63359575Sdim    MCSymbol *Sym = Ctx.GetOrCreateSymbol(Twine(Prefix) + Twine(Name));
64359575Sdim    MachineModuleInfoImpl::StubValueTy &StubSym =
65359575Sdim      getMachOMMI(AP).getFnStubEntry(Sym);
66359575Sdim    if (StubSym.getPointer())
67359575Sdim      return Sym;
68359575Sdim
69359575Sdim    if (MO.isGlobal()) {
70359575Sdim      StubSym =
71359575Sdim      MachineModuleInfoImpl::
72359575Sdim      StubValueTy(AP.getSymbol(MO.getGlobal()),
73359575Sdim                  !MO.getGlobal()->hasInternalLinkage());
74359575Sdim    } else {
75359575Sdim      Name.erase(Name.end()-5, Name.end());
76359575Sdim      StubSym =
77359575Sdim      MachineModuleInfoImpl::
78359575Sdim      StubValueTy(Ctx.GetOrCreateSymbol(Name.str()), false);
79359575Sdim    }
80359575Sdim    return Sym;
81359575Sdim  }
82359575Sdim
83359575Sdim  // If the symbol reference is actually to a non_lazy_ptr, not to the symbol,
84359575Sdim  // then add the suffix.
85359575Sdim  if (MO.getTargetFlags() & PPCII::MO_NLP_FLAG) {
86359575Sdim    Name += "$non_lazy_ptr";
87359575Sdim    MCSymbol *Sym = Ctx.GetOrCreateSymbol(Name.str());
88359575Sdim
89359575Sdim    MachineModuleInfoMachO &MachO = getMachOMMI(AP);
90359575Sdim
91359575Sdim    MachineModuleInfoImpl::StubValueTy &StubSym =
92359575Sdim      (MO.getTargetFlags() & PPCII::MO_NLP_HIDDEN_FLAG) ?
93359575Sdim         MachO.getHiddenGVStubEntry(Sym) : MachO.getGVStubEntry(Sym);
94359575Sdim
95359575Sdim    if (StubSym.getPointer() == 0) {
96359575Sdim      assert(MO.isGlobal() && "Extern symbol not handled yet");
97359575Sdim      StubSym = MachineModuleInfoImpl::
98359575Sdim                   StubValueTy(AP.getSymbol(MO.getGlobal()),
99359575Sdim                               !MO.getGlobal()->hasInternalLinkage());
100359575Sdim    }
101359575Sdim    return Sym;
102359575Sdim  }
103359575Sdim
104359575Sdim  return Ctx.GetOrCreateSymbol(Name.str());
105359575Sdim}
106359575Sdim
107359575Sdimstatic MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol,
108359575Sdim                              AsmPrinter &Printer, bool isDarwin) {
109359575Sdim  MCContext &Ctx = Printer.OutContext;
110359575Sdim  MCSymbolRefExpr::VariantKind RefKind = MCSymbolRefExpr::VK_None;
111359575Sdim
112359575Sdim  unsigned access = MO.getTargetFlags() & PPCII::MO_ACCESS_MASK;
113359575Sdim
114359575Sdim  switch (access) {
115359575Sdim    case PPCII::MO_TPREL_LO:
116359575Sdim      RefKind = MCSymbolRefExpr::VK_PPC_TPREL_LO;
117359575Sdim      break;
118359575Sdim    case PPCII::MO_TPREL_HA:
119359575Sdim      RefKind = MCSymbolRefExpr::VK_PPC_TPREL_HA;
120359575Sdim      break;
121359575Sdim    case PPCII::MO_DTPREL_LO:
122359575Sdim      RefKind = MCSymbolRefExpr::VK_PPC_DTPREL_LO;
123359575Sdim      break;
124359575Sdim    case PPCII::MO_TLSLD_LO:
125359575Sdim      RefKind = MCSymbolRefExpr::VK_PPC_GOT_TLSLD_LO;
126359575Sdim      break;
127359575Sdim    case PPCII::MO_TOC_LO:
128359575Sdim      RefKind = MCSymbolRefExpr::VK_PPC_TOC_LO;
129359575Sdim      break;
130359575Sdim    case PPCII::MO_TLS:
131359575Sdim      RefKind = MCSymbolRefExpr::VK_PPC_TLS;
132359575Sdim      break;
133359575Sdim  }
134359575Sdim
135359575Sdim  const MCExpr *Expr = MCSymbolRefExpr::Create(Symbol, RefKind, Ctx);
136359575Sdim
137359575Sdim  if (!MO.isJTI() && MO.getOffset())
138359575Sdim    Expr = MCBinaryExpr::CreateAdd(Expr,
139359575Sdim                                   MCConstantExpr::Create(MO.getOffset(), Ctx),
140359575Sdim                                   Ctx);
141359575Sdim
142359575Sdim  // Subtract off the PIC base if required.
143359575Sdim  if (MO.getTargetFlags() & PPCII::MO_PIC_FLAG) {
144359575Sdim    const MachineFunction *MF = MO.getParent()->getParent()->getParent();
145359575Sdim
146359575Sdim    const MCExpr *PB = MCSymbolRefExpr::Create(MF->getPICBaseSymbol(), Ctx);
147359575Sdim    Expr = MCBinaryExpr::CreateSub(Expr, PB, Ctx);
148359575Sdim  }
149359575Sdim
150359575Sdim  // Add ha16() / lo16() markers if required.
151359575Sdim  switch (access) {
152359575Sdim    case PPCII::MO_LO:
153359575Sdim      Expr = PPCMCExpr::CreateLo(Expr, isDarwin, Ctx);
154359575Sdim      break;
155359575Sdim    case PPCII::MO_HA:
156359575Sdim      Expr = PPCMCExpr::CreateHa(Expr, isDarwin, Ctx);
157359575Sdim      break;
158359575Sdim  }
159359575Sdim
160359575Sdim  return MCOperand::CreateExpr(Expr);
161359575Sdim}
162359575Sdim
163359575Sdimvoid llvm::LowerPPCMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI,
164359575Sdim                                        AsmPrinter &AP, bool isDarwin) {
165359575Sdim  OutMI.setOpcode(MI->getOpcode());
166359575Sdim
167359575Sdim  for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
168359575Sdim    const MachineOperand &MO = MI->getOperand(i);
169359575Sdim
170359575Sdim    MCOperand MCOp;
171359575Sdim    switch (MO.getType()) {
172359575Sdim    default:
173      MI->dump();
174      llvm_unreachable("unknown operand type");
175    case MachineOperand::MO_Register:
176      assert(!MO.getSubReg() && "Subregs should be eliminated!");
177      MCOp = MCOperand::CreateReg(MO.getReg());
178      break;
179    case MachineOperand::MO_Immediate:
180      MCOp = MCOperand::CreateImm(MO.getImm());
181      break;
182    case MachineOperand::MO_MachineBasicBlock:
183      MCOp = MCOperand::CreateExpr(MCSymbolRefExpr::Create(
184                                      MO.getMBB()->getSymbol(), AP.OutContext));
185      break;
186    case MachineOperand::MO_GlobalAddress:
187    case MachineOperand::MO_ExternalSymbol:
188      MCOp = GetSymbolRef(MO, GetSymbolFromOperand(MO, AP), AP, isDarwin);
189      break;
190    case MachineOperand::MO_JumpTableIndex:
191      MCOp = GetSymbolRef(MO, AP.GetJTISymbol(MO.getIndex()), AP, isDarwin);
192      break;
193    case MachineOperand::MO_ConstantPoolIndex:
194      MCOp = GetSymbolRef(MO, AP.GetCPISymbol(MO.getIndex()), AP, isDarwin);
195      break;
196    case MachineOperand::MO_BlockAddress:
197      MCOp = GetSymbolRef(MO,AP.GetBlockAddressSymbol(MO.getBlockAddress()),AP,
198                          isDarwin);
199      break;
200    case MachineOperand::MO_RegisterMask:
201      continue;
202    }
203
204    OutMI.addOperand(MCOp);
205  }
206}
207