LLVM API Documentation

SparcAsmPrinter.cpp

Go to the documentation of this file.
00001 //===-- SparcAsmPrinter.cpp - Sparc LLVM assembly writer ------------------===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file was developed by the LLVM research group and is distributed under
00006 // the University of Illinois Open Source 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 GAS-format SPARC assembly language.
00012 //
00013 //===----------------------------------------------------------------------===//
00014 
00015 #include "Sparc.h"
00016 #include "SparcInstrInfo.h"
00017 #include "llvm/Constants.h"
00018 #include "llvm/DerivedTypes.h"
00019 #include "llvm/Module.h"
00020 #include "llvm/Assembly/Writer.h"
00021 #include "llvm/CodeGen/AsmPrinter.h"
00022 #include "llvm/CodeGen/MachineFunctionPass.h"
00023 #include "llvm/CodeGen/MachineConstantPool.h"
00024 #include "llvm/CodeGen/MachineInstr.h"
00025 #include "llvm/Target/TargetMachine.h"
00026 #include "llvm/Support/Mangler.h"
00027 #include "llvm/ADT/Statistic.h"
00028 #include "llvm/ADT/StringExtras.h"
00029 #include "llvm/Support/CommandLine.h"
00030 #include "llvm/Support/MathExtras.h"
00031 #include <cctype>
00032 #include <iostream>
00033 using namespace llvm;
00034 
00035 namespace {
00036   Statistic<> EmittedInsts("asm-printer", "Number of machine instrs printed");
00037 
00038   struct SparcAsmPrinter : public AsmPrinter {
00039     SparcAsmPrinter(std::ostream &O, TargetMachine &TM) : AsmPrinter(O, TM) {
00040       Data16bitsDirective = "\t.half\t";
00041       Data32bitsDirective = "\t.word\t";
00042       Data64bitsDirective = 0;  // .xword is only supported by V9.
00043       ZeroDirective = "\t.skip\t";
00044       CommentString = "!";
00045       ConstantPoolSection = "\t.section \".rodata\",#alloc\n";
00046     }
00047 
00048     /// We name each basic block in a Function with a unique number, so
00049     /// that we can consistently refer to them later. This is cleared
00050     /// at the beginning of each call to runOnMachineFunction().
00051     ///
00052     typedef std::map<const Value *, unsigned> ValueMapTy;
00053     ValueMapTy NumberForBB;
00054 
00055     virtual const char *getPassName() const {
00056       return "Sparc Assembly Printer";
00057     }
00058 
00059     void printOperand(const MachineInstr *MI, int opNum);
00060     void printMemOperand(const MachineInstr *MI, int opNum,
00061                          const char *Modifier = 0);
00062     void printCCOperand(const MachineInstr *MI, int opNum);
00063 
00064     bool printInstruction(const MachineInstr *MI);  // autogenerated.
00065     bool runOnMachineFunction(MachineFunction &F);
00066     bool doInitialization(Module &M);
00067     bool doFinalization(Module &M);
00068   };
00069 } // end of anonymous namespace
00070 
00071 #include "SparcGenAsmWriter.inc"
00072 
00073 /// createSparcCodePrinterPass - Returns a pass that prints the SPARC
00074 /// assembly code for a MachineFunction to the given output stream,
00075 /// using the given target machine description.  This should work
00076 /// regardless of whether the function is in SSA form.
00077 ///
00078 FunctionPass *llvm::createSparcCodePrinterPass(std::ostream &o,
00079                                                TargetMachine &tm) {
00080   return new SparcAsmPrinter(o, tm);
00081 }
00082 
00083 /// runOnMachineFunction - This uses the printMachineInstruction()
00084 /// method to print assembly for each instruction.
00085 ///
00086 bool SparcAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
00087   SetupMachineFunction(MF);
00088 
00089   // Print out constants referenced by the function
00090   EmitConstantPool(MF.getConstantPool());
00091 
00092   // BBNumber is used here so that a given Printer will never give two
00093   // BBs the same name. (If you have a better way, please let me know!)
00094   static unsigned BBNumber = 0;
00095 
00096   O << "\n\n";
00097   // What's my mangled name?
00098   CurrentFnName = Mang->getValueName(MF.getFunction());
00099 
00100   // Print out labels for the function.
00101   O << "\t.text\n";
00102   O << "\t.align 16\n";
00103   O << "\t.globl\t" << CurrentFnName << "\n";
00104   O << "\t.type\t" << CurrentFnName << ", #function\n";
00105   O << CurrentFnName << ":\n";
00106 
00107   // Number each basic block so that we can consistently refer to them
00108   // in PC-relative references.
00109   NumberForBB.clear();
00110   for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
00111        I != E; ++I) {
00112     NumberForBB[I->getBasicBlock()] = BBNumber++;
00113   }
00114 
00115   // Print out code for the function.
00116   for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
00117        I != E; ++I) {
00118     // Print a label for the basic block.
00119     if (I != MF.begin())
00120       O << ".LBB" << Mang->getValueName(MF.getFunction ())
00121         << "_" << I->getNumber () << ":\t! "
00122         << I->getBasicBlock ()->getName () << "\n";
00123     for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
00124          II != E; ++II) {
00125       // Print the assembly for the instruction.
00126       O << "\t";
00127       printInstruction(II);
00128       ++EmittedInsts;
00129     }
00130   }
00131 
00132   // We didn't modify anything.
00133   return false;
00134 }
00135 
00136 void SparcAsmPrinter::printOperand(const MachineInstr *MI, int opNum) {
00137   const MachineOperand &MO = MI->getOperand (opNum);
00138   const MRegisterInfo &RI = *TM.getRegisterInfo();
00139   bool CloseParen = false;
00140   if (MI->getOpcode() == SP::SETHIi && !MO.isRegister() && !MO.isImmediate()) {
00141     O << "%hi(";
00142     CloseParen = true;
00143   } else if ((MI->getOpcode() == SP::ORri || MI->getOpcode() == SP::ADDri)
00144              && !MO.isRegister() && !MO.isImmediate()) {
00145     O << "%lo(";
00146     CloseParen = true;
00147   }
00148   switch (MO.getType()) {
00149   case MachineOperand::MO_VirtualRegister:
00150     if (Value *V = MO.getVRegValueOrNull()) {
00151       O << "<" << V->getName() << ">";
00152       break;
00153     }
00154     // FALLTHROUGH
00155   case MachineOperand::MO_MachineRegister:
00156     if (MRegisterInfo::isPhysicalRegister(MO.getReg()))
00157       O << "%" << LowercaseString (RI.get(MO.getReg()).Name);
00158     else
00159       O << "%reg" << MO.getReg();
00160     break;
00161 
00162   case MachineOperand::MO_SignExtendedImmed:
00163   case MachineOperand::MO_UnextendedImmed:
00164     O << (int)MO.getImmedValue();
00165     break;
00166   case MachineOperand::MO_MachineBasicBlock: {
00167     MachineBasicBlock *MBBOp = MO.getMachineBasicBlock();
00168     O << ".LBB" << Mang->getValueName(MBBOp->getParent()->getFunction())
00169       << "_" << MBBOp->getNumber () << "\t! "
00170       << MBBOp->getBasicBlock ()->getName ();
00171     return;
00172   }
00173   case MachineOperand::MO_PCRelativeDisp:
00174     std::cerr << "Shouldn't use addPCDisp() when building Sparc MachineInstrs";
00175     abort ();
00176     return;
00177   case MachineOperand::MO_GlobalAddress:
00178     O << Mang->getValueName(MO.getGlobal());
00179     break;
00180   case MachineOperand::MO_ExternalSymbol:
00181     O << MO.getSymbolName();
00182     break;
00183   case MachineOperand::MO_ConstantPoolIndex:
00184     O << PrivateGlobalPrefix << "CPI" << getFunctionNumber() << "_"
00185       << MO.getConstantPoolIndex();
00186     break;
00187   default:
00188     O << "<unknown operand type>"; abort (); break;
00189   }
00190   if (CloseParen) O << ")";
00191 }
00192 
00193 void SparcAsmPrinter::printMemOperand(const MachineInstr *MI, int opNum,
00194                                       const char *Modifier) {
00195   printOperand(MI, opNum);
00196   
00197   // If this is an ADD operand, emit it like normal operands.
00198   if (Modifier && !strcmp(Modifier, "arith")) {
00199     O << ", ";
00200     printOperand(MI, opNum+1);
00201     return;
00202   }
00203   
00204   MachineOperand::MachineOperandType OpTy = MI->getOperand(opNum+1).getType();
00205   
00206   if ((OpTy == MachineOperand::MO_VirtualRegister ||
00207        OpTy == MachineOperand::MO_MachineRegister) &&
00208       MI->getOperand(opNum+1).getReg() == SP::G0)
00209     return;   // don't print "+%g0"
00210   if ((OpTy == MachineOperand::MO_SignExtendedImmed ||
00211        OpTy == MachineOperand::MO_UnextendedImmed) &&
00212       MI->getOperand(opNum+1).getImmedValue() == 0)
00213     return;   // don't print "+0"
00214   
00215   O << "+";
00216   if (OpTy == MachineOperand::MO_GlobalAddress ||
00217       OpTy == MachineOperand::MO_ConstantPoolIndex) {
00218     O << "%lo(";
00219     printOperand(MI, opNum+1);
00220     O << ")";
00221   } else {
00222     printOperand(MI, opNum+1);
00223   }
00224 }
00225 
00226 void SparcAsmPrinter::printCCOperand(const MachineInstr *MI, int opNum) {
00227   int CC = (int)MI->getOperand(opNum).getImmedValue();
00228   O << SPARCCondCodeToString((SPCC::CondCodes)CC);
00229 }
00230 
00231 
00232 
00233 bool SparcAsmPrinter::doInitialization(Module &M) {
00234   Mang = new Mangler(M);
00235   return false; // success
00236 }
00237 
00238 bool SparcAsmPrinter::doFinalization(Module &M) {
00239   const TargetData &TD = TM.getTargetData();
00240 
00241   // Print out module-level global variables here.
00242   for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
00243        I != E; ++I)
00244     if (I->hasInitializer()) {   // External global require no code
00245       // Check to see if this is a special global used by LLVM, if so, emit it.
00246       if (EmitSpecialLLVMGlobal(I))
00247         continue;
00248       
00249       O << "\n\n";
00250       std::string name = Mang->getValueName(I);
00251       Constant *C = I->getInitializer();
00252       unsigned Size = TD.getTypeSize(C->getType());
00253       unsigned Align = TD.getTypeAlignment(C->getType());
00254 
00255       if (C->isNullValue() &&
00256           (I->hasLinkOnceLinkage() || I->hasInternalLinkage() ||
00257            I->hasWeakLinkage() /* FIXME: Verify correct */)) {
00258         SwitchSection(".data", I);
00259         if (I->hasInternalLinkage())
00260           O << "\t.local " << name << "\n";
00261 
00262         O << "\t.comm " << name << "," << TD.getTypeSize(C->getType())
00263           << "," << (unsigned)TD.getTypeAlignment(C->getType());
00264         O << "\t\t! ";
00265         WriteAsOperand(O, I, true, true, &M);
00266         O << "\n";
00267       } else {
00268         switch (I->getLinkage()) {
00269         case GlobalValue::LinkOnceLinkage:
00270         case GlobalValue::WeakLinkage:   // FIXME: Verify correct for weak.
00271           // Nonnull linkonce -> weak
00272           O << "\t.weak " << name << "\n";
00273           SwitchSection("", I);
00274           O << "\t.section\t\".llvm.linkonce.d." << name
00275             << "\",\"aw\",@progbits\n";
00276           break;
00277 
00278         case GlobalValue::AppendingLinkage:
00279           // FIXME: appending linkage variables should go into a section of
00280           // their name or something.  For now, just emit them as external.
00281         case GlobalValue::ExternalLinkage:
00282           // If external or appending, declare as a global symbol
00283           O << "\t.globl " << name << "\n";
00284           // FALL THROUGH
00285         case GlobalValue::InternalLinkage:
00286           if (C->isNullValue())
00287             SwitchSection(".bss", I);
00288           else
00289             SwitchSection(".data", I);
00290           break;
00291         case GlobalValue::GhostLinkage:
00292           std::cerr << "Should not have any unmaterialized functions!\n";
00293           abort();
00294         }
00295 
00296         O << "\t.align " << Align << "\n";
00297         O << "\t.type " << name << ",#object\n";
00298         O << "\t.size " << name << "," << Size << "\n";
00299         O << name << ":\t\t\t\t! ";
00300         WriteAsOperand(O, I, true, true, &M);
00301         O << "\n";
00302         EmitGlobalConstant(C);
00303       }
00304     }
00305 
00306   AsmPrinter::doFinalization(M);
00307   return false; // success
00308 }