1 //===-- XCoreAsmPrinter.cpp - XCore LLVM assembly writer ------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file contains a printer that converts from our internal representation 11 // of machine-dependent LLVM code to the XAS-format XCore assembly language. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #define DEBUG_TYPE "asm-printer" 16 #include "XCore.h" 17 #include "XCoreInstrInfo.h" 18 #include "XCoreSubtarget.h" 19 #include "XCoreTargetMachine.h" 20 #include "llvm/Constants.h" 21 #include "llvm/DerivedTypes.h" 22 #include "llvm/Module.h" 23 #include "llvm/CodeGen/AsmPrinter.h" 24 #include "llvm/CodeGen/DwarfWriter.h" 25 #include "llvm/CodeGen/MachineModuleInfo.h" 26 #include "llvm/CodeGen/MachineFunctionPass.h" 27 #include "llvm/CodeGen/MachineConstantPool.h" 28 #include "llvm/CodeGen/MachineInstr.h" 29 #include "llvm/Target/TargetAsmInfo.h" 30 #include "llvm/Target/TargetData.h" 31 #include "llvm/Support/Mangler.h" 32 #include "llvm/ADT/Statistic.h" 33 #include "llvm/ADT/StringExtras.h" 34 #include "llvm/Support/CommandLine.h" 35 #include "llvm/Support/MathExtras.h" 36 #include "llvm/Support/raw_ostream.h" 37 #include <algorithm> 38 #include <cctype> 39 using namespace llvm; 40 41 STATISTIC(EmittedInsts, "Number of machine instrs printed"); 42 43 static cl::opt<std::string> FileDirective("xcore-file-directive", cl::Optional, 44 cl::desc("Output a file directive into the assembly file"), 45 cl::Hidden, 46 cl::value_desc("filename"), 47 cl::init("")); 48 49 static cl::opt<unsigned> MaxThreads("xcore-max-threads", cl::Optional, 50 cl::desc("Maximum number of threads (for emulation thread-local storage)"), 51 cl::Hidden, 52 cl::value_desc("number"), 53 cl::init(8)); 54 55 namespace { 56 class VISIBILITY_HIDDEN XCoreAsmPrinter : public AsmPrinter { 57 DwarfWriter *DW; 58 const XCoreSubtarget &Subtarget; 59 public: 60 explicit XCoreAsmPrinter(raw_ostream &O, XCoreTargetMachine &TM, 61 const TargetAsmInfo *T, bool V) 62 : AsmPrinter(O, TM, T, V), DW(0), 63 Subtarget(*TM.getSubtargetImpl()) {} 64 65 virtual const char *getPassName() const { 66 return "XCore Assembly Printer"; 67 } 68 69 void printMemOperand(const MachineInstr *MI, int opNum); 70 void printOperand(const MachineInstr *MI, int opNum); 71 bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 72 unsigned AsmVariant, const char *ExtraCode); 73 74 void emitFileDirective(const std::string &filename); 75 void emitGlobalDirective(const std::string &name); 76 void emitExternDirective(const std::string &name); 77 78 void emitArrayBound(const std::string &name, const GlobalVariable *GV); 79 void emitGlobal(const GlobalVariable *GV); 80 81 void emitFunctionStart(MachineFunction &MF); 82 void emitFunctionEnd(MachineFunction &MF); 83 84 bool printInstruction(const MachineInstr *MI); // autogenerated. 85 void printMachineInstruction(const MachineInstr *MI); 86 bool runOnMachineFunction(MachineFunction &F); 87 bool doInitialization(Module &M); 88 bool doFinalization(Module &M); 89 90 void getAnalysisUsage(AnalysisUsage &AU) const { 91 AsmPrinter::getAnalysisUsage(AU); 92 AU.setPreservesAll(); 93 AU.addRequired<MachineModuleInfo>(); 94 AU.addRequired<DwarfWriter>(); 95 } 96 }; 97 } // end of anonymous namespace 98 99 #include "XCoreGenAsmWriter.inc" 100 101 /// createXCoreCodePrinterPass - Returns a pass that prints the XCore 102 /// assembly code for a MachineFunction to the given output stream, 103 /// using the given target machine description. This should work 104 /// regardless of whether the function is in SSA form. 105 /// 106 FunctionPass *llvm::createXCoreCodePrinterPass(raw_ostream &o, 107 XCoreTargetMachine &tm, 108 bool verbose) { 109 return new XCoreAsmPrinter(o, tm, tm.getTargetAsmInfo(), verbose); 110 } 111 112 // PrintEscapedString - Print each character of the specified string, escaping 113 // it if it is not printable or if it is an escape char. 114 static void PrintEscapedString(const std::string &Str, raw_ostream &Out) { 115 for (unsigned i = 0, e = Str.size(); i != e; ++i) { 116 unsigned char C = Str[i]; 117 if (isprint(C) && C != '"' && C != '\\') { 118 Out << C; 119 } else { 120 Out << '\\' 121 << (char) ((C/16 < 10) ? ( C/16 +'0') : ( C/16 -10+'A')) 122 << (char)(((C&15) < 10) ? ((C&15)+'0') : ((C&15)-10+'A')); 123 } 124 } 125 } 126 127 void XCoreAsmPrinter:: 128 emitFileDirective(const std::string &name) 129 { 130 O << "\t.file\t\""; 131 PrintEscapedString(name, O); 132 O << "\"\n"; 133 } 134 135 void XCoreAsmPrinter:: 136 emitGlobalDirective(const std::string &name) 137 { 138 O << TAI->getGlobalDirective() << name; 139 O << "\n"; 140 } 141 142 void XCoreAsmPrinter:: 143 emitExternDirective(const std::string &name) 144 { 145 O << "\t.extern\t" << name; 146 O << '\n'; 147 } 148 149 void XCoreAsmPrinter:: 150 emitArrayBound(const std::string &name, const GlobalVariable *GV) 151 { 152 assert(((GV->hasExternalLinkage() || 153 GV->hasWeakLinkage()) || 154 GV->hasLinkOnceLinkage()) && "Unexpected linkage"); 155 if (const ArrayType *ATy = dyn_cast<ArrayType>( 156 cast<PointerType>(GV->getType())->getElementType())) 157 { 158 O << TAI->getGlobalDirective() << name << ".globound" << "\n"; 159 O << TAI->getSetDirective() << name << ".globound" << "," 160 << ATy->getNumElements() << "\n"; 161 if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage()) { 162 // TODO Use COMDAT groups for LinkOnceLinkage 163 O << TAI->getWeakDefDirective() << name << ".globound" << "\n"; 164 } 165 } 166 } 167 168 void XCoreAsmPrinter:: 169 emitGlobal(const GlobalVariable *GV) 170 { 171 const TargetData *TD = TM.getTargetData(); 172 173 if (GV->hasInitializer()) { 174 // Check to see if this is a special global used by LLVM, if so, emit it. 175 if (EmitSpecialLLVMGlobal(GV)) 176 return; 177 178 SwitchToSection(TAI->SectionForGlobal(GV)); 179 180 std::string name = Mang->getValueName(GV); 181 Constant *C = GV->getInitializer(); 182 unsigned Align = (unsigned)TD->getPreferredTypeAlignmentShift(C->getType()); 183 184 // Mark the start of the global 185 O << "\t.cc_top " << name << ".data," << name << "\n"; 186 187 switch (GV->getLinkage()) { 188 case GlobalValue::AppendingLinkage: 189 cerr << "AppendingLinkage is not supported by this target!\n"; 190 abort(); 191 case GlobalValue::LinkOnceAnyLinkage: 192 case GlobalValue::LinkOnceODRLinkage: 193 case GlobalValue::WeakAnyLinkage: 194 case GlobalValue::WeakODRLinkage: 195 case GlobalValue::ExternalLinkage: 196 emitArrayBound(name, GV); 197 emitGlobalDirective(name); 198 // TODO Use COMDAT groups for LinkOnceLinkage 199 if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage()) { 200 O << TAI->getWeakDefDirective() << name << "\n"; 201 } 202 // FALL THROUGH 203 case GlobalValue::InternalLinkage: 204 case GlobalValue::PrivateLinkage: 205 break; 206 case GlobalValue::GhostLinkage: 207 cerr << "Should not have any unmaterialized functions!\n"; 208 abort(); 209 case GlobalValue::DLLImportLinkage: 210 cerr << "DLLImport linkage is not supported by this target!\n"; 211 abort(); 212 case GlobalValue::DLLExportLinkage: 213 cerr << "DLLExport linkage is not supported by this target!\n"; 214 abort(); 215 default: 216 assert(0 && "Unknown linkage type!"); 217 } 218 219 EmitAlignment(Align, GV, 2); 220 221 unsigned Size = TD->getTypeAllocSize(C->getType()); 222 if (GV->isThreadLocal()) { 223 Size *= MaxThreads; 224 } 225 if (TAI->hasDotTypeDotSizeDirective()) { 226 O << "\t.type " << name << ",@object\n"; 227 O << "\t.size " << name << "," << Size << "\n"; 228 } 229 O << name << ":\n"; 230 231 EmitGlobalConstant(C); 232 if (GV->isThreadLocal()) { 233 for (unsigned i = 1; i < MaxThreads; ++i) { 234 EmitGlobalConstant(C); 235 } 236 } 237 if (Size < 4) { 238 // The ABI requires that unsigned scalar types smaller than 32 bits 239 // are are padded to 32 bits. 240 EmitZeros(4 - Size); 241 } 242 243 // Mark the end of the global 244 O << "\t.cc_bottom " << name << ".data\n"; 245 } 246 } 247 248 /// Emit the directives on the start of functions 249 void XCoreAsmPrinter:: 250 emitFunctionStart(MachineFunction &MF) 251 { 252 // Print out the label for the function. 253 const Function *F = MF.getFunction(); 254 255 SwitchToSection(TAI->SectionForGlobal(F)); 256 257 // Mark the start of the function 258 O << "\t.cc_top " << CurrentFnName << ".function," << CurrentFnName << "\n"; 259 260 switch (F->getLinkage()) { 261 default: assert(0 && "Unknown linkage type!"); 262 case Function::InternalLinkage: // Symbols default to internal. 263 case Function::PrivateLinkage: 264 break; 265 case Function::ExternalLinkage: 266 emitGlobalDirective(CurrentFnName); 267 break; 268 case Function::LinkOnceAnyLinkage: 269 case Function::LinkOnceODRLinkage: 270 case Function::WeakAnyLinkage: 271 case Function::WeakODRLinkage: 272 // TODO Use COMDAT groups for LinkOnceLinkage 273 O << TAI->getGlobalDirective() << CurrentFnName << "\n"; 274 O << TAI->getWeakDefDirective() << CurrentFnName << "\n"; 275 break; 276 } 277 // (1 << 1) byte aligned 278 EmitAlignment(MF.getAlignment(), F, 1); 279 if (TAI->hasDotTypeDotSizeDirective()) { 280 O << "\t.type " << CurrentFnName << ",@function\n"; 281 } 282 O << CurrentFnName << ":\n"; 283 } 284 285 /// Emit the directives on the end of functions 286 void XCoreAsmPrinter:: 287 emitFunctionEnd(MachineFunction &MF) 288 { 289 // Mark the end of the function 290 O << "\t.cc_bottom " << CurrentFnName << ".function\n"; 291 } 292 293 /// runOnMachineFunction - This uses the printMachineInstruction() 294 /// method to print assembly for each instruction. 295 /// 296 bool XCoreAsmPrinter::runOnMachineFunction(MachineFunction &MF) 297 { 298 this->MF = &MF; 299 300 SetupMachineFunction(MF); 301 302 // Print out constants referenced by the function 303 EmitConstantPool(MF.getConstantPool()); 304 305 // Print out jump tables referenced by the function 306 EmitJumpTableInfo(MF.getJumpTableInfo(), MF); 307 308 // Emit the function start directives 309 emitFunctionStart(MF); 310 311 // Emit pre-function debug information. 312 DW->BeginFunction(&MF); 313 314 // Print out code for the function. 315 for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); 316 I != E; ++I) { 317 318 // Print a label for the basic block. 319 if (I != MF.begin()) { 320 printBasicBlockLabel(I, true , true); 321 O << '\n'; 322 } 323 324 for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end(); 325 II != E; ++II) { 326 // Print the assembly for the instruction. 327 O << "\t"; 328 printMachineInstruction(II); 329 } 330 331 // Each Basic Block is separated by a newline 332 O << '\n'; 333 } 334 335 // Emit function end directives 336 emitFunctionEnd(MF); 337 338 // Emit post-function debug information. 339 DW->EndFunction(&MF); 340 341 // We didn't modify anything. 342 return false; 343 } 344 345 void XCoreAsmPrinter::printMemOperand(const MachineInstr *MI, int opNum) 346 { 347 printOperand(MI, opNum); 348 349 if (MI->getOperand(opNum+1).isImm() 350 && MI->getOperand(opNum+1).getImm() == 0) 351 return; 352 353 O << "+"; 354 printOperand(MI, opNum+1); 355 } 356 357 void XCoreAsmPrinter::printOperand(const MachineInstr *MI, int opNum) { 358 const MachineOperand &MO = MI->getOperand(opNum); 359 switch (MO.getType()) { 360 case MachineOperand::MO_Register: 361 if (TargetRegisterInfo::isPhysicalRegister(MO.getReg())) 362 O << TM.getRegisterInfo()->get(MO.getReg()).AsmName; 363 else 364 assert(0 && "not implemented"); 365 break; 366 case MachineOperand::MO_Immediate: 367 O << MO.getImm(); 368 break; 369 case MachineOperand::MO_MachineBasicBlock: 370 printBasicBlockLabel(MO.getMBB()); 371 break; 372 case MachineOperand::MO_GlobalAddress: 373 O << Mang->getValueName(MO.getGlobal()); 374 break; 375 case MachineOperand::MO_ExternalSymbol: 376 O << MO.getSymbolName(); 377 break; 378 case MachineOperand::MO_ConstantPoolIndex: 379 O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() 380 << '_' << MO.getIndex(); 381 break; 382 case MachineOperand::MO_JumpTableIndex: 383 O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() 384 << '_' << MO.getIndex(); 385 break; 386 default: 387 assert(0 && "not implemented"); 388 } 389 } 390 391 /// PrintAsmOperand - Print out an operand for an inline asm expression. 392 /// 393 bool XCoreAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 394 unsigned AsmVariant, 395 const char *ExtraCode) { 396 printOperand(MI, OpNo); 397 return false; 398 } 399 400 void XCoreAsmPrinter::printMachineInstruction(const MachineInstr *MI) { 401 ++EmittedInsts; 402 403 // Check for mov mnemonic 404 unsigned src, dst, srcSR, dstSR; 405 if (TM.getInstrInfo()->isMoveInstr(*MI, src, dst, srcSR, dstSR)) { 406 O << "\tmov "; 407 O << TM.getRegisterInfo()->get(dst).AsmName; 408 O << ", "; 409 O << TM.getRegisterInfo()->get(src).AsmName; 410 O << "\n"; 411 return; 412 } 413 if (printInstruction(MI)) { 414 return; 415 } 416 assert(0 && "Unhandled instruction in asm writer!"); 417 } 418 419 bool XCoreAsmPrinter::doInitialization(Module &M) { 420 bool Result = AsmPrinter::doInitialization(M); 421 DW = getAnalysisIfAvailable<DwarfWriter>(); 422 423 if (!FileDirective.empty()) 424 emitFileDirective(FileDirective); 425 426 return Result; 427 } 428 429 bool XCoreAsmPrinter::doFinalization(Module &M) { 430 431 // Print out module-level global variables. 432 for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); 433 I != E; ++I) { 434 emitGlobal(I); 435 } 436 437 return AsmPrinter::doFinalization(M); 438 } 439