LLVM 24.0.0git
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
17#include "XCore.h"
18#include "XCoreMCInstLower.h"
19#include "XCoreSubtarget.h"
20#include "XCoreTargetMachine.h"
28#include "llvm/IR/DataLayout.h"
30#include "llvm/IR/Mangler.h"
31#include "llvm/MC/MCAsmInfo.h"
32#include "llvm/MC/MCExpr.h"
33#include "llvm/MC/MCInst.h"
34#include "llvm/MC/MCStreamer.h"
40#include <algorithm>
41using namespace llvm;
42
43#define DEBUG_TYPE "asm-printer"
44
45namespace {
46 class XCoreAsmPrinter : public AsmPrinter {
47 XCoreMCInstLower MCInstLowering;
48 XCoreTargetStreamer &getTargetStreamer();
49
50 public:
51 static char ID;
52
53 explicit XCoreAsmPrinter(TargetMachine &TM,
54 std::unique_ptr<MCStreamer> Streamer)
55 : AsmPrinter(TM, std::move(Streamer), ID), MCInstLowering(*this) {}
56
57 StringRef getPassName() const override { return "XCore Assembly Printer"; }
58
59 void printInlineJT(const MachineInstr *MI, int opNum, raw_ostream &O,
60 const std::string &directive = ".jmptable");
61 void printInlineJT32(const MachineInstr *MI, int opNum, raw_ostream &O) {
62 printInlineJT(MI, opNum, O, ".jmptable32");
63 }
64 void printOperand(const MachineInstr *MI, int opNum, raw_ostream &O);
65 bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
66 const char *ExtraCode, raw_ostream &O) override;
67 bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum,
68 const char *ExtraCode, raw_ostream &O) override;
69
70 void emitArrayBound(MCSymbol *Sym, const GlobalVariable *GV);
71 void emitGlobalVariable(const GlobalVariable *GV) override;
72
73 void emitFunctionEntryLabel() override;
74 void emitInstruction(const MachineInstr *MI) override;
75 void emitFunctionBodyStart() override;
76 void emitFunctionBodyEnd() override;
77 };
78} // end of anonymous namespace
79
80XCoreTargetStreamer &XCoreAsmPrinter::getTargetStreamer() {
81 return static_cast<XCoreTargetStreamer&>(*OutStreamer->getTargetStreamer());
82}
83
84void XCoreAsmPrinter::emitArrayBound(MCSymbol *Sym, const GlobalVariable *GV) {
85 assert( ( GV->hasExternalLinkage() || GV->hasWeakLinkage() ||
86 GV->hasLinkOnceLinkage() || GV->hasCommonLinkage() ) &&
87 "Unexpected linkage");
88 if (ArrayType *ATy = dyn_cast<ArrayType>(GV->getValueType())) {
89
90 MCSymbol *SymGlob = OutContext.getOrCreateSymbol(
91 Twine(Sym->getName() + StringRef(".globound")));
92 OutStreamer->emitSymbolAttribute(SymGlob, MCSA_Global);
93 OutStreamer->emitAssignment(SymGlob,
94 MCConstantExpr::create(ATy->getNumElements(),
95 OutContext));
96 if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage() ||
97 GV->hasCommonLinkage()) {
98 OutStreamer->emitSymbolAttribute(SymGlob, MCSA_Weak);
99 }
100 }
101}
102
103void XCoreAsmPrinter::emitGlobalVariable(const GlobalVariable *GV) {
104 // Check to see if this is a special global used by LLVM, if so, emit it.
105 if (!GV->hasInitializer() || emitSpecialLLVMGlobal(GV))
106 return;
107
108 const DataLayout &DL = getDataLayout();
109 OutStreamer->switchSection(getObjFileLowering().SectionForGlobal(GV, TM));
110
111 MCSymbol *GVSym = getSymbol(GV);
112 const Constant *C = GV->getInitializer();
113 const Align Alignment = DL.getPrefTypeAlign(C->getType());
114
115 // Mark the start of the global
116 getTargetStreamer().emitCCTopData(GVSym->getName());
117
118 switch (GV->getLinkage()) {
120 report_fatal_error("AppendingLinkage is not supported by this target!");
127 emitArrayBound(GVSym, GV);
128 OutStreamer->emitSymbolAttribute(GVSym, MCSA_Global);
129
130 if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage() ||
131 GV->hasCommonLinkage())
132 OutStreamer->emitSymbolAttribute(GVSym, MCSA_Weak);
133 [[fallthrough]];
136 break;
137 default:
138 llvm_unreachable("Unknown linkage type!");
139 }
140
141 emitAlignment(std::max(Alignment, Align(4)), GV);
142
143 if (GV->isThreadLocal()) {
144 report_fatal_error("TLS is not supported by this target!");
145 }
146 unsigned Size = DL.getTypeAllocSize(C->getType());
147 if (MAI.hasDotTypeDotSizeDirective()) {
148 OutStreamer->emitSymbolAttribute(GVSym, MCSA_ELF_TypeObject);
149 OutStreamer->emitELFSize(GVSym, MCConstantExpr::create(Size, OutContext));
150 }
151 OutStreamer->emitLabel(GVSym);
152
153 emitGlobalConstant(DL, C);
154 // The ABI requires that unsigned scalar types smaller than 32 bits
155 // are padded to 32 bits.
156 if (Size < 4)
157 OutStreamer->emitZeros(4 - Size);
158
159 // Mark the end of the global
160 getTargetStreamer().emitCCBottomData(GVSym->getName());
161}
162
163void XCoreAsmPrinter::emitFunctionBodyStart() {
164 MCInstLowering.Initialize(&MF->getContext());
165}
166
167/// EmitFunctionBodyEnd - Targets can override this to emit stuff after
168/// the last basic block in the function.
169void XCoreAsmPrinter::emitFunctionBodyEnd() {
170 // Emit function end directives
171 getTargetStreamer().emitCCBottomFunction(CurrentFnSym->getName());
172}
173
174void XCoreAsmPrinter::emitFunctionEntryLabel() {
175 // Mark the start of the function
176 getTargetStreamer().emitCCTopFunction(CurrentFnSym->getName());
177 OutStreamer->emitLabel(CurrentFnSym);
178}
179
180void XCoreAsmPrinter::
181printInlineJT(const MachineInstr *MI, int opNum, raw_ostream &O,
182 const std::string &directive) {
183 unsigned JTI = MI->getOperand(opNum).getIndex();
184 const MachineFunction *MF = MI->getParent()->getParent();
185 const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
186 const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
187 const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
188 O << "\t" << directive << " ";
189 for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) {
190 MachineBasicBlock *MBB = JTBBs[i];
191 if (i > 0)
192 O << ",";
193 MBB->getSymbol()->print(O, MAI);
194 }
195}
196
197void XCoreAsmPrinter::printOperand(const MachineInstr *MI, int opNum,
198 raw_ostream &O) {
199 const DataLayout &DL = getDataLayout();
200 const MachineOperand &MO = MI->getOperand(opNum);
201 switch (MO.getType()) {
204 break;
206 O << MO.getImm();
207 break;
209 MO.getMBB()->getSymbol()->print(O, MAI);
210 break;
212 PrintSymbolOperand(MO, O);
213 break;
215 O << DL.getInternalSymbolPrefix() << "CPI" << getFunctionNumber() << '_'
216 << MO.getIndex();
217 break;
219 GetBlockAddressSymbol(MO.getBlockAddress())->print(O, MAI);
220 break;
221 default:
222 llvm_unreachable("not implemented");
223 }
224}
225
226/// PrintAsmOperand - Print out an operand for an inline asm expression.
227///
228bool XCoreAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
229 const char *ExtraCode, raw_ostream &O) {
230 // Print the operand if there is no operand modifier.
231 if (!ExtraCode || !ExtraCode[0]) {
232 printOperand(MI, OpNo, O);
233 return false;
234 }
235
236 // Otherwise fallback on the default implementation.
237 return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, O);
238}
239
240bool XCoreAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
241 unsigned OpNum,
242 const char *ExtraCode,
243 raw_ostream &O) {
244 if (ExtraCode && ExtraCode[0]) {
245 return true; // Unknown modifier.
246 }
247 printOperand(MI, OpNum, O);
248 O << '[';
249 printOperand(MI, OpNum + 1, O);
250 O << ']';
251 return false;
252}
253
254void XCoreAsmPrinter::emitInstruction(const MachineInstr *MI) {
255 XCore_MC::verifyInstructionPredicates(MI->getOpcode(),
256 getSubtargetInfo().getFeatureBits());
257
258 SmallString<128> Str;
259 raw_svector_ostream O(Str);
260
261 switch (MI->getOpcode()) {
262 case XCore::DBG_VALUE:
263 llvm_unreachable("Should be handled target independently");
264 case XCore::ADD_2rus:
265 if (MI->getOperand(2).getImm() == 0) {
266 O << "\tmov "
267 << XCoreInstPrinter::getRegisterName(MI->getOperand(0).getReg()) << ", "
268 << XCoreInstPrinter::getRegisterName(MI->getOperand(1).getReg());
269 OutStreamer->emitRawText(O.str());
270 return;
271 }
272 break;
273 case XCore::BR_JT:
274 case XCore::BR_JT32:
275 O << "\tbru "
276 << XCoreInstPrinter::getRegisterName(MI->getOperand(1).getReg()) << '\n';
277 if (MI->getOpcode() == XCore::BR_JT)
278 printInlineJT(MI, 0, O);
279 else
280 printInlineJT32(MI, 0, O);
281 O << '\n';
282 OutStreamer->emitRawText(O.str());
283 return;
284 }
285
286 MCInst TmpInst;
287 MCInstLowering.Lower(MI, TmpInst);
288
289 EmitToStreamer(*OutStreamer, TmpInst);
290}
291
292char XCoreAsmPrinter::ID = 0;
293
294INITIALIZE_PASS(XCoreAsmPrinter, "xcore-asm-printer", "XCore Assembly Printer",
295 false, false)
296
297// Force static initialization.
299LLVMInitializeXCoreAsmPrinter() {
301}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
#define X(NUM, ENUM, NAME)
Definition ELF.h:857
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
#define LLVM_ABI
Definition Compiler.h:215
#define LLVM_EXTERNAL_VISIBILITY
Definition Compiler.h:132
IRTranslator LLVM IR MI
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
static bool printOperand(raw_ostream &OS, const SelectionDAG *G, const SDValue Value)
This file defines the SmallString class.
This file contains some functions that are useful when dealing with strings.
std::unique_ptr< MCStreamer > && Streamer
This file contains the declaration of the XCoreInstPrinter class, which is used to print XCore MCInst...
This class is intended to be used as a driving class for all asm writers.
Definition AsmPrinter.h:91
virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, const char *ExtraCode, raw_ostream &OS)
Print the specified operand of MI, an INLINEASM instruction, using the specified assembler variant.
bool hasLinkOnceLinkage() const
bool hasExternalLinkage() const
bool isThreadLocal() const
If the value is "Thread Local", its value isn't shared by the threads.
LinkageTypes getLinkage() const
bool hasWeakLinkage() const
bool hasCommonLinkage() const
@ PrivateLinkage
Like Internal, but omit from symbol table.
Definition GlobalValue.h:61
@ CommonLinkage
Tentative definitions.
Definition GlobalValue.h:63
@ InternalLinkage
Rename collisions when linking (static functions).
Definition GlobalValue.h:60
@ LinkOnceAnyLinkage
Keep one copy of function when linking (inline)
Definition GlobalValue.h:55
@ WeakODRLinkage
Same, but only replaced by something equivalent.
Definition GlobalValue.h:58
@ ExternalLinkage
Externally visible function.
Definition GlobalValue.h:53
@ WeakAnyLinkage
Keep one copy of named function when linking (weak)
Definition GlobalValue.h:57
@ AppendingLinkage
Special purpose, only applies to global arrays.
Definition GlobalValue.h:59
@ LinkOnceODRLinkage
Same, but only replaced by something equivalent.
Definition GlobalValue.h:56
Type * getValueType() const
const Constant * getInitializer() const
getInitializer - Return the initializer for this global variable.
bool hasInitializer() const
Definitions have initializers, declarations don't.
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition MCExpr.cpp:212
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition MCSymbol.h:42
LLVM_ABI void print(raw_ostream &OS, const MCAsmInfo *MAI) const
print - Print the value to the stream OS.
Definition MCSymbol.cpp:59
StringRef getName() const
getName - Get the symbol name.
Definition MCSymbol.h:188
LLVM_ABI MCSymbol * getSymbol() const
Return the MCSymbol for this basic block.
const MachineJumpTableInfo * getJumpTableInfo() const
getJumpTableInfo - Return the jump table info object for the current function.
Representation of each machine instruction.
const std::vector< MachineJumpTableEntry > & getJumpTables() const
int64_t getImm() const
MachineBasicBlock * getMBB() const
const BlockAddress * getBlockAddress() const
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
Register getReg() const
getReg - Returns the register number.
@ MO_Immediate
Immediate operand.
@ MO_ConstantPoolIndex
Address of indexed Constant in Constant Pool.
@ MO_GlobalAddress
Address of a global value.
@ MO_BlockAddress
Address of a basic block.
@ MO_MachineBasicBlock
MachineBasicBlock reference.
@ MO_Register
Register operand.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
Primary interface to the complete machine description for the target machine.
static const char * getRegisterName(MCRegister Reg)
This class is used to lower an MachineInstr into an MCInst.
void Lower(const MachineInstr *MI, MCInst &OutMI) const
void Initialize(MCContext *C)
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
This is an optimization pass for GlobalISel generic memory operations.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
Target & getTheXCoreTarget()
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:163
@ MCSA_Weak
.weak
@ MCSA_Global
.type _foo, @gnu_unique_object
@ MCSA_ELF_TypeObject
.type _foo, STT_OBJECT # aka @object
RegisterAsmPrinter - Helper template for registering a target specific assembly printer,...