brintos

brintos / llvm-project-archived public Read only

0
0
Text · 10.4 KiB · 0426088 Raw
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