LLVM  4.0.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"
26 #include "llvm/IR/Mangler.h"
27 #include "llvm/MC/MCAsmInfo.h"
28 #include "llvm/MC/MCContext.h"
29 #include "llvm/MC/MCInst.h"
30 #include "llvm/MC/MCStreamer.h"
31 #include "llvm/MC/MCSymbol.h"
34 using namespace llvm;
35 
36 #define DEBUG_TYPE "asm-printer"
37 
38 namespace {
39  class SparcAsmPrinter : public AsmPrinter {
40  SparcTargetStreamer &getTargetStreamer() {
41  return static_cast<SparcTargetStreamer &>(
42  *OutStreamer->getTargetStreamer());
43  }
44  public:
45  explicit SparcAsmPrinter(TargetMachine &TM,
46  std::unique_ptr<MCStreamer> Streamer)
47  : AsmPrinter(TM, std::move(Streamer)) {}
48 
49  StringRef getPassName() const override { return "Sparc Assembly Printer"; }
50 
51  void printOperand(const MachineInstr *MI, int opNum, raw_ostream &OS);
52  void printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &OS,
53  const char *Modifier = nullptr);
54 
55  void EmitFunctionBodyStart() override;
56  void EmitInstruction(const MachineInstr *MI) override;
57 
58  static const char *getRegisterName(unsigned RegNo) {
60  }
61 
62  bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
63  unsigned AsmVariant, const char *ExtraCode,
64  raw_ostream &O) override;
65  bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
66  unsigned AsmVariant, const char *ExtraCode,
67  raw_ostream &O) override;
68 
69  void LowerGETPCXAndEmitMCInsts(const MachineInstr *MI,
70  const MCSubtargetInfo &STI);
71 
72  };
73 } // end of anonymous namespace
74 
76  MCSymbol *Sym, MCContext &OutContext) {
77  const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::create(Sym,
78  OutContext);
79  const SparcMCExpr *expr = SparcMCExpr::create(Kind, MCSym, OutContext);
80  return MCOperand::createExpr(expr);
81 
82 }
84  MCContext &OutContext) {
85  return createSparcMCOperand(SparcMCExpr::VK_Sparc_None, Label, OutContext);
86 }
87 
89  MCSymbol *GOTLabel, MCSymbol *StartLabel,
90  MCSymbol *CurLabel,
91  MCContext &OutContext)
92 {
93  const MCSymbolRefExpr *GOT = MCSymbolRefExpr::create(GOTLabel, OutContext);
94  const MCSymbolRefExpr *Start = MCSymbolRefExpr::create(StartLabel,
95  OutContext);
96  const MCSymbolRefExpr *Cur = MCSymbolRefExpr::create(CurLabel,
97  OutContext);
98 
99  const MCBinaryExpr *Sub = MCBinaryExpr::createSub(Cur, Start, OutContext);
100  const MCBinaryExpr *Add = MCBinaryExpr::createAdd(GOT, Sub, OutContext);
101  const SparcMCExpr *expr = SparcMCExpr::create(Kind,
102  Add, OutContext);
103  return MCOperand::createExpr(expr);
104 }
105 
106 static void EmitCall(MCStreamer &OutStreamer,
107  MCOperand &Callee,
108  const MCSubtargetInfo &STI)
109 {
111  CallInst.setOpcode(SP::CALL);
112  CallInst.addOperand(Callee);
113  OutStreamer.EmitInstruction(CallInst, STI);
114 }
115 
116 static void EmitSETHI(MCStreamer &OutStreamer,
117  MCOperand &Imm, MCOperand &RD,
118  const MCSubtargetInfo &STI)
119 {
120  MCInst SETHIInst;
121  SETHIInst.setOpcode(SP::SETHIi);
122  SETHIInst.addOperand(RD);
123  SETHIInst.addOperand(Imm);
124  OutStreamer.EmitInstruction(SETHIInst, STI);
125 }
126 
127 static void EmitBinary(MCStreamer &OutStreamer, unsigned Opcode,
128  MCOperand &RS1, MCOperand &Src2, MCOperand &RD,
129  const MCSubtargetInfo &STI)
130 {
131  MCInst Inst;
132  Inst.setOpcode(Opcode);
133  Inst.addOperand(RD);
134  Inst.addOperand(RS1);
135  Inst.addOperand(Src2);
136  OutStreamer.EmitInstruction(Inst, STI);
137 }
138 
139 static void EmitOR(MCStreamer &OutStreamer,
140  MCOperand &RS1, MCOperand &Imm, MCOperand &RD,
141  const MCSubtargetInfo &STI) {
142  EmitBinary(OutStreamer, SP::ORri, RS1, Imm, RD, STI);
143 }
144 
145 static void EmitADD(MCStreamer &OutStreamer,
146  MCOperand &RS1, MCOperand &RS2, MCOperand &RD,
147  const MCSubtargetInfo &STI) {
148  EmitBinary(OutStreamer, SP::ADDrr, RS1, RS2, RD, STI);
149 }
150 
151 static void EmitSHL(MCStreamer &OutStreamer,
152  MCOperand &RS1, MCOperand &Imm, MCOperand &RD,
153  const MCSubtargetInfo &STI) {
154  EmitBinary(OutStreamer, SP::SLLri, RS1, Imm, RD, STI);
155 }
156 
157 
158 static void EmitHiLo(MCStreamer &OutStreamer, MCSymbol *GOTSym,
161  MCOperand &RD,
162  MCContext &OutContext,
163  const MCSubtargetInfo &STI) {
164 
165  MCOperand hi = createSparcMCOperand(HiKind, GOTSym, OutContext);
166  MCOperand lo = createSparcMCOperand(LoKind, GOTSym, OutContext);
167  EmitSETHI(OutStreamer, hi, RD, STI);
168  EmitOR(OutStreamer, RD, lo, RD, STI);
169 }
170 
171 void SparcAsmPrinter::LowerGETPCXAndEmitMCInsts(const MachineInstr *MI,
172  const MCSubtargetInfo &STI)
173 {
174  MCSymbol *GOTLabel =
175  OutContext.getOrCreateSymbol(Twine("_GLOBAL_OFFSET_TABLE_"));
176 
177  const MachineOperand &MO = MI->getOperand(0);
178  assert(MO.getReg() != SP::O7 &&
179  "%o7 is assigned as destination for getpcx!");
180 
181  MCOperand MCRegOP = MCOperand::createReg(MO.getReg());
182 
183 
184  if (!isPositionIndependent()) {
185  // Just load the address of GOT to MCRegOP.
186  switch(TM.getCodeModel()) {
187  default:
188  llvm_unreachable("Unsupported absolute code model");
189  case CodeModel::Small:
190  EmitHiLo(*OutStreamer, GOTLabel,
192  MCRegOP, OutContext, STI);
193  break;
194  case CodeModel::Medium: {
195  EmitHiLo(*OutStreamer, GOTLabel,
197  MCRegOP, OutContext, STI);
199  OutContext));
200  EmitSHL(*OutStreamer, MCRegOP, imm, MCRegOP, STI);
202  GOTLabel, OutContext);
203  EmitOR(*OutStreamer, MCRegOP, lo, MCRegOP, STI);
204  break;
205  }
206  case CodeModel::Large: {
207  EmitHiLo(*OutStreamer, GOTLabel,
209  MCRegOP, OutContext, STI);
211  OutContext));
212  EmitSHL(*OutStreamer, MCRegOP, imm, MCRegOP, STI);
213  // Use register %o7 to load the lower 32 bits.
214  MCOperand RegO7 = MCOperand::createReg(SP::O7);
215  EmitHiLo(*OutStreamer, GOTLabel,
217  RegO7, OutContext, STI);
218  EmitADD(*OutStreamer, MCRegOP, RegO7, MCRegOP, STI);
219  }
220  }
221  return;
222  }
223 
224  MCSymbol *StartLabel = OutContext.createTempSymbol();
225  MCSymbol *EndLabel = OutContext.createTempSymbol();
226  MCSymbol *SethiLabel = OutContext.createTempSymbol();
227 
228  MCOperand RegO7 = MCOperand::createReg(SP::O7);
229 
230  // <StartLabel>:
231  // call <EndLabel>
232  // <SethiLabel>:
233  // sethi %hi(_GLOBAL_OFFSET_TABLE_+(<SethiLabel>-<StartLabel>)), <MO>
234  // <EndLabel>:
235  // or <MO>, %lo(_GLOBAL_OFFSET_TABLE_+(<EndLabel>-<StartLabel>))), <MO>
236  // add <MO>, %o7, <MO>
237 
238  OutStreamer->EmitLabel(StartLabel);
239  MCOperand Callee = createPCXCallOP(EndLabel, OutContext);
240  EmitCall(*OutStreamer, Callee, STI);
241  OutStreamer->EmitLabel(SethiLabel);
243  GOTLabel, StartLabel, SethiLabel,
244  OutContext);
245  EmitSETHI(*OutStreamer, hiImm, MCRegOP, STI);
246  OutStreamer->EmitLabel(EndLabel);
248  GOTLabel, StartLabel, EndLabel,
249  OutContext);
250  EmitOR(*OutStreamer, MCRegOP, loImm, MCRegOP, STI);
251  EmitADD(*OutStreamer, MCRegOP, RegO7, MCRegOP, STI);
252 }
253 
254 void SparcAsmPrinter::EmitInstruction(const MachineInstr *MI)
255 {
256 
257  switch (MI->getOpcode()) {
258  default: break;
259  case TargetOpcode::DBG_VALUE:
260  // FIXME: Debug Value.
261  return;
262  case SP::GETPCX:
263  LowerGETPCXAndEmitMCInsts(MI, getSubtargetInfo());
264  return;
265  }
268  do {
269  MCInst TmpInst;
270  LowerSparcMachineInstrToMCInst(&*I, TmpInst, *this);
271  EmitToStreamer(*OutStreamer, TmpInst);
272  } while ((++I != E) && I->isInsideBundle()); // Delay slot check.
273 }
274 
275 void SparcAsmPrinter::EmitFunctionBodyStart() {
276  if (!MF->getSubtarget<SparcSubtarget>().is64Bit())
277  return;
278 
279  const MachineRegisterInfo &MRI = MF->getRegInfo();
280  const unsigned globalRegs[] = { SP::G2, SP::G3, SP::G6, SP::G7, 0 };
281  for (unsigned i = 0; globalRegs[i] != 0; ++i) {
282  unsigned reg = globalRegs[i];
283  if (MRI.use_empty(reg))
284  continue;
285 
286  if (reg == SP::G6 || reg == SP::G7)
287  getTargetStreamer().emitSparcRegisterIgnore(reg);
288  else
289  getTargetStreamer().emitSparcRegisterScratch(reg);
290  }
291 }
292 
293 void SparcAsmPrinter::printOperand(const MachineInstr *MI, int opNum,
294  raw_ostream &O) {
295  const DataLayout &DL = getDataLayout();
296  const MachineOperand &MO = MI->getOperand (opNum);
298 
299 #ifndef NDEBUG
300  // Verify the target flags.
301  if (MO.isGlobal() || MO.isSymbol() || MO.isCPI()) {
302  if (MI->getOpcode() == SP::CALL)
304  "Cannot handle target flags on call address");
305  else if (MI->getOpcode() == SP::SETHIi || MI->getOpcode() == SP::SETHIXi)
308  || TF == SparcMCExpr::VK_Sparc_HH
314  "Invalid target flags for address operand on sethi");
315  else if (MI->getOpcode() == SP::TLS_CALL)
319  "Cannot handle target flags on tls call address");
320  else if (MI->getOpcode() == SP::TLS_ADDrr)
325  "Cannot handle target flags on add for TLS");
326  else if (MI->getOpcode() == SP::TLS_LDrr)
328  "Cannot handle target flags on ld for TLS");
329  else if (MI->getOpcode() == SP::TLS_LDXrr)
331  "Cannot handle target flags on ldx for TLS");
332  else if (MI->getOpcode() == SP::XORri || MI->getOpcode() == SP::XORXri)
335  "Cannot handle target flags on xor for TLS");
336  else
340  || TF == SparcMCExpr::VK_Sparc_HM
344  "Invalid target flags for small address operand");
345  }
346 #endif
347 
348 
349  bool CloseParen = SparcMCExpr::printVariantKind(O, TF);
350 
351  switch (MO.getType()) {
353  O << "%" << StringRef(getRegisterName(MO.getReg())).lower();
354  break;
355 
357  O << (int)MO.getImm();
358  break;
360  MO.getMBB()->getSymbol()->print(O, MAI);
361  return;
363  getSymbol(MO.getGlobal())->print(O, MAI);
364  break;
366  O << GetBlockAddressSymbol(MO.getBlockAddress())->getName();
367  break;
369  O << MO.getSymbolName();
370  break;
372  O << DL.getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << "_"
373  << MO.getIndex();
374  break;
376  MO.getMetadata()->printAsOperand(O, MMI->getModule());
377  break;
378  default:
379  llvm_unreachable("<unknown operand type>");
380  }
381  if (CloseParen) O << ")";
382 }
383 
384 void SparcAsmPrinter::printMemOperand(const MachineInstr *MI, int opNum,
385  raw_ostream &O, const char *Modifier) {
386  printOperand(MI, opNum, O);
387 
388  // If this is an ADD operand, emit it like normal operands.
389  if (Modifier && !strcmp(Modifier, "arith")) {
390  O << ", ";
391  printOperand(MI, opNum+1, O);
392  return;
393  }
394 
395  if (MI->getOperand(opNum+1).isReg() &&
396  MI->getOperand(opNum+1).getReg() == SP::G0)
397  return; // don't print "+%g0"
398  if (MI->getOperand(opNum+1).isImm() &&
399  MI->getOperand(opNum+1).getImm() == 0)
400  return; // don't print "+0"
401 
402  O << "+";
403  printOperand(MI, opNum+1, O);
404 }
405 
406 /// PrintAsmOperand - Print out an operand for an inline asm expression.
407 ///
408 bool SparcAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
409  unsigned AsmVariant,
410  const char *ExtraCode,
411  raw_ostream &O) {
412  if (ExtraCode && ExtraCode[0]) {
413  if (ExtraCode[1] != 0) return true; // Unknown modifier.
414 
415  switch (ExtraCode[0]) {
416  default:
417  // See if this is a generic print operand
418  return AsmPrinter::PrintAsmOperand(MI, OpNo, AsmVariant, ExtraCode, O);
419  case 'f':
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:102
StringRef getPrivateGlobalPrefix() const
Definition: DataLayout.h:284
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:298
void print(raw_ostream &OS, const MCAsmInfo *MAI) const
print - Print the value to the stream OS.
Definition: MCSymbol.cpp:53
size_t i
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
This class represents a function call, abstracting a target machine's calling convention.
MachineBasicBlock reference.
const char * getSymbolName() const
const MDNode * getMetadata() const
Maximum length of the test input libFuzzer tries to guess a good value based on the corpus and reports it always prefer smaller inputs during the corpus shuffle When libFuzzer itself reports a bug this exit code will be used If indicates the maximal total time in seconds to run the fuzzer minimizes the provided crash input Use with strcmp
virtual void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI)
Emit the given Instruction into the current section.
Definition: MCStreamer.cpp:765
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:81
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
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:161
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:51
static std::string getRegisterName(const TargetRegisterInfo *TRI, unsigned Reg)
Definition: MIParser.cpp:785
static const MCBinaryExpr * createSub(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition: MCExpr.h:497
Target & getTheSparcTarget()
int64_t getImm() const
static const MCBinaryExpr * createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition: MCExpr.h:429
Expected< const typename ELFT::Sym * > getSymbol(typename ELFT::SymRange Symbols, uint32_t Index)
Definition: Object/ELF.h:236
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:273
static GCRegistry::Add< CoreCLRGC > E("coreclr","CoreCLR-compatible GC")
const MachineBasicBlock * getParent() const
Definition: MachineInstr.h:131
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:161
unsigned const MachineRegisterInfo * MRI
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:279
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:67
Target & getTheSparcelTarget()
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")
self_iterator getIterator()
Definition: ilist_node.h:81
static void EmitADD(MCStreamer &OutStreamer, MCOperand &RS1, MCOperand &RS2, MCOperand &RD, const MCSubtargetInfo &STI)
Binary assembler expressions.
Definition: MCExpr.h:388
MCSymbol * getSymbol() const
Return the MCSymbol for this basic block.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
void LLVMInitializeSparcAsmPrinter()
Iterator for intrusive lists based on ilist_node.
void setOpcode(unsigned Op)
Definition: MCInst.h:158
MachineOperand class - Representation of each machine instruction operand.
void printAsOperand(raw_ostream &OS, const Module *M=nullptr) const
Print as operand.
Definition: AsmWriter.cpp:3517
static MCOperand createPCXCallOP(MCSymbol *Label, MCContext &OutContext)
Target & getTheSparcV9Target()
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:52
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
static bool printOperand(raw_ostream &OS, const SelectionDAG *G, const SDValue Value)
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
const unsigned Kind
unsigned getReg() const
getReg - Returns the register number.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
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:44
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.
IRTranslator LLVM IR MI
void addOperand(const MCOperand &Op)
Definition: MCInst.h:168
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:47
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
LLVM_NODISCARD std::string lower() const
Definition: StringRef.cpp:122
static const MCConstantExpr * create(int64_t Value, MCContext &Ctx)
Definition: MCExpr.cpp:149
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.
Metadata reference (for debug info)