LLVM  3.7.0
XCoreAsmPrinter.cpp
Go to the documentation of this file.
1 //===-- XCoreAsmPrinter.cpp - XCore 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 the XAS-format XCore assembly language.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #include "XCore.h"
17 #include "XCoreInstrInfo.h"
18 #include "XCoreMCInstLower.h"
19 #include "XCoreSubtarget.h"
20 #include "XCoreTargetMachine.h"
21 #include "XCoreTargetStreamer.h"
22 #include "llvm/ADT/SmallString.h"
23 #include "llvm/ADT/StringExtras.h"
30 #include "llvm/IR/Constants.h"
31 #include "llvm/IR/DataLayout.h"
32 #include "llvm/IR/DebugInfo.h"
33 #include "llvm/IR/DerivedTypes.h"
34 #include "llvm/IR/Mangler.h"
35 #include "llvm/IR/Module.h"
36 #include "llvm/MC/MCAsmInfo.h"
37 #include "llvm/MC/MCExpr.h"
38 #include "llvm/MC/MCInst.h"
39 #include "llvm/MC/MCStreamer.h"
40 #include "llvm/MC/MCSymbolELF.h"
45 #include <algorithm>
46 #include <cctype>
47 using namespace llvm;
48 
49 #define DEBUG_TYPE "asm-printer"
50 
51 namespace {
52  class XCoreAsmPrinter : public AsmPrinter {
53  XCoreMCInstLower MCInstLowering;
54  XCoreTargetStreamer &getTargetStreamer();
55 
56  public:
57  explicit XCoreAsmPrinter(TargetMachine &TM,
58  std::unique_ptr<MCStreamer> Streamer)
59  : AsmPrinter(TM, std::move(Streamer)), MCInstLowering(*this) {}
60 
61  const char *getPassName() const override {
62  return "XCore Assembly Printer";
63  }
64 
65  void printInlineJT(const MachineInstr *MI, int opNum, raw_ostream &O,
66  const std::string &directive = ".jmptable");
67  void printInlineJT32(const MachineInstr *MI, int opNum, raw_ostream &O) {
68  printInlineJT(MI, opNum, O, ".jmptable32");
69  }
70  void printOperand(const MachineInstr *MI, int opNum, raw_ostream &O);
71  bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
72  unsigned AsmVariant, const char *ExtraCode,
73  raw_ostream &O) override;
74  bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum,
75  unsigned AsmVariant, const char *ExtraCode,
76  raw_ostream &O) override;
77 
78  void emitArrayBound(MCSymbol *Sym, const GlobalVariable *GV);
79  void EmitGlobalVariable(const GlobalVariable *GV) override;
80 
81  void EmitFunctionEntryLabel() override;
82  void EmitInstruction(const MachineInstr *MI) override;
83  void EmitFunctionBodyStart() override;
84  void EmitFunctionBodyEnd() override;
85  };
86 } // end of anonymous namespace
87 
88 XCoreTargetStreamer &XCoreAsmPrinter::getTargetStreamer() {
89  return static_cast<XCoreTargetStreamer&>(*OutStreamer->getTargetStreamer());
90 }
91 
92 void XCoreAsmPrinter::emitArrayBound(MCSymbol *Sym, const GlobalVariable *GV) {
93  assert( ( GV->hasExternalLinkage() || GV->hasWeakLinkage() ||
94  GV->hasLinkOnceLinkage() || GV->hasCommonLinkage() ) &&
95  "Unexpected linkage");
96  if (ArrayType *ATy = dyn_cast<ArrayType>(
97  cast<PointerType>(GV->getType())->getElementType())) {
98 
99  MCSymbol *SymGlob = OutContext.getOrCreateSymbol(
100  Twine(Sym->getName() + StringRef(".globound")));
101  OutStreamer->EmitSymbolAttribute(SymGlob, MCSA_Global);
102  OutStreamer->EmitAssignment(SymGlob,
103  MCConstantExpr::create(ATy->getNumElements(),
104  OutContext));
105  if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage() ||
106  GV->hasCommonLinkage()) {
107  OutStreamer->EmitSymbolAttribute(SymGlob, MCSA_Weak);
108  }
109  }
110 }
111 
112 void XCoreAsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) {
113  // Check to see if this is a special global used by LLVM, if so, emit it.
114  if (!GV->hasInitializer() ||
115  EmitSpecialLLVMGlobal(GV))
116  return;
117 
118  const DataLayout *TD = TM.getDataLayout();
119  OutStreamer->SwitchSection(
120  getObjFileLowering().SectionForGlobal(GV, *Mang, TM));
121 
122  MCSymbol *GVSym = getSymbol(GV);
123  const Constant *C = GV->getInitializer();
125 
126  // Mark the start of the global
127  getTargetStreamer().emitCCTopData(GVSym->getName());
128 
129  switch (GV->getLinkage()) {
131  report_fatal_error("AppendingLinkage is not supported by this target!");
138  emitArrayBound(GVSym, GV);
139  OutStreamer->EmitSymbolAttribute(GVSym, MCSA_Global);
140 
141  if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage() ||
142  GV->hasCommonLinkage())
143  OutStreamer->EmitSymbolAttribute(GVSym, MCSA_Weak);
144  // FALL THROUGH
147  break;
148  default:
149  llvm_unreachable("Unknown linkage type!");
150  }
151 
152  EmitAlignment(Align > 2 ? Align : 2, GV);
153 
154  if (GV->isThreadLocal()) {
155  report_fatal_error("TLS is not supported by this target!");
156  }
157  unsigned Size = TD->getTypeAllocSize(C->getType());
158  if (MAI->hasDotTypeDotSizeDirective()) {
159  OutStreamer->EmitSymbolAttribute(GVSym, MCSA_ELF_TypeObject);
160  OutStreamer->emitELFSize(cast<MCSymbolELF>(GVSym),
161  MCConstantExpr::create(Size, OutContext));
162  }
163  OutStreamer->EmitLabel(GVSym);
164 
165  EmitGlobalConstant(C);
166  // The ABI requires that unsigned scalar types smaller than 32 bits
167  // are padded to 32 bits.
168  if (Size < 4)
169  OutStreamer->EmitZeros(4 - Size);
170 
171  // Mark the end of the global
172  getTargetStreamer().emitCCBottomData(GVSym->getName());
173 }
174 
175 void XCoreAsmPrinter::EmitFunctionBodyStart() {
176  MCInstLowering.Initialize(Mang, &MF->getContext());
177 }
178 
179 /// EmitFunctionBodyEnd - Targets can override this to emit stuff after
180 /// the last basic block in the function.
181 void XCoreAsmPrinter::EmitFunctionBodyEnd() {
182  // Emit function end directives
183  getTargetStreamer().emitCCBottomFunction(CurrentFnSym->getName());
184 }
185 
186 void XCoreAsmPrinter::EmitFunctionEntryLabel() {
187  // Mark the start of the function
188  getTargetStreamer().emitCCTopFunction(CurrentFnSym->getName());
189  OutStreamer->EmitLabel(CurrentFnSym);
190 }
191 
192 void XCoreAsmPrinter::
193 printInlineJT(const MachineInstr *MI, int opNum, raw_ostream &O,
194  const std::string &directive) {
195  unsigned JTI = MI->getOperand(opNum).getIndex();
196  const MachineFunction *MF = MI->getParent()->getParent();
197  const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
198  const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
199  const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
200  O << "\t" << directive << " ";
201  for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) {
202  MachineBasicBlock *MBB = JTBBs[i];
203  if (i > 0)
204  O << ",";
205  MBB->getSymbol()->print(O, MAI);
206  }
207 }
208 
209 void XCoreAsmPrinter::printOperand(const MachineInstr *MI, int opNum,
210  raw_ostream &O) {
211  const DataLayout *DL = TM.getDataLayout();
212  const MachineOperand &MO = MI->getOperand(opNum);
213  switch (MO.getType()) {
216  break;
218  O << MO.getImm();
219  break;
221  MO.getMBB()->getSymbol()->print(O, MAI);
222  break;
224  getSymbol(MO.getGlobal())->print(O, MAI);
225  break;
227  O << DL->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
228  << '_' << MO.getIndex();
229  break;
231  GetBlockAddressSymbol(MO.getBlockAddress())->print(O, MAI);
232  break;
233  default:
234  llvm_unreachable("not implemented");
235  }
236 }
237 
238 /// PrintAsmOperand - Print out an operand for an inline asm expression.
239 ///
240 bool XCoreAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
241  unsigned AsmVariant,const char *ExtraCode,
242  raw_ostream &O) {
243  // Print the operand if there is no operand modifier.
244  if (!ExtraCode || !ExtraCode[0]) {
245  printOperand(MI, OpNo, O);
246  return false;
247  }
248 
249  // Otherwise fallback on the default implementation.
250  return AsmPrinter::PrintAsmOperand(MI, OpNo, AsmVariant, ExtraCode, O);
251 }
252 
253 bool XCoreAsmPrinter::
254 PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum,
255  unsigned AsmVariant, const char *ExtraCode,
256  raw_ostream &O) {
257  if (ExtraCode && ExtraCode[0]) {
258  return true; // Unknown modifier.
259  }
260  printOperand(MI, OpNum, O);
261  O << '[';
262  printOperand(MI, OpNum + 1, O);
263  O << ']';
264  return false;
265 }
266 
267 void XCoreAsmPrinter::EmitInstruction(const MachineInstr *MI) {
268  SmallString<128> Str;
269  raw_svector_ostream O(Str);
270 
271  switch (MI->getOpcode()) {
272  case XCore::DBG_VALUE:
273  llvm_unreachable("Should be handled target independently");
274  case XCore::ADD_2rus:
275  if (MI->getOperand(2).getImm() == 0) {
276  O << "\tmov "
278  << XCoreInstPrinter::getRegisterName(MI->getOperand(1).getReg());
279  OutStreamer->EmitRawText(O.str());
280  return;
281  }
282  break;
283  case XCore::BR_JT:
284  case XCore::BR_JT32:
285  O << "\tbru "
287  if (MI->getOpcode() == XCore::BR_JT)
288  printInlineJT(MI, 0, O);
289  else
290  printInlineJT32(MI, 0, O);
291  O << '\n';
292  OutStreamer->EmitRawText(O.str());
293  return;
294  }
295 
296  MCInst TmpInst;
297  MCInstLowering.Lower(MI, TmpInst);
298 
299  EmitToStreamer(*OutStreamer, TmpInst);
300 }
301 
302 // Force static initialization.
303 extern "C" void LLVMInitializeXCoreAsmPrinter() {
305 }
const MachineFunction * getParent() const
getParent - Return the MachineFunction containing this basic block.
A parsed version of the target data layout string in and methods for querying it. ...
Definition: DataLayout.h:104
LinkageTypes getLinkage() const
Definition: GlobalValue.h:289
const GlobalValue * getGlobal() const
Special purpose, only applies to global arrays.
Definition: GlobalValue.h:46
void print(raw_ostream &OS, const MCAsmInfo *MAI) const
print - Print the value to the stream OS.
Definition: MCSymbol.cpp:51
.type _foo, STT_OBJECT # aka
Definition: MCDirectives.h:25
MachineBasicBlock * getMBB() const
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:39
Same, but only replaced by something equivalent.
Definition: GlobalValue.h:45
This class is used to lower an MachineInstr into an MCInst.
const char * getPrivateGlobalPrefix() const
Definition: DataLayout.h:281
Like Internal, but omit from symbol table.
Definition: GlobalValue.h:48
Externally visible function.
Definition: GlobalValue.h:40
A raw_ostream that writes to an SmallVector or SmallString.
Definition: raw_ostream.h:488
MachineBasicBlock reference.
const Constant * getInitializer() const
getInitializer - Return the initializer for this global variable.
Tentative definitions.
Definition: GlobalValue.h:50
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const char *reason, bool gen_crash_diag=true)
Reports a serious error, calling any installed error handler.
const std::vector< MachineJumpTableEntry > & getJumpTables() const
bool hasCommonLinkage() const
Definition: GlobalValue.h:282
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:79
unsigned getPreferredTypeAlignmentShift(Type *Ty) const
Returns the preferred alignment for the specified type, returned as log2 of the value (a shift amount...
Definition: DataLayout.cpp:688
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:98
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.
ArrayType - Class to represent array types.
Definition: DerivedTypes.h:336
const MachineJumpTableInfo * getJumpTableInfo() const
getJumpTableInfo - Return the jump table info object for the current function.
int64_t getImm() const
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
Address of a global value.
Same, but only replaced by something equivalent.
Definition: GlobalValue.h:43
This is an important base class in LLVM.
Definition: Constant.h:41
This file contains the declarations for the subclasses of Constant, which represent the different fla...
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
Address of a basic block.
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang","erlang-compatible garbage collector")
void LLVMInitializeXCoreAsmPrinter()
bool isThreadLocal() const
If the value is "Thread Local", its value isn't shared by the threads.
Definition: GlobalValue.h:152
bool hasWeakLinkage() const
Definition: GlobalValue.h:268
MCSymbol * getSymbol() const
getSymbol - Return the MCSymbol for this basic block.
bool hasExternalLinkage() const
Definition: GlobalValue.h:260
uint64_t getTypeAllocSize(Type *Ty) const
Returns the offset in bytes between successive objects of the specified type, including alignment pad...
Definition: DataLayout.h:388
MachineOperand class - Representation of each machine instruction operand.
Keep one copy of function when linking (inline)
Definition: GlobalValue.h:42
Module.h This file contains the declarations for the Module class.
Type * getType() const
All values are typed, get the type of this value.
Definition: Value.h:222
static cl::opt< AlignMode > Align(cl::desc("Load/store alignment support"), cl::Hidden, cl::init(NoStrictAlign), cl::values(clEnumValN(StrictAlign,"aarch64-strict-align","Disallow all unaligned memory accesses"), clEnumValN(NoStrictAlign,"aarch64-no-strict-align","Allow unaligned memory accesses"), clEnumValEnd))
bool hasInitializer() const
Definitions have initializers, declarations don't.
BR_JT - Jumptable branch.
Definition: ISDOpcodes.h:542
bool hasLinkOnceLinkage() const
Definition: GlobalValue.h:264
Representation of each machine instruction.
Definition: MachineInstr.h:51
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
PointerType * getType() const
Global values are always pointers.
Definition: GlobalValue.h:185
StringRef getName() const
getName - Get the symbol name.
Definition: MCSymbol.h:205
.type _foo,
Definition: MCDirectives.h:30
Target TheXCoreTarget
Keep one copy of named function when linking (weak)
Definition: GlobalValue.h:44
Rename collisions when linking (static functions).
Definition: GlobalValue.h:47
This file contains the declaration of the XCoreInstPrinter class, which is used to print XCore MCInst...
unsigned getReg() const
getReg - Returns the register number.
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
Primary interface to the complete machine description for the target machine.
C - The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
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 const MCConstantExpr * create(int64_t Value, MCContext &Ctx)
Definition: MCExpr.cpp:150
static const char * getRegisterName(unsigned RegNo)