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/Target/TargetLoweringObjectFile.h" 32 #include "llvm/Target/TargetRegistry.h" 33 #include "llvm/Support/Mangler.h" 34 #include "llvm/ADT/Statistic.h" 35 #include "llvm/ADT/StringExtras.h" 36 #include "llvm/Support/CommandLine.h" 37 #include "llvm/Support/ErrorHandling.h" 38 #include "llvm/Support/FormattedStream.h" 39 #include "llvm/Support/MathExtras.h" 40 #include <algorithm> 41 #include <cctype> 42 using namespace llvm; 43 44 STATISTIC(EmittedInsts, "Number of machine instrs printed"); 45 46 static cl::opt<unsigned> MaxThreads("xcore-max-threads", cl::Optional, 47 cl::desc("Maximum number of threads (for emulation thread-local storage)"), 48 cl::Hidden, 49 cl::value_desc("number"), 50 cl::init(8)); 51 52 namespace { 53 class VISIBILITY_HIDDEN XCoreAsmPrinter : public AsmPrinter { 54 DwarfWriter *DW; 55 const XCoreSubtarget &Subtarget; 56 public: 57 explicit XCoreAsmPrinter(formatted_raw_ostream &O, TargetMachine &TM, 58 const TargetAsmInfo *T, bool V) 59 : AsmPrinter(O, TM, T, V), DW(0), 60 Subtarget(TM.getSubtarget<XCoreSubtarget>()) {} 61 62 virtual const char *getPassName() const { 63 return "XCore Assembly Printer"; 64 } 65 66 void printMemOperand(const MachineInstr *MI, int opNum); 67 void printOperand(const MachineInstr *MI, int opNum); 68 bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 69 unsigned AsmVariant, const char *ExtraCode); 70 71 void emitGlobalDirective(const std::string &name); 72 void emitExternDirective(const std::string &name); 73 74 void emitArrayBound(const std::string &name, const GlobalVariable *GV); 75 virtual void PrintGlobalVariable(const GlobalVariable *GV); 76 77 void emitFunctionStart(MachineFunction &MF); 78 void emitFunctionEnd(MachineFunction &MF); 79 80 bool printInstruction(const MachineInstr *MI); // autogenerated. 81 void printMachineInstruction(const MachineInstr *MI); 82 bool runOnMachineFunction(MachineFunction &F); 83 bool doInitialization(Module &M); 84 85 void getAnalysisUsage(AnalysisUsage &AU) const { 86 AsmPrinter::getAnalysisUsage(AU); 87 AU.setPreservesAll(); 88 AU.addRequired<MachineModuleInfo>(); 89 AU.addRequired<DwarfWriter>(); 90 } 91 }; 92 } // end of anonymous namespace 93 94 #include "XCoreGenAsmWriter.inc" 95 96 void XCoreAsmPrinter:: 97 emitGlobalDirective(const std::string &name) 98 { 99 O << TAI->getGlobalDirective() << name; 100 O << "\n"; 101 } 102 103 void XCoreAsmPrinter:: 104 emitExternDirective(const std::string &name) 105 { 106 O << "\t.extern\t" << name; 107 O << '\n'; 108 } 109 110 void XCoreAsmPrinter:: 111 emitArrayBound(const std::string &name, const GlobalVariable *GV) 112 { 113 assert(((GV->hasExternalLinkage() || 114 GV->hasWeakLinkage()) || 115 GV->hasLinkOnceLinkage()) && "Unexpected linkage"); 116 if (const ArrayType *ATy = dyn_cast<ArrayType>( 117 cast<PointerType>(GV->getType())->getElementType())) 118 { 119 O << TAI->getGlobalDirective() << name << ".globound" << "\n"; 120 O << TAI->getSetDirective() << name << ".globound" << "," 121 << ATy->getNumElements() << "\n"; 122 if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage()) { 123 // TODO Use COMDAT groups for LinkOnceLinkage 124 O << TAI->getWeakDefDirective() << name << ".globound" << "\n"; 125 } 126 } 127 } 128 129 void XCoreAsmPrinter::PrintGlobalVariable(const GlobalVariable *GV) { 130 // Check to see if this is a special global used by LLVM, if so, emit it. 131 if (!GV->hasInitializer() || 132 EmitSpecialLLVMGlobal(GV)) 133 return; 134 135 const TargetData *TD = TM.getTargetData(); 136 137 SwitchToSection(getObjFileLowering().SectionForGlobal(GV, Mang, TM)); 138 139 std::string name = Mang->getMangledName(GV); 140 Constant *C = GV->getInitializer(); 141 unsigned Align = (unsigned)TD->getPreferredTypeAlignmentShift(C->getType()); 142 143 // Mark the start of the global 144 O << "\t.cc_top " << name << ".data," << name << "\n"; 145 146 switch (GV->getLinkage()) { 147 case GlobalValue::AppendingLinkage: 148 llvm_report_error("AppendingLinkage is not supported by this target!"); 149 case GlobalValue::LinkOnceAnyLinkage: 150 case GlobalValue::LinkOnceODRLinkage: 151 case GlobalValue::WeakAnyLinkage: 152 case GlobalValue::WeakODRLinkage: 153 case GlobalValue::ExternalLinkage: 154 emitArrayBound(name, GV); 155 emitGlobalDirective(name); 156 // TODO Use COMDAT groups for LinkOnceLinkage 157 if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage()) { 158 O << TAI->getWeakDefDirective() << name << "\n"; 159 } 160 // FALL THROUGH 161 case GlobalValue::InternalLinkage: 162 case GlobalValue::PrivateLinkage: 163 case GlobalValue::LinkerPrivateLinkage: 164 break; 165 case GlobalValue::GhostLinkage: 166 llvm_unreachable("Should not have any unmaterialized functions!"); 167 case GlobalValue::DLLImportLinkage: 168 llvm_unreachable("DLLImport linkage is not supported by this target!"); 169 case GlobalValue::DLLExportLinkage: 170 llvm_unreachable("DLLExport linkage is not supported by this target!"); 171 default: 172 llvm_unreachable("Unknown linkage type!"); 173 } 174 175 EmitAlignment(Align, GV, 2); 176 177 unsigned Size = TD->getTypeAllocSize(C->getType()); 178 if (GV->isThreadLocal()) { 179 Size *= MaxThreads; 180 } 181 if (TAI->hasDotTypeDotSizeDirective()) { 182 O << "\t.type " << name << ",@object\n"; 183 O << "\t.size " << name << "," << Size << "\n"; 184 } 185 O << name << ":\n"; 186 187 EmitGlobalConstant(C); 188 if (GV->isThreadLocal()) { 189 for (unsigned i = 1; i < MaxThreads; ++i) { 190 EmitGlobalConstant(C); 191 } 192 } 193 if (Size < 4) { 194 // The ABI requires that unsigned scalar types smaller than 32 bits 195 // are are padded to 32 bits. 196 EmitZeros(4 - Size); 197 } 198 199 // Mark the end of the global 200 O << "\t.cc_bottom " << name << ".data\n"; 201 } 202 203 /// Emit the directives on the start of functions 204 void XCoreAsmPrinter::emitFunctionStart(MachineFunction &MF) { 205 // Print out the label for the function. 206 const Function *F = MF.getFunction(); 207 208 SwitchToSection(getObjFileLowering().SectionForGlobal(F, Mang, TM)); 209 210 // Mark the start of the function 211 O << "\t.cc_top " << CurrentFnName << ".function," << CurrentFnName << "\n"; 212 213 switch (F->getLinkage()) { 214 default: llvm_unreachable("Unknown linkage type!"); 215 case Function::InternalLinkage: // Symbols default to internal. 216 case Function::PrivateLinkage: 217 case Function::LinkerPrivateLinkage: 218 break; 219 case Function::ExternalLinkage: 220 emitGlobalDirective(CurrentFnName); 221 break; 222 case Function::LinkOnceAnyLinkage: 223 case Function::LinkOnceODRLinkage: 224 case Function::WeakAnyLinkage: 225 case Function::WeakODRLinkage: 226 // TODO Use COMDAT groups for LinkOnceLinkage 227 O << TAI->getGlobalDirective() << CurrentFnName << "\n"; 228 O << TAI->getWeakDefDirective() << CurrentFnName << "\n"; 229 break; 230 } 231 // (1 << 1) byte aligned 232 EmitAlignment(MF.getAlignment(), F, 1); 233 if (TAI->hasDotTypeDotSizeDirective()) { 234 O << "\t.type " << CurrentFnName << ",@function\n"; 235 } 236 O << CurrentFnName << ":\n"; 237 } 238 239 /// Emit the directives on the end of functions 240 void XCoreAsmPrinter:: 241 emitFunctionEnd(MachineFunction &MF) 242 { 243 // Mark the end of the function 244 O << "\t.cc_bottom " << CurrentFnName << ".function\n"; 245 } 246 247 /// runOnMachineFunction - This uses the printMachineInstruction() 248 /// method to print assembly for each instruction. 249 /// 250 bool XCoreAsmPrinter::runOnMachineFunction(MachineFunction &MF) 251 { 252 this->MF = &MF; 253 254 SetupMachineFunction(MF); 255 256 // Print out constants referenced by the function 257 EmitConstantPool(MF.getConstantPool()); 258 259 // Print out jump tables referenced by the function 260 EmitJumpTableInfo(MF.getJumpTableInfo(), MF); 261 262 // Emit the function start directives 263 emitFunctionStart(MF); 264 265 // Emit pre-function debug information. 266 DW->BeginFunction(&MF); 267 268 // Print out code for the function. 269 for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); 270 I != E; ++I) { 271 272 // Print a label for the basic block. 273 if (I != MF.begin()) { 274 printBasicBlockLabel(I, true , true); 275 O << '\n'; 276 } 277 278 for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end(); 279 II != E; ++II) { 280 // Print the assembly for the instruction. 281 O << "\t"; 282 printMachineInstruction(II); 283 } 284 285 // Each Basic Block is separated by a newline 286 O << '\n'; 287 } 288 289 // Emit function end directives 290 emitFunctionEnd(MF); 291 292 // Emit post-function debug information. 293 DW->EndFunction(&MF); 294 295 // We didn't modify anything. 296 return false; 297 } 298 299 void XCoreAsmPrinter::printMemOperand(const MachineInstr *MI, int opNum) 300 { 301 printOperand(MI, opNum); 302 303 if (MI->getOperand(opNum+1).isImm() 304 && MI->getOperand(opNum+1).getImm() == 0) 305 return; 306 307 O << "+"; 308 printOperand(MI, opNum+1); 309 } 310 311 void XCoreAsmPrinter::printOperand(const MachineInstr *MI, int opNum) { 312 const MachineOperand &MO = MI->getOperand(opNum); 313 switch (MO.getType()) { 314 case MachineOperand::MO_Register: 315 if (TargetRegisterInfo::isPhysicalRegister(MO.getReg())) 316 O << TM.getRegisterInfo()->get(MO.getReg()).AsmName; 317 else 318 llvm_unreachable("not implemented"); 319 break; 320 case MachineOperand::MO_Immediate: 321 O << MO.getImm(); 322 break; 323 case MachineOperand::MO_MachineBasicBlock: 324 printBasicBlockLabel(MO.getMBB()); 325 break; 326 case MachineOperand::MO_GlobalAddress: 327 O << Mang->getMangledName(MO.getGlobal()); 328 break; 329 case MachineOperand::MO_ExternalSymbol: 330 O << MO.getSymbolName(); 331 break; 332 case MachineOperand::MO_ConstantPoolIndex: 333 O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() 334 << '_' << MO.getIndex(); 335 break; 336 case MachineOperand::MO_JumpTableIndex: 337 O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() 338 << '_' << MO.getIndex(); 339 break; 340 default: 341 llvm_unreachable("not implemented"); 342 } 343 } 344 345 /// PrintAsmOperand - Print out an operand for an inline asm expression. 346 /// 347 bool XCoreAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 348 unsigned AsmVariant, 349 const char *ExtraCode) { 350 printOperand(MI, OpNo); 351 return false; 352 } 353 354 void XCoreAsmPrinter::printMachineInstruction(const MachineInstr *MI) { 355 ++EmittedInsts; 356 357 // Check for mov mnemonic 358 unsigned src, dst, srcSR, dstSR; 359 if (TM.getInstrInfo()->isMoveInstr(*MI, src, dst, srcSR, dstSR)) { 360 O << "\tmov "; 361 O << TM.getRegisterInfo()->get(dst).AsmName; 362 O << ", "; 363 O << TM.getRegisterInfo()->get(src).AsmName; 364 O << "\n"; 365 return; 366 } 367 if (printInstruction(MI)) { 368 return; 369 } 370 llvm_unreachable("Unhandled instruction in asm writer!"); 371 } 372 373 bool XCoreAsmPrinter::doInitialization(Module &M) { 374 bool Result = AsmPrinter::doInitialization(M); 375 DW = getAnalysisIfAvailable<DwarfWriter>(); 376 377 return Result; 378 } 379 380 381 382 // Force static initialization. 383 extern "C" void LLVMInitializeXCoreTarget() { 384 RegisterTargetMachine<XCoreTargetMachine> X(TheXCoreTarget); 385 RegisterAsmPrinter<XCoreAsmPrinter> Y(TheXCoreTarget); 386 } 387