LLVM API Documentation
00001 //===-- EmitAssembly.cpp - Emit SparcV9 Specific .s File -------------------==// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file was developed by the LLVM research group and is distributed under 00006 // the University of Illinois Open Source License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file implements all of the stuff necessary to output a .s file from 00011 // LLVM. The code in this file assumes that the specified module has already 00012 // been compiled into the internal data structures of the Module. 00013 // 00014 // This code largely consists of two LLVM Pass's: a FunctionPass and a Pass. 00015 // The FunctionPass is pipelined together with all of the rest of the code 00016 // generation stages, and the Pass runs at the end to emit code for global 00017 // variables and such. 00018 // 00019 //===----------------------------------------------------------------------===// 00020 00021 #include "llvm/Constants.h" 00022 #include "llvm/DerivedTypes.h" 00023 #include "llvm/Module.h" 00024 #include "llvm/Pass.h" 00025 #include "llvm/Assembly/Writer.h" 00026 #include "llvm/CodeGen/MachineConstantPool.h" 00027 #include "llvm/CodeGen/MachineFunction.h" 00028 #include "llvm/CodeGen/MachineInstr.h" 00029 #include "llvm/Support/Mangler.h" 00030 #include "llvm/ADT/StringExtras.h" 00031 #include "llvm/ADT/Statistic.h" 00032 #include "SparcV9Internals.h" 00033 #include "MachineFunctionInfo.h" 00034 #include <string> 00035 using namespace llvm; 00036 00037 namespace { 00038 Statistic<> EmittedInsts("asm-printer", "Number of machine instrs printed"); 00039 00040 //===--------------------------------------------------------------------===// 00041 // Utility functions 00042 00043 /// getAsCString - Return the specified array as a C compatible string, only 00044 /// if the predicate isString() is true. 00045 /// 00046 std::string getAsCString(const ConstantArray *CVA) { 00047 assert(CVA->isString() && "Array is not string compatible!"); 00048 00049 std::string Result = "\""; 00050 for (unsigned i = 0; i != CVA->getNumOperands(); ++i) { 00051 unsigned char C = cast<ConstantInt>(CVA->getOperand(i))->getRawValue(); 00052 00053 if (C == '"') { 00054 Result += "\\\""; 00055 } else if (C == '\\') { 00056 Result += "\\\\"; 00057 } else if (isprint(C)) { 00058 Result += C; 00059 } else { 00060 Result += '\\'; // print all other chars as octal value 00061 // Convert C to octal representation 00062 Result += ((C >> 6) & 7) + '0'; 00063 Result += ((C >> 3) & 7) + '0'; 00064 Result += ((C >> 0) & 7) + '0'; 00065 } 00066 } 00067 Result += "\""; 00068 00069 return Result; 00070 } 00071 00072 inline bool ArrayTypeIsString(const ArrayType* arrayType) { 00073 return (arrayType->getElementType() == Type::UByteTy || 00074 arrayType->getElementType() == Type::SByteTy); 00075 } 00076 00077 unsigned findOptimalStorageSize(const TargetMachine &TM, const Type *Ty) { 00078 // All integer types smaller than ints promote to 4 byte integers. 00079 if (Ty->isIntegral() && Ty->getPrimitiveSize() < 4) 00080 return 4; 00081 00082 return TM.getTargetData().getTypeSize(Ty); 00083 } 00084 00085 00086 inline const std::string 00087 TypeToDataDirective(const Type* type) { 00088 switch(type->getTypeID()) { 00089 case Type::BoolTyID: case Type::UByteTyID: case Type::SByteTyID: 00090 return ".byte"; 00091 case Type::UShortTyID: case Type::ShortTyID: 00092 return ".half"; 00093 case Type::UIntTyID: case Type::IntTyID: 00094 return ".word"; 00095 case Type::ULongTyID: case Type::LongTyID: case Type::PointerTyID: 00096 return ".xword"; 00097 case Type::FloatTyID: 00098 return ".word"; 00099 case Type::DoubleTyID: 00100 return ".xword"; 00101 case Type::ArrayTyID: 00102 if (ArrayTypeIsString((ArrayType*) type)) 00103 return ".ascii"; 00104 else 00105 return "<InvaliDataTypeForPrinting>"; 00106 default: 00107 return "<InvaliDataTypeForPrinting>"; 00108 } 00109 } 00110 00111 /// Get the size of the constant for the given target. 00112 /// If this is an unsized array, return 0. 00113 /// 00114 inline unsigned int 00115 ConstantToSize(const Constant* CV, const TargetMachine& target) { 00116 if (const ConstantArray* CVA = dyn_cast<ConstantArray>(CV)) { 00117 const ArrayType *aty = cast<ArrayType>(CVA->getType()); 00118 if (ArrayTypeIsString(aty)) 00119 return 1 + CVA->getNumOperands(); 00120 } 00121 00122 return findOptimalStorageSize(target, CV->getType()); 00123 } 00124 00125 /// Align data larger than one L1 cache line on L1 cache line boundaries. 00126 /// Align all smaller data on the next higher 2^x boundary (4, 8, ...). 00127 /// 00128 inline unsigned int 00129 SizeToAlignment(unsigned int size, const TargetMachine& target) { 00130 const unsigned short cacheLineSize = 16; 00131 if (size > (unsigned) cacheLineSize / 2) 00132 return cacheLineSize; 00133 else 00134 for (unsigned sz=1; /*no condition*/; sz *= 2) 00135 if (sz >= size) 00136 return sz; 00137 } 00138 00139 /// Get the size of the type and then use SizeToAlignment. 00140 /// 00141 inline unsigned int 00142 TypeToAlignment(const Type* type, const TargetMachine& target) { 00143 return SizeToAlignment(findOptimalStorageSize(target, type), target); 00144 } 00145 00146 /// Get the size of the constant and then use SizeToAlignment. 00147 /// Handles strings as a special case; 00148 inline unsigned int 00149 ConstantToAlignment(const Constant* CV, const TargetMachine& target) { 00150 if (const ConstantArray* CVA = dyn_cast<ConstantArray>(CV)) 00151 if (ArrayTypeIsString(cast<ArrayType>(CVA->getType()))) 00152 return SizeToAlignment(1 + CVA->getNumOperands(), target); 00153 00154 return TypeToAlignment(CV->getType(), target); 00155 } 00156 00157 } // End anonymous namespace 00158 00159 namespace { 00160 enum Sections { 00161 Unknown, 00162 Text, 00163 ReadOnlyData, 00164 InitRWData, 00165 ZeroInitRWData, 00166 }; 00167 00168 class AsmPrinter { 00169 // Mangle symbol names appropriately 00170 Mangler *Mang; 00171 00172 public: 00173 std::ostream &O; 00174 const TargetMachine &TM; 00175 00176 enum Sections CurSection; 00177 00178 AsmPrinter(std::ostream &os, const TargetMachine &T) 00179 : /* idTable(0), */ O(os), TM(T), CurSection(Unknown) {} 00180 00181 ~AsmPrinter() { 00182 delete Mang; 00183 } 00184 00185 // (start|end)(Module|Function) - Callback methods invoked by subclasses 00186 void startModule(Module &M) { 00187 Mang = new Mangler(M); 00188 } 00189 00190 void PrintZeroBytesToPad(int numBytes) { 00191 // 00192 // Always use single unsigned bytes for padding. We don't know upon 00193 // what data size the beginning address is aligned, so using anything 00194 // other than a byte may cause alignment errors in the assembler. 00195 // 00196 while (numBytes--) 00197 printSingleConstantValue(Constant::getNullValue(Type::UByteTy)); 00198 } 00199 00200 /// Print a single constant value. 00201 /// 00202 void printSingleConstantValue(const Constant* CV); 00203 00204 /// Print a constant value or values (it may be an aggregate). 00205 /// Uses printSingleConstantValue() to print each individual value. 00206 /// 00207 void printConstantValueOnly(const Constant* CV, int numPadBytesAfter = 0); 00208 00209 // Print a constant (which may be an aggregate) prefixed by all the 00210 // appropriate directives. Uses printConstantValueOnly() to print the 00211 // value or values. 00212 void printConstant(const Constant* CV, std::string valID = "") { 00213 if (valID.length() == 0) 00214 valID = getID(CV); 00215 00216 O << "\t.align\t" << ConstantToAlignment(CV, TM) << "\n"; 00217 00218 // Print .size and .type only if it is not a string. 00219 if (const ConstantArray *CVA = dyn_cast<ConstantArray>(CV)) 00220 if (CVA->isString()) { 00221 // print it as a string and return 00222 O << valID << ":\n"; 00223 O << "\t" << ".ascii" << "\t" << getAsCString(CVA) << "\n"; 00224 return; 00225 } 00226 00227 O << "\t.type" << "\t" << valID << ",#object\n"; 00228 00229 unsigned int constSize = ConstantToSize(CV, TM); 00230 if (constSize) 00231 O << "\t.size" << "\t" << valID << "," << constSize << "\n"; 00232 00233 O << valID << ":\n"; 00234 00235 printConstantValueOnly(CV); 00236 } 00237 00238 // enterSection - Use this method to enter a different section of the output 00239 // executable. This is used to only output necessary section transitions. 00240 // 00241 void enterSection(enum Sections S) { 00242 if (S == CurSection) return; // Only switch section if necessary 00243 CurSection = S; 00244 00245 O << "\n\t.section "; 00246 switch (S) 00247 { 00248 default: assert(0 && "Bad section name!"); 00249 case Text: O << "\".text\""; break; 00250 case ReadOnlyData: O << "\".rodata\",#alloc"; break; 00251 case InitRWData: O << "\".data\",#alloc,#write"; break; 00252 case ZeroInitRWData: O << "\".bss\",#alloc,#write"; break; 00253 } 00254 O << "\n"; 00255 } 00256 00257 // getID Wrappers - Ensure consistent usage 00258 // Symbol names in SparcV9 assembly language have these rules: 00259 // (a) Must match { letter | _ | . | $ } { letter | _ | . | $ | digit }* 00260 // (b) A name beginning in "." is treated as a local name. 00261 std::string getID(const Function *F) { 00262 return Mang->getValueName(F); 00263 } 00264 std::string getID(const BasicBlock *BB) { 00265 return ".L_" + getID(BB->getParent()) + "_" + Mang->getValueName(BB); 00266 } 00267 std::string getID(const GlobalVariable *GV) { 00268 return Mang->getValueName(GV); 00269 } 00270 std::string getID(const Constant *CV) { 00271 return ".C_" + Mang->getValueName(CV); 00272 } 00273 std::string getID(const GlobalValue *GV) { 00274 if (const GlobalVariable *V = dyn_cast<GlobalVariable>(GV)) 00275 return getID(V); 00276 else if (const Function *F = dyn_cast<Function>(GV)) 00277 return getID(F); 00278 assert(0 && "Unexpected type of GlobalValue!"); 00279 return ""; 00280 } 00281 00282 // Combines expressions 00283 inline std::string ConstantArithExprToString(const ConstantExpr* CE, 00284 const TargetMachine &TM, 00285 const std::string &op) { 00286 return "(" + valToExprString(CE->getOperand(0), TM) + op 00287 + valToExprString(CE->getOperand(1), TM) + ")"; 00288 } 00289 00290 /// ConstantExprToString() - Convert a ConstantExpr to an asm expression 00291 /// and return this as a string. 00292 /// 00293 std::string ConstantExprToString(const ConstantExpr* CE, 00294 const TargetMachine& target); 00295 00296 /// valToExprString - Helper function for ConstantExprToString(). 00297 /// Appends result to argument string S. 00298 /// 00299 std::string valToExprString(const Value* V, const TargetMachine& target); 00300 }; 00301 } // End anonymous namespace 00302 00303 00304 /// Print a single constant value. 00305 /// 00306 void AsmPrinter::printSingleConstantValue(const Constant* CV) { 00307 assert(CV->getType() != Type::VoidTy && 00308 CV->getType() != Type::LabelTy && 00309 "Unexpected type for Constant"); 00310 00311 assert((!isa<ConstantArray>(CV) && ! isa<ConstantStruct>(CV)) 00312 && "Aggregate types should be handled outside this function"); 00313 00314 O << "\t" << TypeToDataDirective(CV->getType()) << "\t"; 00315 00316 if (const GlobalValue* GV = dyn_cast<GlobalValue>(CV)) { 00317 O << getID(GV) << "\n"; 00318 } else if (isa<ConstantPointerNull>(CV) || isa<UndefValue>(CV)) { 00319 // Null pointer value 00320 O << "0\n"; 00321 } else if (const ConstantExpr* CE = dyn_cast<ConstantExpr>(CV)) { 00322 // Constant expression built from operators, constants, and symbolic addrs 00323 O << ConstantExprToString(CE, TM) << "\n"; 00324 } else if (CV->getType()->isPrimitiveType()) { 00325 // Check primitive types last 00326 if (isa<UndefValue>(CV)) { 00327 O << "0\n"; 00328 } else if (CV->getType()->isFloatingPoint()) { 00329 // FP Constants are printed as integer constants to avoid losing 00330 // precision... 00331 double Val = cast<ConstantFP>(CV)->getValue(); 00332 if (CV->getType() == Type::FloatTy) { 00333 float FVal = (float)Val; 00334 char *ProxyPtr = (char*)&FVal; // Abide by C TBAA rules 00335 O << *(unsigned int*)ProxyPtr; 00336 } else if (CV->getType() == Type::DoubleTy) { 00337 char *ProxyPtr = (char*)&Val; // Abide by C TBAA rules 00338 O << *(uint64_t*)ProxyPtr; 00339 } else { 00340 assert(0 && "Unknown floating point type!"); 00341 } 00342 00343 O << "\t! " << CV->getType()->getDescription() 00344 << " value: " << Val << "\n"; 00345 } else if (const ConstantBool *CB = dyn_cast<ConstantBool>(CV)) { 00346 O << (int)CB->getValue() << "\n"; 00347 } else { 00348 WriteAsOperand(O, CV, false, false) << "\n"; 00349 } 00350 } else { 00351 assert(0 && "Unknown elementary type for constant"); 00352 } 00353 } 00354 00355 /// Print a constant value or values (it may be an aggregate). 00356 /// Uses printSingleConstantValue() to print each individual value. 00357 /// 00358 void AsmPrinter::printConstantValueOnly(const Constant* CV, 00359 int numPadBytesAfter) { 00360 if (const ConstantArray *CVA = dyn_cast<ConstantArray>(CV)) { 00361 if (CVA->isString()) { 00362 // print the string alone and return 00363 O << "\t" << ".ascii" << "\t" << getAsCString(CVA) << "\n"; 00364 } else { 00365 // Not a string. Print the values in successive locations 00366 for (unsigned i = 0, e = CVA->getNumOperands(); i != e; ++i) 00367 printConstantValueOnly(CVA->getOperand(i)); 00368 } 00369 } else if (const ConstantStruct *CVS = dyn_cast<ConstantStruct>(CV)) { 00370 // Print the fields in successive locations. Pad to align if needed! 00371 const StructLayout *cvsLayout = 00372 TM.getTargetData().getStructLayout(CVS->getType()); 00373 unsigned sizeSoFar = 0; 00374 for (unsigned i = 0, e = CVS->getNumOperands(); i != e; ++i) { 00375 const Constant* field = CVS->getOperand(i); 00376 00377 // Check if padding is needed and insert one or more 0s. 00378 unsigned fieldSize = 00379 TM.getTargetData().getTypeSize(field->getType()); 00380 int padSize = ((i == e-1? cvsLayout->StructSize 00381 : cvsLayout->MemberOffsets[i+1]) 00382 - cvsLayout->MemberOffsets[i]) - fieldSize; 00383 sizeSoFar += (fieldSize + padSize); 00384 00385 // Now print the actual field value 00386 printConstantValueOnly(field, padSize); 00387 } 00388 assert(sizeSoFar == cvsLayout->StructSize && 00389 "Layout of constant struct may be incorrect!"); 00390 } else if (isa<ConstantAggregateZero>(CV) || isa<UndefValue>(CV)) { 00391 PrintZeroBytesToPad(TM.getTargetData().getTypeSize(CV->getType())); 00392 } else 00393 printSingleConstantValue(CV); 00394 00395 if (numPadBytesAfter) 00396 PrintZeroBytesToPad(numPadBytesAfter); 00397 } 00398 00399 /// ConstantExprToString() - Convert a ConstantExpr to an asm expression 00400 /// and return this as a string. 00401 /// 00402 std::string AsmPrinter::ConstantExprToString(const ConstantExpr* CE, 00403 const TargetMachine& target) { 00404 std::string S; 00405 switch(CE->getOpcode()) { 00406 case Instruction::GetElementPtr: 00407 { // generate a symbolic expression for the byte address 00408 const Value* ptrVal = CE->getOperand(0); 00409 std::vector<Value*> idxVec(CE->op_begin()+1, CE->op_end()); 00410 const TargetData &TD = target.getTargetData(); 00411 S += "(" + valToExprString(ptrVal, target) + ") + (" 00412 + utostr(TD.getIndexedOffset(ptrVal->getType(),idxVec)) + ")"; 00413 break; 00414 } 00415 00416 case Instruction::Cast: 00417 // Support only non-converting casts for now, i.e., a no-op. 00418 // This assertion is not a complete check. 00419 assert(target.getTargetData().getTypeSize(CE->getType()) == 00420 target.getTargetData().getTypeSize(CE->getOperand(0)->getType())); 00421 S += "(" + valToExprString(CE->getOperand(0), target) + ")"; 00422 break; 00423 00424 case Instruction::Add: 00425 S += ConstantArithExprToString(CE, target, ") + ("); 00426 break; 00427 00428 case Instruction::Sub: 00429 S += ConstantArithExprToString(CE, target, ") - ("); 00430 break; 00431 00432 case Instruction::Mul: 00433 S += ConstantArithExprToString(CE, target, ") * ("); 00434 break; 00435 00436 case Instruction::Div: 00437 S += ConstantArithExprToString(CE, target, ") / ("); 00438 break; 00439 00440 case Instruction::Rem: 00441 S += ConstantArithExprToString(CE, target, ") % ("); 00442 break; 00443 00444 case Instruction::And: 00445 // Logical && for booleans; bitwise & otherwise 00446 S += ConstantArithExprToString(CE, target, 00447 ((CE->getType() == Type::BoolTy)? ") && (" : ") & (")); 00448 break; 00449 00450 case Instruction::Or: 00451 // Logical || for booleans; bitwise | otherwise 00452 S += ConstantArithExprToString(CE, target, 00453 ((CE->getType() == Type::BoolTy)? ") || (" : ") | (")); 00454 break; 00455 00456 case Instruction::Xor: 00457 // Bitwise ^ for all types 00458 S += ConstantArithExprToString(CE, target, ") ^ ("); 00459 break; 00460 00461 default: 00462 assert(0 && "Unsupported operator in ConstantExprToString()"); 00463 break; 00464 } 00465 00466 return S; 00467 } 00468 00469 /// valToExprString - Helper function for ConstantExprToString(). 00470 /// Appends result to argument string S. 00471 /// 00472 std::string AsmPrinter::valToExprString(const Value* V, 00473 const TargetMachine& target) { 00474 std::string S; 00475 bool failed = false; 00476 if (const GlobalValue* GV = dyn_cast<GlobalValue>(V)) { 00477 S += getID(GV); 00478 } else if (const Constant* CV = dyn_cast<Constant>(V)) { // symbolic or known 00479 if (const ConstantBool *CB = dyn_cast<ConstantBool>(CV)) 00480 S += std::string(CB == ConstantBool::True ? "1" : "0"); 00481 else if (const ConstantSInt *CI = dyn_cast<ConstantSInt>(CV)) 00482 S += itostr(CI->getValue()); 00483 else if (const ConstantUInt *CI = dyn_cast<ConstantUInt>(CV)) 00484 S += utostr(CI->getValue()); 00485 else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV)) 00486 S += ftostr(CFP->getValue()); 00487 else if (isa<ConstantPointerNull>(CV) || isa<UndefValue>(CV)) 00488 S += "0"; 00489 else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV)) 00490 S += ConstantExprToString(CE, target); 00491 else 00492 failed = true; 00493 } else 00494 failed = true; 00495 00496 if (failed) { 00497 assert(0 && "Cannot convert value to string"); 00498 S += "<illegal-value>"; 00499 } 00500 return S; 00501 } 00502 00503 namespace { 00504 00505 struct SparcV9AsmPrinter : public FunctionPass, public AsmPrinter { 00506 inline SparcV9AsmPrinter(std::ostream &os, const TargetMachine &t) 00507 : AsmPrinter(os, t) {} 00508 00509 const Function *currFunction; 00510 00511 const char *getPassName() const { 00512 return "Output SparcV9 Assembly for Functions"; 00513 } 00514 00515 virtual bool doInitialization(Module &M) { 00516 startModule(M); 00517 return false; 00518 } 00519 00520 virtual bool runOnFunction(Function &F) { 00521 currFunction = &F; 00522 emitFunction(F); 00523 return false; 00524 } 00525 00526 virtual bool doFinalization(Module &M) { 00527 emitGlobals(M); 00528 return false; 00529 } 00530 00531 virtual void getAnalysisUsage(AnalysisUsage &AU) const { 00532 AU.setPreservesAll(); 00533 } 00534 00535 void emitFunction(const Function &F); 00536 private : 00537 void emitBasicBlock(const MachineBasicBlock &MBB); 00538 void emitMachineInst(const MachineInstr *MI); 00539 00540 unsigned int printOperands(const MachineInstr *MI, unsigned int opNum); 00541 void printOneOperand(const MachineOperand &Op, MachineOpCode opCode); 00542 00543 bool OpIsBranchTargetLabel(const MachineInstr *MI, unsigned int opNum); 00544 bool OpIsMemoryAddressBase(const MachineInstr *MI, unsigned int opNum); 00545 00546 unsigned getOperandMask(unsigned Opcode) { 00547 switch (Opcode) { 00548 case V9::SUBccr: 00549 case V9::SUBcci: return 1 << 3; // Remove CC argument 00550 default: return 0; // By default, don't hack operands... 00551 } 00552 } 00553 00554 void emitGlobals(const Module &M); 00555 void printGlobalVariable(const GlobalVariable *GV); 00556 }; 00557 00558 } // End anonymous namespace 00559 00560 inline bool 00561 SparcV9AsmPrinter::OpIsBranchTargetLabel(const MachineInstr *MI, 00562 unsigned int opNum) { 00563 switch (MI->getOpcode()) { 00564 case V9::JMPLCALLr: 00565 case V9::JMPLCALLi: 00566 case V9::JMPLRETr: 00567 case V9::JMPLRETi: 00568 return (opNum == 0); 00569 default: 00570 return false; 00571 } 00572 } 00573 00574 inline bool 00575 SparcV9AsmPrinter::OpIsMemoryAddressBase(const MachineInstr *MI, 00576 unsigned int opNum) { 00577 if (TM.getInstrInfo()->isLoad(MI->getOpcode())) 00578 return (opNum == 0); 00579 else if (TM.getInstrInfo()->isStore(MI->getOpcode())) 00580 return (opNum == 1); 00581 else 00582 return false; 00583 } 00584 00585 unsigned int 00586 SparcV9AsmPrinter::printOperands(const MachineInstr *MI, unsigned opNum) { 00587 const MachineOperand& mop = MI->getOperand(opNum); 00588 if (OpIsBranchTargetLabel(MI, opNum)) { 00589 printOneOperand(mop, MI->getOpcode()); 00590 O << "+"; 00591 printOneOperand(MI->getOperand(opNum+1), MI->getOpcode()); 00592 return 2; 00593 } else if (OpIsMemoryAddressBase(MI, opNum)) { 00594 O << "["; 00595 printOneOperand(mop, MI->getOpcode()); 00596 O << "+"; 00597 printOneOperand(MI->getOperand(opNum+1), MI->getOpcode()); 00598 O << "]"; 00599 return 2; 00600 } else { 00601 printOneOperand(mop, MI->getOpcode()); 00602 return 1; 00603 } 00604 } 00605 00606 void 00607 SparcV9AsmPrinter::printOneOperand(const MachineOperand &mop, 00608 MachineOpCode opCode) 00609 { 00610 bool needBitsFlag = true; 00611 00612 if (mop.isHiBits32()) 00613 O << "%lm("; 00614 else if (mop.isLoBits32()) 00615 O << "%lo("; 00616 else if (mop.isHiBits64()) 00617 O << "%hh("; 00618 else if (mop.isLoBits64()) 00619 O << "%hm("; 00620 else 00621 needBitsFlag = false; 00622 00623 switch (mop.getType()) 00624 { 00625 case MachineOperand::MO_VirtualRegister: 00626 case MachineOperand::MO_CCRegister: 00627 case MachineOperand::MO_MachineRegister: 00628 { 00629 int regNum = (int)mop.getReg(); 00630 00631 if (regNum == TM.getRegInfo()->getInvalidRegNum()) { 00632 // better to print code with NULL registers than to die 00633 O << "<NULL VALUE>"; 00634 } else { 00635 O << "%" << TM.getRegInfo()->getUnifiedRegName(regNum); 00636 } 00637 break; 00638 } 00639 00640 case MachineOperand::MO_ConstantPoolIndex: 00641 { 00642 O << ".CPI_" << getID(currFunction) 00643 << "_" << mop.getConstantPoolIndex(); 00644 break; 00645 } 00646 00647 case MachineOperand::MO_PCRelativeDisp: 00648 { 00649 const Value *Val = mop.getVRegValue(); 00650 assert(Val && "\tNULL Value in SparcV9AsmPrinter"); 00651 00652 if (const BasicBlock *BB = dyn_cast<BasicBlock>(Val)) 00653 O << getID(BB); 00654 else if (const Function *F = dyn_cast<Function>(Val)) 00655 O << getID(F); 00656 else if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(Val)) 00657 O << getID(GV); 00658 else if (const Constant *CV = dyn_cast<Constant>(Val)) 00659 O << getID(CV); 00660 else 00661 assert(0 && "Unrecognized value in SparcV9AsmPrinter"); 00662 break; 00663 } 00664 00665 case MachineOperand::MO_SignExtendedImmed: 00666 O << mop.getImmedValue(); 00667 break; 00668 00669 case MachineOperand::MO_UnextendedImmed: 00670 O << (uint64_t) mop.getImmedValue(); 00671 break; 00672 00673 default: 00674 O << mop; // use dump field 00675 break; 00676 } 00677 00678 if (needBitsFlag) 00679 O << ")"; 00680 } 00681 00682 void SparcV9AsmPrinter::emitMachineInst(const MachineInstr *MI) { 00683 unsigned Opcode = MI->getOpcode(); 00684 00685 if (Opcode == V9::PHI) 00686 return; // Ignore Machine-PHI nodes. 00687 00688 O << "\t" << TM.getInstrInfo()->getName(Opcode) << "\t"; 00689 00690 unsigned Mask = getOperandMask(Opcode); 00691 00692 bool NeedComma = false; 00693 unsigned N = 1; 00694 for (unsigned OpNum = 0; OpNum < MI->getNumOperands(); OpNum += N) 00695 if (! ((1 << OpNum) & Mask)) { // Ignore this operand? 00696 if (NeedComma) O << ", "; // Handle comma outputting 00697 NeedComma = true; 00698 N = printOperands(MI, OpNum); 00699 } else 00700 N = 1; 00701 00702 O << "\n"; 00703 ++EmittedInsts; 00704 } 00705 00706 void SparcV9AsmPrinter::emitBasicBlock(const MachineBasicBlock &MBB) { 00707 // Emit a label for the basic block 00708 O << getID(MBB.getBasicBlock()) << ":\n"; 00709 00710 // Loop over all of the instructions in the basic block... 00711 for (MachineBasicBlock::const_iterator MII = MBB.begin(), MIE = MBB.end(); 00712 MII != MIE; ++MII) 00713 emitMachineInst(MII); 00714 O << "\n"; // Separate BB's with newlines 00715 } 00716 00717 void SparcV9AsmPrinter::emitFunction(const Function &F) { 00718 std::string CurrentFnName = getID(&F); 00719 MachineFunction &MF = MachineFunction::get(&F); 00720 O << "!****** Outputing Function: " << CurrentFnName << " ******\n"; 00721 00722 // Emit constant pool for this function 00723 const MachineConstantPool *MCP = MF.getConstantPool(); 00724 const std::vector<Constant*> &CP = MCP->getConstants(); 00725 00726 enterSection(ReadOnlyData); 00727 for (unsigned i = 0, e = CP.size(); i != e; ++i) { 00728 std::string cpiName = ".CPI_" + CurrentFnName + "_" + utostr(i); 00729 printConstant(CP[i], cpiName); 00730 } 00731 00732 enterSection(Text); 00733 O << "\t.align\t4\n\t.global\t" << CurrentFnName << "\n"; 00734 //O << "\t.type\t" << CurrentFnName << ",#function\n"; 00735 O << "\t.type\t" << CurrentFnName << ", 2\n"; 00736 O << CurrentFnName << ":\n"; 00737 00738 // Output code for all of the basic blocks in the function... 00739 for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); I != E;++I) 00740 emitBasicBlock(*I); 00741 00742 // Output a .size directive so the debugger knows the extents of the function 00743 O << ".EndOf_" << CurrentFnName << ":\n\t.size " 00744 << CurrentFnName << ", .EndOf_" 00745 << CurrentFnName << "-" << CurrentFnName << "\n"; 00746 00747 // Put some spaces between the functions 00748 O << "\n\n"; 00749 } 00750 00751 void SparcV9AsmPrinter::printGlobalVariable(const GlobalVariable* GV) { 00752 if (GV->hasExternalLinkage()) 00753 O << "\t.global\t" << getID(GV) << "\n"; 00754 00755 if (GV->hasInitializer() && 00756 !(GV->getInitializer()->isNullValue() || 00757 isa<UndefValue>(GV->getInitializer()))) { 00758 printConstant(GV->getInitializer(), getID(GV)); 00759 } else { 00760 O << "\t.align\t" << TypeToAlignment(GV->getType()->getElementType(), 00761 TM) << "\n"; 00762 O << "\t.type\t" << getID(GV) << ",#object\n"; 00763 O << "\t.reserve\t" << getID(GV) << "," 00764 << findOptimalStorageSize(TM, GV->getType()->getElementType()) 00765 << "\n"; 00766 } 00767 } 00768 00769 void SparcV9AsmPrinter::emitGlobals(const Module &M) { 00770 // Output global variables... 00771 for (Module::const_giterator GI = M.gbegin(), GE = M.gend(); GI != GE; ++GI) 00772 if (! GI->isExternal()) { 00773 assert(GI->hasInitializer()); 00774 if (GI->isConstant()) 00775 enterSection(ReadOnlyData); // read-only, initialized data 00776 else if (GI->getInitializer()->isNullValue() || 00777 isa<UndefValue>(GI->getInitializer())) 00778 enterSection(ZeroInitRWData); // read-write zero data 00779 else 00780 enterSection(InitRWData); // read-write non-zero data 00781 00782 printGlobalVariable(GI); 00783 } 00784 00785 O << "\n"; 00786 } 00787 00788 FunctionPass *llvm::createAsmPrinterPass(std::ostream &Out, TargetMachine &TM) { 00789 return new SparcV9AsmPrinter(Out, TM); 00790 }