303 lines · cpp
1//===-- XCoreAsmPrinter.cpp - XCore LLVM assembly writer ------------------===//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 the XAS-format XCore assembly language.11//12//===----------------------------------------------------------------------===//13 14#include "MCTargetDesc/XCoreInstPrinter.h"15#include "MCTargetDesc/XCoreTargetStreamer.h"16#include "TargetInfo/XCoreTargetInfo.h"17#include "XCore.h"18#include "XCoreMCInstLower.h"19#include "XCoreSubtarget.h"20#include "XCoreTargetMachine.h"21#include "llvm/ADT/SmallString.h"22#include "llvm/ADT/StringExtras.h"23#include "llvm/CodeGen/AsmPrinter.h"24#include "llvm/CodeGen/MachineConstantPool.h"25#include "llvm/CodeGen/MachineInstr.h"26#include "llvm/CodeGen/MachineJumpTableInfo.h"27#include "llvm/CodeGen/MachineModuleInfo.h"28#include "llvm/IR/DataLayout.h"29#include "llvm/IR/DerivedTypes.h"30#include "llvm/IR/Mangler.h"31#include "llvm/MC/MCAsmInfo.h"32#include "llvm/MC/MCExpr.h"33#include "llvm/MC/MCInst.h"34#include "llvm/MC/MCStreamer.h"35#include "llvm/MC/TargetRegistry.h"36#include "llvm/Support/Compiler.h"37#include "llvm/Support/ErrorHandling.h"38#include "llvm/Support/raw_ostream.h"39#include "llvm/Target/TargetLoweringObjectFile.h"40#include <algorithm>41#include <cctype>42using namespace llvm;43 44#define DEBUG_TYPE "asm-printer"45 46namespace {47 class XCoreAsmPrinter : public AsmPrinter {48 XCoreMCInstLower MCInstLowering;49 XCoreTargetStreamer &getTargetStreamer();50 51 public:52 static char ID;53 54 explicit XCoreAsmPrinter(TargetMachine &TM,55 std::unique_ptr<MCStreamer> Streamer)56 : AsmPrinter(TM, std::move(Streamer), ID), MCInstLowering(*this) {}57 58 StringRef getPassName() const override { return "XCore Assembly Printer"; }59 60 void printInlineJT(const MachineInstr *MI, int opNum, raw_ostream &O,61 const std::string &directive = ".jmptable");62 void printInlineJT32(const MachineInstr *MI, int opNum, raw_ostream &O) {63 printInlineJT(MI, opNum, O, ".jmptable32");64 }65 void printOperand(const MachineInstr *MI, int opNum, raw_ostream &O);66 bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,67 const char *ExtraCode, raw_ostream &O) override;68 bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum,69 const char *ExtraCode, raw_ostream &O) override;70 71 void emitArrayBound(MCSymbol *Sym, const GlobalVariable *GV);72 void emitGlobalVariable(const GlobalVariable *GV) override;73 74 void emitFunctionEntryLabel() override;75 void emitInstruction(const MachineInstr *MI) override;76 void emitFunctionBodyStart() override;77 void emitFunctionBodyEnd() override;78 };79} // end of anonymous namespace80 81XCoreTargetStreamer &XCoreAsmPrinter::getTargetStreamer() {82 return static_cast<XCoreTargetStreamer&>(*OutStreamer->getTargetStreamer());83}84 85void XCoreAsmPrinter::emitArrayBound(MCSymbol *Sym, const GlobalVariable *GV) {86 assert( ( GV->hasExternalLinkage() || GV->hasWeakLinkage() ||87 GV->hasLinkOnceLinkage() || GV->hasCommonLinkage() ) &&88 "Unexpected linkage");89 if (ArrayType *ATy = dyn_cast<ArrayType>(GV->getValueType())) {90 91 MCSymbol *SymGlob = OutContext.getOrCreateSymbol(92 Twine(Sym->getName() + StringRef(".globound")));93 OutStreamer->emitSymbolAttribute(SymGlob, MCSA_Global);94 OutStreamer->emitAssignment(SymGlob,95 MCConstantExpr::create(ATy->getNumElements(),96 OutContext));97 if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage() ||98 GV->hasCommonLinkage()) {99 OutStreamer->emitSymbolAttribute(SymGlob, MCSA_Weak);100 }101 }102}103 104void XCoreAsmPrinter::emitGlobalVariable(const GlobalVariable *GV) {105 // Check to see if this is a special global used by LLVM, if so, emit it.106 if (!GV->hasInitializer() || emitSpecialLLVMGlobal(GV))107 return;108 109 const DataLayout &DL = getDataLayout();110 OutStreamer->switchSection(getObjFileLowering().SectionForGlobal(GV, TM));111 112 MCSymbol *GVSym = getSymbol(GV);113 const Constant *C = GV->getInitializer();114 const Align Alignment = DL.getPrefTypeAlign(C->getType());115 116 // Mark the start of the global117 getTargetStreamer().emitCCTopData(GVSym->getName());118 119 switch (GV->getLinkage()) {120 case GlobalValue::AppendingLinkage:121 report_fatal_error("AppendingLinkage is not supported by this target!");122 case GlobalValue::LinkOnceAnyLinkage:123 case GlobalValue::LinkOnceODRLinkage:124 case GlobalValue::WeakAnyLinkage:125 case GlobalValue::WeakODRLinkage:126 case GlobalValue::ExternalLinkage:127 case GlobalValue::CommonLinkage:128 emitArrayBound(GVSym, GV);129 OutStreamer->emitSymbolAttribute(GVSym, MCSA_Global);130 131 if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage() ||132 GV->hasCommonLinkage())133 OutStreamer->emitSymbolAttribute(GVSym, MCSA_Weak);134 [[fallthrough]];135 case GlobalValue::InternalLinkage:136 case GlobalValue::PrivateLinkage:137 break;138 default:139 llvm_unreachable("Unknown linkage type!");140 }141 142 emitAlignment(std::max(Alignment, Align(4)), GV);143 144 if (GV->isThreadLocal()) {145 report_fatal_error("TLS is not supported by this target!");146 }147 unsigned Size = DL.getTypeAllocSize(C->getType());148 if (MAI->hasDotTypeDotSizeDirective()) {149 OutStreamer->emitSymbolAttribute(GVSym, MCSA_ELF_TypeObject);150 OutStreamer->emitELFSize(GVSym, MCConstantExpr::create(Size, OutContext));151 }152 OutStreamer->emitLabel(GVSym);153 154 emitGlobalConstant(DL, C);155 // The ABI requires that unsigned scalar types smaller than 32 bits156 // are padded to 32 bits.157 if (Size < 4)158 OutStreamer->emitZeros(4 - Size);159 160 // Mark the end of the global161 getTargetStreamer().emitCCBottomData(GVSym->getName());162}163 164void XCoreAsmPrinter::emitFunctionBodyStart() {165 MCInstLowering.Initialize(&MF->getContext());166}167 168/// EmitFunctionBodyEnd - Targets can override this to emit stuff after169/// the last basic block in the function.170void XCoreAsmPrinter::emitFunctionBodyEnd() {171 // Emit function end directives172 getTargetStreamer().emitCCBottomFunction(CurrentFnSym->getName());173}174 175void XCoreAsmPrinter::emitFunctionEntryLabel() {176 // Mark the start of the function177 getTargetStreamer().emitCCTopFunction(CurrentFnSym->getName());178 OutStreamer->emitLabel(CurrentFnSym);179}180 181void XCoreAsmPrinter::182printInlineJT(const MachineInstr *MI, int opNum, raw_ostream &O,183 const std::string &directive) {184 unsigned JTI = MI->getOperand(opNum).getIndex();185 const MachineFunction *MF = MI->getParent()->getParent();186 const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();187 const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();188 const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;189 O << "\t" << directive << " ";190 for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) {191 MachineBasicBlock *MBB = JTBBs[i];192 if (i > 0)193 O << ",";194 MBB->getSymbol()->print(O, MAI);195 }196}197 198void XCoreAsmPrinter::printOperand(const MachineInstr *MI, int opNum,199 raw_ostream &O) {200 const DataLayout &DL = getDataLayout();201 const MachineOperand &MO = MI->getOperand(opNum);202 switch (MO.getType()) {203 case MachineOperand::MO_Register:204 O << XCoreInstPrinter::getRegisterName(MO.getReg());205 break;206 case MachineOperand::MO_Immediate:207 O << MO.getImm();208 break;209 case MachineOperand::MO_MachineBasicBlock:210 MO.getMBB()->getSymbol()->print(O, MAI);211 break;212 case MachineOperand::MO_GlobalAddress:213 PrintSymbolOperand(MO, O);214 break;215 case MachineOperand::MO_ConstantPoolIndex:216 O << DL.getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_'217 << MO.getIndex();218 break;219 case MachineOperand::MO_BlockAddress:220 GetBlockAddressSymbol(MO.getBlockAddress())->print(O, MAI);221 break;222 default:223 llvm_unreachable("not implemented");224 }225}226 227/// PrintAsmOperand - Print out an operand for an inline asm expression.228///229bool XCoreAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,230 const char *ExtraCode, raw_ostream &O) {231 // Print the operand if there is no operand modifier.232 if (!ExtraCode || !ExtraCode[0]) {233 printOperand(MI, OpNo, O);234 return false;235 }236 237 // Otherwise fallback on the default implementation.238 return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, O);239}240 241bool XCoreAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,242 unsigned OpNum,243 const char *ExtraCode,244 raw_ostream &O) {245 if (ExtraCode && ExtraCode[0]) {246 return true; // Unknown modifier.247 }248 printOperand(MI, OpNum, O);249 O << '[';250 printOperand(MI, OpNum + 1, O);251 O << ']';252 return false;253}254 255void XCoreAsmPrinter::emitInstruction(const MachineInstr *MI) {256 XCore_MC::verifyInstructionPredicates(MI->getOpcode(),257 getSubtargetInfo().getFeatureBits());258 259 SmallString<128> Str;260 raw_svector_ostream O(Str);261 262 switch (MI->getOpcode()) {263 case XCore::DBG_VALUE:264 llvm_unreachable("Should be handled target independently");265 case XCore::ADD_2rus:266 if (MI->getOperand(2).getImm() == 0) {267 O << "\tmov "268 << XCoreInstPrinter::getRegisterName(MI->getOperand(0).getReg()) << ", "269 << XCoreInstPrinter::getRegisterName(MI->getOperand(1).getReg());270 OutStreamer->emitRawText(O.str());271 return;272 }273 break;274 case XCore::BR_JT:275 case XCore::BR_JT32:276 O << "\tbru "277 << XCoreInstPrinter::getRegisterName(MI->getOperand(1).getReg()) << '\n';278 if (MI->getOpcode() == XCore::BR_JT)279 printInlineJT(MI, 0, O);280 else281 printInlineJT32(MI, 0, O);282 O << '\n';283 OutStreamer->emitRawText(O.str());284 return;285 }286 287 MCInst TmpInst;288 MCInstLowering.Lower(MI, TmpInst);289 290 EmitToStreamer(*OutStreamer, TmpInst);291}292 293char XCoreAsmPrinter::ID = 0;294 295INITIALIZE_PASS(XCoreAsmPrinter, "xcore-asm-printer", "XCore Assembly Printer",296 false, false)297 298// Force static initialization.299extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void300LLVMInitializeXCoreAsmPrinter() {301 RegisterAsmPrinter<XCoreAsmPrinter> X(getTheXCoreTarget());302}303