LLVM 20.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
16#include "XCore.h"
17#include "XCoreInstrInfo.h"
18#include "XCoreMCInstLower.h"
19#include "XCoreSubtarget.h"
20#include "XCoreTargetMachine.h"
21#include "XCoreTargetStreamer.h"
30#include "llvm/IR/Constants.h"
31#include "llvm/IR/DataLayout.h"
32#include "llvm/IR/DebugInfo.h"
34#include "llvm/IR/Mangler.h"
35#include "llvm/IR/Module.h"
36#include "llvm/MC/MCAsmInfo.h"
37#include "llvm/MC/MCExpr.h"
38#include "llvm/MC/MCInst.h"
39#include "llvm/MC/MCStreamer.h"
40#include "llvm/MC/MCSymbolELF.h"
45#include <algorithm>
46#include <cctype>
47using namespace llvm;
48
49#define DEBUG_TYPE "asm-printer"
50
51namespace {
52 class XCoreAsmPrinter : public AsmPrinter {
53 XCoreMCInstLower MCInstLowering;
54 XCoreTargetStreamer &getTargetStreamer();
55
56 public:
57 explicit XCoreAsmPrinter(TargetMachine &TM,
58 std::unique_ptr<MCStreamer> Streamer)
59 : AsmPrinter(TM, std::move(Streamer)), MCInstLowering(*this) {}
60
61 StringRef getPassName() const override { return "XCore Assembly Printer"; }
62
63 void printInlineJT(const MachineInstr *MI, int opNum, raw_ostream &O,
64 const std::string &directive = ".jmptable");
65 void printInlineJT32(const MachineInstr *MI, int opNum, raw_ostream &O) {
66 printInlineJT(MI, opNum, O, ".jmptable32");
67 }
68 void printOperand(const MachineInstr *MI, int opNum, raw_ostream &O);
69 bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
70 const char *ExtraCode, raw_ostream &O) override;
71 bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum,
72 const char *ExtraCode, raw_ostream &O) override;
73
74 void emitArrayBound(MCSymbol *Sym, const GlobalVariable *GV);
75 void emitGlobalVariable(const GlobalVariable *GV) override;
76
77 void emitFunctionEntryLabel() override;
78 void emitInstruction(const MachineInstr *MI) override;
79 void emitFunctionBodyStart() override;
80 void emitFunctionBodyEnd() override;
81 };
82} // end of anonymous namespace
83
84XCoreTargetStreamer &XCoreAsmPrinter::getTargetStreamer() {
85 return static_cast<XCoreTargetStreamer&>(*OutStreamer->getTargetStreamer());
86}
87
88void XCoreAsmPrinter::emitArrayBound(MCSymbol *Sym, const GlobalVariable *GV) {
89 assert( ( GV->hasExternalLinkage() || GV->hasWeakLinkage() ||
90 GV->hasLinkOnceLinkage() || GV->hasCommonLinkage() ) &&
91 "Unexpected linkage");
92 if (ArrayType *ATy = dyn_cast<ArrayType>(GV->getValueType())) {
93
94 MCSymbol *SymGlob = OutContext.getOrCreateSymbol(
95 Twine(Sym->getName() + StringRef(".globound")));
96 OutStreamer->emitSymbolAttribute(SymGlob, MCSA_Global);
97 OutStreamer->emitAssignment(SymGlob,
98 MCConstantExpr::create(ATy->getNumElements(),
99 OutContext));
100 if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage() ||
101 GV->hasCommonLinkage()) {
102 OutStreamer->emitSymbolAttribute(SymGlob, MCSA_Weak);
103 }
104 }
105}
106
107void XCoreAsmPrinter::emitGlobalVariable(const GlobalVariable *GV) {
108 // Check to see if this is a special global used by LLVM, if so, emit it.
109 if (!GV->hasInitializer() || emitSpecialLLVMGlobal(GV))
110 return;
111
112 const DataLayout &DL = getDataLayout();
113 OutStreamer->switchSection(getObjFileLowering().SectionForGlobal(GV, TM));
114
115 MCSymbol *GVSym = getSymbol(GV);
116 const Constant *C = GV->getInitializer();
117 const Align Alignment = DL.getPrefTypeAlign(C->getType());
118
119 // Mark the start of the global
120 getTargetStreamer().emitCCTopData(GVSym->getName());
121
122 switch (GV->getLinkage()) {
124 report_fatal_error("AppendingLinkage is not supported by this target!");
131 emitArrayBound(GVSym, GV);
132 OutStreamer->emitSymbolAttribute(GVSym, MCSA_Global);
133
134 if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage() ||
135 GV->hasCommonLinkage())
136 OutStreamer->emitSymbolAttribute(GVSym, MCSA_Weak);
137 [[fallthrough]];
140 break;
141 default:
142 llvm_unreachable("Unknown linkage type!");
143 }
144
145 emitAlignment(std::max(Alignment, Align(4)), GV);
146
147 if (GV->isThreadLocal()) {
148 report_fatal_error("TLS is not supported by this target!");
149 }
150 unsigned Size = DL.getTypeAllocSize(C->getType());
151 if (MAI->hasDotTypeDotSizeDirective()) {
152 OutStreamer->emitSymbolAttribute(GVSym, MCSA_ELF_TypeObject);
153 OutStreamer->emitELFSize(GVSym, MCConstantExpr::create(Size, OutContext));
154 }
155 OutStreamer->emitLabel(GVSym);
156
157 emitGlobalConstant(DL, C);
158 // The ABI requires that unsigned scalar types smaller than 32 bits
159 // are padded to 32 bits.
160 if (Size < 4)
161 OutStreamer->emitZeros(4 - Size);
162
163 // Mark the end of the global
164 getTargetStreamer().emitCCBottomData(GVSym->getName());
165}
166
167void XCoreAsmPrinter::emitFunctionBodyStart() {
168 MCInstLowering.Initialize(&MF->getContext());
169}
170
171/// EmitFunctionBodyEnd - Targets can override this to emit stuff after
172/// the last basic block in the function.
173void XCoreAsmPrinter::emitFunctionBodyEnd() {
174 // Emit function end directives
175 getTargetStreamer().emitCCBottomFunction(CurrentFnSym->getName());
176}
177
178void XCoreAsmPrinter::emitFunctionEntryLabel() {
179 // Mark the start of the function
180 getTargetStreamer().emitCCTopFunction(CurrentFnSym->getName());
181 OutStreamer->emitLabel(CurrentFnSym);
182}
183
184void XCoreAsmPrinter::
185printInlineJT(const MachineInstr *MI, int opNum, raw_ostream &O,
186 const std::string &directive) {
187 unsigned JTI = MI->getOperand(opNum).getIndex();
188 const MachineFunction *MF = MI->getParent()->getParent();
189 const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
190 const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
191 const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
192 O << "\t" << directive << " ";
193 for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) {
194 MachineBasicBlock *MBB = JTBBs[i];
195 if (i > 0)
196 O << ",";
197 MBB->getSymbol()->print(O, MAI);
198 }
199}
200
201void XCoreAsmPrinter::printOperand(const MachineInstr *MI, int opNum,
202 raw_ostream &O) {
203 const DataLayout &DL = getDataLayout();
204 const MachineOperand &MO = MI->getOperand(opNum);
205 switch (MO.getType()) {
208 break;
210 O << MO.getImm();
211 break;
213 MO.getMBB()->getSymbol()->print(O, MAI);
214 break;
216 PrintSymbolOperand(MO, O);
217 break;
219 O << DL.getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_'
220 << MO.getIndex();
221 break;
223 GetBlockAddressSymbol(MO.getBlockAddress())->print(O, MAI);
224 break;
225 default:
226 llvm_unreachable("not implemented");
227 }
228}
229
230/// PrintAsmOperand - Print out an operand for an inline asm expression.
231///
232bool XCoreAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
233 const char *ExtraCode, raw_ostream &O) {
234 // Print the operand if there is no operand modifier.
235 if (!ExtraCode || !ExtraCode[0]) {
236 printOperand(MI, OpNo, O);
237 return false;
238 }
239
240 // Otherwise fallback on the default implementation.
241 return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, O);
242}
243
244bool XCoreAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
245 unsigned OpNum,
246 const char *ExtraCode,
247 raw_ostream &O) {
248 if (ExtraCode && ExtraCode[0]) {
249 return true; // Unknown modifier.
250 }
251 printOperand(MI, OpNum, O);
252 O << '[';
253 printOperand(MI, OpNum + 1, O);
254 O << ']';
255 return false;
256}
257
258void XCoreAsmPrinter::emitInstruction(const MachineInstr *MI) {
259 XCore_MC::verifyInstructionPredicates(MI->getOpcode(),
260 getSubtargetInfo().getFeatureBits());
261
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 "
271 << XCoreInstPrinter::getRegisterName(MI->getOperand(0).getReg()) << ", "
272 << XCoreInstPrinter::getRegisterName(MI->getOperand(1).getReg());
273 OutStreamer->emitRawText(O.str());
274 return;
275 }
276 break;
277 case XCore::BR_JT:
278 case XCore::BR_JT32:
279 O << "\tbru "
280 << XCoreInstPrinter::getRegisterName(MI->getOperand(1).getReg()) << '\n';
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.
299}
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
#define LLVM_EXTERNAL_VISIBILITY
Definition: Compiler.h:131
This file contains the declarations for the subclasses of Constant, which represent the different fla...
uint64_t Size
Symbol * Sym
Definition: ELF_riscv.cpp:479
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
IRTranslator LLVM IR MI
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
Module.h This file contains the declarations for the Module class.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
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.
LLVM_EXTERNAL_VISIBILITY void LLVMInitializeXCoreAsmPrinter()
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:86
virtual void emitInstruction(const MachineInstr *)
Targets should implement this to emit instructions.
Definition: AsmPrinter.h:561
virtual void emitGlobalVariable(const GlobalVariable *GV)
Emit the specified global variable to the .s file.
Definition: AsmPrinter.cpp:698
virtual void emitFunctionBodyStart()
Targets can override this to emit stuff before the first basic block in the function.
Definition: AsmPrinter.h:545
virtual bool PrintAsmMemoryOperand(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 as...
virtual void emitFunctionBodyEnd()
Targets can override this to emit stuff after the last basic block in the function.
Definition: AsmPrinter.h:549
virtual void emitFunctionEntryLabel()
EmitFunctionEntryLabel - Emit the label that is the entrypoint for the function.
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.
This is an important base class in LLVM.
Definition: Constant.h:42
A parsed version of the target data layout string in and methods for querying it.
Definition: DataLayout.h:63
bool hasLinkOnceLinkage() const
Definition: GlobalValue.h:515
bool hasExternalLinkage() const
Definition: GlobalValue.h:511
bool isThreadLocal() const
If the value is "Thread Local", its value isn't shared by the threads.
Definition: GlobalValue.h:263
LinkageTypes getLinkage() const
Definition: GlobalValue.h:546
bool hasWeakLinkage() const
Definition: GlobalValue.h:522
bool hasCommonLinkage() const
Definition: GlobalValue.h:532
@ PrivateLinkage
Like Internal, but omit from symbol table.
Definition: GlobalValue.h:60
@ CommonLinkage
Tentative definitions.
Definition: GlobalValue.h:62
@ InternalLinkage
Rename collisions when linking (static functions).
Definition: GlobalValue.h:59
@ LinkOnceAnyLinkage
Keep one copy of function when linking (inline)
Definition: GlobalValue.h:54
@ WeakODRLinkage
Same, but only replaced by something equivalent.
Definition: GlobalValue.h:57
@ ExternalLinkage
Externally visible function.
Definition: GlobalValue.h:52
@ WeakAnyLinkage
Keep one copy of named function when linking (weak)
Definition: GlobalValue.h:56
@ AppendingLinkage
Special purpose, only applies to global arrays.
Definition: GlobalValue.h:58
@ LinkOnceODRLinkage
Same, but only replaced by something equivalent.
Definition: GlobalValue.h:55
Type * getValueType() const
Definition: GlobalValue.h:296
const Constant * getInitializer() const
getInitializer - Return the initializer for this global variable.
bool hasInitializer() const
Definitions have initializers, declarations don't.
static const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition: MCExpr.cpp:193
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:184
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:41
void print(raw_ostream &OS, const MCAsmInfo *MAI) const
print - Print the value to the stream OS.
Definition: MCSymbol.cpp:58
StringRef getName() const
getName - Get the symbol name.
Definition: MCSymbol.h:205
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.
Definition: MachineInstr.h:69
const std::vector< MachineJumpTableEntry > & getJumpTables() const
MachineOperand class - Representation of each machine instruction operand.
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.
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Definition: Pass.cpp:81
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition: SmallString.h:26
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
Primary interface to the complete machine description for the target machine.
Definition: TargetMachine.h:77
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
static const char * getRegisterName(MCRegister Reg)
This class is used to lower an MachineInstr into an MCInst.
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
A raw_ostream that writes to an SmallVector or SmallString.
Definition: raw_ostream.h:691
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
Target & getTheXCoreTarget()
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:167
@ MCSA_Weak
.weak
Definition: MCDirectives.h:45
@ MCSA_Global
.type _foo, @gnu_unique_object
Definition: MCDirectives.h:30
@ MCSA_ELF_TypeObject
.type _foo, STT_OBJECT # aka @object
Definition: MCDirectives.h:25
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39
RegisterAsmPrinter - Helper template for registering a target specific assembly printer,...