LLVM API Documentation

AlphaAsmPrinter.cpp

Go to the documentation of this file.
00001 //===-- AlphaAsmPrinter.cpp - Alpha 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 Alpha assembly language.
00012 //
00013 //===----------------------------------------------------------------------===//
00014 
00015 #include "Alpha.h"
00016 #include "AlphaInstrInfo.h"
00017 #include "AlphaTargetMachine.h"
00018 #include "llvm/Module.h"
00019 #include "llvm/Type.h"
00020 #include "llvm/Assembly/Writer.h"
00021 #include "llvm/CodeGen/AsmPrinter.h"
00022 #include "llvm/Target/TargetMachine.h"
00023 #include "llvm/Support/Mangler.h"
00024 #include "llvm/ADT/Statistic.h"
00025 #include <iostream>
00026 using namespace llvm;
00027 
00028 namespace {
00029   Statistic<> EmittedInsts("asm-printer", "Number of machine instrs printed");
00030 
00031   struct AlphaAsmPrinter : public AsmPrinter {
00032 
00033     /// Unique incrementer for label values for referencing Global values.
00034     ///
00035     unsigned LabelNumber;
00036 
00037      AlphaAsmPrinter(std::ostream &o, TargetMachine &tm)
00038        : AsmPrinter(o, tm), LabelNumber(0) {
00039       AlignmentIsInBytes = false;
00040       PrivateGlobalPrefix = "$";
00041     }
00042 
00043     /// We name each basic block in a Function with a unique number, so
00044     /// that we can consistently refer to them later. This is cleared
00045     /// at the beginning of each call to runOnMachineFunction().
00046     ///
00047     typedef std::map<const Value *, unsigned> ValueMapTy;
00048     ValueMapTy NumberForBB;
00049     std::string CurSection;
00050 
00051     virtual const char *getPassName() const {
00052       return "Alpha Assembly Printer";
00053     }
00054     bool printInstruction(const MachineInstr *MI);
00055     void printOp(const MachineOperand &MO, bool IsCallOp = false);
00056     void printOperand(const MachineInstr *MI, int opNum);
00057     void printBaseOffsetPair (const MachineInstr *MI, int i, bool brackets=true);
00058     void printMachineInstruction(const MachineInstr *MI);
00059     bool runOnMachineFunction(MachineFunction &F);
00060     bool doInitialization(Module &M);
00061     bool doFinalization(Module &M);
00062   };
00063 } // end of anonymous namespace
00064 
00065 /// createAlphaCodePrinterPass - Returns a pass that prints the Alpha
00066 /// assembly code for a MachineFunction to the given output stream,
00067 /// using the given target machine description.  This should work
00068 /// regardless of whether the function is in SSA form.
00069 ///
00070 FunctionPass *llvm::createAlphaCodePrinterPass (std::ostream &o,
00071                                                   TargetMachine &tm) {
00072   return new AlphaAsmPrinter(o, tm);
00073 }
00074 
00075 #include "AlphaGenAsmWriter.inc"
00076 
00077 void AlphaAsmPrinter::printOperand(const MachineInstr *MI, int opNum)
00078 {
00079   const MachineOperand &MO = MI->getOperand(opNum);
00080   if (MO.getType() == MachineOperand::MO_MachineRegister) {
00081     assert(MRegisterInfo::isPhysicalRegister(MO.getReg())&&"Not physreg??");
00082     O << TM.getRegisterInfo()->get(MO.getReg()).Name;
00083   } else if (MO.isImmediate()) {
00084     O << MO.getImmedValue();
00085   } else {
00086     printOp(MO);
00087   }
00088 }
00089 
00090 
00091 void AlphaAsmPrinter::printOp(const MachineOperand &MO, bool IsCallOp) {
00092   const MRegisterInfo &RI = *TM.getRegisterInfo();
00093   int new_symbol;
00094 
00095   switch (MO.getType()) {
00096   case MachineOperand::MO_VirtualRegister:
00097     if (Value *V = MO.getVRegValueOrNull()) {
00098       O << "<" << V->getName() << ">";
00099       return;
00100     }
00101     // FALLTHROUGH
00102   case MachineOperand::MO_MachineRegister:
00103   case MachineOperand::MO_CCRegister:
00104     O << RI.get(MO.getReg()).Name;
00105     return;
00106 
00107   case MachineOperand::MO_SignExtendedImmed:
00108   case MachineOperand::MO_UnextendedImmed:
00109     std::cerr << "printOp() does not handle immediate values\n";
00110     abort();
00111     return;
00112 
00113   case MachineOperand::MO_PCRelativeDisp:
00114     std::cerr << "Shouldn't use addPCDisp() when building Alpha MachineInstrs";
00115     abort();
00116     return;
00117 
00118   case MachineOperand::MO_MachineBasicBlock: {
00119     MachineBasicBlock *MBBOp = MO.getMachineBasicBlock();
00120     O << PrivateGlobalPrefix << "LBB"
00121       << Mang->getValueName(MBBOp->getParent()->getFunction())
00122       << "_" << MBBOp->getNumber() << "\t" << CommentString << " "
00123       << MBBOp->getBasicBlock()->getName();
00124     return;
00125   }
00126 
00127   case MachineOperand::MO_ConstantPoolIndex:
00128     O << PrivateGlobalPrefix << "CPI" << getFunctionNumber() << "_"
00129       << MO.getConstantPoolIndex();
00130     return;
00131 
00132   case MachineOperand::MO_ExternalSymbol:
00133     O << MO.getSymbolName();
00134     return;
00135 
00136   case MachineOperand::MO_GlobalAddress:
00137     //Abuse PCrel to specify pcrel calls
00138     //calls are the only thing that use this flag
00139 //     if (MO.isPCRelative())
00140 //       O << PrivateGlobalPrefix << Mang->getValueName(MO.getGlobal()) << "..ng";
00141 //     else
00142       O << Mang->getValueName(MO.getGlobal());
00143     return;
00144 
00145   default:
00146     O << "<unknown operand type: " << MO.getType() << ">";
00147     return;
00148   }
00149 }
00150 
00151 /// printMachineInstruction -- Print out a single Alpha MI to
00152 /// the current output stream.
00153 ///
00154 void AlphaAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
00155   ++EmittedInsts;
00156   if (printInstruction(MI))
00157     return; // Printer was automatically generated
00158 
00159   assert(0 && "Unhandled instruction in asm writer!");
00160   abort();
00161   return;
00162 }
00163 
00164 
00165 /// runOnMachineFunction - This uses the printMachineInstruction()
00166 /// method to print assembly for each instruction.
00167 ///
00168 bool AlphaAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
00169   SetupMachineFunction(MF);
00170   O << "\n\n";
00171 
00172   // Print out constants referenced by the function
00173   EmitConstantPool(MF.getConstantPool());
00174 
00175   // Print out labels for the function.
00176   const Function *F = MF.getFunction();
00177   SwitchSection(".text", F);
00178   EmitAlignment(4, F);
00179   switch (F->getLinkage()) {
00180   default: assert(0 && "Unknown linkage type!");
00181   case Function::InternalLinkage:  // Symbols default to internal.
00182     break;
00183    case Function::ExternalLinkage:
00184      O << "\t.globl " << CurrentFnName << "\n";
00185      break;
00186   case Function::WeakLinkage:
00187   case Function::LinkOnceLinkage:
00188     O << "\t.weak " << CurrentFnName << "\n";
00189     break;
00190   }
00191 
00192   O << "\t.ent " << CurrentFnName << "\n";
00193 
00194   O << CurrentFnName << ":\n";
00195 
00196   // Print out code for the function.
00197   for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
00198        I != E; ++I) {
00199     // Print a label for the basic block.
00200     O << PrivateGlobalPrefix << "LBB" << CurrentFnName << "_" << I->getNumber()
00201       << ":\t" << CommentString << " " << I->getBasicBlock()->getName() << "\n";
00202     for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
00203          II != E; ++II) {
00204       // Print the assembly for the instruction.
00205       O << "\t";
00206       printMachineInstruction(II);
00207     }
00208   }
00209   ++LabelNumber;
00210 
00211   O << "\t.end " << CurrentFnName << "\n";
00212 
00213   // We didn't modify anything.
00214   return false;
00215 }
00216 
00217 bool AlphaAsmPrinter::doInitialization(Module &M)
00218 {
00219   AsmPrinter::doInitialization(M);
00220   if(TM.getSubtarget<AlphaSubtarget>().hasF2I() 
00221      || TM.getSubtarget<AlphaSubtarget>().hasCT())
00222     O << "\t.arch ev6\n";
00223   else
00224     O << "\t.arch ev56\n";
00225   O << "\t.set noat\n";
00226   return false;
00227 }
00228 
00229 bool AlphaAsmPrinter::doFinalization(Module &M) {
00230   const TargetData &TD = TM.getTargetData();
00231 
00232   for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I)
00233     if (I->hasInitializer()) {   // External global require no code
00234       // Check to see if this is a special global used by LLVM, if so, emit it.
00235       if (EmitSpecialLLVMGlobal(I))
00236         continue;
00237       
00238       O << "\n\n";
00239       std::string name = Mang->getValueName(I);
00240       Constant *C = I->getInitializer();
00241       unsigned Size = TD.getTypeSize(C->getType());
00242       //      unsigned Align = TD.getTypeAlignmentShift(C->getType());
00243       unsigned Align = getPreferredAlignmentLog(I);
00244 
00245       if (C->isNullValue() &&
00246           (I->hasLinkOnceLinkage() || I->hasInternalLinkage() ||
00247            I->hasWeakLinkage() /* FIXME: Verify correct */)) {
00248         SwitchSection("\t.section .data", I);
00249         if (I->hasInternalLinkage())
00250           O << "\t.local " << name << "\n";
00251 
00252         O << "\t.comm " << name << "," << TD.getTypeSize(C->getType())
00253           << "," << (1 << Align)
00254           <<  "\n";
00255       } else {
00256         switch (I->getLinkage()) {
00257         case GlobalValue::LinkOnceLinkage:
00258         case GlobalValue::WeakLinkage:   // FIXME: Verify correct for weak.
00259           // Nonnull linkonce -> weak
00260           O << "\t.weak " << name << "\n";
00261           O << "\t.section\t.llvm.linkonce.d." << name << ",\"aw\",@progbits\n";
00262           SwitchSection("", I);
00263           break;
00264         case GlobalValue::AppendingLinkage:
00265           // FIXME: appending linkage variables should go into a section of
00266           // their name or something.  For now, just emit them as external.
00267         case GlobalValue::ExternalLinkage:
00268           // If external or appending, declare as a global symbol
00269           O << "\t.globl " << name << "\n";
00270           // FALL THROUGH
00271         case GlobalValue::InternalLinkage:
00272           SwitchSection(C->isNullValue() ? "\t.section .bss" : 
00273                         "\t.section .data", I);
00274           break;
00275         case GlobalValue::GhostLinkage:
00276           std::cerr << "GhostLinkage cannot appear in AlphaAsmPrinter!\n";
00277           abort();
00278         }
00279 
00280         EmitAlignment(Align);
00281         O << "\t.type " << name << ",@object\n";
00282         O << "\t.size " << name << "," << Size << "\n";
00283         O << name << ":\n";
00284         EmitGlobalConstant(C);
00285       }
00286     }
00287 
00288   AsmPrinter::doFinalization(M);
00289   return false;
00290 }