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