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