1*0fca6ea1SDimitry Andric //===- XtensaAsmPrinter.cpp Xtensa LLVM Assembly Printer ------------------===// 2*0fca6ea1SDimitry Andric // 3*0fca6ea1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0fca6ea1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0fca6ea1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0fca6ea1SDimitry Andric // 7*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 8*0fca6ea1SDimitry Andric // 9*0fca6ea1SDimitry Andric // This file contains a printer that converts from our internal representation 10*0fca6ea1SDimitry Andric // of machine-dependent LLVM code to GAS-format Xtensa assembly language. 11*0fca6ea1SDimitry Andric // 12*0fca6ea1SDimitry Andric //===----------------------------------------------------------------------===// 13*0fca6ea1SDimitry Andric 14*0fca6ea1SDimitry Andric #include "XtensaAsmPrinter.h" 15*0fca6ea1SDimitry Andric #include "MCTargetDesc/XtensaMCExpr.h" 16*0fca6ea1SDimitry Andric #include "MCTargetDesc/XtensaTargetStreamer.h" 17*0fca6ea1SDimitry Andric #include "TargetInfo/XtensaTargetInfo.h" 18*0fca6ea1SDimitry Andric #include "XtensaConstantPoolValue.h" 19*0fca6ea1SDimitry Andric #include "llvm/ADT/StringExtras.h" 20*0fca6ea1SDimitry Andric #include "llvm/BinaryFormat/ELF.h" 21*0fca6ea1SDimitry Andric #include "llvm/CodeGen/MachineConstantPool.h" 22*0fca6ea1SDimitry Andric #include "llvm/CodeGen/MachineModuleInfoImpls.h" 23*0fca6ea1SDimitry Andric #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" 24*0fca6ea1SDimitry Andric #include "llvm/MC/MCExpr.h" 25*0fca6ea1SDimitry Andric #include "llvm/MC/MCInstBuilder.h" 26*0fca6ea1SDimitry Andric #include "llvm/MC/MCSectionELF.h" 27*0fca6ea1SDimitry Andric #include "llvm/MC/MCStreamer.h" 28*0fca6ea1SDimitry Andric #include "llvm/MC/MCSymbol.h" 29*0fca6ea1SDimitry Andric #include "llvm/MC/MCSymbolELF.h" 30*0fca6ea1SDimitry Andric #include "llvm/MC/TargetRegistry.h" 31*0fca6ea1SDimitry Andric 32*0fca6ea1SDimitry Andric using namespace llvm; 33*0fca6ea1SDimitry Andric 34*0fca6ea1SDimitry Andric static MCSymbolRefExpr::VariantKind 35*0fca6ea1SDimitry Andric getModifierVariantKind(XtensaCP::XtensaCPModifier Modifier) { 36*0fca6ea1SDimitry Andric switch (Modifier) { 37*0fca6ea1SDimitry Andric case XtensaCP::no_modifier: 38*0fca6ea1SDimitry Andric return MCSymbolRefExpr::VK_None; 39*0fca6ea1SDimitry Andric case XtensaCP::TPOFF: 40*0fca6ea1SDimitry Andric return MCSymbolRefExpr::VK_TPOFF; 41*0fca6ea1SDimitry Andric } 42*0fca6ea1SDimitry Andric report_fatal_error("Invalid XtensaCPModifier!"); 43*0fca6ea1SDimitry Andric } 44*0fca6ea1SDimitry Andric 45*0fca6ea1SDimitry Andric void XtensaAsmPrinter::emitInstruction(const MachineInstr *MI) { 46*0fca6ea1SDimitry Andric unsigned Opc = MI->getOpcode(); 47*0fca6ea1SDimitry Andric 48*0fca6ea1SDimitry Andric switch (Opc) { 49*0fca6ea1SDimitry Andric case Xtensa::BR_JT: 50*0fca6ea1SDimitry Andric EmitToStreamer( 51*0fca6ea1SDimitry Andric *OutStreamer, 52*0fca6ea1SDimitry Andric MCInstBuilder(Xtensa::JX).addReg(MI->getOperand(0).getReg())); 53*0fca6ea1SDimitry Andric return; 54*0fca6ea1SDimitry Andric default: 55*0fca6ea1SDimitry Andric MCInst LoweredMI; 56*0fca6ea1SDimitry Andric lowerToMCInst(MI, LoweredMI); 57*0fca6ea1SDimitry Andric EmitToStreamer(*OutStreamer, LoweredMI); 58*0fca6ea1SDimitry Andric return; 59*0fca6ea1SDimitry Andric } 60*0fca6ea1SDimitry Andric } 61*0fca6ea1SDimitry Andric 62*0fca6ea1SDimitry Andric void XtensaAsmPrinter::emitMachineConstantPoolValue( 63*0fca6ea1SDimitry Andric MachineConstantPoolValue *MCPV) { 64*0fca6ea1SDimitry Andric XtensaConstantPoolValue *ACPV = static_cast<XtensaConstantPoolValue *>(MCPV); 65*0fca6ea1SDimitry Andric MCSymbol *MCSym; 66*0fca6ea1SDimitry Andric 67*0fca6ea1SDimitry Andric if (ACPV->isBlockAddress()) { 68*0fca6ea1SDimitry Andric const BlockAddress *BA = 69*0fca6ea1SDimitry Andric cast<XtensaConstantPoolConstant>(ACPV)->getBlockAddress(); 70*0fca6ea1SDimitry Andric MCSym = GetBlockAddressSymbol(BA); 71*0fca6ea1SDimitry Andric } else if (ACPV->isJumpTable()) { 72*0fca6ea1SDimitry Andric unsigned Idx = cast<XtensaConstantPoolJumpTable>(ACPV)->getIndex(); 73*0fca6ea1SDimitry Andric MCSym = this->GetJTISymbol(Idx, false); 74*0fca6ea1SDimitry Andric } else { 75*0fca6ea1SDimitry Andric assert(ACPV->isExtSymbol() && "unrecognized constant pool value"); 76*0fca6ea1SDimitry Andric XtensaConstantPoolSymbol *XtensaSym = cast<XtensaConstantPoolSymbol>(ACPV); 77*0fca6ea1SDimitry Andric const char *SymName = XtensaSym->getSymbol(); 78*0fca6ea1SDimitry Andric 79*0fca6ea1SDimitry Andric if (XtensaSym->isPrivateLinkage()) { 80*0fca6ea1SDimitry Andric const DataLayout &DL = getDataLayout(); 81*0fca6ea1SDimitry Andric MCSym = OutContext.getOrCreateSymbol(Twine(DL.getPrivateGlobalPrefix()) + 82*0fca6ea1SDimitry Andric SymName); 83*0fca6ea1SDimitry Andric } else { 84*0fca6ea1SDimitry Andric MCSym = OutContext.getOrCreateSymbol(SymName); 85*0fca6ea1SDimitry Andric } 86*0fca6ea1SDimitry Andric } 87*0fca6ea1SDimitry Andric 88*0fca6ea1SDimitry Andric MCSymbol *LblSym = GetCPISymbol(ACPV->getLabelId()); 89*0fca6ea1SDimitry Andric auto *TS = 90*0fca6ea1SDimitry Andric static_cast<XtensaTargetStreamer *>(OutStreamer->getTargetStreamer()); 91*0fca6ea1SDimitry Andric MCSymbolRefExpr::VariantKind VK = getModifierVariantKind(ACPV->getModifier()); 92*0fca6ea1SDimitry Andric 93*0fca6ea1SDimitry Andric if (ACPV->getModifier() != XtensaCP::no_modifier) { 94*0fca6ea1SDimitry Andric std::string SymName(MCSym->getName()); 95*0fca6ea1SDimitry Andric StringRef Modifier = ACPV->getModifierText(); 96*0fca6ea1SDimitry Andric SymName += Modifier; 97*0fca6ea1SDimitry Andric MCSym = OutContext.getOrCreateSymbol(SymName); 98*0fca6ea1SDimitry Andric } 99*0fca6ea1SDimitry Andric 100*0fca6ea1SDimitry Andric const MCExpr *Expr = MCSymbolRefExpr::create(MCSym, VK, OutContext); 101*0fca6ea1SDimitry Andric TS->emitLiteral(LblSym, Expr, false); 102*0fca6ea1SDimitry Andric } 103*0fca6ea1SDimitry Andric 104*0fca6ea1SDimitry Andric void XtensaAsmPrinter::emitMachineConstantPoolEntry( 105*0fca6ea1SDimitry Andric const MachineConstantPoolEntry &CPE, int i) { 106*0fca6ea1SDimitry Andric if (CPE.isMachineConstantPoolEntry()) { 107*0fca6ea1SDimitry Andric XtensaConstantPoolValue *ACPV = 108*0fca6ea1SDimitry Andric static_cast<XtensaConstantPoolValue *>(CPE.Val.MachineCPVal); 109*0fca6ea1SDimitry Andric ACPV->setLabelId(i); 110*0fca6ea1SDimitry Andric emitMachineConstantPoolValue(CPE.Val.MachineCPVal); 111*0fca6ea1SDimitry Andric } else { 112*0fca6ea1SDimitry Andric MCSymbol *LblSym = GetCPISymbol(i); 113*0fca6ea1SDimitry Andric auto *TS = 114*0fca6ea1SDimitry Andric static_cast<XtensaTargetStreamer *>(OutStreamer->getTargetStreamer()); 115*0fca6ea1SDimitry Andric const Constant *C = CPE.Val.ConstVal; 116*0fca6ea1SDimitry Andric const MCExpr *Value = nullptr; 117*0fca6ea1SDimitry Andric 118*0fca6ea1SDimitry Andric Type *Ty = C->getType(); 119*0fca6ea1SDimitry Andric if (const auto *CFP = dyn_cast<ConstantFP>(C)) { 120*0fca6ea1SDimitry Andric Value = MCConstantExpr::create( 121*0fca6ea1SDimitry Andric CFP->getValueAPF().bitcastToAPInt().getSExtValue(), OutContext); 122*0fca6ea1SDimitry Andric } else if (const auto *CI = dyn_cast<ConstantInt>(C)) { 123*0fca6ea1SDimitry Andric Value = MCConstantExpr::create(CI->getValue().getSExtValue(), OutContext); 124*0fca6ea1SDimitry Andric } else if (isa<PointerType>(Ty)) { 125*0fca6ea1SDimitry Andric Value = lowerConstant(C); 126*0fca6ea1SDimitry Andric } else { 127*0fca6ea1SDimitry Andric llvm_unreachable("unexpected constant pool entry type"); 128*0fca6ea1SDimitry Andric } 129*0fca6ea1SDimitry Andric 130*0fca6ea1SDimitry Andric TS->emitLiteral(LblSym, Value, false); 131*0fca6ea1SDimitry Andric } 132*0fca6ea1SDimitry Andric } 133*0fca6ea1SDimitry Andric 134*0fca6ea1SDimitry Andric // EmitConstantPool - Print to the current output stream assembly 135*0fca6ea1SDimitry Andric // representations of the constants in the constant pool MCP. This is 136*0fca6ea1SDimitry Andric // used to print out constants which have been "spilled to memory" by 137*0fca6ea1SDimitry Andric // the code generator. 138*0fca6ea1SDimitry Andric void XtensaAsmPrinter::emitConstantPool() { 139*0fca6ea1SDimitry Andric const Function &F = MF->getFunction(); 140*0fca6ea1SDimitry Andric const MachineConstantPool *MCP = MF->getConstantPool(); 141*0fca6ea1SDimitry Andric const std::vector<MachineConstantPoolEntry> &CP = MCP->getConstants(); 142*0fca6ea1SDimitry Andric if (CP.empty()) 143*0fca6ea1SDimitry Andric return; 144*0fca6ea1SDimitry Andric 145*0fca6ea1SDimitry Andric OutStreamer->pushSection(); 146*0fca6ea1SDimitry Andric 147*0fca6ea1SDimitry Andric auto *TS = 148*0fca6ea1SDimitry Andric static_cast<XtensaTargetStreamer *>(OutStreamer->getTargetStreamer()); 149*0fca6ea1SDimitry Andric MCSection *CS = getObjFileLowering().SectionForGlobal(&F, TM); 150*0fca6ea1SDimitry Andric TS->startLiteralSection(CS); 151*0fca6ea1SDimitry Andric 152*0fca6ea1SDimitry Andric int CPIdx = 0; 153*0fca6ea1SDimitry Andric for (const MachineConstantPoolEntry &CPE : CP) { 154*0fca6ea1SDimitry Andric emitMachineConstantPoolEntry(CPE, CPIdx++); 155*0fca6ea1SDimitry Andric } 156*0fca6ea1SDimitry Andric 157*0fca6ea1SDimitry Andric OutStreamer->popSection(); 158*0fca6ea1SDimitry Andric } 159*0fca6ea1SDimitry Andric 160*0fca6ea1SDimitry Andric MCSymbol * 161*0fca6ea1SDimitry Andric XtensaAsmPrinter::GetConstantPoolIndexSymbol(const MachineOperand &MO) const { 162*0fca6ea1SDimitry Andric // Create a symbol for the name. 163*0fca6ea1SDimitry Andric return GetCPISymbol(MO.getIndex()); 164*0fca6ea1SDimitry Andric } 165*0fca6ea1SDimitry Andric 166*0fca6ea1SDimitry Andric MCSymbol *XtensaAsmPrinter::GetJumpTableSymbol(const MachineOperand &MO) const { 167*0fca6ea1SDimitry Andric return GetJTISymbol(MO.getIndex()); 168*0fca6ea1SDimitry Andric } 169*0fca6ea1SDimitry Andric 170*0fca6ea1SDimitry Andric MCOperand 171*0fca6ea1SDimitry Andric XtensaAsmPrinter::LowerSymbolOperand(const MachineOperand &MO, 172*0fca6ea1SDimitry Andric MachineOperand::MachineOperandType MOTy, 173*0fca6ea1SDimitry Andric unsigned Offset) const { 174*0fca6ea1SDimitry Andric const MCSymbol *Symbol; 175*0fca6ea1SDimitry Andric XtensaMCExpr::VariantKind Kind = XtensaMCExpr::VK_Xtensa_None; 176*0fca6ea1SDimitry Andric 177*0fca6ea1SDimitry Andric switch (MOTy) { 178*0fca6ea1SDimitry Andric case MachineOperand::MO_GlobalAddress: 179*0fca6ea1SDimitry Andric Symbol = getSymbol(MO.getGlobal()); 180*0fca6ea1SDimitry Andric Offset += MO.getOffset(); 181*0fca6ea1SDimitry Andric break; 182*0fca6ea1SDimitry Andric case MachineOperand::MO_MachineBasicBlock: 183*0fca6ea1SDimitry Andric Symbol = MO.getMBB()->getSymbol(); 184*0fca6ea1SDimitry Andric break; 185*0fca6ea1SDimitry Andric case MachineOperand::MO_BlockAddress: 186*0fca6ea1SDimitry Andric Symbol = GetBlockAddressSymbol(MO.getBlockAddress()); 187*0fca6ea1SDimitry Andric Offset += MO.getOffset(); 188*0fca6ea1SDimitry Andric break; 189*0fca6ea1SDimitry Andric case MachineOperand::MO_ExternalSymbol: 190*0fca6ea1SDimitry Andric Symbol = GetExternalSymbolSymbol(MO.getSymbolName()); 191*0fca6ea1SDimitry Andric Offset += MO.getOffset(); 192*0fca6ea1SDimitry Andric break; 193*0fca6ea1SDimitry Andric case MachineOperand::MO_JumpTableIndex: 194*0fca6ea1SDimitry Andric Symbol = GetJumpTableSymbol(MO); 195*0fca6ea1SDimitry Andric break; 196*0fca6ea1SDimitry Andric case MachineOperand::MO_ConstantPoolIndex: 197*0fca6ea1SDimitry Andric Symbol = GetConstantPoolIndexSymbol(MO); 198*0fca6ea1SDimitry Andric Offset += MO.getOffset(); 199*0fca6ea1SDimitry Andric break; 200*0fca6ea1SDimitry Andric default: 201*0fca6ea1SDimitry Andric report_fatal_error("<unknown operand type>"); 202*0fca6ea1SDimitry Andric } 203*0fca6ea1SDimitry Andric 204*0fca6ea1SDimitry Andric const MCExpr *ME = 205*0fca6ea1SDimitry Andric MCSymbolRefExpr::create(Symbol, MCSymbolRefExpr::VK_None, OutContext); 206*0fca6ea1SDimitry Andric ME = XtensaMCExpr::create(ME, Kind, OutContext); 207*0fca6ea1SDimitry Andric 208*0fca6ea1SDimitry Andric if (Offset) { 209*0fca6ea1SDimitry Andric // Assume offset is never negative. 210*0fca6ea1SDimitry Andric assert(Offset > 0); 211*0fca6ea1SDimitry Andric 212*0fca6ea1SDimitry Andric const MCConstantExpr *OffsetExpr = 213*0fca6ea1SDimitry Andric MCConstantExpr::create(Offset, OutContext); 214*0fca6ea1SDimitry Andric ME = MCBinaryExpr::createAdd(ME, OffsetExpr, OutContext); 215*0fca6ea1SDimitry Andric } 216*0fca6ea1SDimitry Andric 217*0fca6ea1SDimitry Andric return MCOperand::createExpr(ME); 218*0fca6ea1SDimitry Andric } 219*0fca6ea1SDimitry Andric 220*0fca6ea1SDimitry Andric MCOperand XtensaAsmPrinter::lowerOperand(const MachineOperand &MO, 221*0fca6ea1SDimitry Andric unsigned Offset) const { 222*0fca6ea1SDimitry Andric MachineOperand::MachineOperandType MOTy = MO.getType(); 223*0fca6ea1SDimitry Andric 224*0fca6ea1SDimitry Andric switch (MOTy) { 225*0fca6ea1SDimitry Andric case MachineOperand::MO_Register: 226*0fca6ea1SDimitry Andric // Ignore all implicit register operands. 227*0fca6ea1SDimitry Andric if (MO.isImplicit()) 228*0fca6ea1SDimitry Andric break; 229*0fca6ea1SDimitry Andric return MCOperand::createReg(MO.getReg()); 230*0fca6ea1SDimitry Andric case MachineOperand::MO_Immediate: 231*0fca6ea1SDimitry Andric return MCOperand::createImm(MO.getImm() + Offset); 232*0fca6ea1SDimitry Andric case MachineOperand::MO_RegisterMask: 233*0fca6ea1SDimitry Andric break; 234*0fca6ea1SDimitry Andric case MachineOperand::MO_GlobalAddress: 235*0fca6ea1SDimitry Andric case MachineOperand::MO_MachineBasicBlock: 236*0fca6ea1SDimitry Andric case MachineOperand::MO_BlockAddress: 237*0fca6ea1SDimitry Andric case MachineOperand::MO_ExternalSymbol: 238*0fca6ea1SDimitry Andric case MachineOperand::MO_JumpTableIndex: 239*0fca6ea1SDimitry Andric case MachineOperand::MO_ConstantPoolIndex: 240*0fca6ea1SDimitry Andric return LowerSymbolOperand(MO, MOTy, Offset); 241*0fca6ea1SDimitry Andric default: 242*0fca6ea1SDimitry Andric report_fatal_error("unknown operand type"); 243*0fca6ea1SDimitry Andric } 244*0fca6ea1SDimitry Andric 245*0fca6ea1SDimitry Andric return MCOperand(); 246*0fca6ea1SDimitry Andric } 247*0fca6ea1SDimitry Andric 248*0fca6ea1SDimitry Andric void XtensaAsmPrinter::lowerToMCInst(const MachineInstr *MI, 249*0fca6ea1SDimitry Andric MCInst &OutMI) const { 250*0fca6ea1SDimitry Andric OutMI.setOpcode(MI->getOpcode()); 251*0fca6ea1SDimitry Andric 252*0fca6ea1SDimitry Andric for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { 253*0fca6ea1SDimitry Andric const MachineOperand &MO = MI->getOperand(i); 254*0fca6ea1SDimitry Andric MCOperand MCOp = lowerOperand(MO); 255*0fca6ea1SDimitry Andric 256*0fca6ea1SDimitry Andric if (MCOp.isValid()) 257*0fca6ea1SDimitry Andric OutMI.addOperand(MCOp); 258*0fca6ea1SDimitry Andric } 259*0fca6ea1SDimitry Andric } 260*0fca6ea1SDimitry Andric 261*0fca6ea1SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeXtensaAsmPrinter() { 262*0fca6ea1SDimitry Andric RegisterAsmPrinter<XtensaAsmPrinter> A(getTheXtensaTarget()); 263*0fca6ea1SDimitry Andric } 264