LLVM API Documentation

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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 #define DEBUG_TYPE "asm-printer"
16 #include "XCore.h"
18 #include "XCoreInstrInfo.h"
19 #include "XCoreMCInstLower.h"
20 #include "XCoreSubtarget.h"
21 #include "XCoreTargetMachine.h"
22 #include "llvm/ADT/SmallString.h"
23 #include "llvm/ADT/StringExtras.h"
30 #include "llvm/DebugInfo.h"
31 #include "llvm/IR/Constants.h"
32 #include "llvm/IR/DataLayout.h"
33 #include "llvm/IR/DerivedTypes.h"
34 #include "llvm/IR/Module.h"
35 #include "llvm/MC/MCAsmInfo.h"
36 #include "llvm/MC/MCInst.h"
37 #include "llvm/MC/MCStreamer.h"
38 #include "llvm/MC/MCSymbol.h"
39 #include "llvm/MC/MCExpr.h"
43 #include "llvm/Target/Mangler.h"
45 #include <algorithm>
46 #include <cctype>
47 using namespace llvm;
48 
49 namespace {
50  class XCoreAsmPrinter : public AsmPrinter {
51  const XCoreSubtarget &Subtarget;
52  XCoreMCInstLower MCInstLowering;
53  public:
54  explicit XCoreAsmPrinter(TargetMachine &TM, MCStreamer &Streamer)
55  : AsmPrinter(TM, Streamer), Subtarget(TM.getSubtarget<XCoreSubtarget>()),
56  MCInstLowering(*this) {}
57 
58  virtual const char *getPassName() const {
59  return "XCore Assembly Printer";
60  }
61 
62  void printInlineJT(const MachineInstr *MI, int opNum, raw_ostream &O,
63  const std::string &directive = ".jmptable");
64  void printInlineJT32(const MachineInstr *MI, int opNum, raw_ostream &O) {
65  printInlineJT(MI, opNum, O, ".jmptable32");
66  }
67  void printOperand(const MachineInstr *MI, int opNum, raw_ostream &O);
68  bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
69  unsigned AsmVariant, const char *ExtraCode,
70  raw_ostream &O);
71 
72  void emitArrayBound(MCSymbol *Sym, const GlobalVariable *GV);
73  virtual void EmitGlobalVariable(const GlobalVariable *GV);
74 
75  void EmitFunctionEntryLabel();
76  void EmitInstruction(const MachineInstr *MI);
77  void EmitFunctionBodyStart();
78  void EmitFunctionBodyEnd();
79  };
80 } // end of anonymous namespace
81 
82 void XCoreAsmPrinter::emitArrayBound(MCSymbol *Sym, const GlobalVariable *GV) {
83  assert(((GV->hasExternalLinkage() ||
84  GV->hasWeakLinkage()) ||
85  GV->hasLinkOnceLinkage()) && "Unexpected linkage");
86  if (ArrayType *ATy = dyn_cast<ArrayType>(
87  cast<PointerType>(GV->getType())->getElementType())) {
88 
89  MCSymbol *SymGlob = OutContext.GetOrCreateSymbol(
90  Twine(Sym->getName() + StringRef(".globound")));
91  OutStreamer.EmitSymbolAttribute(SymGlob, MCSA_Global);
92  OutStreamer.EmitAssignment(SymGlob,
93  MCConstantExpr::Create(ATy->getNumElements(),
94  OutContext));
95  if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage()) {
96  // TODO Use COMDAT groups for LinkOnceLinkage
97  OutStreamer.EmitSymbolAttribute(SymGlob, MCSA_Weak);
98  }
99  }
100 }
101 
102 void XCoreAsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) {
103  // Check to see if this is a special global used by LLVM, if so, emit it.
104  if (!GV->hasInitializer() ||
105  EmitSpecialLLVMGlobal(GV))
106  return;
107 
108  const DataLayout *TD = TM.getDataLayout();
109  OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(GV, Mang,TM));
110 
111 
112  MCSymbol *GVSym = getSymbol(GV);
113  const Constant *C = GV->getInitializer();
115 
116  // Mark the start of the global
117  OutStreamer.EmitRawText("\t.cc_top " + Twine(GVSym->getName()) + ".data," +
118  GVSym->getName());
119 
120  switch (GV->getLinkage()) {
122  report_fatal_error("AppendingLinkage is not supported by this target!");
128  emitArrayBound(GVSym, GV);
129  OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Global);
130 
131  // TODO Use COMDAT groups for LinkOnceLinkage
132  if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage())
133  OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Weak);
134  // FALL THROUGH
137  break;
139  llvm_unreachable("DLLImport linkage is not supported by this target!");
141  llvm_unreachable("DLLExport linkage is not supported by this target!");
142  default:
143  llvm_unreachable("Unknown linkage type!");
144  }
145 
146  EmitAlignment(Align > 2 ? Align : 2, GV);
147 
148  if (GV->isThreadLocal()) {
149  report_fatal_error("TLS is not supported by this target!");
150  }
151  unsigned Size = TD->getTypeAllocSize(C->getType());
152  if (MAI->hasDotTypeDotSizeDirective()) {
153  OutStreamer.EmitSymbolAttribute(GVSym, MCSA_ELF_TypeObject);
154  OutStreamer.EmitRawText("\t.size " + Twine(GVSym->getName()) + "," +
155  Twine(Size));
156  }
157  OutStreamer.EmitLabel(GVSym);
158 
159  EmitGlobalConstant(C);
160  // The ABI requires that unsigned scalar types smaller than 32 bits
161  // are padded to 32 bits.
162  if (Size < 4)
163  OutStreamer.EmitZeros(4 - Size);
164 
165  // Mark the end of the global
166  OutStreamer.EmitRawText("\t.cc_bottom " + Twine(GVSym->getName()) + ".data");
167 }
168 
169 void XCoreAsmPrinter::EmitFunctionBodyStart() {
170  MCInstLowering.Initialize(Mang, &MF->getContext());
171 }
172 
173 /// EmitFunctionBodyEnd - Targets can override this to emit stuff after
174 /// the last basic block in the function.
175 void XCoreAsmPrinter::EmitFunctionBodyEnd() {
176  // Emit function end directives
177  OutStreamer.EmitRawText("\t.cc_bottom " + Twine(CurrentFnSym->getName()) +
178  ".function");
179 }
180 
181 void XCoreAsmPrinter::EmitFunctionEntryLabel() {
182  // Mark the start of the function
183  OutStreamer.EmitRawText("\t.cc_top " + Twine(CurrentFnSym->getName()) +
184  ".function," + CurrentFnSym->getName());
185  OutStreamer.EmitLabel(CurrentFnSym);
186 }
187 
188 void XCoreAsmPrinter::
189 printInlineJT(const MachineInstr *MI, int opNum, raw_ostream &O,
190  const std::string &directive) {
191  unsigned JTI = MI->getOperand(opNum).getIndex();
192  const MachineFunction *MF = MI->getParent()->getParent();
193  const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
194  const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
195  const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
196  O << "\t" << directive << " ";
197  for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) {
198  MachineBasicBlock *MBB = JTBBs[i];
199  if (i > 0)
200  O << ",";
201  O << *MBB->getSymbol();
202  }
203 }
204 
205 void XCoreAsmPrinter::printOperand(const MachineInstr *MI, int opNum,
206  raw_ostream &O) {
207  const MachineOperand &MO = MI->getOperand(opNum);
208  switch (MO.getType()) {
211  break;
213  O << MO.getImm();
214  break;
216  O << *MO.getMBB()->getSymbol();
217  break;
219  O << *getSymbol(MO.getGlobal());
220  break;
222  O << MO.getSymbolName();
223  break;
225  O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
226  << '_' << MO.getIndex();
227  break;
229  O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
230  << '_' << MO.getIndex();
231  break;
233  O << *GetBlockAddressSymbol(MO.getBlockAddress());
234  break;
235  default:
236  llvm_unreachable("not implemented");
237  }
238 }
239 
240 /// PrintAsmOperand - Print out an operand for an inline asm expression.
241 ///
242 bool XCoreAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
243  unsigned AsmVariant,const char *ExtraCode,
244  raw_ostream &O) {
245  // Print the operand if there is no operand modifier.
246  if (!ExtraCode || !ExtraCode[0]) {
247  printOperand(MI, OpNo, O);
248  return false;
249  }
250 
251  // Otherwise fallback on the default implementation.
252  return AsmPrinter::PrintAsmOperand(MI, OpNo, AsmVariant, ExtraCode, O);
253 }
254 
255 void XCoreAsmPrinter::EmitInstruction(const MachineInstr *MI) {
256  SmallString<128> Str;
257  raw_svector_ostream O(Str);
258 
259  switch (MI->getOpcode()) {
260  case XCore::DBG_VALUE:
261  llvm_unreachable("Should be handled target independently");
262  case XCore::ADD_2rus:
263  if (MI->getOperand(2).getImm() == 0) {
264  O << "\tmov "
266  << XCoreInstPrinter::getRegisterName(MI->getOperand(1).getReg());
267  OutStreamer.EmitRawText(O.str());
268  return;
269  }
270  break;
271  case XCore::BR_JT:
272  case XCore::BR_JT32:
273  O << "\tbru "
275  if (MI->getOpcode() == XCore::BR_JT)
276  printInlineJT(MI, 0, O);
277  else
278  printInlineJT32(MI, 0, O);
279  O << '\n';
280  OutStreamer.EmitRawText(O.str());
281  return;
282  }
283 
284  MCInst TmpInst;
285  MCInstLowering.Lower(MI, TmpInst);
286 
287  OutStreamer.EmitInstruction(TmpInst);
288 }
289 
290 // Force static initialization.
291 extern "C" void LLVMInitializeXCoreAsmPrinter() {
293 }
const MachineFunction * getParent() const
LinkageTypes getLinkage() const
Definition: GlobalValue.h:218
const GlobalValue * getGlobal() const
Special purpose, only applies to global arrays.
Definition: GlobalValue.h:40
.type _foo, STT_OBJECT # aka
Definition: MCDirectives.h:25
MachineBasicBlock * getMBB() const
static const MCConstantExpr * Create(int64_t Value, MCContext &Ctx)
Definition: MCExpr.cpp:152
Same, but only replaced by something equivalent.
Definition: GlobalValue.h:39
This class is used to lower an MachineInstr into an MCInst.
Like Internal, but omit from symbol table.
Definition: GlobalValue.h:42
Externally visible function.
Definition: GlobalValue.h:34
const char * getSymbolName() const
const Constant * getInitializer() const
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const char *reason, bool gen_crash_diag=true)
Address of indexed Jump Table for switch.
const std::vector< MachineJumpTableEntry > & getJumpTables() const
unsigned getPreferredTypeAlignmentShift(Type *Ty) const
Definition: DataLayout.cpp:604
bool isThreadLocal() const
If the value is "Thread Local", its value isn't shared by the threads.
#define llvm_unreachable(msg)
int getOpcode() const
Definition: MachineInstr.h:261
Function to be imported from DLL.
Definition: GlobalValue.h:45
const MachineJumpTableInfo * getJumpTableInfo() const
int64_t getImm() const
Address of indexed Constant in Constant Pool.
const MachineBasicBlock * getParent() const
Definition: MachineInstr.h:119
Same, but only replaced by something equivalent.
Definition: GlobalValue.h:37
LLVM Constant Representation.
Definition: Constant.h:41
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:267
virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, unsigned AsmVariant, const char *ExtraCode, raw_ostream &OS)
void LLVMInitializeXCoreAsmPrinter()
Function to be accessible from DLL.
Definition: GlobalValue.h:46
bool hasWeakLinkage() const
Definition: GlobalValue.h:201
MCSymbol * getSymbol() const
bool hasExternalLinkage() const
Definition: GlobalValue.h:194
const STC & getSubtarget() const
uint64_t getTypeAllocSize(Type *Ty) const
Definition: DataLayout.h:326
Keep one copy of function when linking (inline)
Definition: GlobalValue.h:36
Type * getType() const
Definition: Value.h:111
bool hasInitializer() const
static cl::opt< AlignMode > Align(cl::desc("Load/store alignment support"), cl::Hidden, cl::init(DefaultAlign), cl::values(clEnumValN(DefaultAlign,"arm-default-align","Generate unaligned accesses only on hardware/OS ""combinations that are known to support them"), clEnumValN(StrictAlign,"arm-strict-align","Disallow all unaligned memory accesses"), clEnumValN(NoStrictAlign,"arm-no-strict-align","Allow unaligned memory accesses"), clEnumValEnd))
bool hasLinkOnceLinkage() const
Definition: GlobalValue.h:198
MachineOperandType getType() const
PointerType * getType() const
getType - Global values are always pointers.
Definition: GlobalValue.h:107
StringRef getName() const
getName - Get the symbol name.
Definition: MCSymbol.h:70
.type _foo,
Definition: MCDirectives.h:30
Target TheXCoreTarget
DBG_VALUE - a mapping of the llvm.dbg.value intrinsic.
Definition: TargetOpcodes.h:69
Keep one copy of named function when linking (weak)
Definition: GlobalValue.h:38
Rename collisions when linking (static functions).
Definition: GlobalValue.h:41
This file contains the declaration of the XCoreInstPrinter class, which is used to print XCore MCInst...
unsigned getReg() const
getReg - Returns the register number.
Address of a basic block.
const BlockAddress * getBlockAddress() const
static RegisterPass< NVPTXAllocaHoisting > X("alloca-hoisting","Hoisting alloca instructions in non-entry ""blocks to the entry block")
INITIALIZE_PASS(GlobalMerge,"global-merge","Global Merge", false, false) bool GlobalMerge const DataLayout * TD
MachineBasicBlock reference.
static const char * getRegisterName(unsigned RegNo)
Address of a global value.
Name of external global symbol.