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