LLVM 22.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>
41#include <cctype>
42using namespace llvm;
43
44#define DEBUG_TYPE "asm-printer"
45
46namespace {
47 class XCoreAsmPrinter : public AsmPrinter {
48 XCoreMCInstLower MCInstLowering;
49 XCoreTargetStreamer &getTargetStreamer();
50
51 public:
52 static char ID;
53
54 explicit XCoreAsmPrinter(TargetMachine &TM,
55 std::unique_ptr<MCStreamer> Streamer)
56 : AsmPrinter(TM, std::move(Streamer), ID), MCInstLowering(*this) {}
57
58 StringRef getPassName() const override { return "XCore Assembly Printer"; }
59
60 void printInlineJT(const MachineInstr *MI, int opNum, raw_ostream &O,
61 const std::string &directive = ".jmptable");
62 void printInlineJT32(const MachineInstr *MI, int opNum, raw_ostream &O) {
63 printInlineJT(MI, opNum, O, ".jmptable32");
64 }
65 void printOperand(const MachineInstr *MI, int opNum, raw_ostream &O);
66 bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
67 const char *ExtraCode, raw_ostream &O) override;
68 bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum,
69 const char *ExtraCode, raw_ostream &O) override;
70
71 void emitArrayBound(MCSymbol *Sym, const GlobalVariable *GV);
72 void emitGlobalVariable(const GlobalVariable *GV) override;
73
74 void emitFunctionEntryLabel() override;
75 void emitInstruction(const MachineInstr *MI) override;
76 void emitFunctionBodyStart() override;
77 void emitFunctionBodyEnd() override;
78 };
79} // end of anonymous namespace
80
81XCoreTargetStreamer &XCoreAsmPrinter::getTargetStreamer() {
82 return static_cast<XCoreTargetStreamer&>(*OutStreamer->getTargetStreamer());
83}
84
85void XCoreAsmPrinter::emitArrayBound(MCSymbol *Sym, const GlobalVariable *GV) {
86 assert( ( GV->hasExternalLinkage() || GV->hasWeakLinkage() ||
87 GV->hasLinkOnceLinkage() || GV->hasCommonLinkage() ) &&
88 "Unexpected linkage");
89 if (ArrayType *ATy = dyn_cast<ArrayType>(GV->getValueType())) {
90
91 MCSymbol *SymGlob = OutContext.getOrCreateSymbol(
92 Twine(Sym->getName() + StringRef(".globound")));
93 OutStreamer->emitSymbolAttribute(SymGlob, MCSA_Global);
94 OutStreamer->emitAssignment(SymGlob,
95 MCConstantExpr::create(ATy->getNumElements(),
96 OutContext));
97 if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage() ||
98 GV->hasCommonLinkage()) {
99 OutStreamer->emitSymbolAttribute(SymGlob, MCSA_Weak);
100 }
101 }
102}
103
104void XCoreAsmPrinter::emitGlobalVariable(const GlobalVariable *GV) {
105 // Check to see if this is a special global used by LLVM, if so, emit it.
106 if (!GV->hasInitializer() || emitSpecialLLVMGlobal(GV))
107 return;
108
109 const DataLayout &DL = getDataLayout();
110 OutStreamer->switchSection(getObjFileLowering().SectionForGlobal(GV, TM));
111
112 MCSymbol *GVSym = getSymbol(GV);
113 const Constant *C = GV->getInitializer();
114 const Align Alignment = DL.getPrefTypeAlign(C->getType());
115
116 // Mark the start of the global
117 getTargetStreamer().emitCCTopData(GVSym->getName());
118
119 switch (GV->getLinkage()) {
121 report_fatal_error("AppendingLinkage is not supported by this target!");
128 emitArrayBound(GVSym, GV);
129 OutStreamer->emitSymbolAttribute(GVSym, MCSA_Global);
130
131 if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage() ||
132 GV->hasCommonLinkage())
133 OutStreamer->emitSymbolAttribute(GVSym, MCSA_Weak);
134 [[fallthrough]];
137 break;
138 default:
139 llvm_unreachable("Unknown linkage type!");
140 }
141
142 emitAlignment(std::max(Alignment, Align(4)), GV);
143
144 if (GV->isThreadLocal()) {
145 report_fatal_error("TLS is not supported by this target!");
146 }
147 unsigned Size = DL.getTypeAllocSize(C->getType());
148 if (MAI->hasDotTypeDotSizeDirective()) {
149 OutStreamer->emitSymbolAttribute(GVSym, MCSA_ELF_TypeObject);
150 OutStreamer->emitELFSize(GVSym, MCConstantExpr::create(Size, OutContext));
151 }
152 OutStreamer->emitLabel(GVSym);
153
154 emitGlobalConstant(DL, C);
155 // The ABI requires that unsigned scalar types smaller than 32 bits
156 // are padded to 32 bits.
157 if (Size < 4)
158 OutStreamer->emitZeros(4 - Size);
159
160 // Mark the end of the global
161 getTargetStreamer().emitCCBottomData(GVSym->getName());
162}
163
164void XCoreAsmPrinter::emitFunctionBodyStart() {
165 MCInstLowering.Initialize(&MF->getContext());
166}
167
168/// EmitFunctionBodyEnd - Targets can override this to emit stuff after
169/// the last basic block in the function.
170void XCoreAsmPrinter::emitFunctionBodyEnd() {
171 // Emit function end directives
172 getTargetStreamer().emitCCBottomFunction(CurrentFnSym->getName());
173}
174
175void XCoreAsmPrinter::emitFunctionEntryLabel() {
176 // Mark the start of the function
177 getTargetStreamer().emitCCTopFunction(CurrentFnSym->getName());
178 OutStreamer->emitLabel(CurrentFnSym);
179}
180
181void XCoreAsmPrinter::
182printInlineJT(const MachineInstr *MI, int opNum, raw_ostream &O,
183 const std::string &directive) {
184 unsigned JTI = MI->getOperand(opNum).getIndex();
185 const MachineFunction *MF = MI->getParent()->getParent();
186 const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
187 const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
188 const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
189 O << "\t" << directive << " ";
190 for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) {
191 MachineBasicBlock *MBB = JTBBs[i];
192 if (i > 0)
193 O << ",";
194 MBB->getSymbol()->print(O, MAI);
195 }
196}
197
198void XCoreAsmPrinter::printOperand(const MachineInstr *MI, int opNum,
199 raw_ostream &O) {
200 const DataLayout &DL = getDataLayout();
201 const MachineOperand &MO = MI->getOperand(opNum);
202 switch (MO.getType()) {
205 break;
207 O << MO.getImm();
208 break;
210 MO.getMBB()->getSymbol()->print(O, MAI);
211 break;
213 PrintSymbolOperand(MO, O);
214 break;
216 O << DL.getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_'
217 << MO.getIndex();
218 break;
220 GetBlockAddressSymbol(MO.getBlockAddress())->print(O, MAI);
221 break;
222 default:
223 llvm_unreachable("not implemented");
224 }
225}
226
227/// PrintAsmOperand - Print out an operand for an inline asm expression.
228///
229bool XCoreAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
230 const char *ExtraCode, raw_ostream &O) {
231 // Print the operand if there is no operand modifier.
232 if (!ExtraCode || !ExtraCode[0]) {
233 printOperand(MI, OpNo, O);
234 return false;
235 }
236
237 // Otherwise fallback on the default implementation.
238 return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, O);
239}
240
241bool XCoreAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
242 unsigned OpNum,
243 const char *ExtraCode,
244 raw_ostream &O) {
245 if (ExtraCode && ExtraCode[0]) {
246 return true; // Unknown modifier.
247 }
248 printOperand(MI, OpNum, O);
249 O << '[';
250 printOperand(MI, OpNum + 1, O);
251 O << ']';
252 return false;
253}
254
255void XCoreAsmPrinter::emitInstruction(const MachineInstr *MI) {
256 XCore_MC::verifyInstructionPredicates(MI->getOpcode(),
257 getSubtargetInfo().getFeatureBits());
258
259 SmallString<128> Str;
260 raw_svector_ostream O(Str);
261
262 switch (MI->getOpcode()) {
263 case XCore::DBG_VALUE:
264 llvm_unreachable("Should be handled target independently");
265 case XCore::ADD_2rus:
266 if (MI->getOperand(2).getImm() == 0) {
267 O << "\tmov "
268 << XCoreInstPrinter::getRegisterName(MI->getOperand(0).getReg()) << ", "
269 << XCoreInstPrinter::getRegisterName(MI->getOperand(1).getReg());
270 OutStreamer->emitRawText(O.str());
271 return;
272 }
273 break;
274 case XCore::BR_JT:
275 case XCore::BR_JT32:
276 O << "\tbru "
277 << XCoreInstPrinter::getRegisterName(MI->getOperand(1).getReg()) << '\n';
278 if (MI->getOpcode() == XCore::BR_JT)
279 printInlineJT(MI, 0, O);
280 else
281 printInlineJT32(MI, 0, O);
282 O << '\n';
283 OutStreamer->emitRawText(O.str());
284 return;
285 }
286
287 MCInst TmpInst;
288 MCInstLowering.Lower(MI, TmpInst);
289
290 EmitToStreamer(*OutStreamer, TmpInst);
291}
292
293char XCoreAsmPrinter::ID = 0;
294
295INITIALIZE_PASS(XCoreAsmPrinter, "xcore-asm-printer", "XCore Assembly Printer",
296 false, false)
297
298// Force static initialization.
300LLVMInitializeXCoreAsmPrinter() {
302}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
#define LLVM_ABI
Definition Compiler.h:213
#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.
static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
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:90
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.
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
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.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
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:649
Target & getTheXCoreTarget()
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:167
@ 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,...