LLVM  9.0.0svn
XCoreAsmPrinter.cpp
Go to the documentation of this file.
1 //===-- XCoreAsmPrinter.cpp - XCore 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 the XAS-format XCore assembly language.
11 //
12 //===----------------------------------------------------------------------===//
13 
15 #include "XCore.h"
16 #include "XCoreInstrInfo.h"
17 #include "XCoreMCInstLower.h"
18 #include "XCoreSubtarget.h"
19 #include "XCoreTargetMachine.h"
20 #include "XCoreTargetStreamer.h"
21 #include "llvm/ADT/SmallString.h"
22 #include "llvm/ADT/StringExtras.h"
29 #include "llvm/IR/Constants.h"
30 #include "llvm/IR/DataLayout.h"
31 #include "llvm/IR/DebugInfo.h"
32 #include "llvm/IR/DerivedTypes.h"
33 #include "llvm/IR/Mangler.h"
34 #include "llvm/IR/Module.h"
35 #include "llvm/MC/MCAsmInfo.h"
36 #include "llvm/MC/MCExpr.h"
37 #include "llvm/MC/MCInst.h"
38 #include "llvm/MC/MCStreamer.h"
39 #include "llvm/MC/MCSymbolELF.h"
44 #include <algorithm>
45 #include <cctype>
46 using namespace llvm;
47 
48 #define DEBUG_TYPE "asm-printer"
49 
50 namespace {
51  class XCoreAsmPrinter : public AsmPrinter {
52  XCoreMCInstLower MCInstLowering;
53  XCoreTargetStreamer &getTargetStreamer();
54 
55  public:
56  explicit XCoreAsmPrinter(TargetMachine &TM,
57  std::unique_ptr<MCStreamer> Streamer)
58  : AsmPrinter(TM, std::move(Streamer)), MCInstLowering(*this) {}
59 
60  StringRef getPassName() const override { return "XCore Assembly Printer"; }
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) override;
71  bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum,
72  unsigned AsmVariant, const char *ExtraCode,
73  raw_ostream &O) override;
74 
75  void emitArrayBound(MCSymbol *Sym, const GlobalVariable *GV);
76  void EmitGlobalVariable(const GlobalVariable *GV) override;
77 
78  void EmitFunctionEntryLabel() override;
79  void EmitInstruction(const MachineInstr *MI) override;
80  void EmitFunctionBodyStart() override;
81  void EmitFunctionBodyEnd() override;
82  };
83 } // end of anonymous namespace
84 
85 XCoreTargetStreamer &XCoreAsmPrinter::getTargetStreamer() {
86  return static_cast<XCoreTargetStreamer&>(*OutStreamer->getTargetStreamer());
87 }
88 
89 void XCoreAsmPrinter::emitArrayBound(MCSymbol *Sym, const GlobalVariable *GV) {
90  assert( ( GV->hasExternalLinkage() || GV->hasWeakLinkage() ||
91  GV->hasLinkOnceLinkage() || GV->hasCommonLinkage() ) &&
92  "Unexpected linkage");
93  if (ArrayType *ATy = dyn_cast<ArrayType>(GV->getValueType())) {
94 
95  MCSymbol *SymGlob = OutContext.getOrCreateSymbol(
96  Twine(Sym->getName() + StringRef(".globound")));
97  OutStreamer->EmitSymbolAttribute(SymGlob, MCSA_Global);
98  OutStreamer->EmitAssignment(SymGlob,
99  MCConstantExpr::create(ATy->getNumElements(),
100  OutContext));
101  if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage() ||
102  GV->hasCommonLinkage()) {
103  OutStreamer->EmitSymbolAttribute(SymGlob, MCSA_Weak);
104  }
105  }
106 }
107 
108 void XCoreAsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) {
109  // Check to see if this is a special global used by LLVM, if so, emit it.
110  if (!GV->hasInitializer() ||
111  EmitSpecialLLVMGlobal(GV))
112  return;
113 
114  const DataLayout &DL = getDataLayout();
115  OutStreamer->SwitchSection(getObjFileLowering().SectionForGlobal(GV, TM));
116 
117  MCSymbol *GVSym = getSymbol(GV);
118  const Constant *C = GV->getInitializer();
120 
121  // Mark the start of the global
122  getTargetStreamer().emitCCTopData(GVSym->getName());
123 
124  switch (GV->getLinkage()) {
126  report_fatal_error("AppendingLinkage is not supported by this target!");
133  emitArrayBound(GVSym, GV);
134  OutStreamer->EmitSymbolAttribute(GVSym, MCSA_Global);
135 
136  if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage() ||
137  GV->hasCommonLinkage())
138  OutStreamer->EmitSymbolAttribute(GVSym, MCSA_Weak);
142  break;
143  default:
144  llvm_unreachable("Unknown linkage type!");
145  }
146 
147  EmitAlignment(Align > 2 ? Align : 2, GV);
148 
149  if (GV->isThreadLocal()) {
150  report_fatal_error("TLS is not supported by this target!");
151  }
152  unsigned Size = DL.getTypeAllocSize(C->getType());
153  if (MAI->hasDotTypeDotSizeDirective()) {
154  OutStreamer->EmitSymbolAttribute(GVSym, MCSA_ELF_TypeObject);
155  OutStreamer->emitELFSize(GVSym, MCConstantExpr::create(Size, OutContext));
156  }
157  OutStreamer->EmitLabel(GVSym);
158 
159  EmitGlobalConstant(DL, 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  getTargetStreamer().emitCCBottomData(GVSym->getName());
167 }
168 
169 void XCoreAsmPrinter::EmitFunctionBodyStart() {
170  MCInstLowering.Initialize(&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  getTargetStreamer().emitCCBottomFunction(CurrentFnSym->getName());
178 }
179 
180 void XCoreAsmPrinter::EmitFunctionEntryLabel() {
181  // Mark the start of the function
182  getTargetStreamer().emitCCTopFunction(CurrentFnSym->getName());
183  OutStreamer->EmitLabel(CurrentFnSym);
184 }
185 
186 void XCoreAsmPrinter::
187 printInlineJT(const MachineInstr *MI, int opNum, raw_ostream &O,
188  const std::string &directive) {
189  unsigned JTI = MI->getOperand(opNum).getIndex();
190  const MachineFunction *MF = MI->getParent()->getParent();
191  const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
192  const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
193  const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
194  O << "\t" << directive << " ";
195  for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) {
196  MachineBasicBlock *MBB = JTBBs[i];
197  if (i > 0)
198  O << ",";
199  MBB->getSymbol()->print(O, MAI);
200  }
201 }
202 
203 void XCoreAsmPrinter::printOperand(const MachineInstr *MI, int opNum,
204  raw_ostream &O) {
205  const DataLayout &DL = getDataLayout();
206  const MachineOperand &MO = MI->getOperand(opNum);
207  switch (MO.getType()) {
210  break;
212  O << MO.getImm();
213  break;
215  MO.getMBB()->getSymbol()->print(O, MAI);
216  break;
218  getSymbol(MO.getGlobal())->print(O, MAI);
219  break;
221  O << DL.getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_'
222  << MO.getIndex();
223  break;
225  GetBlockAddressSymbol(MO.getBlockAddress())->print(O, MAI);
226  break;
227  default:
228  llvm_unreachable("not implemented");
229  }
230 }
231 
232 /// PrintAsmOperand - Print out an operand for an inline asm expression.
233 ///
234 bool XCoreAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
235  unsigned AsmVariant,const char *ExtraCode,
236  raw_ostream &O) {
237  // Print the operand if there is no operand modifier.
238  if (!ExtraCode || !ExtraCode[0]) {
239  printOperand(MI, OpNo, O);
240  return false;
241  }
242 
243  // Otherwise fallback on the default implementation.
244  return AsmPrinter::PrintAsmOperand(MI, OpNo, AsmVariant, ExtraCode, O);
245 }
246 
247 bool XCoreAsmPrinter::
248 PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum,
249  unsigned AsmVariant, const char *ExtraCode,
250  raw_ostream &O) {
251  if (ExtraCode && ExtraCode[0]) {
252  return true; // Unknown modifier.
253  }
254  printOperand(MI, OpNum, O);
255  O << '[';
256  printOperand(MI, OpNum + 1, O);
257  O << ']';
258  return false;
259 }
260 
261 void XCoreAsmPrinter::EmitInstruction(const MachineInstr *MI) {
262  SmallString<128> Str;
263  raw_svector_ostream O(Str);
264 
265  switch (MI->getOpcode()) {
266  case XCore::DBG_VALUE:
267  llvm_unreachable("Should be handled target independently");
268  case XCore::ADD_2rus:
269  if (MI->getOperand(2).getImm() == 0) {
270  O << "\tmov "
273  OutStreamer->EmitRawText(O.str());
274  return;
275  }
276  break;
277  case XCore::BR_JT:
278  case XCore::BR_JT32:
279  O << "\tbru "
281  if (MI->getOpcode() == XCore::BR_JT)
282  printInlineJT(MI, 0, O);
283  else
284  printInlineJT32(MI, 0, O);
285  O << '\n';
286  OutStreamer->EmitRawText(O.str());
287  return;
288  }
289 
290  MCInst TmpInst;
291  MCInstLowering.Lower(MI, TmpInst);
292 
293  EmitToStreamer(*OutStreamer, TmpInst);
294 }
295 
296 // Force static initialization.
297 extern "C" void LLVMInitializeXCoreAsmPrinter() {
299 }
uint64_t CallInst * C
A parsed version of the target data layout string in and methods for querying it. ...
Definition: DataLayout.h:110
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
const std::vector< MachineJumpTableEntry > & getJumpTables() const
Special purpose, only applies to global arrays.
Definition: GlobalValue.h:54
MachineBasicBlock * getMBB() const
const Constant * getInitializer() const
getInitializer - Return the initializer for this global variable.
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:139
This class represents lattice values for constants.
Definition: AllocatorList.h:23
.type _foo, STT_OBJECT # aka
Definition: MCDirectives.h:25
StringRef getPrivateGlobalPrefix() const
Definition: DataLayout.h:293
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:41
Same, but only replaced by something equivalent.
Definition: GlobalValue.h:53
This class is used to lower an MachineInstr into an MCInst.
unsigned getReg() const
getReg - Returns the register number.
Like Internal, but omit from symbol table.
Definition: GlobalValue.h:56
Externally visible function.
Definition: GlobalValue.h:48
A raw_ostream that writes to an SmallVector or SmallString.
Definition: raw_ostream.h:509
MachineBasicBlock reference.
Tentative definitions.
Definition: GlobalValue.h:58
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:80
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:408
bool hasCommonLinkage() const
Definition: GlobalValue.h:439
bool hasExternalLinkage() const
Definition: GlobalValue.h:421
Type * getType() const
All values are typed, get the type of this value.
Definition: Value.h:244
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:743
Class to represent array types.
Definition: DerivedTypes.h:400
RegisterAsmPrinter - Helper template for registering a target specific assembly printer, for use in the target machine initialization function.
LinkageTypes getLinkage() const
Definition: GlobalValue.h:450
bool hasLinkOnceLinkage() const
Definition: GlobalValue.h:425
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
Address of a global value.
Same, but only replaced by something equivalent.
Definition: GlobalValue.h:51
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 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
Address of a basic block.
void LLVMInitializeXCoreAsmPrinter()
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
bool hasWeakLinkage() const
Definition: GlobalValue.h:429
Target & getTheXCoreTarget()
MachineOperand class - Representation of each machine instruction operand.
Keep one copy of function when linking (inline)
Definition: GlobalValue.h:50
Module.h This file contains the declarations for the Module class.
StringRef str()
Return a StringRef for the vector contents.
Definition: raw_ostream.h:534
int64_t getImm() const
const MachineBasicBlock * getParent() const
Definition: MachineInstr.h:253
uint64_t getTypeAllocSize(Type *Ty) const
Returns the offset in bytes between successive objects of the specified type, including alignment pad...
Definition: DataLayout.h:435
BR_JT - Jumptable branch.
Definition: ISDOpcodes.h:639
Representation of each machine instruction.
Definition: MachineInstr.h:63
static bool printOperand(raw_ostream &OS, const SelectionDAG *G, const SDValue Value)
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
.type _foo,
Definition: MCDirectives.h:30
const BlockAddress * getBlockAddress() const
MCSymbol * getSymbol() const
Return the MCSymbol for this basic block.
Type * getValueType() const
Definition: GlobalValue.h:275
uint32_t Size
Definition: Profile.cpp:46
Keep one copy of named function when linking (weak)
Definition: GlobalValue.h:52
Rename collisions when linking (static functions).
Definition: GlobalValue.h:55
This file contains the declaration of the XCoreInstPrinter class, which is used to print XCore MCInst...
StringRef getName() const
getName - Get the symbol name.
Definition: MCSymbol.h:202
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
bool hasInitializer() const
Definitions have initializers, declarations don&#39;t.
#define LLVM_FALLTHROUGH
LLVM_FALLTHROUGH - Mark fallthrough cases in switch statements.
Definition: Compiler.h:250
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:45
Primary interface to the complete machine description for the target machine.
Definition: TargetMachine.h:58
bool isThreadLocal() const
If the value is "Thread Local", its value isn&#39;t shared by the threads.
Definition: GlobalValue.h:246
IRTranslator LLVM IR MI
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:48
Address of indexed Constant in Constant Pool.
const MachineJumpTableInfo * getJumpTableInfo() const
getJumpTableInfo - Return the jump table info object for the current function.
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:413
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
static const MCConstantExpr * create(int64_t Value, MCContext &Ctx)
Definition: MCExpr.cpp:163
static const char * getRegisterName(unsigned RegNo)
void print(raw_ostream &OS, const MCAsmInfo *MAI) const
print - Print the value to the stream OS.
Definition: MCSymbol.cpp:59