1//===-- SparcAsmPrinter.cpp - Sparc LLVM assembly writer ------------------===// 
  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 
  7//===----------------------------------------------------------------------===// 
  9// This file contains a printer that converts from our internal representation 
  10// of machine-dependent LLVM code to GAS-format SPARC assembly language. 
  12//===----------------------------------------------------------------------===// 
  39 #define DEBUG_TYPE "asm-printer" 
  45 *OutStreamer->getTargetStreamer());
 
  50 std::unique_ptr<MCStreamer> Streamer)
 
  53 StringRef getPassName()
 const override { 
return "Sparc Assembly Printer"; }
 
  58 void emitFunctionBodyStart() 
override;
 
  81} 
// end of anonymous namespace 
  154 EmitBinary(OutStreamer, SP::ORri, RS1, Imm, RD, STI);
 
 
  160 EmitBinary(OutStreamer, SP::ADDrr, RS1, RS2, RD, STI);
 
 
  166 EmitBinary(OutStreamer, SP::SLLri, RS1, Imm, RD, STI);
 
 
  175 EmitOR(OutStreamer, RD, lo, RD, STI);
 
 
  178void SparcAsmPrinter::LowerGETPCXAndEmitMCInsts(
const MachineInstr *
MI,
 
  182 OutContext.getOrCreateSymbol(Twine(
"_GLOBAL_OFFSET_TABLE_"));
 
  184 const MachineOperand &MO = 
MI->getOperand(0);
 
  186 "%o7 is assigned as destination for getpcx!");
 
  191 if (!isPositionIndependent()) {
 
  192 // Just load the address of GOT to MCRegOP. 
  193 switch(
TM.getCodeModel()) {
 
  197 emitHiLo(*OutStreamer, GOTLabel, ELF::R_SPARC_HI22, ELF::R_SPARC_LO10,
 
  198 MCRegOP, OutContext, STI);
 
  201 emitHiLo(*OutStreamer, GOTLabel, ELF::R_SPARC_H44, ELF::R_SPARC_M44,
 
  202 MCRegOP, OutContext, STI);
 
  205 EmitSHL(*OutStreamer, MCRegOP, imm, MCRegOP, STI);
 
  208 EmitOR(*OutStreamer, MCRegOP, lo, MCRegOP, STI);
 
  212 emitHiLo(*OutStreamer, GOTLabel, ELF::R_SPARC_HH22, ELF::R_SPARC_HM10,
 
  213 MCRegOP, OutContext, STI);
 
  216 EmitSHL(*OutStreamer, MCRegOP, imm, MCRegOP, STI);
 
  217 // Use register %o7 to load the lower 32 bits. 
  219 emitHiLo(*OutStreamer, GOTLabel, ELF::R_SPARC_HI22, ELF::R_SPARC_LO10,
 
  220 RegO7, OutContext, STI);
 
  221 EmitADD(*OutStreamer, MCRegOP, RegO7, MCRegOP, STI);
 
  227 MCSymbol *StartLabel = OutContext.createTempSymbol();
 
  228 MCSymbol *EndLabel = OutContext.createTempSymbol();
 
  229 MCSymbol *SethiLabel = OutContext.createTempSymbol();
 
  234 // <GET-PC> // This will be either `call <EndLabel>` or `rd %pc, %o7`. 
  236 // sethi %hi(_GLOBAL_OFFSET_TABLE_+(<SethiLabel>-<StartLabel>)), <MO> 
  238 // or <MO>, %lo(_GLOBAL_OFFSET_TABLE_+(<EndLabel>-<StartLabel>))), <MO> 
  239 // add <MO>, %o7, <MO> 
  241 OutStreamer->emitLabel(StartLabel);
 
  245 EmitCall(*OutStreamer, Callee, STI);
 
  247 // TODO find out whether it is possible to store PC 
  248 // in other registers, to enable leaf function optimization. 
  249 // (On the other hand, approx. over 97.8% of GETPCXes happen 
  250 // in non-leaf functions, so would this be worth the effort?) 
  253 OutStreamer->emitLabel(SethiLabel);
 
  255 SethiLabel, OutContext);
 
  256 EmitSETHI(*OutStreamer, hiImm, MCRegOP, STI);
 
  257 OutStreamer->emitLabel(EndLabel);
 
  259 EndLabel, OutContext);
 
  260 EmitOR(*OutStreamer, MCRegOP, loImm, MCRegOP, STI);
 
  261 EmitADD(*OutStreamer, MCRegOP, RegO7, MCRegOP, STI);
 
  264MCOperand SparcAsmPrinter::lowerOperand(
const MachineOperand &MO)
 const {
 
  316void SparcAsmPrinter::lowerToMCInst(
const MachineInstr *
MI, MCInst &OutMI) {
 
  319 for (
const MachineOperand &MO : 
MI->operands()) {
 
  320 MCOperand MCOp = lowerOperand(MO);
 
  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();
 
  339 switch (
MI->getOpcode()) {
 
  341 case TargetOpcode::DBG_VALUE:
 
  342 // FIXME: Debug Value. 
  347 if (MF->getSubtarget<SparcSubtarget>().fixTN0011())
 
  348 OutStreamer->emitCodeAlignment(
Align(16), &getSubtargetInfo());
 
  351 LowerGETPCXAndEmitMCInsts(
MI, getSubtargetInfo());
 
  358 lowerToMCInst(&*
I, TmpInst);
 
  359 EmitToStreamer(*OutStreamer, TmpInst);
 
  360 } 
while ((++
I != 
E) && 
I->isInsideBundle()); 
// Delay slot check. 
  363void SparcAsmPrinter::emitFunctionBodyStart() {
 
  364 if (!MF->getSubtarget<SparcSubtarget>().is64Bit())
 
  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))
 
  374 if (reg == SP::G6 || reg == SP::G7)
 
  375 getTargetStreamer().emitSparcRegisterIgnore(reg);
 
  377 getTargetStreamer().emitSparcRegisterScratch(reg);
 
  381void SparcAsmPrinter::printOperand(
const MachineInstr *
MI, 
int opNum,
 
  383 const DataLayout &
DL = getDataLayout();
 
  384 const MachineOperand &MO = 
MI->getOperand(opNum);
 
  397 PrintSymbolOperand(MO, O);
 
  406 O << 
DL.getPrivateGlobalPrefix() << 
"CPI" << getFunctionNumber() << 
"_" 
  417void SparcAsmPrinter::printMemOperand(
const MachineInstr *
MI, 
int opNum,
 
  421 if (
MI->getOperand(opNum+1).isReg() &&
 
  422 MI->getOperand(opNum+1).getReg() == SP::G0)
 
  423 return; 
// don't print "+%g0" 
  424 if (
MI->getOperand(opNum+1).isImm() &&
 
  425 MI->getOperand(opNum+1).getImm() == 0)
 
  426 return; 
// don't print "+0" 
  432/// PrintAsmOperand - Print out an operand for an inline asm expression. 
  434bool SparcAsmPrinter::PrintAsmOperand(
const MachineInstr *
MI, 
unsigned OpNo,
 
  435 const char *ExtraCode,
 
  437 if (ExtraCode && ExtraCode[0]) {
 
  438 if (ExtraCode[1] != 0) 
return true; 
// Unknown modifier. 
  440 switch (ExtraCode[0]) {
 
  442 // See if this is a generic print operand 
  444 case 'L': 
// Low order register of a twin word register operand 
  445 case 'H': 
// High order register of a twin word register operand 
  447 const SparcSubtarget &Subtarget = MF->getSubtarget<SparcSubtarget>();
 
  448 const MachineOperand &MO = 
MI->getOperand(OpNo);
 
  453 if (!SP::IntPairRegClass.
contains(MOReg)) {
 
  454 // If we aren't given a register pair already, find out which pair it 
  455 // belongs to. Note that here, the specified register operand, which 
  456 // refers to the high part of the twinword, needs to be an even-numbered 
  458 MOReg = RegisterInfo->getMatchingSuperReg(MOReg, SP::sub_even,
 
  459 &SP::IntPairRegClass);
 
  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)");
 
  472 HiReg = RegisterInfo->getSubReg(MOReg, SP::sub_even);
 
  473 LoReg = RegisterInfo->getSubReg(MOReg, SP::sub_odd);
 
  476 switch (ExtraCode[0]) {
 
  499bool SparcAsmPrinter::PrintAsmMemoryOperand(
const MachineInstr *
MI,
 
  501 const char *ExtraCode,
 
  503 if (ExtraCode && ExtraCode[0])
 
  504 return true; 
// Unknown modifier 
  513char SparcAsmPrinter::ID = 0;
 
  518// Force static initialization. 
  520LLVMInitializeSparcAsmPrinter() {
 
 
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)
 
static MCOperand createPCXCallOP(MCSymbol *Label, MCContext &OutContext)
 
static void EmitSHL(MCStreamer &OutStreamer, MCOperand &RS1, MCOperand &Imm, MCOperand &RD, const MCSubtargetInfo &STI)
 
static void EmitCall(MCStreamer &OutStreamer, MCOperand &Callee, const MCSubtargetInfo &STI)
 
static MCOperand createSparcMCOperand(uint16_t Kind, MCSymbol *Sym, MCContext &OutContext)
 
static void EmitSETHI(MCStreamer &OutStreamer, MCOperand &Imm, MCOperand &RD, const MCSubtargetInfo &STI)
 
static void EmitOR(MCStreamer &OutStreamer, MCOperand &RS1, MCOperand &Imm, MCOperand &RD, const MCSubtargetInfo &STI)
 
static void EmitBinary(MCStreamer &OutStreamer, unsigned Opcode, MCOperand &RS1, MCOperand &Src2, MCOperand &RD, const MCSubtargetInfo &STI)
 
static void EmitRDPC(MCStreamer &OutStreamer, MCOperand &RD, const MCSubtargetInfo &STI)
 
static void emitHiLo(MCStreamer &OutStreamer, MCSymbol *GOTSym, uint16_t HiKind, uint16_t LoKind, MCOperand &RD, MCContext &OutContext, const MCSubtargetInfo &STI)
 
static void EmitADD(MCStreamer &OutStreamer, MCOperand &RS1, MCOperand &RS2, MCOperand &RD, const MCSubtargetInfo &STI)
 
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,...