LLVM API Documentation
00001 //===-- XCoreAsmPrinter.cpp - XCore 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 the XAS-format XCore assembly language. 00012 // 00013 //===----------------------------------------------------------------------===// 00014 00015 #define DEBUG_TYPE "asm-printer" 00016 #include "XCore.h" 00017 #include "XCoreInstrInfo.h" 00018 #include "XCoreSubtarget.h" 00019 #include "XCoreTargetMachine.h" 00020 #include "llvm/Constants.h" 00021 #include "llvm/DerivedTypes.h" 00022 #include "llvm/Module.h" 00023 #include "llvm/CodeGen/AsmPrinter.h" 00024 #include "llvm/CodeGen/DwarfWriter.h" 00025 #include "llvm/CodeGen/MachineModuleInfo.h" 00026 #include "llvm/CodeGen/MachineFunctionPass.h" 00027 #include "llvm/CodeGen/MachineConstantPool.h" 00028 #include "llvm/CodeGen/MachineInstr.h" 00029 #include "llvm/Target/TargetAsmInfo.h" 00030 #include "llvm/Target/TargetData.h" 00031 #include "llvm/Support/Mangler.h" 00032 #include "llvm/ADT/Statistic.h" 00033 #include "llvm/ADT/StringExtras.h" 00034 #include "llvm/Support/CommandLine.h" 00035 #include "llvm/Support/MathExtras.h" 00036 #include "llvm/Support/raw_ostream.h" 00037 #include <algorithm> 00038 #include <cctype> 00039 using namespace llvm; 00040 00041 STATISTIC(EmittedInsts, "Number of machine instrs printed"); 00042 00043 static cl::opt<std::string> FileDirective("xcore-file-directive", cl::Optional, 00044 cl::desc("Output a file directive into the assembly file"), 00045 cl::Hidden, 00046 cl::value_desc("filename"), 00047 cl::init("")); 00048 00049 static cl::opt<unsigned> MaxThreads("xcore-max-threads", cl::Optional, 00050 cl::desc("Maximum number of threads (for emulation thread-local storage)"), 00051 cl::Hidden, 00052 cl::value_desc("number"), 00053 cl::init(8)); 00054 00055 namespace { 00056 struct VISIBILITY_HIDDEN XCoreAsmPrinter : public AsmPrinter { 00057 XCoreAsmPrinter(raw_ostream &O, XCoreTargetMachine &TM, 00058 const TargetAsmInfo *T) 00059 : AsmPrinter(O, TM, T), DW(0), 00060 Subtarget(*TM.getSubtargetImpl()) { } 00061 00062 DwarfWriter *DW; 00063 const XCoreSubtarget &Subtarget; 00064 00065 virtual const char *getPassName() const { 00066 return "XCore Assembly Printer"; 00067 } 00068 00069 void printMemOperand(const MachineInstr *MI, int opNum); 00070 void printOperand(const MachineInstr *MI, int opNum); 00071 bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 00072 unsigned AsmVariant, const char *ExtraCode); 00073 00074 void emitFileDirective(const std::string &filename); 00075 void emitGlobalDirective(const std::string &name); 00076 void emitExternDirective(const std::string &name); 00077 00078 void emitArrayBound(const std::string &name, const GlobalVariable *GV); 00079 void emitGlobal(const GlobalVariable *GV); 00080 00081 void emitFunctionStart(MachineFunction &MF); 00082 void emitFunctionEnd(MachineFunction &MF); 00083 00084 bool printInstruction(const MachineInstr *MI); // autogenerated. 00085 void printMachineInstruction(const MachineInstr *MI); 00086 bool runOnMachineFunction(MachineFunction &F); 00087 bool doInitialization(Module &M); 00088 bool doFinalization(Module &M); 00089 00090 void getAnalysisUsage(AnalysisUsage &AU) const { 00091 AsmPrinter::getAnalysisUsage(AU); 00092 AU.setPreservesAll(); 00093 AU.addRequired<MachineModuleInfo>(); 00094 AU.addRequired<DwarfWriter>(); 00095 } 00096 }; 00097 } // end of anonymous namespace 00098 00099 #include "XCoreGenAsmWriter.inc" 00100 00101 /// createXCoreCodePrinterPass - Returns a pass that prints the XCore 00102 /// assembly code for a MachineFunction to the given output stream, 00103 /// using the given target machine description. This should work 00104 /// regardless of whether the function is in SSA form. 00105 /// 00106 FunctionPass *llvm::createXCoreCodePrinterPass(raw_ostream &o, 00107 XCoreTargetMachine &tm) { 00108 return new XCoreAsmPrinter(o, tm, tm.getTargetAsmInfo()); 00109 } 00110 00111 // PrintEscapedString - Print each character of the specified string, escaping 00112 // it if it is not printable or if it is an escape char. 00113 static void PrintEscapedString(const std::string &Str, raw_ostream &Out) { 00114 for (unsigned i = 0, e = Str.size(); i != e; ++i) { 00115 unsigned char C = Str[i]; 00116 if (isprint(C) && C != '"' && C != '\\') { 00117 Out << C; 00118 } else { 00119 Out << '\\' 00120 << (char) ((C/16 < 10) ? ( C/16 +'0') : ( C/16 -10+'A')) 00121 << (char)(((C&15) < 10) ? ((C&15)+'0') : ((C&15)-10+'A')); 00122 } 00123 } 00124 } 00125 00126 void XCoreAsmPrinter:: 00127 emitFileDirective(const std::string &name) 00128 { 00129 O << "\t.file\t\""; 00130 PrintEscapedString(name, O); 00131 O << "\"\n"; 00132 } 00133 00134 void XCoreAsmPrinter:: 00135 emitGlobalDirective(const std::string &name) 00136 { 00137 O << TAI->getGlobalDirective() << name; 00138 O << "\n"; 00139 } 00140 00141 void XCoreAsmPrinter:: 00142 emitExternDirective(const std::string &name) 00143 { 00144 O << "\t.extern\t" << name; 00145 O << '\n'; 00146 } 00147 00148 void XCoreAsmPrinter:: 00149 emitArrayBound(const std::string &name, const GlobalVariable *GV) 00150 { 00151 assert(((GV->hasExternalLinkage() || 00152 GV->hasWeakLinkage()) || 00153 GV->hasLinkOnceLinkage()) && "Unexpected linkage"); 00154 if (const ArrayType *ATy = dyn_cast<ArrayType>( 00155 cast<PointerType>(GV->getType())->getElementType())) 00156 { 00157 O << TAI->getGlobalDirective() << name << ".globound" << "\n"; 00158 O << TAI->getSetDirective() << name << ".globound" << "," 00159 << ATy->getNumElements() << "\n"; 00160 if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage()) { 00161 // TODO Use COMDAT groups for LinkOnceLinkage 00162 O << TAI->getWeakDefDirective() << name << ".globound" << "\n"; 00163 } 00164 } 00165 } 00166 00167 void XCoreAsmPrinter:: 00168 emitGlobal(const GlobalVariable *GV) 00169 { 00170 const TargetData *TD = TM.getTargetData(); 00171 00172 if (GV->hasInitializer()) { 00173 // Check to see if this is a special global used by LLVM, if so, emit it. 00174 if (EmitSpecialLLVMGlobal(GV)) 00175 return; 00176 00177 SwitchToSection(TAI->SectionForGlobal(GV)); 00178 00179 std::string name = Mang->getValueName(GV); 00180 Constant *C = GV->getInitializer(); 00181 unsigned Align = (unsigned)TD->getPreferredTypeAlignmentShift(C->getType()); 00182 00183 // Mark the start of the global 00184 O << "\t.cc_top " << name << ".data," << name << "\n"; 00185 00186 switch (GV->getLinkage()) { 00187 case GlobalValue::AppendingLinkage: 00188 cerr << "AppendingLinkage is not supported by this target!\n"; 00189 abort(); 00190 case GlobalValue::LinkOnceLinkage: 00191 case GlobalValue::WeakLinkage: 00192 case GlobalValue::ExternalLinkage: 00193 emitArrayBound(name, GV); 00194 emitGlobalDirective(name); 00195 // TODO Use COMDAT groups for LinkOnceLinkage 00196 if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage()) { 00197 O << TAI->getWeakDefDirective() << name << "\n"; 00198 } 00199 // FALL THROUGH 00200 case GlobalValue::InternalLinkage: 00201 case GlobalValue::PrivateLinkage: 00202 break; 00203 case GlobalValue::GhostLinkage: 00204 cerr << "Should not have any unmaterialized functions!\n"; 00205 abort(); 00206 case GlobalValue::DLLImportLinkage: 00207 cerr << "DLLImport linkage is not supported by this target!\n"; 00208 abort(); 00209 case GlobalValue::DLLExportLinkage: 00210 cerr << "DLLExport linkage is not supported by this target!\n"; 00211 abort(); 00212 default: 00213 assert(0 && "Unknown linkage type!"); 00214 } 00215 00216 EmitAlignment(Align, GV, 2); 00217 00218 unsigned Size = TD->getTypePaddedSize(C->getType()); 00219 if (GV->isThreadLocal()) { 00220 Size *= MaxThreads; 00221 } 00222 if (TAI->hasDotTypeDotSizeDirective()) { 00223 O << "\t.type " << name << ",@object\n"; 00224 O << "\t.size " << name << "," << Size << "\n"; 00225 } 00226 O << name << ":\n"; 00227 00228 EmitGlobalConstant(C); 00229 if (GV->isThreadLocal()) { 00230 for (unsigned i = 1; i < MaxThreads; ++i) { 00231 EmitGlobalConstant(C); 00232 } 00233 } 00234 if (Size < 4) { 00235 // The ABI requires that unsigned scalar types smaller than 32 bits 00236 // are are padded to 32 bits. 00237 EmitZeros(4 - Size); 00238 } 00239 00240 // Mark the end of the global 00241 O << "\t.cc_bottom " << name << ".data\n"; 00242 } else { 00243 if (GV->hasExternalWeakLinkage()) 00244 ExtWeakSymbols.insert(GV); 00245 } 00246 } 00247 00248 /// Emit the directives on the start of functions 00249 void XCoreAsmPrinter:: 00250 emitFunctionStart(MachineFunction &MF) 00251 { 00252 // Print out the label for the function. 00253 const Function *F = MF.getFunction(); 00254 00255 SwitchToSection(TAI->SectionForGlobal(F)); 00256 00257 // Mark the start of the function 00258 O << "\t.cc_top " << CurrentFnName << ".function," << CurrentFnName << "\n"; 00259 00260 switch (F->getLinkage()) { 00261 default: assert(0 && "Unknown linkage type!"); 00262 case Function::InternalLinkage: // Symbols default to internal. 00263 case Function::PrivateLinkage: 00264 break; 00265 case Function::ExternalLinkage: 00266 emitGlobalDirective(CurrentFnName); 00267 break; 00268 case Function::LinkOnceLinkage: 00269 case Function::WeakLinkage: 00270 // TODO Use COMDAT groups for LinkOnceLinkage 00271 O << TAI->getGlobalDirective() << CurrentFnName << "\n"; 00272 O << TAI->getWeakDefDirective() << CurrentFnName << "\n"; 00273 break; 00274 } 00275 // (1 << 1) byte aligned 00276 EmitAlignment(1, F, 1); 00277 if (TAI->hasDotTypeDotSizeDirective()) { 00278 O << "\t.type " << CurrentFnName << ",@function\n"; 00279 } 00280 O << CurrentFnName << ":\n"; 00281 } 00282 00283 /// Emit the directives on the end of functions 00284 void XCoreAsmPrinter:: 00285 emitFunctionEnd(MachineFunction &MF) 00286 { 00287 // Mark the end of the function 00288 O << "\t.cc_bottom " << CurrentFnName << ".function\n"; 00289 } 00290 00291 /// runOnMachineFunction - This uses the printMachineInstruction() 00292 /// method to print assembly for each instruction. 00293 /// 00294 bool XCoreAsmPrinter::runOnMachineFunction(MachineFunction &MF) 00295 { 00296 SetupMachineFunction(MF); 00297 00298 // Print out constants referenced by the function 00299 EmitConstantPool(MF.getConstantPool()); 00300 00301 // Print out jump tables referenced by the function 00302 EmitJumpTableInfo(MF.getJumpTableInfo(), MF); 00303 00304 // Emit the function start directives 00305 emitFunctionStart(MF); 00306 00307 // Emit pre-function debug information. 00308 DW->BeginFunction(&MF); 00309 00310 // Print out code for the function. 00311 for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); 00312 I != E; ++I) { 00313 00314 // Print a label for the basic block. 00315 if (I != MF.begin()) { 00316 printBasicBlockLabel(I, true , true); 00317 O << '\n'; 00318 } 00319 00320 for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end(); 00321 II != E; ++II) { 00322 // Print the assembly for the instruction. 00323 O << "\t"; 00324 printMachineInstruction(II); 00325 } 00326 00327 // Each Basic Block is separated by a newline 00328 O << '\n'; 00329 } 00330 00331 // Emit function end directives 00332 emitFunctionEnd(MF); 00333 00334 // Emit post-function debug information. 00335 DW->EndFunction(&MF); 00336 00337 // We didn't modify anything. 00338 return false; 00339 } 00340 00341 void XCoreAsmPrinter::printMemOperand(const MachineInstr *MI, int opNum) 00342 { 00343 printOperand(MI, opNum); 00344 00345 if (MI->getOperand(opNum+1).isImm() 00346 && MI->getOperand(opNum+1).getImm() == 0) 00347 return; 00348 00349 O << "+"; 00350 printOperand(MI, opNum+1); 00351 } 00352 00353 void XCoreAsmPrinter::printOperand(const MachineInstr *MI, int opNum) { 00354 const MachineOperand &MO = MI->getOperand(opNum); 00355 switch (MO.getType()) { 00356 case MachineOperand::MO_Register: 00357 if (TargetRegisterInfo::isPhysicalRegister(MO.getReg())) 00358 O << TM.getRegisterInfo()->get(MO.getReg()).AsmName; 00359 else 00360 assert(0 && "not implemented"); 00361 break; 00362 case MachineOperand::MO_Immediate: 00363 O << MO.getImm(); 00364 break; 00365 case MachineOperand::MO_MachineBasicBlock: 00366 printBasicBlockLabel(MO.getMBB()); 00367 break; 00368 case MachineOperand::MO_GlobalAddress: 00369 { 00370 const GlobalValue *GV = MO.getGlobal(); 00371 O << Mang->getValueName(GV); 00372 if (GV->hasExternalWeakLinkage()) 00373 ExtWeakSymbols.insert(GV); 00374 } 00375 break; 00376 case MachineOperand::MO_ExternalSymbol: 00377 O << MO.getSymbolName(); 00378 break; 00379 case MachineOperand::MO_ConstantPoolIndex: 00380 O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() 00381 << '_' << MO.getIndex(); 00382 break; 00383 case MachineOperand::MO_JumpTableIndex: 00384 O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() 00385 << '_' << MO.getIndex(); 00386 break; 00387 default: 00388 assert(0 && "not implemented"); 00389 } 00390 } 00391 00392 /// PrintAsmOperand - Print out an operand for an inline asm expression. 00393 /// 00394 bool XCoreAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 00395 unsigned AsmVariant, 00396 const char *ExtraCode) { 00397 printOperand(MI, OpNo); 00398 return false; 00399 } 00400 00401 void XCoreAsmPrinter::printMachineInstruction(const MachineInstr *MI) { 00402 ++EmittedInsts; 00403 00404 // Check for mov mnemonic 00405 unsigned src, dst, srcSR, dstSR; 00406 if (TM.getInstrInfo()->isMoveInstr(*MI, src, dst, srcSR, dstSR)) { 00407 O << "\tmov "; 00408 O << TM.getRegisterInfo()->get(dst).AsmName; 00409 O << ", "; 00410 O << TM.getRegisterInfo()->get(src).AsmName; 00411 O << "\n"; 00412 return; 00413 } 00414 if (printInstruction(MI)) { 00415 return; 00416 } 00417 assert(0 && "Unhandled instruction in asm writer!"); 00418 } 00419 00420 bool XCoreAsmPrinter::doInitialization(Module &M) { 00421 bool Result = AsmPrinter::doInitialization(M); 00422 00423 if (!FileDirective.empty()) { 00424 emitFileDirective(FileDirective); 00425 } 00426 00427 // Print out type strings for external functions here 00428 for (Module::const_iterator I = M.begin(), E = M.end(); 00429 I != E; ++I) { 00430 if (I->isDeclaration() && !I->isIntrinsic()) { 00431 switch (I->getLinkage()) { 00432 default: 00433 assert(0 && "Unexpected linkage"); 00434 case Function::ExternalWeakLinkage: 00435 ExtWeakSymbols.insert(I); 00436 // fallthrough 00437 case Function::ExternalLinkage: 00438 break; 00439 } 00440 } 00441 } 00442 00443 // Emit initial debug information. 00444 DW = getAnalysisIfAvailable<DwarfWriter>(); 00445 assert(DW && "Dwarf Writer is not available"); 00446 DW->BeginModule(&M, getAnalysisIfAvailable<MachineModuleInfo>(), 00447 O, this, TAI); 00448 return Result; 00449 } 00450 00451 bool XCoreAsmPrinter::doFinalization(Module &M) { 00452 00453 // Print out module-level global variables. 00454 for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); 00455 I != E; ++I) { 00456 emitGlobal(I); 00457 } 00458 00459 // Emit final debug information. 00460 DW->EndModule(); 00461 00462 return AsmPrinter::doFinalization(M); 00463 }