LLVM API Documentation
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 }