LLVM API Documentation

XCoreAsmPrinter.cpp
Go to the documentation of this file.
00001 //===-- XCoreAsmPrinter.cpp - XCore LLVM assembly writer ------------------===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This file contains a printer that converts from our internal representation
00011 // of machine-dependent LLVM code to the XAS-format XCore assembly language.
00012 //
00013 //===----------------------------------------------------------------------===//
00014 
00015 #include "XCore.h"
00016 #include "InstPrinter/XCoreInstPrinter.h"
00017 #include "XCoreInstrInfo.h"
00018 #include "XCoreMCInstLower.h"
00019 #include "XCoreSubtarget.h"
00020 #include "XCoreTargetMachine.h"
00021 #include "XCoreTargetStreamer.h"
00022 #include "llvm/ADT/SmallString.h"
00023 #include "llvm/ADT/StringExtras.h"
00024 #include "llvm/CodeGen/AsmPrinter.h"
00025 #include "llvm/CodeGen/MachineConstantPool.h"
00026 #include "llvm/CodeGen/MachineFunctionPass.h"
00027 #include "llvm/CodeGen/MachineInstr.h"
00028 #include "llvm/CodeGen/MachineJumpTableInfo.h"
00029 #include "llvm/CodeGen/MachineModuleInfo.h"
00030 #include "llvm/IR/Constants.h"
00031 #include "llvm/IR/DataLayout.h"
00032 #include "llvm/IR/DebugInfo.h"
00033 #include "llvm/IR/DerivedTypes.h"
00034 #include "llvm/IR/Mangler.h"
00035 #include "llvm/IR/Module.h"
00036 #include "llvm/MC/MCAsmInfo.h"
00037 #include "llvm/MC/MCExpr.h"
00038 #include "llvm/MC/MCInst.h"
00039 #include "llvm/MC/MCStreamer.h"
00040 #include "llvm/MC/MCSymbol.h"
00041 #include "llvm/Support/ErrorHandling.h"
00042 #include "llvm/Support/TargetRegistry.h"
00043 #include "llvm/Support/raw_ostream.h"
00044 #include "llvm/Target/TargetLoweringObjectFile.h"
00045 #include <algorithm>
00046 #include <cctype>
00047 using namespace llvm;
00048 
00049 #define DEBUG_TYPE "asm-printer"
00050 
00051 namespace {
00052   class XCoreAsmPrinter : public AsmPrinter {
00053     const XCoreSubtarget &Subtarget;
00054     XCoreMCInstLower MCInstLowering;
00055     XCoreTargetStreamer &getTargetStreamer();
00056 
00057   public:
00058     explicit XCoreAsmPrinter(TargetMachine &TM, MCStreamer &Streamer)
00059       : AsmPrinter(TM, Streamer), Subtarget(TM.getSubtarget<XCoreSubtarget>()),
00060         MCInstLowering(*this) {}
00061 
00062     const char *getPassName() const override {
00063       return "XCore Assembly Printer";
00064     }
00065 
00066     void printInlineJT(const MachineInstr *MI, int opNum, raw_ostream &O,
00067                        const std::string &directive = ".jmptable");
00068     void printInlineJT32(const MachineInstr *MI, int opNum, raw_ostream &O) {
00069       printInlineJT(MI, opNum, O, ".jmptable32");
00070     }
00071     void printOperand(const MachineInstr *MI, int opNum, raw_ostream &O);
00072     bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
00073                          unsigned AsmVariant, const char *ExtraCode,
00074                          raw_ostream &O) override;
00075     bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum,
00076                                unsigned AsmVariant, const char *ExtraCode,
00077                                raw_ostream &O) override;
00078 
00079     void emitArrayBound(MCSymbol *Sym, const GlobalVariable *GV);
00080     void EmitGlobalVariable(const GlobalVariable *GV) override;
00081 
00082     void EmitFunctionEntryLabel() override;
00083     void EmitInstruction(const MachineInstr *MI) override;
00084     void EmitFunctionBodyStart() override;
00085     void EmitFunctionBodyEnd() override;
00086   };
00087 } // end of anonymous namespace
00088 
00089 XCoreTargetStreamer &XCoreAsmPrinter::getTargetStreamer() {
00090   return static_cast<XCoreTargetStreamer&>(*OutStreamer.getTargetStreamer());
00091 }
00092 
00093 void XCoreAsmPrinter::emitArrayBound(MCSymbol *Sym, const GlobalVariable *GV) {
00094   assert( ( GV->hasExternalLinkage() || GV->hasWeakLinkage() ||
00095             GV->hasLinkOnceLinkage() || GV->hasCommonLinkage() ) &&
00096           "Unexpected linkage");
00097   if (ArrayType *ATy = dyn_cast<ArrayType>(
00098                         cast<PointerType>(GV->getType())->getElementType())) {
00099 
00100     MCSymbol *SymGlob = OutContext.GetOrCreateSymbol(
00101                           Twine(Sym->getName() + StringRef(".globound")));
00102     OutStreamer.EmitSymbolAttribute(SymGlob, MCSA_Global);
00103     OutStreamer.EmitAssignment(SymGlob,
00104                                MCConstantExpr::Create(ATy->getNumElements(),
00105                                                       OutContext));
00106     if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage() ||
00107         GV->hasCommonLinkage()) {
00108       // TODO Use COMDAT groups for LinkOnceLinkage
00109       OutStreamer.EmitSymbolAttribute(SymGlob, MCSA_Weak);
00110     }
00111   }
00112 }
00113 
00114 void XCoreAsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) {
00115   // Check to see if this is a special global used by LLVM, if so, emit it.
00116   if (!GV->hasInitializer() ||
00117       EmitSpecialLLVMGlobal(GV))
00118     return;
00119 
00120   const DataLayout *TD = TM.getSubtargetImpl()->getDataLayout();
00121   OutStreamer.SwitchSection(
00122       getObjFileLowering().SectionForGlobal(GV, *Mang, TM));
00123 
00124   MCSymbol *GVSym = getSymbol(GV);
00125   const Constant *C = GV->getInitializer();
00126   unsigned Align = (unsigned)TD->getPreferredTypeAlignmentShift(C->getType());
00127   
00128   // Mark the start of the global
00129   getTargetStreamer().emitCCTopData(GVSym->getName());
00130 
00131   switch (GV->getLinkage()) {
00132   case GlobalValue::AppendingLinkage:
00133     report_fatal_error("AppendingLinkage is not supported by this target!");
00134   case GlobalValue::LinkOnceAnyLinkage:
00135   case GlobalValue::LinkOnceODRLinkage:
00136   case GlobalValue::WeakAnyLinkage:
00137   case GlobalValue::WeakODRLinkage:
00138   case GlobalValue::ExternalLinkage:
00139   case GlobalValue::CommonLinkage:
00140     emitArrayBound(GVSym, GV);
00141     OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Global);
00142 
00143     // TODO Use COMDAT groups for LinkOnceLinkage
00144     if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage() ||
00145         GV->hasCommonLinkage())
00146       OutStreamer.EmitSymbolAttribute(GVSym, MCSA_Weak);
00147     // FALL THROUGH
00148   case GlobalValue::InternalLinkage:
00149   case GlobalValue::PrivateLinkage:
00150     break;
00151   default:
00152     llvm_unreachable("Unknown linkage type!");
00153   }
00154 
00155   EmitAlignment(Align > 2 ? Align : 2, GV);
00156   
00157   if (GV->isThreadLocal()) {
00158     report_fatal_error("TLS is not supported by this target!");
00159   }
00160   unsigned Size = TD->getTypeAllocSize(C->getType());
00161   if (MAI->hasDotTypeDotSizeDirective()) {
00162     OutStreamer.EmitSymbolAttribute(GVSym, MCSA_ELF_TypeObject);
00163     OutStreamer.EmitELFSize(GVSym, MCConstantExpr::Create(Size, OutContext));
00164   }
00165   OutStreamer.EmitLabel(GVSym);
00166   
00167   EmitGlobalConstant(C);
00168   // The ABI requires that unsigned scalar types smaller than 32 bits
00169   // are padded to 32 bits.
00170   if (Size < 4)
00171     OutStreamer.EmitZeros(4 - Size);
00172   
00173   // Mark the end of the global
00174   getTargetStreamer().emitCCBottomData(GVSym->getName());
00175 }
00176 
00177 void XCoreAsmPrinter::EmitFunctionBodyStart() {
00178   MCInstLowering.Initialize(Mang, &MF->getContext());
00179 }
00180 
00181 /// EmitFunctionBodyEnd - Targets can override this to emit stuff after
00182 /// the last basic block in the function.
00183 void XCoreAsmPrinter::EmitFunctionBodyEnd() {
00184   // Emit function end directives
00185   getTargetStreamer().emitCCBottomFunction(CurrentFnSym->getName());
00186 }
00187 
00188 void XCoreAsmPrinter::EmitFunctionEntryLabel() {
00189   // Mark the start of the function
00190   getTargetStreamer().emitCCTopFunction(CurrentFnSym->getName());
00191   OutStreamer.EmitLabel(CurrentFnSym);
00192 }
00193 
00194 void XCoreAsmPrinter::
00195 printInlineJT(const MachineInstr *MI, int opNum, raw_ostream &O,
00196               const std::string &directive) {
00197   unsigned JTI = MI->getOperand(opNum).getIndex();
00198   const MachineFunction *MF = MI->getParent()->getParent();
00199   const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
00200   const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
00201   const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
00202   O << "\t" << directive << " ";
00203   for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) {
00204     MachineBasicBlock *MBB = JTBBs[i];
00205     if (i > 0)
00206       O << ",";
00207     O << *MBB->getSymbol();
00208   }
00209 }
00210 
00211 void XCoreAsmPrinter::printOperand(const MachineInstr *MI, int opNum,
00212                                    raw_ostream &O) {
00213   const DataLayout *DL = TM.getSubtargetImpl()->getDataLayout();
00214   const MachineOperand &MO = MI->getOperand(opNum);
00215   switch (MO.getType()) {
00216   case MachineOperand::MO_Register:
00217     O << XCoreInstPrinter::getRegisterName(MO.getReg());
00218     break;
00219   case MachineOperand::MO_Immediate:
00220     O << MO.getImm();
00221     break;
00222   case MachineOperand::MO_MachineBasicBlock:
00223     O << *MO.getMBB()->getSymbol();
00224     break;
00225   case MachineOperand::MO_GlobalAddress:
00226     O << *getSymbol(MO.getGlobal());
00227     break;
00228   case MachineOperand::MO_ConstantPoolIndex:
00229     O << DL->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
00230       << '_' << MO.getIndex();
00231     break;
00232   case MachineOperand::MO_BlockAddress:
00233     O << *GetBlockAddressSymbol(MO.getBlockAddress());
00234     break;
00235   default:
00236     llvm_unreachable("not implemented");
00237   }
00238 }
00239 
00240 /// PrintAsmOperand - Print out an operand for an inline asm expression.
00241 ///
00242 bool XCoreAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
00243                                       unsigned AsmVariant,const char *ExtraCode,
00244                                       raw_ostream &O) {
00245   // Print the operand if there is no operand modifier.
00246   if (!ExtraCode || !ExtraCode[0]) {
00247     printOperand(MI, OpNo, O);
00248     return false;
00249   }
00250 
00251   // Otherwise fallback on the default implementation.
00252   return AsmPrinter::PrintAsmOperand(MI, OpNo, AsmVariant, ExtraCode, O);
00253 }
00254 
00255 bool XCoreAsmPrinter::
00256 PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum,
00257                       unsigned AsmVariant, const char *ExtraCode,
00258                       raw_ostream &O) {
00259   if (ExtraCode && ExtraCode[0]) {
00260     return true; // Unknown modifier.
00261   }
00262   printOperand(MI, OpNum, O);
00263   O << '[';
00264   printOperand(MI, OpNum + 1, O);
00265   O << ']';
00266   return false;
00267 }
00268 
00269 void XCoreAsmPrinter::EmitInstruction(const MachineInstr *MI) {
00270   SmallString<128> Str;
00271   raw_svector_ostream O(Str);
00272 
00273   switch (MI->getOpcode()) {
00274   case XCore::DBG_VALUE:
00275     llvm_unreachable("Should be handled target independently");
00276   case XCore::ADD_2rus:
00277     if (MI->getOperand(2).getImm() == 0) {
00278       O << "\tmov "
00279         << XCoreInstPrinter::getRegisterName(MI->getOperand(0).getReg()) << ", "
00280         << XCoreInstPrinter::getRegisterName(MI->getOperand(1).getReg());
00281       OutStreamer.EmitRawText(O.str());
00282       return;
00283     }
00284     break;
00285   case XCore::BR_JT:
00286   case XCore::BR_JT32:
00287     O << "\tbru "
00288       << XCoreInstPrinter::getRegisterName(MI->getOperand(1).getReg()) << '\n';
00289     if (MI->getOpcode() == XCore::BR_JT)
00290       printInlineJT(MI, 0, O);
00291     else
00292       printInlineJT32(MI, 0, O);
00293     O << '\n';
00294     OutStreamer.EmitRawText(O.str());
00295     return;
00296   }
00297 
00298   MCInst TmpInst;
00299   MCInstLowering.Lower(MI, TmpInst);
00300 
00301   EmitToStreamer(OutStreamer, TmpInst);
00302 }
00303 
00304 // Force static initialization.
00305 extern "C" void LLVMInitializeXCoreAsmPrinter() { 
00306   RegisterAsmPrinter<XCoreAsmPrinter> X(TheXCoreTarget);
00307 }