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
14#include "XCoreAsmPrinter.h"
18#include "XCore.h"
19#include "XCoreMCInstLower.h"
20#include "XCoreSubtarget.h"
21#include "XCoreTargetMachine.h"
30#include "llvm/IR/DataLayout.h"
32#include "llvm/IR/Mangler.h"
33#include "llvm/MC/MCAsmInfo.h"
34#include "llvm/MC/MCExpr.h"
35#include "llvm/MC/MCInst.h"
36#include "llvm/MC/MCStreamer.h"
42#include <algorithm>
43using namespace llvm;
44
45#define DEBUG_TYPE "asm-printer"
46
47namespace {
48 class XCoreAsmPrinter : public AsmPrinter {
49 XCoreMCInstLower MCInstLowering;
50 XCoreTargetStreamer &getTargetStreamer();
51
52 public:
53 static char ID;
54
55 explicit XCoreAsmPrinter(TargetMachine &TM,
56 std::unique_ptr<MCStreamer> Streamer)
57 : AsmPrinter(TM, std::move(Streamer), ID), MCInstLowering(*this) {}
58
59 StringRef getPassName() const override { return "XCore Assembly Printer"; }
60
61 void printInlineJT(const MachineInstr *MI, int opNum, raw_ostream &O,
62 const std::string &directive = ".jmptable");
63 void printInlineJT32(const MachineInstr *MI, int opNum, raw_ostream &O) {
64 printInlineJT(MI, opNum, O, ".jmptable32");
65 }
66 void printOperand(const MachineInstr *MI, int opNum, raw_ostream &O);
67 bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
68 const char *ExtraCode, raw_ostream &O) override;
69 bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum,
70 const char *ExtraCode, raw_ostream &O) override;
71
72 void emitArrayBound(MCSymbol *Sym, const GlobalVariable *GV);
73 void emitGlobalVariable(const GlobalVariable *GV) override;
74
75 void emitFunctionEntryLabel() override;
76 void emitInstruction(const MachineInstr *MI) override;
77 void emitFunctionBodyStart() override;
78 void emitFunctionBodyEnd() override;
79 };
80} // end of anonymous namespace
81
82XCoreTargetStreamer &XCoreAsmPrinter::getTargetStreamer() {
83 return static_cast<XCoreTargetStreamer&>(*OutStreamer->getTargetStreamer());
84}
85
86void XCoreAsmPrinter::emitArrayBound(MCSymbol *Sym, const GlobalVariable *GV) {
87 assert( ( GV->hasExternalLinkage() || GV->hasWeakLinkage() ||
88 GV->hasLinkOnceLinkage() || GV->hasCommonLinkage() ) &&
89 "Unexpected linkage");
90 if (ArrayType *ATy = dyn_cast<ArrayType>(GV->getValueType())) {
91
92 MCSymbol *SymGlob = OutContext.getOrCreateSymbol(
93 Twine(Sym->getName() + StringRef(".globound")));
94 OutStreamer->emitSymbolAttribute(SymGlob, MCSA_Global);
95 OutStreamer->emitAssignment(SymGlob,
96 MCConstantExpr::create(ATy->getNumElements(),
97 OutContext));
98 if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage() ||
99 GV->hasCommonLinkage()) {
100 OutStreamer->emitSymbolAttribute(SymGlob, MCSA_Weak);
101 }
102 }
103}
104
105void XCoreAsmPrinter::emitGlobalVariable(const GlobalVariable *GV) {
106 // Check to see if this is a special global used by LLVM, if so, emit it.
107 if (!GV->hasInitializer() || emitSpecialLLVMGlobal(GV))
108 return;
109
110 const DataLayout &DL = getDataLayout();
111 OutStreamer->switchSection(getObjFileLowering().SectionForGlobal(GV, TM));
112
113 MCSymbol *GVSym = getSymbol(GV);
114 const Constant *C = GV->getInitializer();
115 const Align Alignment = DL.getPrefTypeAlign(C->getType());
116
117 // Mark the start of the global
118 getTargetStreamer().emitCCTopData(GVSym->getName());
119
120 switch (GV->getLinkage()) {
122 report_fatal_error("AppendingLinkage is not supported by this target!");
129 emitArrayBound(GVSym, GV);
130 OutStreamer->emitSymbolAttribute(GVSym, MCSA_Global);
131
132 if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage() ||
133 GV->hasCommonLinkage())
134 OutStreamer->emitSymbolAttribute(GVSym, MCSA_Weak);
135 [[fallthrough]];
138 break;
139 default:
140 llvm_unreachable("Unknown linkage type!");
141 }
142
143 emitAlignment(std::max(Alignment, Align(4)), GV);
144
145 if (GV->isThreadLocal()) {
146 report_fatal_error("TLS is not supported by this target!");
147 }
148 unsigned Size = DL.getTypeAllocSize(C->getType());
149 if (MAI.hasDotTypeDotSizeDirective()) {
150 OutStreamer->emitSymbolAttribute(GVSym, MCSA_ELF_TypeObject);
151 OutStreamer->emitELFSize(GVSym, MCConstantExpr::create(Size, OutContext));
152 }
153 OutStreamer->emitLabel(GVSym);
154
155 emitGlobalConstant(DL, C);
156 // The ABI requires that unsigned scalar types smaller than 32 bits
157 // are padded to 32 bits.
158 if (Size < 4)
159 OutStreamer->emitZeros(4 - Size);
160
161 // Mark the end of the global
162 getTargetStreamer().emitCCBottomData(GVSym->getName());
163}
164
165void XCoreAsmPrinter::emitFunctionBodyStart() {
166 MCInstLowering.Initialize(&MF->getContext());
167}
168
169/// EmitFunctionBodyEnd - Targets can override this to emit stuff after
170/// the last basic block in the function.
171void XCoreAsmPrinter::emitFunctionBodyEnd() {
172 // Emit function end directives
173 getTargetStreamer().emitCCBottomFunction(CurrentFnSym->getName());
174}
175
176void XCoreAsmPrinter::emitFunctionEntryLabel() {
177 // Mark the start of the function
178 getTargetStreamer().emitCCTopFunction(CurrentFnSym->getName());
179 OutStreamer->emitLabel(CurrentFnSym);
180}
181
182void XCoreAsmPrinter::
183printInlineJT(const MachineInstr *MI, int opNum, raw_ostream &O,
184 const std::string &directive) {
185 unsigned JTI = MI->getOperand(opNum).getIndex();
186 const MachineFunction *MF = MI->getParent()->getParent();
187 const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
188 const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
189 const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
190 O << "\t" << directive << " ";
191 for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) {
192 MachineBasicBlock *MBB = JTBBs[i];
193 if (i > 0)
194 O << ",";
195 MBB->getSymbol()->print(O, MAI);
196 }
197}
198
199void XCoreAsmPrinter::printOperand(const MachineInstr *MI, int opNum,
200 raw_ostream &O) {
201 const DataLayout &DL = getDataLayout();
202 const MachineOperand &MO = MI->getOperand(opNum);
203 switch (MO.getType()) {
206 break;
208 O << MO.getImm();
209 break;
211 MO.getMBB()->getSymbol()->print(O, MAI);
212 break;
214 PrintSymbolOperand(MO, O);
215 break;
217 O << DL.getInternalSymbolPrefix() << "CPI" << getFunctionNumber() << '_'
218 << MO.getIndex();
219 break;
221 GetBlockAddressSymbol(MO.getBlockAddress())->print(O, MAI);
222 break;
223 default:
224 llvm_unreachable("not implemented");
225 }
226}
227
228/// PrintAsmOperand - Print out an operand for an inline asm expression.
229///
230bool XCoreAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
231 const char *ExtraCode, raw_ostream &O) {
232 // Print the operand if there is no operand modifier.
233 if (!ExtraCode || !ExtraCode[0]) {
234 printOperand(MI, OpNo, O);
235 return false;
236 }
237
238 // Otherwise fallback on the default implementation.
239 return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, O);
240}
241
242bool XCoreAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
243 unsigned OpNum,
244 const char *ExtraCode,
245 raw_ostream &O) {
246 if (ExtraCode && ExtraCode[0]) {
247 return true; // Unknown modifier.
248 }
249 printOperand(MI, OpNum, O);
250 O << '[';
251 printOperand(MI, OpNum + 1, O);
252 O << ']';
253 return false;
254}
255
256void XCoreAsmPrinter::emitInstruction(const MachineInstr *MI) {
257 XCore_MC::verifyInstructionPredicates(MI->getOpcode(),
258 getSubtargetInfo().getFeatureBits());
259
260 SmallString<128> Str;
261 raw_svector_ostream O(Str);
262
263 switch (MI->getOpcode()) {
264 case XCore::DBG_VALUE:
265 llvm_unreachable("Should be handled target independently");
266 case XCore::ADD_2rus:
267 if (MI->getOperand(2).getImm() == 0) {
268 O << "\tmov "
269 << XCoreInstPrinter::getRegisterName(MI->getOperand(0).getReg()) << ", "
270 << XCoreInstPrinter::getRegisterName(MI->getOperand(1).getReg());
271 OutStreamer->emitRawText(O.str());
272 return;
273 }
274 break;
275 case XCore::BR_JT:
276 case XCore::BR_JT32:
277 O << "\tbru "
278 << XCoreInstPrinter::getRegisterName(MI->getOperand(1).getReg()) << '\n';
279 if (MI->getOpcode() == XCore::BR_JT)
280 printInlineJT(MI, 0, O);
281 else
282 printInlineJT32(MI, 0, O);
283 O << '\n';
284 OutStreamer->emitRawText(O.str());
285 return;
286 }
287
288 MCInst TmpInst;
289 MCInstLowering.Lower(MI, TmpInst);
290
291 EmitToStreamer(*OutStreamer, TmpInst);
292}
293
294char XCoreAsmPrinter::ID = 0;
295
296INITIALIZE_PASS(XCoreAsmPrinter, "xcore-asm-printer", "XCore Assembly Printer",
297 false, false)
298
299// Force static initialization.
301LLVMInitializeXCoreAsmPrinter() {
303}
304
307 XCoreAsmPrinter &AsmPrinter = static_cast<XCoreAsmPrinter &>(
308 MAM.getResult<AsmPrinterAnalysis>(M).getPrinter());
311 return PreservedAnalyses::all();
312}
313
317 XCoreAsmPrinter &AsmPrinter = static_cast<XCoreAsmPrinter &>(
319 .getCachedResult<AsmPrinterAnalysis>(*MF.getFunction().getParent())
320 ->getPrinter());
323 return PreservedAnalyses::all();
324}
325
328 XCoreAsmPrinter &AsmPrinter = static_cast<XCoreAsmPrinter &>(
329 MAM.getResult<AsmPrinterAnalysis>(M).getPrinter());
332 return PreservedAnalyses::all();
333}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static const Function * getParent(const Value *V)
#define X(NUM, ENUM, NAME)
Definition ELF.h:665
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
#define LLVM_ABI
Definition Compiler.h:211
#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 ...
ModuleAnalysisManager MAM
#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...
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
This class is intended to be used as a driving class for all asm writers.
Definition AsmPrinter.h:95
bool doInitialization(Module &M) override
Set up the AsmPrinter when we are working on a new module.
bool doFinalization(Module &M) override
Shut down the asmprinter.
bool runOnMachineFunction(MachineFunction &MF) override
Emit the specified function out to the OutStreamer.
Definition AsmPrinter.h:478
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.
Function & getFunction()
Return the LLVM function that this machine code represents.
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.
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:68
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
Primary interface to the complete machine description for the target machine.
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MFAM)
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MFAM)
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
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.
OuterAnalysisManagerProxy< ModuleAnalysisManager, MachineFunction > ModuleAnalysisManagerMachineFunctionProxy
Provide the ModuleAnalysisManager to Function proxy.
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()
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
LLVM_ABI void setupModuleAsmPrinter(Module &M, ModuleAnalysisManager &MAM, AsmPrinter &AsmPrinter)
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:163
LLVM_ABI void setupMachineFunctionAsmPrinter(MachineFunctionAnalysisManager &MFAM, MachineFunction &MF, AsmPrinter &AsmPrinter)
@ MCSA_Weak
.weak
@ MCSA_Global
.type _foo, @gnu_unique_object
@ MCSA_ELF_TypeObject
.type _foo, STT_OBJECT # aka @object
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
Definition MIRParser.h:39
RegisterAsmPrinter - Helper template for registering a target specific assembly printer,...