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     bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
00064                          unsigned AsmVariant, const char *ExtraCode);
00065     bool PrintAsmMemoryOperand(const MachineInstr *MI, 
00066              unsigned OpNo,
00067              unsigned AsmVariant, 
00068              const char *ExtraCode);
00069   };
00070 } // end of anonymous namespace
00071 
00072 /// createAlphaCodePrinterPass - Returns a pass that prints the Alpha
00073 /// assembly code for a MachineFunction to the given output stream,
00074 /// using the given target machine description.  This should work
00075 /// regardless of whether the function is in SSA form.
00076 ///
00077 FunctionPass *llvm::createAlphaCodePrinterPass (std::ostream &o,
00078                                                   TargetMachine &tm) {
00079   return new AlphaAsmPrinter(o, tm);
00080 }
00081 
00082 #include "AlphaGenAsmWriter.inc"
00083 
00084 void AlphaAsmPrinter::printOperand(const MachineInstr *MI, int opNum)
00085 {
00086   const MachineOperand &MO = MI->getOperand(opNum);
00087   if (MO.getType() == MachineOperand::MO_Register) {
00088     assert(MRegisterInfo::isPhysicalRegister(MO.getReg())&&"Not physreg??");
00089     O << TM.getRegisterInfo()->get(MO.getReg()).Name;
00090   } else if (MO.isImmediate()) {
00091     O << MO.getImmedValue();
00092     assert(MO.getImmedValue() < (1 << 30));
00093   } else {
00094     printOp(MO);
00095   }
00096 }
00097 
00098 
00099 void AlphaAsmPrinter::printOp(const MachineOperand &MO, bool IsCallOp) {
00100   const MRegisterInfo &RI = *TM.getRegisterInfo();
00101   int new_symbol;
00102 
00103   switch (MO.getType()) {
00104   case MachineOperand::MO_Register:
00105     O << RI.get(MO.getReg()).Name;
00106     return;
00107 
00108   case MachineOperand::MO_Immediate:
00109     std::cerr << "printOp() does not handle immediate values\n";
00110     abort();
00111     return;
00112 
00113   case MachineOperand::MO_MachineBasicBlock:
00114     printBasicBlockLabel(MO.getMachineBasicBlock());
00115     return;
00116 
00117   case MachineOperand::MO_ConstantPoolIndex:
00118     O << PrivateGlobalPrefix << "CPI" << getFunctionNumber() << "_"
00119       << MO.getConstantPoolIndex();
00120     return;
00121 
00122   case MachineOperand::MO_ExternalSymbol:
00123     O << MO.getSymbolName();
00124     return;
00125 
00126   case MachineOperand::MO_GlobalAddress:
00127     O << Mang->getValueName(MO.getGlobal());
00128     return;
00129 
00130   default:
00131     O << "<unknown operand type: " << MO.getType() << ">";
00132     return;
00133   }
00134 }
00135 
00136 /// printMachineInstruction -- Print out a single Alpha MI to
00137 /// the current output stream.
00138 ///
00139 void AlphaAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
00140   ++EmittedInsts;
00141   if (printInstruction(MI))
00142     return; // Printer was automatically generated
00143 
00144   assert(0 && "Unhandled instruction in asm writer!");
00145   abort();
00146   return;
00147 }
00148 
00149 
00150 /// runOnMachineFunction - This uses the printMachineInstruction()
00151 /// method to print assembly for each instruction.
00152 ///
00153 bool AlphaAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
00154   SetupMachineFunction(MF);
00155   O << "\n\n";
00156 
00157   // Print out constants referenced by the function
00158   EmitConstantPool(MF.getConstantPool());
00159 
00160   // Print out labels for the function.
00161   const Function *F = MF.getFunction();
00162   SwitchToTextSection(".text", F);
00163   EmitAlignment(4, F);
00164   switch (F->getLinkage()) {
00165   default: assert(0 && "Unknown linkage type!");
00166   case Function::InternalLinkage:  // Symbols default to internal.
00167     break;
00168    case Function::ExternalLinkage:
00169      O << "\t.globl " << CurrentFnName << "\n";
00170      break;
00171   case Function::WeakLinkage:
00172   case Function::LinkOnceLinkage:
00173     O << "\t.weak " << CurrentFnName << "\n";
00174     break;
00175   }
00176 
00177   O << "\t.ent " << CurrentFnName << "\n";
00178 
00179   O << CurrentFnName << ":\n";
00180 
00181   // Print out code for the function.
00182   for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
00183        I != E; ++I) {
00184     printBasicBlockLabel(I, true);
00185     O << '\n';
00186     for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
00187          II != E; ++II) {
00188       // Print the assembly for the instruction.
00189       O << "\t";
00190       printMachineInstruction(II);
00191     }
00192   }
00193   ++LabelNumber;
00194 
00195   O << "\t.end " << CurrentFnName << "\n";
00196 
00197   // We didn't modify anything.
00198   return false;
00199 }
00200 
00201 bool AlphaAsmPrinter::doInitialization(Module &M)
00202 {
00203   AsmPrinter::doInitialization(M);
00204   if(TM.getSubtarget<AlphaSubtarget>().hasF2I() 
00205      || TM.getSubtarget<AlphaSubtarget>().hasCT())
00206     O << "\t.arch ev6\n";
00207   else
00208     O << "\t.arch ev56\n";
00209   O << "\t.set noat\n";
00210   return false;
00211 }
00212 
00213 bool AlphaAsmPrinter::doFinalization(Module &M) {
00214   const TargetData *TD = TM.getTargetData();
00215 
00216   for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I)
00217     if (I->hasInitializer()) {   // External global require no code
00218       // Check to see if this is a special global used by LLVM, if so, emit it.
00219       if (EmitSpecialLLVMGlobal(I))
00220         continue;
00221       
00222       O << "\n\n";
00223       std::string name = Mang->getValueName(I);
00224       Constant *C = I->getInitializer();
00225       unsigned Size = TD->getTypeSize(C->getType());
00226       //      unsigned Align = TD->getTypeAlignmentShift(C->getType());
00227       unsigned Align = getPreferredAlignmentLog(I);
00228 
00229       if (C->isNullValue() &&
00230           (I->hasLinkOnceLinkage() || I->hasInternalLinkage() ||
00231            I->hasWeakLinkage() /* FIXME: Verify correct */)) {
00232         SwitchToDataSection("\t.section .data", I);
00233         if (I->hasInternalLinkage())
00234           O << "\t.local " << name << "\n";
00235 
00236         O << "\t.comm " << name << "," << TD->getTypeSize(C->getType())
00237           << "," << (1 << Align)
00238           <<  "\n";
00239       } else {
00240         switch (I->getLinkage()) {
00241         case GlobalValue::LinkOnceLinkage:
00242         case GlobalValue::WeakLinkage:   // FIXME: Verify correct for weak.
00243           // Nonnull linkonce -> weak
00244           O << "\t.weak " << name << "\n";
00245           O << "\t.section\t.llvm.linkonce.d." << name << ",\"aw\",@progbits\n";
00246           SwitchToDataSection("", I);
00247           break;
00248         case GlobalValue::AppendingLinkage:
00249           // FIXME: appending linkage variables should go into a section of
00250           // their name or something.  For now, just emit them as external.
00251         case GlobalValue::ExternalLinkage:
00252           // If external or appending, declare as a global symbol
00253           O << "\t.globl " << name << "\n";
00254           // FALL THROUGH
00255         case GlobalValue::InternalLinkage:
00256           SwitchToDataSection(C->isNullValue() ? "\t.section .bss" : 
00257                               "\t.section .data", I);
00258           break;
00259         case GlobalValue::GhostLinkage:
00260           std::cerr << "GhostLinkage cannot appear in AlphaAsmPrinter!\n";
00261           abort();
00262         }
00263 
00264         EmitAlignment(Align);
00265         O << "\t.type " << name << ",@object\n";
00266         O << "\t.size " << name << "," << Size << "\n";
00267         O << name << ":\n";
00268         EmitGlobalConstant(C);
00269       }
00270     }
00271 
00272   AsmPrinter::doFinalization(M);
00273   return false;
00274 }
00275 
00276 /// PrintAsmOperand - Print out an operand for an inline asm expression.
00277 ///
00278 bool AlphaAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
00279                                     unsigned AsmVariant, 
00280                                     const char *ExtraCode) {
00281   printOperand(MI, OpNo);
00282   return false;
00283 }
00284 
00285 bool AlphaAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, 
00286               unsigned OpNo,
00287               unsigned AsmVariant, 
00288               const char *ExtraCode) {
00289   if (ExtraCode && ExtraCode[0])
00290     return true; // Unknown modifier.
00291   O << "0(";
00292   printOperand(MI, OpNo);
00293   O << ")";
00294   return false;
00295 }