Home | History | Annotate | Download | only in XCore
      1 //===-- XCoreAsmPrinter.cpp - XCore LLVM assembly writer ------------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This file contains a printer that converts from our internal representation
     11 // of machine-dependent LLVM code to the XAS-format XCore assembly language.
     12 //
     13 //===----------------------------------------------------------------------===//
     14 
     15 #define DEBUG_TYPE "asm-printer"
     16 #include "XCore.h"
     17 #include "InstPrinter/XCoreInstPrinter.h"
     18 #include "XCoreInstrInfo.h"
     19 #include "XCoreMCInstLower.h"
     20 #include "XCoreSubtarget.h"
     21 #include "XCoreTargetMachine.h"
     22 #include "llvm/ADT/SmallString.h"
     23 #include "llvm/ADT/StringExtras.h"
     24 #include "llvm/CodeGen/AsmPrinter.h"
     25 #include "llvm/CodeGen/MachineConstantPool.h"
     26 #include "llvm/CodeGen/MachineFunctionPass.h"
     27 #include "llvm/CodeGen/MachineInstr.h"
     28 #include "llvm/CodeGen/MachineJumpTableInfo.h"
     29 #include "llvm/CodeGen/MachineModuleInfo.h"
     30 #include "llvm/DebugInfo.h"
     31 #include "llvm/IR/Constants.h"
     32 #include "llvm/IR/DataLayout.h"
     33 #include "llvm/IR/DerivedTypes.h"
     34 #include "llvm/IR/Module.h"
     35 #include "llvm/MC/MCAsmInfo.h"
     36 #include "llvm/MC/MCInst.h"
     37 #include "llvm/MC/MCStreamer.h"
     38 #include "llvm/MC/MCSymbol.h"
     39 #include "llvm/Support/ErrorHandling.h"
     40 #include "llvm/Support/TargetRegistry.h"
     41 #include "llvm/Support/raw_ostream.h"
     42 #include "llvm/Target/Mangler.h"
     43 #include "llvm/Target/TargetLoweringObjectFile.h"
     44 #include <algorithm>
     45 #include <cctype>
     46 using namespace llvm;
     47 
     48 namespace {
     49   class XCoreAsmPrinter : public AsmPrinter {
     50     const XCoreSubtarget &Subtarget;
     51     XCoreMCInstLower MCInstLowering;
     52   public:
     53     explicit XCoreAsmPrinter(TargetMachine &TM, MCStreamer &Streamer)
     54       : AsmPrinter(TM, Streamer), Subtarget(TM.getSubtarget<XCoreSubtarget>()),
     55         MCInstLowering(*this) {}
     56 
     57     virtual const char *getPassName() const {
     58       return "XCore Assembly Printer";
     59     }
     60 
     61     void printInlineJT(const MachineInstr *MI, int opNum, raw_ostream &O,
     62                        const std::string &directive = ".jmptable");
     63     void printInlineJT32(const MachineInstr *MI, int opNum, raw_ostream &O) {
     64       printInlineJT(MI, opNum, O, ".jmptable32");
     65     }
     66     void printOperand(const MachineInstr *MI, int opNum, raw_ostream &O);
     67     bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
     68                          unsigned AsmVariant, const char *ExtraCode,
     69                          raw_ostream &O);
     70 
     71     void emitArrayBound(MCSymbol *Sym, const GlobalVariable *GV);
     72     virtual void EmitGlobalVariable(const GlobalVariable *GV);
     73 
     74     void EmitFunctionEntryLabel();
     75     void EmitInstruction(const MachineInstr *MI);
     76     void EmitFunctionBodyStart();
     77     void EmitFunctionBodyEnd();
     78   };
     79 } // end of anonymous namespace
     80 
     81 void XCoreAsmPrinter::emitArrayBound(MCSymbol *Sym, const GlobalVariable *GV) {
     82   assert(((GV->hasExternalLinkage() ||
     83     GV->hasWeakLinkage()) ||
     84     GV->hasLinkOnceLinkage()) && "Unexpected linkage");
     85   if (ArrayType *ATy = dyn_cast<ArrayType>(
     86                         cast<PointerType>(GV->getType())->getElementType())) {
     87 
     88     MCSymbol *SymGlob = OutContext.GetOrCreateSymbol(
     89                           Twine(Sym->getName() + StringRef(".globound")));
     90     OutStreamer.EmitSymbolAttribute(SymGlob, MCSA_Global);
     91 
     92     OutStreamer.EmitRawText("\t.set\t" + Twine(Sym->getName()) +
     93                             ".globound," + Twine(ATy->getNumElements()));
     94 
     95     if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage()) {
     96       // TODO Use COMDAT groups for LinkOnceLinkage
     97       OutStreamer.EmitRawText(MAI->getWeakDefDirective() +Twine(Sym->getName())+
     98                               ".globound");
     99     }
    100   }
    101 }
    102 
    103 void XCoreAsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) {
    104   // Check to see if this is a special global used by LLVM, if so, emit it.
    105   if (!GV->hasInitializer() ||
    106       EmitSpecialLLVMGlobal(GV))
    107     return;
    108 
    109   const DataLayout *TD = TM.getDataLayout();
    110   OutStreamer.SwitchSection(getObjFileLowering().SectionForGlobal(GV, Mang,TM));
    111 
    112 
    113   MCSymbol *GVSym = Mang->getSymbol(GV);
    114   const Constant *C = GV->getInitializer();
    115   unsigned Align = (unsigned)TD->getPreferredTypeAlignmentShift(C->getType());
    116 
    117   // Mark the start of the global
    118   OutStreamer.EmitRawText("\t.cc_top " + Twine(GVSym->getName()) + ".data," +
    119                           GVSym->getName());
    120 
    121   switch (GV->getLinkage()) {
    122   case GlobalValue::AppendingLinkage:
    123     report_fatal_error("AppendingLinkage is not supported by this target!");
    124   case GlobalValue::LinkOnceAnyLinkage:
    125   case GlobalValue::LinkOnceODRLinkage:
    126   case GlobalValue::WeakAnyLinkage:
    127   case GlobalValue::WeakODRLinkage:
    128   case GlobalValue::ExternalLinkage:
    129     emitArrayBound(GVSym, GV);
    130     OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Global);
    131 
    132     // TODO Use COMDAT groups for LinkOnceLinkage
    133     if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage())
    134       OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Weak);
    135     // FALL THROUGH
    136   case GlobalValue::InternalLinkage:
    137   case GlobalValue::PrivateLinkage:
    138     break;
    139   case GlobalValue::DLLImportLinkage:
    140     llvm_unreachable("DLLImport linkage is not supported by this target!");
    141   case GlobalValue::DLLExportLinkage:
    142     llvm_unreachable("DLLExport linkage is not supported by this target!");
    143   default:
    144     llvm_unreachable("Unknown linkage type!");
    145   }
    146 
    147   EmitAlignment(Align > 2 ? Align : 2, GV);
    148 
    149   if (GV->isThreadLocal()) {
    150     report_fatal_error("TLS is not supported by this target!");
    151   }
    152   unsigned Size = TD->getTypeAllocSize(C->getType());
    153   if (MAI->hasDotTypeDotSizeDirective()) {
    154     OutStreamer.EmitSymbolAttribute(GVSym, MCSA_ELF_TypeObject);
    155     OutStreamer.EmitRawText("\t.size " + Twine(GVSym->getName()) + "," +
    156                             Twine(Size));
    157   }
    158   OutStreamer.EmitLabel(GVSym);
    159 
    160   EmitGlobalConstant(C);
    161   // The ABI requires that unsigned scalar types smaller than 32 bits
    162   // are padded to 32 bits.
    163   if (Size < 4)
    164     OutStreamer.EmitZeros(4 - Size);
    165 
    166   // Mark the end of the global
    167   OutStreamer.EmitRawText("\t.cc_bottom " + Twine(GVSym->getName()) + ".data");
    168 }
    169 
    170 void XCoreAsmPrinter::EmitFunctionBodyStart() {
    171   MCInstLowering.Initialize(Mang, &MF->getContext());
    172 }
    173 
    174 /// EmitFunctionBodyEnd - Targets can override this to emit stuff after
    175 /// the last basic block in the function.
    176 void XCoreAsmPrinter::EmitFunctionBodyEnd() {
    177   // Emit function end directives
    178   OutStreamer.EmitRawText("\t.cc_bottom " + Twine(CurrentFnSym->getName()) +
    179                           ".function");
    180 }
    181 
    182 void XCoreAsmPrinter::EmitFunctionEntryLabel() {
    183   // Mark the start of the function
    184   OutStreamer.EmitRawText("\t.cc_top " + Twine(CurrentFnSym->getName()) +
    185                           ".function," + CurrentFnSym->getName());
    186   OutStreamer.EmitLabel(CurrentFnSym);
    187 }
    188 
    189 void XCoreAsmPrinter::
    190 printInlineJT(const MachineInstr *MI, int opNum, raw_ostream &O,
    191               const std::string &directive) {
    192   unsigned JTI = MI->getOperand(opNum).getIndex();
    193   const MachineFunction *MF = MI->getParent()->getParent();
    194   const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
    195   const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
    196   const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
    197   O << "\t" << directive << " ";
    198   for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) {
    199     MachineBasicBlock *MBB = JTBBs[i];
    200     if (i > 0)
    201       O << ",";
    202     O << *MBB->getSymbol();
    203   }
    204 }
    205 
    206 void XCoreAsmPrinter::printOperand(const MachineInstr *MI, int opNum,
    207                                    raw_ostream &O) {
    208   const MachineOperand &MO = MI->getOperand(opNum);
    209   switch (MO.getType()) {
    210   case MachineOperand::MO_Register:
    211     O << XCoreInstPrinter::getRegisterName(MO.getReg());
    212     break;
    213   case MachineOperand::MO_Immediate:
    214     O << MO.getImm();
    215     break;
    216   case MachineOperand::MO_MachineBasicBlock:
    217     O << *MO.getMBB()->getSymbol();
    218     break;
    219   case MachineOperand::MO_GlobalAddress:
    220     O << *Mang->getSymbol(MO.getGlobal());
    221     break;
    222   case MachineOperand::MO_ExternalSymbol:
    223     O << MO.getSymbolName();
    224     break;
    225   case MachineOperand::MO_ConstantPoolIndex:
    226     O << MAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
    227       << '_' << MO.getIndex();
    228     break;
    229   case MachineOperand::MO_JumpTableIndex:
    230     O << MAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
    231       << '_' << MO.getIndex();
    232     break;
    233   case MachineOperand::MO_BlockAddress:
    234     O << *GetBlockAddressSymbol(MO.getBlockAddress());
    235     break;
    236   default:
    237     llvm_unreachable("not implemented");
    238   }
    239 }
    240 
    241 /// PrintAsmOperand - Print out an operand for an inline asm expression.
    242 ///
    243 bool XCoreAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
    244                                       unsigned AsmVariant,const char *ExtraCode,
    245                                       raw_ostream &O) {
    246   // Print the operand if there is no operand modifier.
    247   if (!ExtraCode || !ExtraCode[0]) {
    248     printOperand(MI, OpNo, O);
    249     return false;
    250   }
    251 
    252   // Otherwise fallback on the default implementation.
    253   return AsmPrinter::PrintAsmOperand(MI, OpNo, AsmVariant, ExtraCode, O);
    254 }
    255 
    256 void XCoreAsmPrinter::EmitInstruction(const MachineInstr *MI) {
    257   SmallString<128> Str;
    258   raw_svector_ostream O(Str);
    259 
    260   switch (MI->getOpcode()) {
    261   case XCore::DBG_VALUE:
    262     llvm_unreachable("Should be handled target independently");
    263   case XCore::ADD_2rus:
    264     if (MI->getOperand(2).getImm() == 0) {
    265       O << "\tmov "
    266         << XCoreInstPrinter::getRegisterName(MI->getOperand(0).getReg()) << ", "
    267         << XCoreInstPrinter::getRegisterName(MI->getOperand(1).getReg());
    268       OutStreamer.EmitRawText(O.str());
    269       return;
    270     }
    271     break;
    272   case XCore::BR_JT:
    273   case XCore::BR_JT32:
    274     O << "\tbru "
    275       << XCoreInstPrinter::getRegisterName(MI->getOperand(1).getReg()) << '\n';
    276     if (MI->getOpcode() == XCore::BR_JT)
    277       printInlineJT(MI, 0, O);
    278     else
    279       printInlineJT32(MI, 0, O);
    280     O << '\n';
    281     OutStreamer.EmitRawText(O.str());
    282     return;
    283   }
    284 
    285   MCInst TmpInst;
    286   MCInstLowering.Lower(MI, TmpInst);
    287 
    288   OutStreamer.EmitInstruction(TmpInst);
    289 }
    290 
    291 // Force static initialization.
    292 extern "C" void LLVMInitializeXCoreAsmPrinter() {
    293   RegisterAsmPrinter<XCoreAsmPrinter> X(TheXCoreTarget);
    294 }
    295