LLVM  3.7.0
SparcAsmPrinter.cpp
Go to the documentation of this file.
1 //===-- SparcAsmPrinter.cpp - Sparc LLVM assembly writer ------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file contains a printer that converts from our internal representation
11 // of machine-dependent LLVM code to GAS-format SPARC assembly language.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #include "Sparc.h"
18 #include "SparcInstrInfo.h"
19 #include "SparcTargetMachine.h"
20 #include "SparcTargetStreamer.h"
21 #include "llvm/ADT/SmallString.h"
27 #include "llvm/IR/Mangler.h"
28 #include "llvm/MC/MCAsmInfo.h"
29 #include "llvm/MC/MCContext.h"
30 #include "llvm/MC/MCInst.h"
31 #include "llvm/MC/MCStreamer.h"
32 #include "llvm/MC/MCSymbol.h"
35 using namespace llvm;
36 
37 #define DEBUG_TYPE "asm-printer"
38 
39 namespace {
40  class SparcAsmPrinter : public AsmPrinter {
41  SparcTargetStreamer &getTargetStreamer() {
42  return static_cast<SparcTargetStreamer &>(
43  *OutStreamer->getTargetStreamer());
44  }
45  public:
46  explicit SparcAsmPrinter(TargetMachine &TM,
47  std::unique_ptr<MCStreamer> Streamer)
48  : AsmPrinter(TM, std::move(Streamer)) {}
49 
50  const char *getPassName() const override {
51  return "Sparc Assembly Printer";
52  }
53 
54  void printOperand(const MachineInstr *MI, int opNum, raw_ostream &OS);
55  void printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &OS,
56  const char *Modifier = nullptr);
57  void printCCOperand(const MachineInstr *MI, int opNum, raw_ostream &OS);
58 
59  void EmitFunctionBodyStart() override;
60  void EmitInstruction(const MachineInstr *MI) override;
61 
62  static const char *getRegisterName(unsigned RegNo) {
64  }
65 
66  bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
67  unsigned AsmVariant, const char *ExtraCode,
68  raw_ostream &O) override;
69  bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
70  unsigned AsmVariant, const char *ExtraCode,
71  raw_ostream &O) override;
72 
73  void LowerGETPCXAndEmitMCInsts(const MachineInstr *MI,
74  const MCSubtargetInfo &STI);
75 
76  };
77 } // end of anonymous namespace
78 
80  MCSymbol *Sym, MCContext &OutContext) {
81  const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::create(Sym,
82  OutContext);
83  const SparcMCExpr *expr = SparcMCExpr::create(Kind, MCSym, OutContext);
84  return MCOperand::createExpr(expr);
85 
86 }
88  MCContext &OutContext) {
89  return createSparcMCOperand(SparcMCExpr::VK_Sparc_None, Label, OutContext);
90 }
91 
93  MCSymbol *GOTLabel, MCSymbol *StartLabel,
94  MCSymbol *CurLabel,
95  MCContext &OutContext)
96 {
97  const MCSymbolRefExpr *GOT = MCSymbolRefExpr::create(GOTLabel, OutContext);
98  const MCSymbolRefExpr *Start = MCSymbolRefExpr::create(StartLabel,
99  OutContext);
100  const MCSymbolRefExpr *Cur = MCSymbolRefExpr::create(CurLabel,
101  OutContext);
102 
103  const MCBinaryExpr *Sub = MCBinaryExpr::createSub(Cur, Start, OutContext);
104  const MCBinaryExpr *Add = MCBinaryExpr::createAdd(GOT, Sub, OutContext);
105  const SparcMCExpr *expr = SparcMCExpr::create(Kind,
106  Add, OutContext);
107  return MCOperand::createExpr(expr);
108 }
109 
110 static void EmitCall(MCStreamer &OutStreamer,
111  MCOperand &Callee,
112  const MCSubtargetInfo &STI)
113 {
115  CallInst.setOpcode(SP::CALL);
116  CallInst.addOperand(Callee);
117  OutStreamer.EmitInstruction(CallInst, STI);
118 }
119 
120 static void EmitSETHI(MCStreamer &OutStreamer,
121  MCOperand &Imm, MCOperand &RD,
122  const MCSubtargetInfo &STI)
123 {
124  MCInst SETHIInst;
125  SETHIInst.setOpcode(SP::SETHIi);
126  SETHIInst.addOperand(RD);
127  SETHIInst.addOperand(Imm);
128  OutStreamer.EmitInstruction(SETHIInst, STI);
129 }
130 
131 static void EmitBinary(MCStreamer &OutStreamer, unsigned Opcode,
132  MCOperand &RS1, MCOperand &Src2, MCOperand &RD,
133  const MCSubtargetInfo &STI)
134 {
135  MCInst Inst;
136  Inst.setOpcode(Opcode);
137  Inst.addOperand(RD);
138  Inst.addOperand(RS1);
139  Inst.addOperand(Src2);
140  OutStreamer.EmitInstruction(Inst, STI);
141 }
142 
143 static void EmitOR(MCStreamer &OutStreamer,
144  MCOperand &RS1, MCOperand &Imm, MCOperand &RD,
145  const MCSubtargetInfo &STI) {
146  EmitBinary(OutStreamer, SP::ORri, RS1, Imm, RD, STI);
147 }
148 
149 static void EmitADD(MCStreamer &OutStreamer,
150  MCOperand &RS1, MCOperand &RS2, MCOperand &RD,
151  const MCSubtargetInfo &STI) {
152  EmitBinary(OutStreamer, SP::ADDrr, RS1, RS2, RD, STI);
153 }
154 
155 static void EmitSHL(MCStreamer &OutStreamer,
156  MCOperand &RS1, MCOperand &Imm, MCOperand &RD,
157  const MCSubtargetInfo &STI) {
158  EmitBinary(OutStreamer, SP::SLLri, RS1, Imm, RD, STI);
159 }
160 
161 
162 static void EmitHiLo(MCStreamer &OutStreamer, MCSymbol *GOTSym,
165  MCOperand &RD,
166  MCContext &OutContext,
167  const MCSubtargetInfo &STI) {
168 
169  MCOperand hi = createSparcMCOperand(HiKind, GOTSym, OutContext);
170  MCOperand lo = createSparcMCOperand(LoKind, GOTSym, OutContext);
171  EmitSETHI(OutStreamer, hi, RD, STI);
172  EmitOR(OutStreamer, RD, lo, RD, STI);
173 }
174 
175 void SparcAsmPrinter::LowerGETPCXAndEmitMCInsts(const MachineInstr *MI,
176  const MCSubtargetInfo &STI)
177 {
178  MCSymbol *GOTLabel =
179  OutContext.getOrCreateSymbol(Twine("_GLOBAL_OFFSET_TABLE_"));
180 
181  const MachineOperand &MO = MI->getOperand(0);
182  assert(MO.getReg() != SP::O7 &&
183  "%o7 is assigned as destination for getpcx!");
184 
185  MCOperand MCRegOP = MCOperand::createReg(MO.getReg());
186 
187 
188  if (TM.getRelocationModel() != Reloc::PIC_) {
189  // Just load the address of GOT to MCRegOP.
190  switch(TM.getCodeModel()) {
191  default:
192  llvm_unreachable("Unsupported absolute code model");
193  case CodeModel::Small:
194  EmitHiLo(*OutStreamer, GOTLabel,
196  MCRegOP, OutContext, STI);
197  break;
198  case CodeModel::Medium: {
199  EmitHiLo(*OutStreamer, GOTLabel,
201  MCRegOP, OutContext, STI);
203  OutContext));
204  EmitSHL(*OutStreamer, MCRegOP, imm, MCRegOP, STI);
206  GOTLabel, OutContext);
207  EmitOR(*OutStreamer, MCRegOP, lo, MCRegOP, STI);
208  break;
209  }
210  case CodeModel::Large: {
211  EmitHiLo(*OutStreamer, GOTLabel,
213  MCRegOP, OutContext, STI);
215  OutContext));
216  EmitSHL(*OutStreamer, MCRegOP, imm, MCRegOP, STI);
217  // Use register %o7 to load the lower 32 bits.
218  MCOperand RegO7 = MCOperand::createReg(SP::O7);
219  EmitHiLo(*OutStreamer, GOTLabel,
221  RegO7, OutContext, STI);
222  EmitADD(*OutStreamer, MCRegOP, RegO7, MCRegOP, STI);
223  }
224  }
225  return;
226  }
227 
228  MCSymbol *StartLabel = OutContext.createTempSymbol();
229  MCSymbol *EndLabel = OutContext.createTempSymbol();
230  MCSymbol *SethiLabel = OutContext.createTempSymbol();
231 
232  MCOperand RegO7 = MCOperand::createReg(SP::O7);
233 
234  // <StartLabel>:
235  // call <EndLabel>
236  // <SethiLabel>:
237  // sethi %hi(_GLOBAL_OFFSET_TABLE_+(<SethiLabel>-<StartLabel>)), <MO>
238  // <EndLabel>:
239  // or <MO>, %lo(_GLOBAL_OFFSET_TABLE_+(<EndLabel>-<StartLabel>))), <MO>
240  // add <MO>, %o7, <MO>
241 
242  OutStreamer->EmitLabel(StartLabel);
243  MCOperand Callee = createPCXCallOP(EndLabel, OutContext);
244  EmitCall(*OutStreamer, Callee, STI);
245  OutStreamer->EmitLabel(SethiLabel);
247  GOTLabel, StartLabel, SethiLabel,
248  OutContext);
249  EmitSETHI(*OutStreamer, hiImm, MCRegOP, STI);
250  OutStreamer->EmitLabel(EndLabel);
252  GOTLabel, StartLabel, EndLabel,
253  OutContext);
254  EmitOR(*OutStreamer, MCRegOP, loImm, MCRegOP, STI);
255  EmitADD(*OutStreamer, MCRegOP, RegO7, MCRegOP, STI);
256 }
257 
258 void SparcAsmPrinter::EmitInstruction(const MachineInstr *MI)
259 {
260 
261  switch (MI->getOpcode()) {
262  default: break;
264  // FIXME: Debug Value.
265  return;
266  case SP::GETPCX:
267  LowerGETPCXAndEmitMCInsts(MI, getSubtargetInfo());
268  return;
269  }
272  do {
273  MCInst TmpInst;
274  LowerSparcMachineInstrToMCInst(I, TmpInst, *this);
275  EmitToStreamer(*OutStreamer, TmpInst);
276  } while ((++I != E) && I->isInsideBundle()); // Delay slot check.
277 }
278 
279 void SparcAsmPrinter::EmitFunctionBodyStart() {
280  if (!MF->getSubtarget<SparcSubtarget>().is64Bit())
281  return;
282 
283  const MachineRegisterInfo &MRI = MF->getRegInfo();
284  const unsigned globalRegs[] = { SP::G2, SP::G3, SP::G6, SP::G7, 0 };
285  for (unsigned i = 0; globalRegs[i] != 0; ++i) {
286  unsigned reg = globalRegs[i];
287  if (MRI.use_empty(reg))
288  continue;
289 
290  if (reg == SP::G6 || reg == SP::G7)
291  getTargetStreamer().emitSparcRegisterIgnore(reg);
292  else
293  getTargetStreamer().emitSparcRegisterScratch(reg);
294  }
295 }
296 
297 void SparcAsmPrinter::printOperand(const MachineInstr *MI, int opNum,
298  raw_ostream &O) {
299  const DataLayout *DL = TM.getDataLayout();
300  const MachineOperand &MO = MI->getOperand (opNum);
302 
303 #ifndef NDEBUG
304  // Verify the target flags.
305  if (MO.isGlobal() || MO.isSymbol() || MO.isCPI()) {
306  if (MI->getOpcode() == SP::CALL)
307  assert(TF == SparcMCExpr::VK_Sparc_None &&
308  "Cannot handle target flags on call address");
309  else if (MI->getOpcode() == SP::SETHIi || MI->getOpcode() == SP::SETHIXi)
310  assert((TF == SparcMCExpr::VK_Sparc_HI
312  || TF == SparcMCExpr::VK_Sparc_HH
318  "Invalid target flags for address operand on sethi");
319  else if (MI->getOpcode() == SP::TLS_CALL)
320  assert((TF == SparcMCExpr::VK_Sparc_None
323  "Cannot handle target flags on tls call address");
324  else if (MI->getOpcode() == SP::TLS_ADDrr)
329  "Cannot handle target flags on add for TLS");
330  else if (MI->getOpcode() == SP::TLS_LDrr)
331  assert(TF == SparcMCExpr::VK_Sparc_TLS_IE_LD &&
332  "Cannot handle target flags on ld for TLS");
333  else if (MI->getOpcode() == SP::TLS_LDXrr)
334  assert(TF == SparcMCExpr::VK_Sparc_TLS_IE_LDX &&
335  "Cannot handle target flags on ldx for TLS");
336  else if (MI->getOpcode() == SP::XORri || MI->getOpcode() == SP::XORXri)
339  "Cannot handle target flags on xor for TLS");
340  else
341  assert((TF == SparcMCExpr::VK_Sparc_LO
344  || TF == SparcMCExpr::VK_Sparc_HM
348  "Invalid target flags for small address operand");
349  }
350 #endif
351 
352 
353  bool CloseParen = SparcMCExpr::printVariantKind(O, TF);
354 
355  switch (MO.getType()) {
357  O << "%" << StringRef(getRegisterName(MO.getReg())).lower();
358  break;
359 
361  O << (int)MO.getImm();
362  break;
364  MO.getMBB()->getSymbol()->print(O, MAI);
365  return;
367  getSymbol(MO.getGlobal())->print(O, MAI);
368  break;
370  O << GetBlockAddressSymbol(MO.getBlockAddress())->getName();
371  break;
373  O << MO.getSymbolName();
374  break;
376  O << DL->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << "_"
377  << MO.getIndex();
378  break;
379  default:
380  llvm_unreachable("<unknown operand type>");
381  }
382  if (CloseParen) O << ")";
383 }
384 
385 void SparcAsmPrinter::printMemOperand(const MachineInstr *MI, int opNum,
386  raw_ostream &O, const char *Modifier) {
387  printOperand(MI, opNum, O);
388 
389  // If this is an ADD operand, emit it like normal operands.
390  if (Modifier && !strcmp(Modifier, "arith")) {
391  O << ", ";
392  printOperand(MI, opNum+1, O);
393  return;
394  }
395 
396  if (MI->getOperand(opNum+1).isReg() &&
397  MI->getOperand(opNum+1).getReg() == SP::G0)
398  return; // don't print "+%g0"
399  if (MI->getOperand(opNum+1).isImm() &&
400  MI->getOperand(opNum+1).getImm() == 0)
401  return; // don't print "+0"
402 
403  O << "+";
404  printOperand(MI, opNum+1, O);
405 }
406 
407 /// PrintAsmOperand - Print out an operand for an inline asm expression.
408 ///
409 bool SparcAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
410  unsigned AsmVariant,
411  const char *ExtraCode,
412  raw_ostream &O) {
413  if (ExtraCode && ExtraCode[0]) {
414  if (ExtraCode[1] != 0) return true; // Unknown modifier.
415 
416  switch (ExtraCode[0]) {
417  default:
418  // See if this is a generic print operand
419  return AsmPrinter::PrintAsmOperand(MI, OpNo, AsmVariant, ExtraCode, O);
420  case 'r':
421  break;
422  }
423  }
424 
425  printOperand(MI, OpNo, O);
426 
427  return false;
428 }
429 
430 bool SparcAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
431  unsigned OpNo, unsigned AsmVariant,
432  const char *ExtraCode,
433  raw_ostream &O) {
434  if (ExtraCode && ExtraCode[0])
435  return true; // Unknown modifier
436 
437  O << '[';
438  printMemOperand(MI, OpNo, O);
439  O << ']';
440 
441  return false;
442 }
443 
444 // Force static initialization.
445 extern "C" void LLVMInitializeSparcAsmPrinter() {
449 }
A parsed version of the target data layout string in and methods for querying it. ...
Definition: DataLayout.h:104
const GlobalValue * getGlobal() const
static MCOperand createPCXRelExprOp(SparcMCExpr::VariantKind Kind, MCSymbol *GOTLabel, MCSymbol *StartLabel, MCSymbol *CurLabel, MCContext &OutContext)
instr_iterator instr_end()
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx)
Definition: MCExpr.h:315
void print(raw_ostream &OS, const MCAsmInfo *MAI) const
print - Print the value to the stream OS.
Definition: MCSymbol.cpp:51
MachineBasicBlock * getMBB() const
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:39
static MCOperand createExpr(const MCExpr *Val)
Definition: MCInst.h:129
static bool printVariantKind(raw_ostream &OS, VariantKind Kind)
Definition: SparcMCExpr.cpp:44
CallInst - This class represents a function call, abstracting a target machine's calling convention...
const char * getPrivateGlobalPrefix() const
Definition: DataLayout.h:281
MachineBasicBlock reference.
const char * getSymbolName() const
virtual void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI)
Emit the given Instruction into the current section.
Definition: MCStreamer.cpp:639
Target TheSparcTarget
static MCOperand createReg(unsigned Reg)
Definition: MCInst.h:111
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:79
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:98
static const char * getRegisterName(unsigned RegNo)
bool isReg() const
isReg - Tests if this is a MO_Register operand.
static void EmitHiLo(MCStreamer &OutStreamer, MCSymbol *GOTSym, SparcMCExpr::VariantKind HiKind, SparcMCExpr::VariantKind LoKind, MCOperand &RD, MCContext &OutContext, const MCSubtargetInfo &STI)
Name of external global symbol.
static StringRef getName(Value *V)
Represent a reference to a symbol from inside an expression.
Definition: MCExpr.h:159
static void printOperand(raw_ostream &OS, uint8_t Opcode, unsigned OperandIdx, uint64_t Operand, uint64_t CodeAlignmentFactor, int64_t DataAlignmentFactor)
Print Opcode's operand number OperandIdx which has value Operand.
bool isCPI() const
isCPI - Tests if this is a MO_ConstantPoolIndex operand.
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
Context object for machine code objects.
Definition: MCContext.h:48
static std::string getRegisterName(const TargetRegisterInfo *TRI, unsigned Reg)
Definition: MIParser.cpp:236
static const MCBinaryExpr * createSub(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition: MCExpr.h:514
int64_t getImm() const
static const MCBinaryExpr * createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition: MCExpr.h:446
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:150
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:267
const MachineBasicBlock * getParent() const
Definition: MachineInstr.h:120
DBG_VALUE - a mapping of the llvm.dbg.value intrinsic.
Definition: TargetOpcodes.h:69
static void EmitSHL(MCStreamer &OutStreamer, MCOperand &RS1, MCOperand &Imm, MCOperand &RD, const MCSubtargetInfo &STI)
Address of a global value.
unsigned getTargetFlags() const
Streaming machine code generation interface.
Definition: MCStreamer.h:157
static void EmitBinary(MCStreamer &OutStreamer, unsigned Opcode, MCOperand &RS1, MCOperand &Src2, MCOperand &RD, const MCSubtargetInfo &STI)
static void EmitCall(MCStreamer &OutStreamer, MCOperand &Callee, const MCSubtargetInfo &STI)
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:273
virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, unsigned AsmVariant, const char *ExtraCode, raw_ostream &OS)
Print the specified operand of MI, an INLINEASM instruction, using the specified assembler variant...
This class is intended to be used as a driving class for all asm writers.
Definition: AsmPrinter.h:66
bool isSymbol() const
isSymbol - Tests if this is a MO_ExternalSymbol operand.
static void EmitOR(MCStreamer &OutStreamer, MCOperand &RS1, MCOperand &Imm, MCOperand &RD, const MCSubtargetInfo &STI)
Address of a basic block.
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang","erlang-compatible garbage collector")
static void EmitADD(MCStreamer &OutStreamer, MCOperand &RS1, MCOperand &RS2, MCOperand &RD, const MCSubtargetInfo &STI)
Binary assembler expressions.
Definition: MCExpr.h:405
MCSymbol * getSymbol() const
getSymbol - Return the MCSymbol for this basic block.
void LLVMInitializeSparcAsmPrinter()
void setOpcode(unsigned Op)
Definition: MCInst.h:158
MachineOperand class - Representation of each machine instruction operand.
static MCOperand createPCXCallOP(MCSymbol *Label, MCContext &OutContext)
Target TheSparcV9Target
MachineRegisterInfo - Keep track of information for virtual and physical registers, including vreg register classes, use/def chains for registers, etc.
Representation of each machine instruction.
Definition: MachineInstr.h:51
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
void LowerSparcMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI, AsmPrinter &AP)
#define I(x, y, z)
Definition: MD5.cpp:54
MCSubtargetInfo - Generic base class for all target subtargets.
static const SparcMCExpr * create(VariantKind Kind, const MCExpr *Expr, MCContext &Ctx)
Definition: SparcMCExpr.cpp:28
unsigned getReg() const
getReg - Returns the register number.
const ARM::ArchExtKind Kind
Target TheSparcelTarget
RegisterAsmPrinter - Helper template for registering a target specific assembly printer, for use in the target machine initialization function.
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:38
static void EmitSETHI(MCStreamer &OutStreamer, MCOperand &Imm, MCOperand &RD, const MCSubtargetInfo &STI)
bool is64Bit() const
Primary interface to the complete machine description for the target machine.
void addOperand(const MCOperand &Op)
Definition: MCInst.h:168
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:40
const BlockAddress * getBlockAddress() const
Address of indexed Constant in Constant Pool.
static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml","ocaml 3.10-compatible collector")
Instances of this class represent operands of the MCInst class.
Definition: MCInst.h:33
std::string lower() const
Definition: StringRef.cpp:117
static const MCConstantExpr * create(int64_t Value, MCContext &Ctx)
Definition: MCExpr.cpp:150
static MCOperand createSparcMCOperand(SparcMCExpr::VariantKind Kind, MCSymbol *Sym, MCContext &OutContext)
bool use_empty(unsigned RegNo) const
use_empty - Return true if there are no instructions using the specified register.