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