LLVM API Documentation
00001 //===-- SparcV9AsmPrinter.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, unsigned Alignment, 00213 std::string valID = "") { 00214 if (valID.length() == 0) 00215 valID = getID(CV); 00216 00217 if (Alignment == 0) 00218 Alignment = ConstantToAlignment(CV, TM); 00219 if (Alignment != 1) 00220 O << "\t.align\t" << Alignment << "\n"; 00221 00222 // Print .size and .type only if it is not a string. 00223 if (const ConstantArray *CVA = dyn_cast<ConstantArray>(CV)) 00224 if (CVA->isString()) { 00225 // print it as a string and return 00226 O << valID << ":\n"; 00227 O << "\t" << ".ascii" << "\t" << getAsCString(CVA) << "\n"; 00228 return; 00229 } 00230 00231 O << "\t.type" << "\t" << valID << ",#object\n"; 00232 00233 unsigned int constSize = ConstantToSize(CV, TM); 00234 if (constSize) 00235 O << "\t.size" << "\t" << valID << "," << constSize << "\n"; 00236 00237 O << valID << ":\n"; 00238 00239 printConstantValueOnly(CV); 00240 } 00241 00242 // enterSection - Use this method to enter a different section of the output 00243 // executable. This is used to only output necessary section transitions. 00244 // 00245 void enterSection(enum Sections S) { 00246 if (S == CurSection) return; // Only switch section if necessary 00247 CurSection = S; 00248 00249 O << "\n\t.section "; 00250 switch (S) 00251 { 00252 default: assert(0 && "Bad section name!"); 00253 case Text: O << "\".text\""; break; 00254 case ReadOnlyData: O << "\".rodata\",#alloc"; break; 00255 case InitRWData: O << "\".data\",#alloc,#write"; break; 00256 case ZeroInitRWData: O << "\".bss\",#alloc,#write"; break; 00257 } 00258 O << "\n"; 00259 } 00260 00261 // getID Wrappers - Ensure consistent usage 00262 // Symbol names in SparcV9 assembly language have these rules: 00263 // (a) Must match { letter | _ | . | $ } { letter | _ | . | $ | digit }* 00264 // (b) A name beginning in "." is treated as a local name. 00265 std::string getID(const Function *F) { 00266 return Mang->getValueName(F); 00267 } 00268 std::string getID(const BasicBlock *BB) { 00269 return ".L_" + getID(BB->getParent()) + "_" + Mang->getValueName(BB); 00270 } 00271 std::string getID(const GlobalVariable *GV) { 00272 return Mang->getValueName(GV); 00273 } 00274 std::string getID(const Constant *CV) { 00275 return ".C_" + Mang->getValueName(CV); 00276 } 00277 std::string getID(const GlobalValue *GV) { 00278 if (const GlobalVariable *V = dyn_cast<GlobalVariable>(GV)) 00279 return getID(V); 00280 else if (const Function *F = dyn_cast<Function>(GV)) 00281 return getID(F); 00282 assert(0 && "Unexpected type of GlobalValue!"); 00283 return ""; 00284 } 00285 00286 // Combines expressions 00287 inline std::string ConstantArithExprToString(const ConstantExpr* CE, 00288 const TargetMachine &TM, 00289 const std::string &op) { 00290 return "(" + valToExprString(CE->getOperand(0), TM) + op 00291 + valToExprString(CE->getOperand(1), TM) + ")"; 00292 } 00293 00294 /// ConstantExprToString() - Convert a ConstantExpr to an asm expression 00295 /// and return this as a string. 00296 /// 00297 std::string ConstantExprToString(const ConstantExpr* CE, 00298 const TargetMachine& target); 00299 00300 /// valToExprString - Helper function for ConstantExprToString(). 00301 /// Appends result to argument string S. 00302 /// 00303 std::string valToExprString(const Value* V, const TargetMachine& target); 00304 }; 00305 } // End anonymous namespace 00306 00307 00308 /// Print a single constant value. 00309 /// 00310 void AsmPrinter::printSingleConstantValue(const Constant* CV) { 00311 assert(CV->getType() != Type::VoidTy && 00312 CV->getType() != Type::LabelTy && 00313 "Unexpected type for Constant"); 00314 00315 assert((!isa<ConstantArray>(CV) && ! isa<ConstantStruct>(CV)) 00316 && "Aggregate types should be handled outside this function"); 00317 00318 O << "\t" << TypeToDataDirective(CV->getType()) << "\t"; 00319 00320 if (const GlobalValue* GV = dyn_cast<GlobalValue>(CV)) { 00321 O << getID(GV) << "\n"; 00322 } else if (isa<ConstantPointerNull>(CV) || isa<UndefValue>(CV)) { 00323 // Null pointer value 00324 O << "0\n"; 00325 } else if (const ConstantExpr* CE = dyn_cast<ConstantExpr>(CV)) { 00326 // Constant expression built from operators, constants, and symbolic addrs 00327 O << ConstantExprToString(CE, TM) << "\n"; 00328 } else if (CV->getType()->isPrimitiveType()) { 00329 // Check primitive types last 00330 if (isa<UndefValue>(CV)) { 00331 O << "0\n"; 00332 } else if (CV->getType()->isFloatingPoint()) { 00333 // FP Constants are printed as integer constants to avoid losing 00334 // precision... 00335 double Val = cast<ConstantFP>(CV)->getValue(); 00336 if (CV->getType() == Type::FloatTy) { 00337 float FVal = (float)Val; 00338 char *ProxyPtr = (char*)&FVal; // Abide by C TBAA rules 00339 O << *(unsigned int*)ProxyPtr; 00340 } else if (CV->getType() == Type::DoubleTy) { 00341 char *ProxyPtr = (char*)&Val; // Abide by C TBAA rules 00342 O << *(uint64_t*)ProxyPtr; 00343 } else { 00344 assert(0 && "Unknown floating point type!"); 00345 } 00346 00347 O << "\t! " << CV->getType()->getDescription() 00348 << " value: " << Val << "\n"; 00349 } else if (const ConstantBool *CB = dyn_cast<ConstantBool>(CV)) { 00350 O << (int)CB->getValue() << "\n"; 00351 } else { 00352 WriteAsOperand(O, CV, false, false) << "\n"; 00353 } 00354 } else { 00355 assert(0 && "Unknown elementary type for constant"); 00356 } 00357 } 00358 00359 /// Print a constant value or values (it may be an aggregate). 00360 /// Uses printSingleConstantValue() to print each individual value. 00361 /// 00362 void AsmPrinter::printConstantValueOnly(const Constant* CV, 00363 int numPadBytesAfter) { 00364 if (const ConstantArray *CVA = dyn_cast<ConstantArray>(CV)) { 00365 if (CVA->isString()) { 00366 // print the string alone and return 00367 O << "\t" << ".ascii" << "\t" << getAsCString(CVA) << "\n"; 00368 } else { 00369 // Not a string. Print the values in successive locations 00370 for (unsigned i = 0, e = CVA->getNumOperands(); i != e; ++i) 00371 printConstantValueOnly(CVA->getOperand(i)); 00372 } 00373 } else if (const ConstantStruct *CVS = dyn_cast<ConstantStruct>(CV)) { 00374 // Print the fields in successive locations. Pad to align if needed! 00375 const StructLayout *cvsLayout = 00376 TM.getTargetData().getStructLayout(CVS->getType()); 00377 unsigned sizeSoFar = 0; 00378 for (unsigned i = 0, e = CVS->getNumOperands(); i != e; ++i) { 00379 const Constant* field = CVS->getOperand(i); 00380 00381 // Check if padding is needed and insert one or more 0s. 00382 unsigned fieldSize = 00383 TM.getTargetData().getTypeSize(field->getType()); 00384 int padSize = ((i == e-1? cvsLayout->StructSize 00385 : cvsLayout->MemberOffsets[i+1]) 00386 - cvsLayout->MemberOffsets[i]) - fieldSize; 00387 sizeSoFar += (fieldSize + padSize); 00388 00389 // Now print the actual field value 00390 printConstantValueOnly(field, padSize); 00391 } 00392 assert(sizeSoFar == cvsLayout->StructSize && 00393 "Layout of constant struct may be incorrect!"); 00394 } else if (isa<ConstantAggregateZero>(CV) || isa<UndefValue>(CV)) { 00395 PrintZeroBytesToPad(TM.getTargetData().getTypeSize(CV->getType())); 00396 } else 00397 printSingleConstantValue(CV); 00398 00399 if (numPadBytesAfter) 00400 PrintZeroBytesToPad(numPadBytesAfter); 00401 } 00402 00403 /// ConstantExprToString() - Convert a ConstantExpr to an asm expression 00404 /// and return this as a string. 00405 /// 00406 std::string AsmPrinter::ConstantExprToString(const ConstantExpr* CE, 00407 const TargetMachine& target) { 00408 std::string S; 00409 switch(CE->getOpcode()) { 00410 case Instruction::GetElementPtr: 00411 { // generate a symbolic expression for the byte address 00412 const Value* ptrVal = CE->getOperand(0); 00413 std::vector<Value*> idxVec(CE->op_begin()+1, CE->op_end()); 00414 const TargetData &TD = target.getTargetData(); 00415 S += "(" + valToExprString(ptrVal, target) + ") + (" 00416 + utostr(TD.getIndexedOffset(ptrVal->getType(),idxVec)) + ")"; 00417 break; 00418 } 00419 00420 case Instruction::Cast: 00421 // Support only non-converting casts for now, i.e., a no-op. 00422 // This assertion is not a complete check. 00423 assert(target.getTargetData().getTypeSize(CE->getType()) == 00424 target.getTargetData().getTypeSize(CE->getOperand(0)->getType())); 00425 S += "(" + valToExprString(CE->getOperand(0), target) + ")"; 00426 break; 00427 00428 case Instruction::Add: 00429 S += ConstantArithExprToString(CE, target, ") + ("); 00430 break; 00431 00432 case Instruction::Sub: 00433 S += ConstantArithExprToString(CE, target, ") - ("); 00434 break; 00435 00436 case Instruction::Mul: 00437 S += ConstantArithExprToString(CE, target, ") * ("); 00438 break; 00439 00440 case Instruction::Div: 00441 S += ConstantArithExprToString(CE, target, ") / ("); 00442 break; 00443 00444 case Instruction::Rem: 00445 S += ConstantArithExprToString(CE, target, ") % ("); 00446 break; 00447 00448 case Instruction::And: 00449 // Logical && for booleans; bitwise & otherwise 00450 S += ConstantArithExprToString(CE, target, 00451 ((CE->getType() == Type::BoolTy)? ") && (" : ") & (")); 00452 break; 00453 00454 case Instruction::Or: 00455 // Logical || for booleans; bitwise | otherwise 00456 S += ConstantArithExprToString(CE, target, 00457 ((CE->getType() == Type::BoolTy)? ") || (" : ") | (")); 00458 break; 00459 00460 case Instruction::Xor: 00461 // Bitwise ^ for all types 00462 S += ConstantArithExprToString(CE, target, ") ^ ("); 00463 break; 00464 00465 default: 00466 assert(0 && "Unsupported operator in ConstantExprToString()"); 00467 break; 00468 } 00469 00470 return S; 00471 } 00472 00473 /// valToExprString - Helper function for ConstantExprToString(). 00474 /// Appends result to argument string S. 00475 /// 00476 std::string AsmPrinter::valToExprString(const Value* V, 00477 const TargetMachine& target) { 00478 std::string S; 00479 bool failed = false; 00480 if (const GlobalValue* GV = dyn_cast<GlobalValue>(V)) { 00481 S += getID(GV); 00482 } else if (const Constant* CV = dyn_cast<Constant>(V)) { // symbolic or known 00483 if (const ConstantBool *CB = dyn_cast<ConstantBool>(CV)) 00484 S += std::string(CB == ConstantBool::True ? "1" : "0"); 00485 else if (const ConstantSInt *CI = dyn_cast<ConstantSInt>(CV)) 00486 S += itostr(CI->getValue()); 00487 else if (const ConstantUInt *CI = dyn_cast<ConstantUInt>(CV)) 00488 S += utostr(CI->getValue()); 00489 else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV)) 00490 S += ftostr(CFP->getValue()); 00491 else if (isa<ConstantPointerNull>(CV) || isa<UndefValue>(CV)) 00492 S += "0"; 00493 else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV)) 00494 S += ConstantExprToString(CE, target); 00495 else 00496 failed = true; 00497 } else 00498 failed = true; 00499 00500 if (failed) { 00501 assert(0 && "Cannot convert value to string"); 00502 S += "<illegal-value>"; 00503 } 00504 return S; 00505 } 00506 00507 namespace { 00508 00509 struct SparcV9AsmPrinter : public FunctionPass, public AsmPrinter { 00510 inline SparcV9AsmPrinter(std::ostream &os, const TargetMachine &t) 00511 : AsmPrinter(os, t) {} 00512 00513 const Function *currFunction; 00514 00515 const char *getPassName() const { 00516 return "Output SparcV9 Assembly for Functions"; 00517 } 00518 00519 virtual bool doInitialization(Module &M) { 00520 startModule(M); 00521 return false; 00522 } 00523 00524 virtual bool runOnFunction(Function &F) { 00525 currFunction = &F; 00526 emitFunction(F); 00527 return false; 00528 } 00529 00530 virtual bool doFinalization(Module &M) { 00531 emitGlobals(M); 00532 return false; 00533 } 00534 00535 virtual void getAnalysisUsage(AnalysisUsage &AU) const { 00536 AU.setPreservesAll(); 00537 } 00538 00539 void emitFunction(const Function &F); 00540 private : 00541 void emitBasicBlock(const MachineBasicBlock &MBB); 00542 void emitMachineInst(const MachineInstr *MI); 00543 00544 unsigned int printOperands(const MachineInstr *MI, unsigned int opNum); 00545 void printOneOperand(const MachineOperand &Op, MachineOpCode opCode); 00546 00547 bool OpIsBranchTargetLabel(const MachineInstr *MI, unsigned int opNum); 00548 bool OpIsMemoryAddressBase(const MachineInstr *MI, unsigned int opNum); 00549 00550 unsigned getOperandMask(unsigned Opcode) { 00551 switch (Opcode) { 00552 case V9::SUBccr: 00553 case V9::SUBcci: return 1 << 3; // Remove CC argument 00554 default: return 0; // By default, don't hack operands... 00555 } 00556 } 00557 00558 void emitGlobals(const Module &M); 00559 void printGlobalVariable(const GlobalVariable *GV); 00560 }; 00561 00562 } // End anonymous namespace 00563 00564 inline bool 00565 SparcV9AsmPrinter::OpIsBranchTargetLabel(const MachineInstr *MI, 00566 unsigned int opNum) { 00567 switch (MI->getOpcode()) { 00568 case V9::JMPLCALLr: 00569 case V9::JMPLCALLi: 00570 case V9::JMPLRETr: 00571 case V9::JMPLRETi: 00572 return (opNum == 0); 00573 default: 00574 return false; 00575 } 00576 } 00577 00578 inline bool 00579 SparcV9AsmPrinter::OpIsMemoryAddressBase(const MachineInstr *MI, 00580 unsigned int opNum) { 00581 if (TM.getInstrInfo()->isLoad(MI->getOpcode())) 00582 return (opNum == 0); 00583 else if (TM.getInstrInfo()->isStore(MI->getOpcode())) 00584 return (opNum == 1); 00585 else 00586 return false; 00587 } 00588 00589 unsigned int 00590 SparcV9AsmPrinter::printOperands(const MachineInstr *MI, unsigned opNum) { 00591 const MachineOperand& mop = MI->getOperand(opNum); 00592 if (OpIsBranchTargetLabel(MI, opNum)) { 00593 printOneOperand(mop, MI->getOpcode()); 00594 O << "+"; 00595 printOneOperand(MI->getOperand(opNum+1), MI->getOpcode()); 00596 return 2; 00597 } else if (OpIsMemoryAddressBase(MI, opNum)) { 00598 O << "["; 00599 printOneOperand(mop, MI->getOpcode()); 00600 O << "+"; 00601 printOneOperand(MI->getOperand(opNum+1), MI->getOpcode()); 00602 O << "]"; 00603 return 2; 00604 } else { 00605 printOneOperand(mop, MI->getOpcode()); 00606 return 1; 00607 } 00608 } 00609 00610 void 00611 SparcV9AsmPrinter::printOneOperand(const MachineOperand &mop, 00612 MachineOpCode opCode) 00613 { 00614 bool needBitsFlag = true; 00615 00616 if (mop.isHiBits32()) 00617 O << "%lm("; 00618 else if (mop.isLoBits32()) 00619 O << "%lo("; 00620 else if (mop.isHiBits64()) 00621 O << "%hh("; 00622 else if (mop.isLoBits64()) 00623 O << "%hm("; 00624 else 00625 needBitsFlag = false; 00626 00627 switch (mop.getType()) 00628 { 00629 case MachineOperand::MO_VirtualRegister: 00630 case MachineOperand::MO_CCRegister: 00631 case MachineOperand::MO_MachineRegister: 00632 { 00633 int regNum = (int)mop.getReg(); 00634 00635 if (regNum == TM.getRegInfo()->getInvalidRegNum()) { 00636 // better to print code with NULL registers than to die 00637 O << "<NULL VALUE>"; 00638 } else { 00639 O << "%" << TM.getRegInfo()->getUnifiedRegName(regNum); 00640 } 00641 break; 00642 } 00643 00644 case MachineOperand::MO_ConstantPoolIndex: 00645 { 00646 O << ".CPI_" << getID(currFunction) 00647 << "_" << mop.getConstantPoolIndex(); 00648 break; 00649 } 00650 00651 case MachineOperand::MO_PCRelativeDisp: 00652 { 00653 const Value *Val = mop.getVRegValue(); 00654 assert(Val && "\tNULL Value in SparcV9AsmPrinter"); 00655 00656 if (const BasicBlock *BB = dyn_cast<BasicBlock>(Val)) 00657 O << getID(BB); 00658 else if (const Function *F = dyn_cast<Function>(Val)) 00659 O << getID(F); 00660 else if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(Val)) 00661 O << getID(GV); 00662 else if (const Constant *CV = dyn_cast<Constant>(Val)) 00663 O << getID(CV); 00664 else 00665 assert(0 && "Unrecognized value in SparcV9AsmPrinter"); 00666 break; 00667 } 00668 00669 case MachineOperand::MO_SignExtendedImmed: 00670 O << mop.getImmedValue(); 00671 break; 00672 00673 case MachineOperand::MO_UnextendedImmed: 00674 O << (uint64_t) mop.getImmedValue(); 00675 break; 00676 00677 default: 00678 O << mop; // use dump field 00679 break; 00680 } 00681 00682 if (needBitsFlag) 00683 O << ")"; 00684 } 00685 00686 void SparcV9AsmPrinter::emitMachineInst(const MachineInstr *MI) { 00687 unsigned Opcode = MI->getOpcode(); 00688 00689 if (Opcode == V9::PHI) 00690 return; // Ignore Machine-PHI nodes. 00691 00692 O << "\t" << TM.getInstrInfo()->getName(Opcode) << "\t"; 00693 00694 unsigned Mask = getOperandMask(Opcode); 00695 00696 bool NeedComma = false; 00697 unsigned N = 1; 00698 for (unsigned OpNum = 0; OpNum < MI->getNumOperands(); OpNum += N) 00699 if (! ((1 << OpNum) & Mask)) { // Ignore this operand? 00700 if (NeedComma) O << ", "; // Handle comma outputting 00701 NeedComma = true; 00702 N = printOperands(MI, OpNum); 00703 } else 00704 N = 1; 00705 00706 O << "\n"; 00707 ++EmittedInsts; 00708 } 00709 00710 void SparcV9AsmPrinter::emitBasicBlock(const MachineBasicBlock &MBB) { 00711 // Emit a label for the basic block 00712 O << getID(MBB.getBasicBlock()) << ":\n"; 00713 00714 // Loop over all of the instructions in the basic block... 00715 for (MachineBasicBlock::const_iterator MII = MBB.begin(), MIE = MBB.end(); 00716 MII != MIE; ++MII) 00717 emitMachineInst(MII); 00718 O << "\n"; // Separate BB's with newlines 00719 } 00720 00721 void SparcV9AsmPrinter::emitFunction(const Function &F) { 00722 std::string CurrentFnName = getID(&F); 00723 MachineFunction &MF = MachineFunction::get(&F); 00724 O << "!****** Outputing Function: " << CurrentFnName << " ******\n"; 00725 00726 // Emit constant pool for this function 00727 const MachineConstantPool *MCP = MF.getConstantPool(); 00728 const std::vector<MachineConstantPoolEntry> &CP = MCP->getConstants(); 00729 00730 enterSection(ReadOnlyData); 00731 O << "\t.align\t" << (1 << MCP->getConstantPoolAlignment()) << "\n"; 00732 for (unsigned i = 0, e = CP.size(); i != e; ++i) { 00733 std::string cpiName = ".CPI_" + CurrentFnName + "_" + utostr(i); 00734 printConstant(CP[i].Val, 1, cpiName); 00735 00736 if (i != e-1) { 00737 unsigned EntSize = TM.getTargetData().getTypeSize(CP[i].Val->getType()); 00738 unsigned ValEnd = CP[i].Offset + EntSize; 00739 // Emit inter-object padding for alignment. 00740 for (unsigned NumZeros = CP[i+1].Offset-ValEnd; NumZeros; --NumZeros) 00741 O << "\t.byte 0\n"; 00742 } 00743 } 00744 00745 enterSection(Text); 00746 O << "\t.align\t4\n\t.global\t" << CurrentFnName << "\n"; 00747 //O << "\t.type\t" << CurrentFnName << ",#function\n"; 00748 O << "\t.type\t" << CurrentFnName << ", 2\n"; 00749 O << CurrentFnName << ":\n"; 00750 00751 // Output code for all of the basic blocks in the function... 00752 for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); I != E;++I) 00753 emitBasicBlock(*I); 00754 00755 // Output a .size directive so the debugger knows the extents of the function 00756 O << ".EndOf_" << CurrentFnName << ":\n\t.size " 00757 << CurrentFnName << ", .EndOf_" 00758 << CurrentFnName << "-" << CurrentFnName << "\n"; 00759 00760 // Put some spaces between the functions 00761 O << "\n\n"; 00762 } 00763 00764 void SparcV9AsmPrinter::printGlobalVariable(const GlobalVariable* GV) { 00765 if (GV->hasExternalLinkage()) 00766 O << "\t.global\t" << getID(GV) << "\n"; 00767 00768 if (GV->hasInitializer() && 00769 !(GV->getInitializer()->isNullValue() || 00770 isa<UndefValue>(GV->getInitializer()))) { 00771 printConstant(GV->getInitializer(), 0, getID(GV)); 00772 } else { 00773 O << "\t.align\t" << TypeToAlignment(GV->getType()->getElementType(), 00774 TM) << "\n"; 00775 O << "\t.type\t" << getID(GV) << ",#object\n"; 00776 O << "\t.reserve\t" << getID(GV) << "," 00777 << findOptimalStorageSize(TM, GV->getType()->getElementType()) 00778 << "\n"; 00779 } 00780 } 00781 00782 void SparcV9AsmPrinter::emitGlobals(const Module &M) { 00783 // Output global variables... 00784 for (Module::const_global_iterator GI = M.global_begin(), GE = M.global_end(); GI != GE; ++GI) 00785 if (! GI->isExternal()) { 00786 assert(GI->hasInitializer()); 00787 if (GI->isConstant()) 00788 enterSection(ReadOnlyData); // read-only, initialized data 00789 else if (GI->getInitializer()->isNullValue() || 00790 isa<UndefValue>(GI->getInitializer())) 00791 enterSection(ZeroInitRWData); // read-write zero data 00792 else 00793 enterSection(InitRWData); // read-write non-zero data 00794 00795 printGlobalVariable(GI); 00796 } 00797 00798 O << "\n"; 00799 } 00800 00801 FunctionPass *llvm::createAsmPrinterPass(std::ostream &Out, TargetMachine &TM) { 00802 return new SparcV9AsmPrinter(Out, TM); 00803 }