LLVM  9.0.0svn
SparcAsmPrinter.cpp
Go to the documentation of this file.
1 //===-- SparcAsmPrinter.cpp - Sparc LLVM assembly writer ------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file contains a printer that converts from our internal representation
10 // of machine-dependent LLVM code to GAS-format SPARC assembly language.
11 //
12 //===----------------------------------------------------------------------===//
13 
17 #include "Sparc.h"
18 #include "SparcInstrInfo.h"
19 #include "SparcTargetMachine.h"
25 #include "llvm/IR/Mangler.h"
26 #include "llvm/MC/MCAsmInfo.h"
27 #include "llvm/MC/MCContext.h"
28 #include "llvm/MC/MCInst.h"
29 #include "llvm/MC/MCStreamer.h"
30 #include "llvm/MC/MCSymbol.h"
33 using namespace llvm;
34 
35 #define DEBUG_TYPE "asm-printer"
36 
37 namespace {
38  class SparcAsmPrinter : public AsmPrinter {
39  SparcTargetStreamer &getTargetStreamer() {
40  return static_cast<SparcTargetStreamer &>(
41  *OutStreamer->getTargetStreamer());
42  }
43  public:
44  explicit SparcAsmPrinter(TargetMachine &TM,
45  std::unique_ptr<MCStreamer> Streamer)
46  : AsmPrinter(TM, std::move(Streamer)) {}
47 
48  StringRef getPassName() const override { return "Sparc Assembly Printer"; }
49 
50  void printOperand(const MachineInstr *MI, int opNum, raw_ostream &OS);
51  void printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &OS,
52  const char *Modifier = nullptr);
53 
54  void EmitFunctionBodyStart() override;
55  void EmitInstruction(const MachineInstr *MI) override;
56 
57  static const char *getRegisterName(unsigned RegNo) {
59  }
60 
61  bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
62  unsigned AsmVariant, const char *ExtraCode,
63  raw_ostream &O) override;
64  bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
65  unsigned AsmVariant, const char *ExtraCode,
66  raw_ostream &O) override;
67 
68  void LowerGETPCXAndEmitMCInsts(const MachineInstr *MI,
69  const MCSubtargetInfo &STI);
70 
71  };
72 } // end of anonymous namespace
73 
75  MCSymbol *Sym, MCContext &OutContext) {
76  const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::create(Sym,
77  OutContext);
78  const SparcMCExpr *expr = SparcMCExpr::create(Kind, MCSym, OutContext);
79  return MCOperand::createExpr(expr);
80 
81 }
83  MCContext &OutContext) {
84  return createSparcMCOperand(SparcMCExpr::VK_Sparc_None, Label, OutContext);
85 }
86 
88  MCSymbol *GOTLabel, MCSymbol *StartLabel,
89  MCSymbol *CurLabel,
90  MCContext &OutContext)
91 {
92  const MCSymbolRefExpr *GOT = MCSymbolRefExpr::create(GOTLabel, OutContext);
93  const MCSymbolRefExpr *Start = MCSymbolRefExpr::create(StartLabel,
94  OutContext);
95  const MCSymbolRefExpr *Cur = MCSymbolRefExpr::create(CurLabel,
96  OutContext);
97 
98  const MCBinaryExpr *Sub = MCBinaryExpr::createSub(Cur, Start, OutContext);
99  const MCBinaryExpr *Add = MCBinaryExpr::createAdd(GOT, Sub, OutContext);
100  const SparcMCExpr *expr = SparcMCExpr::create(Kind,
101  Add, OutContext);
102  return MCOperand::createExpr(expr);
103 }
104 
105 static void EmitCall(MCStreamer &OutStreamer,
106  MCOperand &Callee,
107  const MCSubtargetInfo &STI)
108 {
110  CallInst.setOpcode(SP::CALL);
111  CallInst.addOperand(Callee);
112  OutStreamer.EmitInstruction(CallInst, STI);
113 }
114 
115 static void EmitSETHI(MCStreamer &OutStreamer,
116  MCOperand &Imm, MCOperand &RD,
117  const MCSubtargetInfo &STI)
118 {
119  MCInst SETHIInst;
120  SETHIInst.setOpcode(SP::SETHIi);
121  SETHIInst.addOperand(RD);
122  SETHIInst.addOperand(Imm);
123  OutStreamer.EmitInstruction(SETHIInst, STI);
124 }
125 
126 static void EmitBinary(MCStreamer &OutStreamer, unsigned Opcode,
127  MCOperand &RS1, MCOperand &Src2, MCOperand &RD,
128  const MCSubtargetInfo &STI)
129 {
130  MCInst Inst;
131  Inst.setOpcode(Opcode);
132  Inst.addOperand(RD);
133  Inst.addOperand(RS1);
134  Inst.addOperand(Src2);
135  OutStreamer.EmitInstruction(Inst, STI);
136 }
137 
138 static void EmitOR(MCStreamer &OutStreamer,
139  MCOperand &RS1, MCOperand &Imm, MCOperand &RD,
140  const MCSubtargetInfo &STI) {
141  EmitBinary(OutStreamer, SP::ORri, RS1, Imm, RD, STI);
142 }
143 
144 static void EmitADD(MCStreamer &OutStreamer,
145  MCOperand &RS1, MCOperand &RS2, MCOperand &RD,
146  const MCSubtargetInfo &STI) {
147  EmitBinary(OutStreamer, SP::ADDrr, RS1, RS2, RD, STI);
148 }
149 
150 static void EmitSHL(MCStreamer &OutStreamer,
151  MCOperand &RS1, MCOperand &Imm, MCOperand &RD,
152  const MCSubtargetInfo &STI) {
153  EmitBinary(OutStreamer, SP::SLLri, RS1, Imm, RD, STI);
154 }
155 
156 
157 static void EmitHiLo(MCStreamer &OutStreamer, MCSymbol *GOTSym,
160  MCOperand &RD,
161  MCContext &OutContext,
162  const MCSubtargetInfo &STI) {
163 
164  MCOperand hi = createSparcMCOperand(HiKind, GOTSym, OutContext);
165  MCOperand lo = createSparcMCOperand(LoKind, GOTSym, OutContext);
166  EmitSETHI(OutStreamer, hi, RD, STI);
167  EmitOR(OutStreamer, RD, lo, RD, STI);
168 }
169 
170 void SparcAsmPrinter::LowerGETPCXAndEmitMCInsts(const MachineInstr *MI,
171  const MCSubtargetInfo &STI)
172 {
173  MCSymbol *GOTLabel =
174  OutContext.getOrCreateSymbol(Twine("_GLOBAL_OFFSET_TABLE_"));
175 
176  const MachineOperand &MO = MI->getOperand(0);
177  assert(MO.getReg() != SP::O7 &&
178  "%o7 is assigned as destination for getpcx!");
179 
180  MCOperand MCRegOP = MCOperand::createReg(MO.getReg());
181 
182 
183  if (!isPositionIndependent()) {
184  // Just load the address of GOT to MCRegOP.
185  switch(TM.getCodeModel()) {
186  default:
187  llvm_unreachable("Unsupported absolute code model");
188  case CodeModel::Small:
189  EmitHiLo(*OutStreamer, GOTLabel,
191  MCRegOP, OutContext, STI);
192  break;
193  case CodeModel::Medium: {
194  EmitHiLo(*OutStreamer, GOTLabel,
196  MCRegOP, OutContext, STI);
198  OutContext));
199  EmitSHL(*OutStreamer, MCRegOP, imm, MCRegOP, STI);
201  GOTLabel, OutContext);
202  EmitOR(*OutStreamer, MCRegOP, lo, MCRegOP, STI);
203  break;
204  }
205  case CodeModel::Large: {
206  EmitHiLo(*OutStreamer, GOTLabel,
208  MCRegOP, OutContext, STI);
210  OutContext));
211  EmitSHL(*OutStreamer, MCRegOP, imm, MCRegOP, STI);
212  // Use register %o7 to load the lower 32 bits.
213  MCOperand RegO7 = MCOperand::createReg(SP::O7);
214  EmitHiLo(*OutStreamer, GOTLabel,
216  RegO7, OutContext, STI);
217  EmitADD(*OutStreamer, MCRegOP, RegO7, MCRegOP, STI);
218  }
219  }
220  return;
221  }
222 
223  MCSymbol *StartLabel = OutContext.createTempSymbol();
224  MCSymbol *EndLabel = OutContext.createTempSymbol();
225  MCSymbol *SethiLabel = OutContext.createTempSymbol();
226 
227  MCOperand RegO7 = MCOperand::createReg(SP::O7);
228 
229  // <StartLabel>:
230  // call <EndLabel>
231  // <SethiLabel>:
232  // sethi %hi(_GLOBAL_OFFSET_TABLE_+(<SethiLabel>-<StartLabel>)), <MO>
233  // <EndLabel>:
234  // or <MO>, %lo(_GLOBAL_OFFSET_TABLE_+(<EndLabel>-<StartLabel>))), <MO>
235  // add <MO>, %o7, <MO>
236 
237  OutStreamer->EmitLabel(StartLabel);
238  MCOperand Callee = createPCXCallOP(EndLabel, OutContext);
239  EmitCall(*OutStreamer, Callee, STI);
240  OutStreamer->EmitLabel(SethiLabel);
242  GOTLabel, StartLabel, SethiLabel,
243  OutContext);
244  EmitSETHI(*OutStreamer, hiImm, MCRegOP, STI);
245  OutStreamer->EmitLabel(EndLabel);
247  GOTLabel, StartLabel, EndLabel,
248  OutContext);
249  EmitOR(*OutStreamer, MCRegOP, loImm, MCRegOP, STI);
250  EmitADD(*OutStreamer, MCRegOP, RegO7, MCRegOP, STI);
251 }
252 
253 void SparcAsmPrinter::EmitInstruction(const MachineInstr *MI)
254 {
255 
256  switch (MI->getOpcode()) {
257  default: break;
258  case TargetOpcode::DBG_VALUE:
259  // FIXME: Debug Value.
260  return;
261  case SP::GETPCX:
262  LowerGETPCXAndEmitMCInsts(MI, getSubtargetInfo());
263  return;
264  }
267  do {
268  MCInst TmpInst;
269  LowerSparcMachineInstrToMCInst(&*I, TmpInst, *this);
270  EmitToStreamer(*OutStreamer, TmpInst);
271  } while ((++I != E) && I->isInsideBundle()); // Delay slot check.
272 }
273 
274 void SparcAsmPrinter::EmitFunctionBodyStart() {
275  if (!MF->getSubtarget<SparcSubtarget>().is64Bit())
276  return;
277 
278  const MachineRegisterInfo &MRI = MF->getRegInfo();
279  const unsigned globalRegs[] = { SP::G2, SP::G3, SP::G6, SP::G7, 0 };
280  for (unsigned i = 0; globalRegs[i] != 0; ++i) {
281  unsigned reg = globalRegs[i];
282  if (MRI.use_empty(reg))
283  continue;
284 
285  if (reg == SP::G6 || reg == SP::G7)
286  getTargetStreamer().emitSparcRegisterIgnore(reg);
287  else
288  getTargetStreamer().emitSparcRegisterScratch(reg);
289  }
290 }
291 
292 void SparcAsmPrinter::printOperand(const MachineInstr *MI, int opNum,
293  raw_ostream &O) {
294  const DataLayout &DL = getDataLayout();
295  const MachineOperand &MO = MI->getOperand (opNum);
297 
298 #ifndef NDEBUG
299  // Verify the target flags.
300  if (MO.isGlobal() || MO.isSymbol() || MO.isCPI()) {
301  if (MI->getOpcode() == SP::CALL)
303  "Cannot handle target flags on call address");
304  else if (MI->getOpcode() == SP::SETHIi || MI->getOpcode() == SP::SETHIXi)
307  || TF == SparcMCExpr::VK_Sparc_HH
313  "Invalid target flags for address operand on sethi");
314  else if (MI->getOpcode() == SP::TLS_CALL)
318  "Cannot handle target flags on tls call address");
319  else if (MI->getOpcode() == SP::TLS_ADDrr)
324  "Cannot handle target flags on add for TLS");
325  else if (MI->getOpcode() == SP::TLS_LDrr)
327  "Cannot handle target flags on ld for TLS");
328  else if (MI->getOpcode() == SP::TLS_LDXrr)
330  "Cannot handle target flags on ldx for TLS");
331  else if (MI->getOpcode() == SP::XORri || MI->getOpcode() == SP::XORXri)
334  "Cannot handle target flags on xor for TLS");
335  else
339  || TF == SparcMCExpr::VK_Sparc_HM
343  "Invalid target flags for small address operand");
344  }
345 #endif
346 
347 
348  bool CloseParen = SparcMCExpr::printVariantKind(O, TF);
349 
350  switch (MO.getType()) {
352  O << "%" << StringRef(getRegisterName(MO.getReg())).lower();
353  break;
354 
356  O << (int)MO.getImm();
357  break;
359  MO.getMBB()->getSymbol()->print(O, MAI);
360  return;
362  getSymbol(MO.getGlobal())->print(O, MAI);
363  break;
365  O << GetBlockAddressSymbol(MO.getBlockAddress())->getName();
366  break;
368  O << MO.getSymbolName();
369  break;
371  O << DL.getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << "_"
372  << MO.getIndex();
373  break;
375  MO.getMetadata()->printAsOperand(O, MMI->getModule());
376  break;
377  default:
378  llvm_unreachable("<unknown operand type>");
379  }
380  if (CloseParen) O << ")";
381 }
382 
383 void SparcAsmPrinter::printMemOperand(const MachineInstr *MI, int opNum,
384  raw_ostream &O, const char *Modifier) {
385  printOperand(MI, opNum, O);
386 
387  // If this is an ADD operand, emit it like normal operands.
388  if (Modifier && !strcmp(Modifier, "arith")) {
389  O << ", ";
390  printOperand(MI, opNum+1, O);
391  return;
392  }
393 
394  if (MI->getOperand(opNum+1).isReg() &&
395  MI->getOperand(opNum+1).getReg() == SP::G0)
396  return; // don't print "+%g0"
397  if (MI->getOperand(opNum+1).isImm() &&
398  MI->getOperand(opNum+1).getImm() == 0)
399  return; // don't print "+0"
400 
401  O << "+";
402  printOperand(MI, opNum+1, O);
403 }
404 
405 /// PrintAsmOperand - Print out an operand for an inline asm expression.
406 ///
407 bool SparcAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
408  unsigned AsmVariant,
409  const char *ExtraCode,
410  raw_ostream &O) {
411  if (ExtraCode && ExtraCode[0]) {
412  if (ExtraCode[1] != 0) return true; // Unknown modifier.
413 
414  switch (ExtraCode[0]) {
415  default:
416  // See if this is a generic print operand
417  return AsmPrinter::PrintAsmOperand(MI, OpNo, AsmVariant, ExtraCode, O);
418  case 'f':
419  case 'r':
420  break;
421  }
422  }
423 
424  printOperand(MI, OpNo, O);
425 
426  return false;
427 }
428 
429 bool SparcAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
430  unsigned OpNo, unsigned AsmVariant,
431  const char *ExtraCode,
432  raw_ostream &O) {
433  if (ExtraCode && ExtraCode[0])
434  return true; // Unknown modifier
435 
436  O << '[';
437  printMemOperand(MI, OpNo, O);
438  O << ']';
439 
440  return false;
441 }
442 
443 // Force static initialization.
444 extern "C" void LLVMInitializeSparcAsmPrinter() {
448 }
unsigned getTargetFlags() const
A parsed version of the target data layout string in and methods for querying it. ...
Definition: DataLayout.h:110
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
static MCOperand createPCXRelExprOp(SparcMCExpr::VariantKind Kind, MCSymbol *GOTLabel, MCSymbol *StartLabel, MCSymbol *CurLabel, MCContext &OutContext)
instr_iterator instr_end()
MachineBasicBlock * getMBB() const
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx)
Definition: MCExpr.h:319
This class represents lattice values for constants.
Definition: AllocatorList.h:23
StringRef getPrivateGlobalPrefix() const
Definition: DataLayout.h:316
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:41
static MCOperand createExpr(const MCExpr *Val)
Definition: MCInst.h:136
unsigned getReg() const
getReg - Returns the register number.
static bool printVariantKind(raw_ostream &OS, VariantKind Kind)
Definition: SparcMCExpr.cpp:42
This class represents a function call, abstracting a target machine&#39;s calling convention.
MachineBasicBlock reference.
bool isCPI() const
isCPI - Tests if this is a MO_ConstantPoolIndex operand.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
virtual void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI)
Emit the given Instruction into the current section.
Definition: MCStreamer.cpp:955
static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml", "ocaml 3.10-compatible collector")
static MCOperand createReg(unsigned Reg)
Definition: MCInst.h:115
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:80
static const char * getRegisterName(unsigned RegNo)
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:165
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:408
const char * getSymbolName() const
zlib-gnu style compression
Context object for machine code objects.
Definition: MCContext.h:62
static std::string getRegisterName(const TargetRegisterInfo *TRI, unsigned Reg)
Definition: MIParser.cpp:1079
static const MCBinaryExpr * createSub(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition: MCExpr.h:542
RegisterAsmPrinter - Helper template for registering a target specific assembly printer, for use in the target machine initialization function.
Target & getTheSparcTarget()
static const MCBinaryExpr * createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition: MCExpr.h:457
Expected< const typename ELFT::Sym * > getSymbol(typename ELFT::SymRange Symbols, uint32_t Index)
Definition: ELF.h:336
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:158
static void EmitSHL(MCStreamer &OutStreamer, MCOperand &RS1, MCOperand &Imm, MCOperand &RD, const MCSubtargetInfo &STI)
Address of a global value.
Streaming machine code generation interface.
Definition: MCStreamer.h:188
unsigned const MachineRegisterInfo * MRI
static void EmitBinary(MCStreamer &OutStreamer, unsigned Opcode, MCOperand &RS1, MCOperand &Src2, MCOperand &RD, const MCSubtargetInfo &STI)
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static void EmitCall(MCStreamer &OutStreamer, MCOperand &Callee, const MCSubtargetInfo &STI)
const GlobalValue * getGlobal() const
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:78
Target & getTheSparcelTarget()
static void EmitOR(MCStreamer &OutStreamer, MCOperand &RS1, MCOperand &Imm, MCOperand &RD, const MCSubtargetInfo &STI)
Address of a basic block.
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
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:413
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
void LLVMInitializeSparcAsmPrinter()
static void printMemOperand(raw_ostream &OS, const MachineMemOperand &MMO, const MachineFunction *MF, const Module *M, const MachineFrameInfo *MFI, const TargetInstrInfo *TII, LLVMContext &Ctx)
Iterator for intrusive lists based on ilist_node.
void setOpcode(unsigned Op)
Definition: MCInst.h:170
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
MachineOperand class - Representation of each machine instruction operand.
static MCOperand createPCXCallOP(MCSymbol *Label, MCContext &OutContext)
int64_t getImm() const
amdgpu Simplify well known AMD library false FunctionCallee Callee
bool use_empty(unsigned RegNo) const
use_empty - Return true if there are no instructions using the specified register.
Target & getTheSparcV9Target()
const MachineBasicBlock * getParent() const
Definition: MachineInstr.h:253
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:63
static bool printOperand(raw_ostream &OS, const SelectionDAG *G, const SDValue Value)
void LowerSparcMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI, AsmPrinter &AP)
const BlockAddress * getBlockAddress() const
MCSymbol * getSymbol() const
Return the MCSymbol for this basic block.
#define I(x, y, z)
Definition: MD5.cpp:58
Generic base class for all target subtargets.
static const SparcMCExpr * create(VariantKind Kind, const MCExpr *Expr, MCContext &Ctx)
Definition: SparcMCExpr.cpp:26
bool isSymbol() const
isSymbol - Tests if this is a MO_ExternalSymbol operand.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
LLVM_NODISCARD std::string lower() const
Definition: StringRef.cpp:107
void printAsOperand(raw_ostream &OS, const Module *M=nullptr) const
Print as operand.
Definition: AsmWriter.cpp:4317
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:45
static void EmitSETHI(MCStreamer &OutStreamer, MCOperand &Imm, MCOperand &RD, const MCSubtargetInfo &STI)
Primary interface to the complete machine description for the target machine.
Definition: TargetMachine.h:65
IRTranslator LLVM IR MI
void addOperand(const MCOperand &Op)
Definition: MCInst.h:183
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:48
Address of indexed Constant in Constant Pool.
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:413
Instances of this class represent operands of the MCInst class.
Definition: MCInst.h:34
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
static const MCConstantExpr * create(int64_t Value, MCContext &Ctx)
Definition: MCExpr.cpp:163
const MDNode * getMetadata() const
static MCOperand createSparcMCOperand(SparcMCExpr::VariantKind Kind, MCSymbol *Sym, MCContext &OutContext)
Metadata reference (for debug info)
void print(raw_ostream &OS, const MCAsmInfo *MAI) const
print - Print the value to the stream OS.
Definition: MCSymbol.cpp:59