1218885Sdim//===-- PPCMCInstLower.cpp - Convert PPC MachineInstr to an MCInst --------===//
2218885Sdim//
3218885Sdim//                     The LLVM Compiler Infrastructure
4218885Sdim//
5218885Sdim// This file is distributed under the University of Illinois Open Source
6218885Sdim// License. See LICENSE.TXT for details.
7218885Sdim//
8218885Sdim//===----------------------------------------------------------------------===//
9218885Sdim//
10218885Sdim// This file contains code to lower PPC MachineInstrs to their corresponding
11218885Sdim// MCInst records.
12218885Sdim//
13218885Sdim//===----------------------------------------------------------------------===//
14218885Sdim
15218885Sdim#include "PPC.h"
16263508Sdim#include "MCTargetDesc/PPCMCExpr.h"
17249423Sdim#include "llvm/ADT/SmallString.h"
18251662Sdim#include "llvm/ADT/Twine.h"
19218885Sdim#include "llvm/CodeGen/AsmPrinter.h"
20218885Sdim#include "llvm/CodeGen/MachineFunction.h"
21218885Sdim#include "llvm/CodeGen/MachineModuleInfoImpls.h"
22249423Sdim#include "llvm/IR/GlobalValue.h"
23218885Sdim#include "llvm/MC/MCAsmInfo.h"
24218885Sdim#include "llvm/MC/MCExpr.h"
25218885Sdim#include "llvm/MC/MCInst.h"
26218885Sdim#include "llvm/Target/Mangler.h"
27218885Sdimusing namespace llvm;
28218885Sdim
29218885Sdimstatic MachineModuleInfoMachO &getMachOMMI(AsmPrinter &AP) {
30218885Sdim  return AP.MMI->getObjFileInfo<MachineModuleInfoMachO>();
31218885Sdim}
32218885Sdim
33218885Sdim
34218885Sdimstatic MCSymbol *GetSymbolFromOperand(const MachineOperand &MO, AsmPrinter &AP){
35218885Sdim  MCContext &Ctx = AP.OutContext;
36218885Sdim
37218885Sdim  SmallString<128> Name;
38218885Sdim  if (!MO.isGlobal()) {
39218885Sdim    assert(MO.isSymbol() && "Isn't a symbol reference");
40218885Sdim    Name += AP.MAI->getGlobalPrefix();
41218885Sdim    Name += MO.getSymbolName();
42218885Sdim  } else {
43218885Sdim    const GlobalValue *GV = MO.getGlobal();
44218885Sdim    bool isImplicitlyPrivate = false;
45218885Sdim    if (MO.getTargetFlags() == PPCII::MO_DARWIN_STUB ||
46218885Sdim        (MO.getTargetFlags() & PPCII::MO_NLP_FLAG))
47218885Sdim      isImplicitlyPrivate = true;
48218885Sdim
49218885Sdim    AP.Mang->getNameWithPrefix(Name, GV, isImplicitlyPrivate);
50218885Sdim  }
51218885Sdim
52218885Sdim  // If the target flags on the operand changes the name of the symbol, do that
53218885Sdim  // before we return the symbol.
54218885Sdim  if (MO.getTargetFlags() == PPCII::MO_DARWIN_STUB) {
55218885Sdim    Name += "$stub";
56251662Sdim    const char *PGP = AP.MAI->getPrivateGlobalPrefix();
57251662Sdim    const char *Prefix = "";
58251662Sdim    if (!Name.startswith(PGP)) {
59251662Sdim      // http://llvm.org/bugs/show_bug.cgi?id=15763
60251662Sdim      // all stubs and lazy_ptrs should be local symbols, which need leading 'L'
61251662Sdim      Prefix = PGP;
62251662Sdim    }
63251662Sdim    MCSymbol *Sym = Ctx.GetOrCreateSymbol(Twine(Prefix) + Twine(Name));
64218885Sdim    MachineModuleInfoImpl::StubValueTy &StubSym =
65218885Sdim      getMachOMMI(AP).getFnStubEntry(Sym);
66218885Sdim    if (StubSym.getPointer())
67218885Sdim      return Sym;
68218885Sdim
69218885Sdim    if (MO.isGlobal()) {
70218885Sdim      StubSym =
71218885Sdim      MachineModuleInfoImpl::
72263508Sdim      StubValueTy(AP.getSymbol(MO.getGlobal()),
73218885Sdim                  !MO.getGlobal()->hasInternalLinkage());
74218885Sdim    } else {
75218885Sdim      Name.erase(Name.end()-5, Name.end());
76218885Sdim      StubSym =
77218885Sdim      MachineModuleInfoImpl::
78218885Sdim      StubValueTy(Ctx.GetOrCreateSymbol(Name.str()), false);
79218885Sdim    }
80218885Sdim    return Sym;
81218885Sdim  }
82218885Sdim
83218885Sdim  // If the symbol reference is actually to a non_lazy_ptr, not to the symbol,
84218885Sdim  // then add the suffix.
85218885Sdim  if (MO.getTargetFlags() & PPCII::MO_NLP_FLAG) {
86218885Sdim    Name += "$non_lazy_ptr";
87218885Sdim    MCSymbol *Sym = Ctx.GetOrCreateSymbol(Name.str());
88218885Sdim
89218885Sdim    MachineModuleInfoMachO &MachO = getMachOMMI(AP);
90218885Sdim
91218885Sdim    MachineModuleInfoImpl::StubValueTy &StubSym =
92218885Sdim      (MO.getTargetFlags() & PPCII::MO_NLP_HIDDEN_FLAG) ?
93218885Sdim         MachO.getHiddenGVStubEntry(Sym) : MachO.getGVStubEntry(Sym);
94218885Sdim
95218885Sdim    if (StubSym.getPointer() == 0) {
96218885Sdim      assert(MO.isGlobal() && "Extern symbol not handled yet");
97218885Sdim      StubSym = MachineModuleInfoImpl::
98263508Sdim                   StubValueTy(AP.getSymbol(MO.getGlobal()),
99218885Sdim                               !MO.getGlobal()->hasInternalLinkage());
100218885Sdim    }
101218885Sdim    return Sym;
102218885Sdim  }
103218885Sdim
104218885Sdim  return Ctx.GetOrCreateSymbol(Name.str());
105218885Sdim}
106218885Sdim
107218885Sdimstatic MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol,
108223017Sdim                              AsmPrinter &Printer, bool isDarwin) {
109218885Sdim  MCContext &Ctx = Printer.OutContext;
110218885Sdim  MCSymbolRefExpr::VariantKind RefKind = MCSymbolRefExpr::VK_None;
111218885Sdim
112239462Sdim  unsigned access = MO.getTargetFlags() & PPCII::MO_ACCESS_MASK;
113218885Sdim
114239462Sdim  switch (access) {
115263508Sdim    case PPCII::MO_TPREL_LO:
116263508Sdim      RefKind = MCSymbolRefExpr::VK_PPC_TPREL_LO;
117263508Sdim      break;
118263508Sdim    case PPCII::MO_TPREL_HA:
119263508Sdim      RefKind = MCSymbolRefExpr::VK_PPC_TPREL_HA;
120263508Sdim      break;
121263508Sdim    case PPCII::MO_DTPREL_LO:
122263508Sdim      RefKind = MCSymbolRefExpr::VK_PPC_DTPREL_LO;
123263508Sdim      break;
124263508Sdim    case PPCII::MO_TLSLD_LO:
125263508Sdim      RefKind = MCSymbolRefExpr::VK_PPC_GOT_TLSLD_LO;
126263508Sdim      break;
127263508Sdim    case PPCII::MO_TOC_LO:
128263508Sdim      RefKind = MCSymbolRefExpr::VK_PPC_TOC_LO;
129263508Sdim      break;
130263508Sdim    case PPCII::MO_TLS:
131263508Sdim      RefKind = MCSymbolRefExpr::VK_PPC_TLS;
132263508Sdim      break;
133263508Sdim  }
134239462Sdim
135218885Sdim  const MCExpr *Expr = MCSymbolRefExpr::Create(Symbol, RefKind, Ctx);
136218885Sdim
137218885Sdim  if (!MO.isJTI() && MO.getOffset())
138218885Sdim    Expr = MCBinaryExpr::CreateAdd(Expr,
139218885Sdim                                   MCConstantExpr::Create(MO.getOffset(), Ctx),
140218885Sdim                                   Ctx);
141218885Sdim
142218885Sdim  // Subtract off the PIC base if required.
143218885Sdim  if (MO.getTargetFlags() & PPCII::MO_PIC_FLAG) {
144218885Sdim    const MachineFunction *MF = MO.getParent()->getParent()->getParent();
145218885Sdim
146218885Sdim    const MCExpr *PB = MCSymbolRefExpr::Create(MF->getPICBaseSymbol(), Ctx);
147218885Sdim    Expr = MCBinaryExpr::CreateSub(Expr, PB, Ctx);
148218885Sdim  }
149263508Sdim
150263508Sdim  // Add ha16() / lo16() markers if required.
151263508Sdim  switch (access) {
152263508Sdim    case PPCII::MO_LO:
153263508Sdim      Expr = PPCMCExpr::CreateLo(Expr, isDarwin, Ctx);
154263508Sdim      break;
155263508Sdim    case PPCII::MO_HA:
156263508Sdim      Expr = PPCMCExpr::CreateHa(Expr, isDarwin, Ctx);
157263508Sdim      break;
158263508Sdim  }
159263508Sdim
160218885Sdim  return MCOperand::CreateExpr(Expr);
161218885Sdim}
162218885Sdim
163218885Sdimvoid llvm::LowerPPCMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI,
164223017Sdim                                        AsmPrinter &AP, bool isDarwin) {
165218885Sdim  OutMI.setOpcode(MI->getOpcode());
166218885Sdim
167218885Sdim  for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
168218885Sdim    const MachineOperand &MO = MI->getOperand(i);
169218885Sdim
170218885Sdim    MCOperand MCOp;
171218885Sdim    switch (MO.getType()) {
172218885Sdim    default:
173218885Sdim      MI->dump();
174234353Sdim      llvm_unreachable("unknown operand type");
175218885Sdim    case MachineOperand::MO_Register:
176218885Sdim      assert(!MO.getSubReg() && "Subregs should be eliminated!");
177218885Sdim      MCOp = MCOperand::CreateReg(MO.getReg());
178218885Sdim      break;
179218885Sdim    case MachineOperand::MO_Immediate:
180218885Sdim      MCOp = MCOperand::CreateImm(MO.getImm());
181218885Sdim      break;
182218885Sdim    case MachineOperand::MO_MachineBasicBlock:
183218885Sdim      MCOp = MCOperand::CreateExpr(MCSymbolRefExpr::Create(
184218885Sdim                                      MO.getMBB()->getSymbol(), AP.OutContext));
185218885Sdim      break;
186218885Sdim    case MachineOperand::MO_GlobalAddress:
187218885Sdim    case MachineOperand::MO_ExternalSymbol:
188223017Sdim      MCOp = GetSymbolRef(MO, GetSymbolFromOperand(MO, AP), AP, isDarwin);
189218885Sdim      break;
190218885Sdim    case MachineOperand::MO_JumpTableIndex:
191223017Sdim      MCOp = GetSymbolRef(MO, AP.GetJTISymbol(MO.getIndex()), AP, isDarwin);
192218885Sdim      break;
193218885Sdim    case MachineOperand::MO_ConstantPoolIndex:
194223017Sdim      MCOp = GetSymbolRef(MO, AP.GetCPISymbol(MO.getIndex()), AP, isDarwin);
195218885Sdim      break;
196218885Sdim    case MachineOperand::MO_BlockAddress:
197223017Sdim      MCOp = GetSymbolRef(MO,AP.GetBlockAddressSymbol(MO.getBlockAddress()),AP,
198223017Sdim                          isDarwin);
199218885Sdim      break;
200234353Sdim    case MachineOperand::MO_RegisterMask:
201234353Sdim      continue;
202218885Sdim    }
203218885Sdim
204218885Sdim    OutMI.addOperand(MCOp);
205218885Sdim  }
206218885Sdim}
207