LLVM API Documentation
00001 //===-- AlphaAsmPrinter.cpp - Alpha 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 GAS-format Alpha assembly language. 00012 // 00013 //===----------------------------------------------------------------------===// 00014 00015 #define DEBUG_TYPE "asm-printer" 00016 #include "Alpha.h" 00017 #include "AlphaInstrInfo.h" 00018 #include "AlphaTargetMachine.h" 00019 #include "llvm/Module.h" 00020 #include "llvm/Type.h" 00021 #include "llvm/Assembly/Writer.h" 00022 #include "llvm/CodeGen/AsmPrinter.h" 00023 #include "llvm/Target/TargetAsmInfo.h" 00024 #include "llvm/Target/TargetMachine.h" 00025 #include "llvm/Support/Compiler.h" 00026 #include "llvm/Support/Mangler.h" 00027 #include "llvm/Support/raw_ostream.h" 00028 #include "llvm/ADT/Statistic.h" 00029 using namespace llvm; 00030 00031 STATISTIC(EmittedInsts, "Number of machine instrs printed"); 00032 00033 namespace { 00034 struct VISIBILITY_HIDDEN AlphaAsmPrinter : public AsmPrinter { 00035 00036 /// Unique incrementer for label values for referencing Global values. 00037 /// 00038 00039 AlphaAsmPrinter(raw_ostream &o, TargetMachine &tm, const TargetAsmInfo *T) 00040 : AsmPrinter(o, tm, T) { 00041 } 00042 00043 virtual const char *getPassName() const { 00044 return "Alpha Assembly Printer"; 00045 } 00046 bool printInstruction(const MachineInstr *MI); 00047 void printOp(const MachineOperand &MO, bool IsCallOp = false); 00048 void printOperand(const MachineInstr *MI, int opNum); 00049 void printBaseOffsetPair (const MachineInstr *MI, int i, bool brackets=true); 00050 void printModuleLevelGV(const GlobalVariable* GVar); 00051 bool runOnMachineFunction(MachineFunction &F); 00052 bool doInitialization(Module &M); 00053 bool doFinalization(Module &M); 00054 00055 bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 00056 unsigned AsmVariant, const char *ExtraCode); 00057 bool PrintAsmMemoryOperand(const MachineInstr *MI, 00058 unsigned OpNo, 00059 unsigned AsmVariant, 00060 const char *ExtraCode); 00061 }; 00062 } // end of anonymous namespace 00063 00064 /// createAlphaCodePrinterPass - Returns a pass that prints the Alpha 00065 /// assembly code for a MachineFunction to the given output stream, 00066 /// using the given target machine description. This should work 00067 /// regardless of whether the function is in SSA form. 00068 /// 00069 FunctionPass *llvm::createAlphaCodePrinterPass(raw_ostream &o, 00070 TargetMachine &tm) { 00071 return new AlphaAsmPrinter(o, tm, tm.getTargetAsmInfo()); 00072 } 00073 00074 #include "AlphaGenAsmWriter.inc" 00075 00076 void AlphaAsmPrinter::printOperand(const MachineInstr *MI, int opNum) 00077 { 00078 const MachineOperand &MO = MI->getOperand(opNum); 00079 if (MO.getType() == MachineOperand::MO_Register) { 00080 assert(TargetRegisterInfo::isPhysicalRegister(MO.getReg()) && 00081 "Not physreg??"); 00082 O << TM.getRegisterInfo()->get(MO.getReg()).AsmName; 00083 } else if (MO.isImm()) { 00084 O << MO.getImm(); 00085 assert(MO.getImm() < (1 << 30)); 00086 } else { 00087 printOp(MO); 00088 } 00089 } 00090 00091 00092 void AlphaAsmPrinter::printOp(const MachineOperand &MO, bool IsCallOp) { 00093 const TargetRegisterInfo &RI = *TM.getRegisterInfo(); 00094 00095 switch (MO.getType()) { 00096 case MachineOperand::MO_Register: 00097 O << RI.get(MO.getReg()).AsmName; 00098 return; 00099 00100 case MachineOperand::MO_Immediate: 00101 cerr << "printOp() does not handle immediate values\n"; 00102 abort(); 00103 return; 00104 00105 case MachineOperand::MO_MachineBasicBlock: 00106 printBasicBlockLabel(MO.getMBB()); 00107 return; 00108 00109 case MachineOperand::MO_ConstantPoolIndex: 00110 O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << "_" 00111 << MO.getIndex(); 00112 return; 00113 00114 case MachineOperand::MO_ExternalSymbol: 00115 O << MO.getSymbolName(); 00116 return; 00117 00118 case MachineOperand::MO_GlobalAddress: { 00119 GlobalValue *GV = MO.getGlobal(); 00120 O << Mang->getValueName(GV); 00121 if (GV->isDeclaration() && GV->hasExternalWeakLinkage()) 00122 ExtWeakSymbols.insert(GV); 00123 return; 00124 } 00125 00126 case MachineOperand::MO_JumpTableIndex: 00127 O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() 00128 << '_' << MO.getIndex(); 00129 return; 00130 00131 default: 00132 O << "<unknown operand type: " << MO.getType() << ">"; 00133 return; 00134 } 00135 } 00136 00137 /// runOnMachineFunction - This uses the printMachineInstruction() 00138 /// method to print assembly for each instruction. 00139 /// 00140 bool AlphaAsmPrinter::runOnMachineFunction(MachineFunction &MF) { 00141 SetupMachineFunction(MF); 00142 O << "\n\n"; 00143 00144 // Print out constants referenced by the function 00145 EmitConstantPool(MF.getConstantPool()); 00146 00147 // Print out jump tables referenced by the function 00148 EmitJumpTableInfo(MF.getJumpTableInfo(), MF); 00149 00150 // Print out labels for the function. 00151 const Function *F = MF.getFunction(); 00152 SwitchToSection(TAI->SectionForGlobal(F)); 00153 00154 EmitAlignment(4, F); 00155 switch (F->getLinkage()) { 00156 default: assert(0 && "Unknown linkage type!"); 00157 case Function::InternalLinkage: // Symbols default to internal. 00158 break; 00159 case Function::ExternalLinkage: 00160 O << "\t.globl " << CurrentFnName << "\n"; 00161 break; 00162 case Function::WeakLinkage: 00163 case Function::LinkOnceLinkage: 00164 O << TAI->getWeakRefDirective() << CurrentFnName << "\n"; 00165 break; 00166 } 00167 00168 printVisibility(CurrentFnName, F->getVisibility()); 00169 00170 O << "\t.ent " << CurrentFnName << "\n"; 00171 00172 O << CurrentFnName << ":\n"; 00173 00174 // Print out code for the function. 00175 for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); 00176 I != E; ++I) { 00177 if (I != MF.begin()) { 00178 printBasicBlockLabel(I, true, true); 00179 O << '\n'; 00180 } 00181 for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end(); 00182 II != E; ++II) { 00183 // Print the assembly for the instruction. 00184 ++EmittedInsts; 00185 if (!printInstruction(II)) { 00186 assert(0 && "Unhandled instruction in asm writer!"); 00187 abort(); 00188 } 00189 } 00190 } 00191 00192 O << "\t.end " << CurrentFnName << "\n"; 00193 00194 // We didn't modify anything. 00195 return false; 00196 } 00197 00198 bool AlphaAsmPrinter::doInitialization(Module &M) 00199 { 00200 if(TM.getSubtarget<AlphaSubtarget>().hasCT()) 00201 O << "\t.arch ev6\n"; //This might need to be ev67, so leave this test here 00202 else 00203 O << "\t.arch ev6\n"; 00204 O << "\t.set noat\n"; 00205 return AsmPrinter::doInitialization(M); 00206 } 00207 00208 void AlphaAsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) { 00209 const TargetData *TD = TM.getTargetData(); 00210 00211 if (!GVar->hasInitializer()) return; // External global require no code 00212 00213 // Check to see if this is a special global used by LLVM, if so, emit it. 00214 if (EmitSpecialLLVMGlobal(GVar)) 00215 return; 00216 00217 std::string name = Mang->getValueName(GVar); 00218 Constant *C = GVar->getInitializer(); 00219 unsigned Size = TD->getABITypeSize(C->getType()); 00220 unsigned Align = TD->getPreferredAlignmentLog(GVar); 00221 00222 // 0: Switch to section 00223 SwitchToSection(TAI->SectionForGlobal(GVar)); 00224 00225 // 1: Check visibility 00226 printVisibility(name, GVar->getVisibility()); 00227 00228 // 2: Kind 00229 switch (GVar->getLinkage()) { 00230 case GlobalValue::LinkOnceLinkage: 00231 case GlobalValue::WeakLinkage: 00232 case GlobalValue::CommonLinkage: 00233 O << TAI->getWeakRefDirective() << name << '\n'; 00234 break; 00235 case GlobalValue::AppendingLinkage: 00236 case GlobalValue::ExternalLinkage: 00237 O << TAI->getGlobalDirective() << name << "\n"; 00238 break; 00239 case GlobalValue::InternalLinkage: 00240 break; 00241 default: 00242 assert(0 && "Unknown linkage type!"); 00243 cerr << "Unknown linkage type!\n"; 00244 abort(); 00245 } 00246 00247 // 3: Type, Size, Align 00248 if (TAI->hasDotTypeDotSizeDirective()) { 00249 O << "\t.type\t" << name << ", @object\n"; 00250 O << "\t.size\t" << name << ", " << Size << "\n"; 00251 } 00252 00253 EmitAlignment(Align, GVar); 00254 00255 O << name << ":\n"; 00256 00257 // If the initializer is a extern weak symbol, remember to emit the weak 00258 // reference! 00259 if (const GlobalValue *GV = dyn_cast<GlobalValue>(C)) 00260 if (GV->hasExternalWeakLinkage()) 00261 ExtWeakSymbols.insert(GV); 00262 00263 EmitGlobalConstant(C); 00264 O << '\n'; 00265 } 00266 00267 bool AlphaAsmPrinter::doFinalization(Module &M) { 00268 for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); 00269 I != E; ++I) 00270 printModuleLevelGV(I); 00271 00272 return AsmPrinter::doFinalization(M); 00273 } 00274 00275 /// PrintAsmOperand - Print out an operand for an inline asm expression. 00276 /// 00277 bool AlphaAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 00278 unsigned AsmVariant, 00279 const char *ExtraCode) { 00280 printOperand(MI, OpNo); 00281 return false; 00282 } 00283 00284 bool AlphaAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, 00285 unsigned OpNo, 00286 unsigned AsmVariant, 00287 const char *ExtraCode) { 00288 if (ExtraCode && ExtraCode[0]) 00289 return true; // Unknown modifier. 00290 O << "0("; 00291 printOperand(MI, OpNo); 00292 O << ")"; 00293 return false; 00294 }