LLVM: lib/Target/Sparc/SparcAsmPrinter.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
37using namespace llvm;
38
39#define DEBUG_TYPE "asm-printer"
40
41namespace {
42class SparcAsmPrinter : public AsmPrinter {
45 *OutStreamer->getTargetStreamer());
46 }
47
48public:
50 std::unique_ptr Streamer)
52
53 StringRef getPassName() const override { return "Sparc Assembly Printer"; }
54
57
58 void emitFunctionBodyStart() override;
59 void emitInstruction(const MachineInstr *MI) override;
60
63 }
64
65 bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
66 const char *ExtraCode, raw_ostream &O) override;
67 bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
68 const char *ExtraCode, raw_ostream &O) override;
69
70 void LowerGETPCXAndEmitMCInsts(const MachineInstr *MI,
72
74
75private:
77
78public:
79 static char ID;
80};
81}
82
93
99 OutContext);
101 OutContext);
102
107}
108
112{
114 CallInst.setOpcode(SP::CALL);
117}
118
127
138
150
154 EmitBinary(OutStreamer, SP::ORri, RS1, Imm, RD, STI);
155}
156
160 EmitBinary(OutStreamer, SP::ADDrr, RS1, RS2, RD, STI);
161}
162
166 EmitBinary(OutStreamer, SP::SLLri, RS1, Imm, RD, STI);
167}
168
174 EmitSETHI(OutStreamer, hi, RD, STI);
175 EmitOR(OutStreamer, RD, lo, RD, STI);
176}
177
178void SparcAsmPrinter::LowerGETPCXAndEmitMCInsts(const MachineInstr *MI,
180{
182 OutContext.getOrCreateSymbol(Twine("_GLOBAL_OFFSET_TABLE_"));
183
184 const MachineOperand &MO = MI->getOperand(0);
186 "%o7 is assigned as destination for getpcx!");
187
189
190
191 if (!isPositionIndependent()) {
192
193 switch(TM.getCodeModel()) {
194 default:
197 emitHiLo(*OutStreamer, GOTLabel, ELF::R_SPARC_HI22, ELF::R_SPARC_LO10,
198 MCRegOP, OutContext, STI);
199 break;
201 emitHiLo(*OutStreamer, GOTLabel, ELF::R_SPARC_H44, ELF::R_SPARC_M44,
202 MCRegOP, OutContext, STI);
204 OutContext));
205 EmitSHL(*OutStreamer, MCRegOP, imm, MCRegOP, STI);
206 MCOperand lo =
208 EmitOR(*OutStreamer, MCRegOP, lo, MCRegOP, STI);
209 break;
210 }
212 emitHiLo(*OutStreamer, GOTLabel, ELF::R_SPARC_HH22, ELF::R_SPARC_HM10,
213 MCRegOP, OutContext, STI);
215 OutContext));
216 EmitSHL(*OutStreamer, MCRegOP, imm, MCRegOP, STI);
217
219 emitHiLo(*OutStreamer, GOTLabel, ELF::R_SPARC_HI22, ELF::R_SPARC_LO10,
220 RegO7, OutContext, STI);
221 EmitADD(*OutStreamer, MCRegOP, RegO7, MCRegOP, STI);
222 }
223 }
224 return;
225 }
226
227 MCSymbol *StartLabel = OutContext.createTempSymbol();
228 MCSymbol *EndLabel = OutContext.createTempSymbol();
229 MCSymbol *SethiLabel = OutContext.createTempSymbol();
230
232
233
234
235
236
237
238
239
240
241 OutStreamer->emitLabel(StartLabel);
243 STI.hasFeature(Sparc::TuneSlowRDPC)) {
245 EmitCall(*OutStreamer, Callee, STI);
246 } else {
247
248
249
250
251 EmitRDPC(*OutStreamer, RegO7, STI);
252 }
253 OutStreamer->emitLabel(SethiLabel);
254 MCOperand hiImm = createPCXRelExprOp(ELF::R_SPARC_PC22, GOTLabel, StartLabel,
255 SethiLabel, OutContext);
256 EmitSETHI(*OutStreamer, hiImm, MCRegOP, STI);
257 OutStreamer->emitLabel(EndLabel);
258 MCOperand loImm = createPCXRelExprOp(ELF::R_SPARC_PC10, GOTLabel, StartLabel,
259 EndLabel, OutContext);
260 EmitOR(*OutStreamer, MCRegOP, loImm, MCRegOP, STI);
261 EmitADD(*OutStreamer, MCRegOP, RegO7, MCRegOP, STI);
262}
263
264MCOperand SparcAsmPrinter::lowerOperand(const MachineOperand &MO) const {
266 default:
268 break;
271 break;
273
276
285 default:
289 break;
292 break;
295 break;
298 break;
301 break;
302 }
303
305 if (RelType)
308 }
309
311 break;
312 }
313 return MCOperand();
314}
315
316void SparcAsmPrinter::lowerToMCInst(const MachineInstr *MI, MCInst &OutMI) {
318
319 for (const MachineOperand &MO : MI->operands()) {
320 MCOperand MCOp = lowerOperand(MO);
323 }
324}
325
326void SparcAsmPrinter::emitInstruction(const MachineInstr *MI) {
327 Sparc_MC::verifyInstructionPredicates(MI->getOpcode(),
328 getSubtargetInfo().getFeatureBits());
329 if (MI->isBundle()) {
330 const MachineBasicBlock *MBB = MI->getParent();
332 while (I != MBB->instr_end() && I->isInsideBundle()) {
334 ++I;
335 }
336 return;
337 }
338
339 switch (MI->getOpcode()) {
340 default: break;
341 case TargetOpcode::DBG_VALUE:
342
343 return;
344 case SP::CASArr:
345 case SP::SWAPrr:
346 case SP::SWAPri:
347 if (MF->getSubtarget().fixTN0011())
348 OutStreamer->emitCodeAlignment(Align(16), &getSubtargetInfo());
349 break;
350 case SP::GETPCX:
351 LowerGETPCXAndEmitMCInsts(MI, getSubtargetInfo());
352 return;
353 }
356 do {
357 MCInst TmpInst;
358 lowerToMCInst(&*I, TmpInst);
359 EmitToStreamer(*OutStreamer, TmpInst);
360 } while ((++I != E) && I->isInsideBundle());
361}
362
363void SparcAsmPrinter::emitFunctionBodyStart() {
364 if (!MF->getSubtarget().is64Bit())
365 return;
366
367 const MachineRegisterInfo &MRI = MF->getRegInfo();
368 const unsigned globalRegs[] = { SP::G2, SP::G3, SP::G6, SP::G7, 0 };
369 for (unsigned i = 0; globalRegs[i] != 0; ++i) {
370 unsigned reg = globalRegs[i];
371 if (MRI.use_empty(reg))
372 continue;
373
374 if (reg == SP::G6 || reg == SP::G7)
375 getTargetStreamer().emitSparcRegisterIgnore(reg);
376 else
377 getTargetStreamer().emitSparcRegisterScratch(reg);
378 }
379}
380
381void SparcAsmPrinter::printOperand(const MachineInstr *MI, int opNum,
382 raw_ostream &O) {
383 const DataLayout &DL = getDataLayout();
384 const MachineOperand &MO = MI->getOperand(opNum);
388 break;
389
392 break;
395 return;
397 PrintSymbolOperand(MO, O);
398 break;
401 break;
404 break;
406 O << DL.getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << "_"
408 break;
411 break;
412 default:
414 }
415}
416
417void SparcAsmPrinter::printMemOperand(const MachineInstr *MI, int opNum,
418 raw_ostream &O) {
420
421 if (MI->getOperand(opNum+1).isReg() &&
422 MI->getOperand(opNum+1).getReg() == SP::G0)
423 return;
424 if (MI->getOperand(opNum+1).isImm() &&
425 MI->getOperand(opNum+1).getImm() == 0)
426 return;
427
428 O << "+";
430}
431
432
433
434bool SparcAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
435 const char *ExtraCode,
436 raw_ostream &O) {
437 if (ExtraCode && ExtraCode[0]) {
438 if (ExtraCode[1] != 0) return true;
439
440 switch (ExtraCode[0]) {
441 default:
442
444 case 'L':
445 case 'H':
446 {
447 const SparcSubtarget &Subtarget = MF->getSubtarget();
448 const MachineOperand &MO = MI->getOperand(OpNo);
449 const SparcRegisterInfo *RegisterInfo = Subtarget.getRegisterInfo();
450 Register MOReg = MO.getReg();
451
453 if (!SP::IntPairRegClass.contains(MOReg)) {
454
455
456
457
458 MOReg = RegisterInfo->getMatchingSuperReg(MOReg, SP::sub_even,
459 &SP::IntPairRegClass);
460 if (!MOReg) {
461 SMLoc Loc;
462 OutContext.reportError(
463 Loc, "Hi part of pair should point to an even-numbered register");
464 OutContext.reportError(
465 Loc, "(note that in some cases it might be necessary to manually "
466 "bind the input/output registers instead of relying on "
467 "automatic allocation)");
468 return true;
469 }
470 }
471
472 HiReg = RegisterInfo->getSubReg(MOReg, SP::sub_even);
473 LoReg = RegisterInfo->getSubReg(MOReg, SP::sub_odd);
474
476 switch (ExtraCode[0]) {
477 case 'L':
478 Reg = LoReg;
479 break;
480 case 'H':
481 Reg = HiReg;
482 break;
483 }
484
486 return false;
487 }
488 case 'f':
489 case 'r':
490 break;
491 }
492 }
493
495
496 return false;
497}
498
499bool SparcAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
500 unsigned OpNo,
501 const char *ExtraCode,
502 raw_ostream &O) {
503 if (ExtraCode && ExtraCode[0])
504 return true;
505
506 O << '[';
508 O << ']';
509
510 return false;
511}
512
513char SparcAsmPrinter::ID = 0;
514
515INITIALIZE_PASS(SparcAsmPrinter, "sparc-asm-printer", "Sparc Assembly Printer",
516 false, false)
517
518
520LLVMInitializeSparcAsmPrinter() {
524}
unsigned const MachineRegisterInfo * MRI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define LLVM_EXTERNAL_VISIBILITY
static std::string getRegisterName(const TargetRegisterInfo *TRI, Register Reg)
Promote Memory to Register
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
static bool printOperand(raw_ostream &OS, const SelectionDAG *G, const SDValue Value)
static void printMemOperand(raw_ostream &OS, const MachineMemOperand &MMO, const MachineFunction *MF, const Module *M, const MachineFrameInfo *MFI, const TargetInstrInfo *TII, LLVMContext &Ctx)
static MCOperand createPCXRelExprOp(uint16_t Spec, MCSymbol *GOTLabel, MCSymbol *StartLabel, MCSymbol *CurLabel, MCContext &OutContext)
Definition SparcAsmPrinter.cpp:94
static MCOperand createPCXCallOP(MCSymbol *Label, MCContext &OutContext)
Definition SparcAsmPrinter.cpp:89
static void EmitSHL(MCStreamer &OutStreamer, MCOperand &RS1, MCOperand &Imm, MCOperand &RD, const MCSubtargetInfo &STI)
Definition SparcAsmPrinter.cpp:163
static void EmitCall(MCStreamer &OutStreamer, MCOperand &Callee, const MCSubtargetInfo &STI)
Definition SparcAsmPrinter.cpp:109
static MCOperand createSparcMCOperand(uint16_t Kind, MCSymbol *Sym, MCContext &OutContext)
Definition SparcAsmPrinter.cpp:83
static void EmitSETHI(MCStreamer &OutStreamer, MCOperand &Imm, MCOperand &RD, const MCSubtargetInfo &STI)
Definition SparcAsmPrinter.cpp:128
static void EmitOR(MCStreamer &OutStreamer, MCOperand &RS1, MCOperand &Imm, MCOperand &RD, const MCSubtargetInfo &STI)
Definition SparcAsmPrinter.cpp:151
static void EmitBinary(MCStreamer &OutStreamer, unsigned Opcode, MCOperand &RS1, MCOperand &Src2, MCOperand &RD, const MCSubtargetInfo &STI)
Definition SparcAsmPrinter.cpp:139
static void EmitRDPC(MCStreamer &OutStreamer, MCOperand &RD, const MCSubtargetInfo &STI)
Definition SparcAsmPrinter.cpp:119
static void emitHiLo(MCStreamer &OutStreamer, MCSymbol *GOTSym, uint16_t HiKind, uint16_t LoKind, MCOperand &RD, MCContext &OutContext, const MCSubtargetInfo &STI)
Definition SparcAsmPrinter.cpp:169
static void EmitADD(MCStreamer &OutStreamer, MCOperand &RS1, MCOperand &RS2, MCOperand &RD, const MCSubtargetInfo &STI)
Definition SparcAsmPrinter.cpp:157
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
This class is intended to be used as a driving class for all asm writers.
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 class represents a function call, abstracting a target machine's calling convention.
Binary assembler expressions.
static const MCBinaryExpr * createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx, SMLoc Loc=SMLoc())
static const MCBinaryExpr * createSub(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Context object for machine code objects.
Instances of this class represent a single low-level machine instruction.
void addOperand(const MCOperand Op)
void setOpcode(unsigned Op)
Instances of this class represent operands of the MCInst class.
static MCOperand createExpr(const MCExpr *Val)
static MCOperand createReg(MCRegister Reg)
static MCOperand createImm(int64_t Val)
Wrapper class representing physical registers. Should be passed by value.
static const MCSpecifierExpr * create(const MCExpr *Expr, Spec S, MCContext &Ctx, SMLoc Loc=SMLoc())
Streaming machine code generation interface.
virtual void emitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI)
Emit the given Instruction into the current section.
Generic base class for all target subtargets.
bool hasFeature(unsigned Feature) const
const Triple & getTargetTriple() const
Represent a reference to a symbol from inside an expression.
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
LLVM_ABI void print(raw_ostream &OS, const MCAsmInfo *MAI) const
print - Print the value to the stream OS.
LLVM_ABI MCSymbol * getSymbol() const
Return the MCSymbol for this basic block.
instr_iterator instr_end()
Instructions::const_iterator const_instr_iterator
Representation of each machine instruction.
MachineOperand class - Representation of each machine instruction operand.
const GlobalValue * getGlobal() const
const MDNode * getMetadata() const
MachineBasicBlock * getMBB() const
const BlockAddress * getBlockAddress() const
unsigned getTargetFlags() const
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
const char * getSymbolName() const
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_RegisterMask
Mask of preserved registers.
@ MO_BlockAddress
Address of a basic block.
@ MO_MachineBasicBlock
MachineBasicBlock reference.
@ MO_Register
Register operand.
@ MO_ExternalSymbol
Name of external global symbol.
@ MO_Metadata
Metadata reference (for debug info)
static const char * getRegisterName(MCRegister Reg, unsigned AltIdx=SP::NoRegAltName)
const SparcRegisterInfo * getRegisterInfo() const override
StringRef - Represent a constant reference to a string, i.e.
Primary interface to the complete machine description for the target machine.
bool isSPARC64() const
Tests whether the target is 64-bit SPARC (big endian).
This class implements an extremely fast bulk output stream that can only output to a stream.
#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.
void emitInstruction(MCObjectStreamer &, const MCInst &Inst, const MCSubtargetInfo &STI)
This is an optimization pass for GlobalISel generic memory operations.
Target & getTheSparcTarget()
Target & getTheSparcV9Target()
@ Sub
Subtraction of integers.
Target & getTheSparcelTarget()
ArrayRef< int > lo(ArrayRef< int > Vuu)
RegisterAsmPrinter - Helper template for registering a target specific assembly printer,...