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 #define DEBUG_TYPE "asm-printer"
00016 #include "XCore.h"
00017 #include "XCoreInstrInfo.h"
00018 #include "XCoreSubtarget.h"
00019 #include "XCoreTargetMachine.h"
00020 #include "llvm/Constants.h"
00021 #include "llvm/DerivedTypes.h"
00022 #include "llvm/Module.h"
00023 #include "llvm/CodeGen/AsmPrinter.h"
00024 #include "llvm/CodeGen/DwarfWriter.h"
00025 #include "llvm/CodeGen/MachineModuleInfo.h"
00026 #include "llvm/CodeGen/MachineFunctionPass.h"
00027 #include "llvm/CodeGen/MachineConstantPool.h"
00028 #include "llvm/CodeGen/MachineInstr.h"
00029 #include "llvm/Target/TargetAsmInfo.h"
00030 #include "llvm/Target/TargetData.h"
00031 #include "llvm/Support/Mangler.h"
00032 #include "llvm/ADT/Statistic.h"
00033 #include "llvm/ADT/StringExtras.h"
00034 #include "llvm/Support/CommandLine.h"
00035 #include "llvm/Support/MathExtras.h"
00036 #include "llvm/Support/raw_ostream.h"
00037 #include <algorithm>
00038 #include <cctype>
00039 using namespace llvm;
00040 
00041 STATISTIC(EmittedInsts, "Number of machine instrs printed");
00042 
00043 static cl::opt<std::string> FileDirective("xcore-file-directive", cl::Optional,
00044   cl::desc("Output a file directive into the assembly file"),
00045   cl::Hidden,
00046   cl::value_desc("filename"),
00047   cl::init(""));
00048 
00049 static cl::opt<unsigned> MaxThreads("xcore-max-threads", cl::Optional,
00050   cl::desc("Maximum number of threads (for emulation thread-local storage)"),
00051   cl::Hidden,
00052   cl::value_desc("number"),
00053   cl::init(8));
00054 
00055 namespace {
00056   struct VISIBILITY_HIDDEN XCoreAsmPrinter : public AsmPrinter {
00057     XCoreAsmPrinter(raw_ostream &O, XCoreTargetMachine &TM,
00058                     const TargetAsmInfo *T)
00059       : AsmPrinter(O, TM, T), DW(0),
00060         Subtarget(*TM.getSubtargetImpl()) { }
00061 
00062     DwarfWriter *DW;
00063     const XCoreSubtarget &Subtarget;
00064 
00065     virtual const char *getPassName() const {
00066       return "XCore Assembly Printer";
00067     }
00068 
00069     void printMemOperand(const MachineInstr *MI, int opNum);
00070     void printOperand(const MachineInstr *MI, int opNum);
00071     bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
00072                         unsigned AsmVariant, const char *ExtraCode);
00073     
00074     void emitFileDirective(const std::string &filename);
00075     void emitGlobalDirective(const std::string &name);
00076     void emitExternDirective(const std::string &name);
00077     
00078     void emitArrayBound(const std::string &name, const GlobalVariable *GV);
00079     void emitGlobal(const GlobalVariable *GV);
00080 
00081     void emitFunctionStart(MachineFunction &MF);
00082     void emitFunctionEnd(MachineFunction &MF);
00083 
00084     bool printInstruction(const MachineInstr *MI);  // autogenerated.
00085     void printMachineInstruction(const MachineInstr *MI);
00086     bool runOnMachineFunction(MachineFunction &F);
00087     bool doInitialization(Module &M);
00088     bool doFinalization(Module &M);
00089     
00090     void getAnalysisUsage(AnalysisUsage &AU) const {
00091       AsmPrinter::getAnalysisUsage(AU);
00092       AU.setPreservesAll();
00093       AU.addRequired<MachineModuleInfo>();
00094       AU.addRequired<DwarfWriter>();
00095     }
00096   };
00097 } // end of anonymous namespace
00098 
00099 #include "XCoreGenAsmWriter.inc"
00100 
00101 /// createXCoreCodePrinterPass - Returns a pass that prints the XCore
00102 /// assembly code for a MachineFunction to the given output stream,
00103 /// using the given target machine description.  This should work
00104 /// regardless of whether the function is in SSA form.
00105 ///
00106 FunctionPass *llvm::createXCoreCodePrinterPass(raw_ostream &o,
00107                                                XCoreTargetMachine &tm) {
00108   return new XCoreAsmPrinter(o, tm, tm.getTargetAsmInfo());
00109 }
00110 
00111 // PrintEscapedString - Print each character of the specified string, escaping
00112 // it if it is not printable or if it is an escape char.
00113 static void PrintEscapedString(const std::string &Str, raw_ostream &Out) {
00114   for (unsigned i = 0, e = Str.size(); i != e; ++i) {
00115     unsigned char C = Str[i];
00116     if (isprint(C) && C != '"' && C != '\\') {
00117       Out << C;
00118     } else {
00119       Out << '\\'
00120           << (char) ((C/16  < 10) ? ( C/16 +'0') : ( C/16 -10+'A'))
00121           << (char)(((C&15) < 10) ? ((C&15)+'0') : ((C&15)-10+'A'));
00122     }
00123   }
00124 }
00125 
00126 void XCoreAsmPrinter::
00127 emitFileDirective(const std::string &name)
00128 {
00129   O << "\t.file\t\"";
00130   PrintEscapedString(name, O);
00131   O << "\"\n";
00132 }
00133 
00134 void XCoreAsmPrinter::
00135 emitGlobalDirective(const std::string &name)
00136 {
00137   O << TAI->getGlobalDirective() << name;
00138   O << "\n";
00139 }
00140 
00141 void XCoreAsmPrinter::
00142 emitExternDirective(const std::string &name)
00143 {
00144   O << "\t.extern\t" << name;
00145   O << '\n';
00146 }
00147 
00148 void XCoreAsmPrinter::
00149 emitArrayBound(const std::string &name, const GlobalVariable *GV)
00150 {
00151   assert(((GV->hasExternalLinkage() ||
00152     GV->hasWeakLinkage()) ||
00153     GV->hasLinkOnceLinkage()) && "Unexpected linkage");
00154   if (const ArrayType *ATy = dyn_cast<ArrayType>(
00155     cast<PointerType>(GV->getType())->getElementType()))
00156   {
00157     O << TAI->getGlobalDirective() << name << ".globound" << "\n";
00158     O << TAI->getSetDirective() << name << ".globound" << ","
00159       << ATy->getNumElements() << "\n";
00160     if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage()) {
00161       // TODO Use COMDAT groups for LinkOnceLinkage
00162       O << TAI->getWeakDefDirective() << name << ".globound" << "\n";
00163     }
00164   }
00165 }
00166 
00167 void XCoreAsmPrinter::
00168 emitGlobal(const GlobalVariable *GV)
00169 {
00170   const TargetData *TD = TM.getTargetData();
00171 
00172   if (GV->hasInitializer()) {
00173     // Check to see if this is a special global used by LLVM, if so, emit it.
00174     if (EmitSpecialLLVMGlobal(GV))
00175       return;
00176 
00177     SwitchToSection(TAI->SectionForGlobal(GV));
00178     
00179     std::string name = Mang->getValueName(GV);
00180     Constant *C = GV->getInitializer();
00181     unsigned Align = (unsigned)TD->getPreferredTypeAlignmentShift(C->getType());
00182     
00183     // Mark the start of the global
00184     O << "\t.cc_top " << name << ".data," << name << "\n";
00185 
00186     switch (GV->getLinkage()) {
00187     case GlobalValue::AppendingLinkage:
00188       cerr << "AppendingLinkage is not supported by this target!\n";
00189       abort();
00190     case GlobalValue::LinkOnceLinkage:
00191     case GlobalValue::WeakLinkage:
00192     case GlobalValue::ExternalLinkage:
00193       emitArrayBound(name, GV);
00194       emitGlobalDirective(name);
00195       // TODO Use COMDAT groups for LinkOnceLinkage
00196       if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage()) {
00197         O << TAI->getWeakDefDirective() << name << "\n";
00198       }
00199       // FALL THROUGH
00200     case GlobalValue::InternalLinkage:
00201     case GlobalValue::PrivateLinkage:
00202       break;
00203     case GlobalValue::GhostLinkage:
00204       cerr << "Should not have any unmaterialized functions!\n";
00205       abort();
00206     case GlobalValue::DLLImportLinkage:
00207       cerr << "DLLImport linkage is not supported by this target!\n";
00208       abort();
00209     case GlobalValue::DLLExportLinkage:
00210       cerr << "DLLExport linkage is not supported by this target!\n";
00211       abort();
00212     default:
00213       assert(0 && "Unknown linkage type!");
00214     }
00215 
00216     EmitAlignment(Align, GV, 2);
00217     
00218     unsigned Size = TD->getTypePaddedSize(C->getType());
00219     if (GV->isThreadLocal()) {
00220       Size *= MaxThreads;
00221     }
00222     if (TAI->hasDotTypeDotSizeDirective()) {
00223       O << "\t.type " << name << ",@object\n";
00224       O << "\t.size " << name << "," << Size << "\n";
00225     }
00226     O << name << ":\n";
00227     
00228     EmitGlobalConstant(C);
00229     if (GV->isThreadLocal()) {
00230       for (unsigned i = 1; i < MaxThreads; ++i) {
00231         EmitGlobalConstant(C);
00232       }
00233     }
00234     if (Size < 4) {
00235       // The ABI requires that unsigned scalar types smaller than 32 bits
00236       // are are padded to 32 bits.
00237       EmitZeros(4 - Size);
00238     }
00239     
00240     // Mark the end of the global
00241     O << "\t.cc_bottom " << name << ".data\n";
00242   } else {
00243     if (GV->hasExternalWeakLinkage())
00244       ExtWeakSymbols.insert(GV);
00245   }
00246 }
00247 
00248 /// Emit the directives on the start of functions
00249 void XCoreAsmPrinter::
00250 emitFunctionStart(MachineFunction &MF)
00251 {
00252   // Print out the label for the function.
00253   const Function *F = MF.getFunction();
00254 
00255   SwitchToSection(TAI->SectionForGlobal(F));
00256   
00257   // Mark the start of the function
00258   O << "\t.cc_top " << CurrentFnName << ".function," << CurrentFnName << "\n";
00259 
00260   switch (F->getLinkage()) {
00261   default: assert(0 && "Unknown linkage type!");
00262   case Function::InternalLinkage:  // Symbols default to internal.
00263   case Function::PrivateLinkage:
00264     break;
00265   case Function::ExternalLinkage:
00266     emitGlobalDirective(CurrentFnName);
00267     break;
00268   case Function::LinkOnceLinkage:
00269   case Function::WeakLinkage:
00270     // TODO Use COMDAT groups for LinkOnceLinkage
00271     O << TAI->getGlobalDirective() << CurrentFnName << "\n";
00272     O << TAI->getWeakDefDirective() << CurrentFnName << "\n";
00273     break;
00274   }
00275   // (1 << 1) byte aligned
00276   EmitAlignment(1, F, 1);
00277   if (TAI->hasDotTypeDotSizeDirective()) {
00278     O << "\t.type " << CurrentFnName << ",@function\n";
00279   }
00280   O << CurrentFnName << ":\n";
00281 }
00282 
00283 /// Emit the directives on the end of functions
00284 void XCoreAsmPrinter::
00285 emitFunctionEnd(MachineFunction &MF) 
00286 {
00287   // Mark the end of the function
00288   O << "\t.cc_bottom " << CurrentFnName << ".function\n";
00289 }
00290 
00291 /// runOnMachineFunction - This uses the printMachineInstruction()
00292 /// method to print assembly for each instruction.
00293 ///
00294 bool XCoreAsmPrinter::runOnMachineFunction(MachineFunction &MF)
00295 {
00296   SetupMachineFunction(MF);
00297 
00298   // Print out constants referenced by the function
00299   EmitConstantPool(MF.getConstantPool());
00300 
00301   // Print out jump tables referenced by the function
00302   EmitJumpTableInfo(MF.getJumpTableInfo(), MF);
00303 
00304   // Emit the function start directives
00305   emitFunctionStart(MF);
00306   
00307   // Emit pre-function debug information.
00308   DW->BeginFunction(&MF);
00309 
00310   // Print out code for the function.
00311   for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
00312        I != E; ++I) {
00313 
00314     // Print a label for the basic block.
00315     if (I != MF.begin()) {
00316       printBasicBlockLabel(I, true , true);
00317       O << '\n';
00318     }
00319 
00320     for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
00321          II != E; ++II) {
00322       // Print the assembly for the instruction.
00323       O << "\t";
00324       printMachineInstruction(II);
00325     }
00326 
00327     // Each Basic Block is separated by a newline
00328     O << '\n';
00329   }
00330 
00331   // Emit function end directives
00332   emitFunctionEnd(MF);
00333   
00334   // Emit post-function debug information.
00335   DW->EndFunction(&MF);
00336 
00337   // We didn't modify anything.
00338   return false;
00339 }
00340 
00341 void XCoreAsmPrinter::printMemOperand(const MachineInstr *MI, int opNum)
00342 {
00343   printOperand(MI, opNum);
00344   
00345   if (MI->getOperand(opNum+1).isImm()
00346     && MI->getOperand(opNum+1).getImm() == 0)
00347     return;
00348   
00349   O << "+";
00350   printOperand(MI, opNum+1);
00351 }
00352 
00353 void XCoreAsmPrinter::printOperand(const MachineInstr *MI, int opNum) {
00354   const MachineOperand &MO = MI->getOperand(opNum);
00355   switch (MO.getType()) {
00356   case MachineOperand::MO_Register:
00357     if (TargetRegisterInfo::isPhysicalRegister(MO.getReg()))
00358       O << TM.getRegisterInfo()->get(MO.getReg()).AsmName;
00359     else
00360       assert(0 && "not implemented");
00361     break;
00362   case MachineOperand::MO_Immediate:
00363     O << MO.getImm();
00364     break;
00365   case MachineOperand::MO_MachineBasicBlock:
00366     printBasicBlockLabel(MO.getMBB());
00367     break;
00368   case MachineOperand::MO_GlobalAddress:
00369     {
00370       const GlobalValue *GV = MO.getGlobal();
00371       O << Mang->getValueName(GV);
00372       if (GV->hasExternalWeakLinkage())
00373         ExtWeakSymbols.insert(GV);
00374     }
00375     break;
00376   case MachineOperand::MO_ExternalSymbol:
00377     O << MO.getSymbolName();
00378     break;
00379   case MachineOperand::MO_ConstantPoolIndex:
00380     O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
00381       << '_' << MO.getIndex();
00382     break;
00383   case MachineOperand::MO_JumpTableIndex:
00384     O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
00385       << '_' << MO.getIndex();
00386     break;
00387   default:
00388     assert(0 && "not implemented");
00389   }
00390 }
00391 
00392 /// PrintAsmOperand - Print out an operand for an inline asm expression.
00393 ///
00394 bool XCoreAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
00395                                       unsigned AsmVariant, 
00396                                       const char *ExtraCode) {
00397   printOperand(MI, OpNo);
00398   return false;
00399 }
00400 
00401 void XCoreAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
00402   ++EmittedInsts;
00403 
00404   // Check for mov mnemonic
00405   unsigned src, dst, srcSR, dstSR;
00406   if (TM.getInstrInfo()->isMoveInstr(*MI, src, dst, srcSR, dstSR)) {
00407     O << "\tmov ";
00408     O << TM.getRegisterInfo()->get(dst).AsmName;
00409     O << ", ";
00410     O << TM.getRegisterInfo()->get(src).AsmName;
00411     O << "\n";
00412     return;
00413   }
00414   if (printInstruction(MI)) {
00415     return;
00416   }
00417   assert(0 && "Unhandled instruction in asm writer!");
00418 }
00419 
00420 bool XCoreAsmPrinter::doInitialization(Module &M) {
00421   bool Result = AsmPrinter::doInitialization(M);
00422   
00423   if (!FileDirective.empty()) {
00424     emitFileDirective(FileDirective);
00425   }
00426   
00427   // Print out type strings for external functions here
00428   for (Module::const_iterator I = M.begin(), E = M.end();
00429        I != E; ++I) {
00430     if (I->isDeclaration() && !I->isIntrinsic()) {
00431       switch (I->getLinkage()) {
00432       default:
00433         assert(0 && "Unexpected linkage");
00434       case Function::ExternalWeakLinkage:
00435         ExtWeakSymbols.insert(I);
00436         // fallthrough
00437       case Function::ExternalLinkage:
00438         break;
00439       }
00440     }
00441   }
00442 
00443   // Emit initial debug information.
00444   DW = getAnalysisIfAvailable<DwarfWriter>();
00445   assert(DW && "Dwarf Writer is not available");
00446   DW->BeginModule(&M, getAnalysisIfAvailable<MachineModuleInfo>(),
00447                   O, this, TAI);
00448   return Result;
00449 }
00450 
00451 bool XCoreAsmPrinter::doFinalization(Module &M) {
00452 
00453   // Print out module-level global variables.
00454   for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
00455        I != E; ++I) {
00456     emitGlobal(I);
00457   }
00458   
00459   // Emit final debug information.
00460   DW->EndModule();
00461 
00462   return AsmPrinter::doFinalization(M);
00463 }