| Brian Gaeke | 4acfd03 | 2004-03-04 06:00:41 +0000 | [diff] [blame] | 1 | //===-- SparcV8AsmPrinter.cpp - SparcV8 LLVM assembly writer --------------===// | 
 | 2 | //  | 
 | 3 | //                     The LLVM Compiler Infrastructure | 
 | 4 | // | 
 | 5 | // This file was developed by the LLVM research group and is distributed under | 
 | 6 | // the University of Illinois Open Source 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 GAS-format Sparc V8 assembly language. | 
 | 12 | // | 
 | 13 | //===----------------------------------------------------------------------===// | 
 | 14 |  | 
 | 15 | #include "SparcV8.h" | 
 | 16 | #include "SparcV8InstrInfo.h" | 
 | 17 | #include "llvm/Constants.h" | 
 | 18 | #include "llvm/DerivedTypes.h" | 
 | 19 | #include "llvm/Module.h" | 
 | 20 | #include "llvm/Assembly/Writer.h" | 
 | 21 | #include "llvm/CodeGen/MachineFunctionPass.h" | 
 | 22 | #include "llvm/CodeGen/MachineConstantPool.h" | 
 | 23 | #include "llvm/CodeGen/MachineInstr.h" | 
 | 24 | #include "llvm/Target/TargetMachine.h" | 
 | 25 | #include "llvm/Support/Mangler.h" | 
 | 26 | #include "Support/Statistic.h" | 
 | 27 | #include "Support/StringExtras.h" | 
 | 28 | #include "Support/CommandLine.h" | 
| Brian Gaeke | a8b00ca | 2004-03-06 05:30:21 +0000 | [diff] [blame] | 29 | #include <cctype> | 
| Brian Gaeke | 4acfd03 | 2004-03-04 06:00:41 +0000 | [diff] [blame] | 30 | using namespace llvm; | 
 | 31 |  | 
 | 32 | namespace { | 
 | 33 |   Statistic<> EmittedInsts("asm-printer", "Number of machine instrs printed"); | 
 | 34 |  | 
 | 35 |   struct V8Printer : public MachineFunctionPass { | 
 | 36 |     /// Output stream on which we're printing assembly code. | 
 | 37 |     /// | 
 | 38 |     std::ostream &O; | 
 | 39 |  | 
 | 40 |     /// Target machine description which we query for reg. names, data | 
 | 41 |     /// layout, etc. | 
 | 42 |     /// | 
 | 43 |     TargetMachine &TM; | 
 | 44 |  | 
 | 45 |     /// Name-mangler for global names. | 
 | 46 |     /// | 
 | 47 |     Mangler *Mang; | 
 | 48 |  | 
 | 49 |     V8Printer(std::ostream &o, TargetMachine &tm) : O(o), TM(tm) { } | 
 | 50 |  | 
 | 51 |     /// We name each basic block in a Function with a unique number, so | 
 | 52 |     /// that we can consistently refer to them later. This is cleared | 
 | 53 |     /// at the beginning of each call to runOnMachineFunction(). | 
 | 54 |     /// | 
 | 55 |     typedef std::map<const Value *, unsigned> ValueMapTy; | 
 | 56 |     ValueMapTy NumberForBB; | 
 | 57 |  | 
 | 58 |     /// Cache of mangled name for current function. This is | 
 | 59 |     /// recalculated at the beginning of each call to | 
 | 60 |     /// runOnMachineFunction(). | 
 | 61 |     /// | 
 | 62 |     std::string CurrentFnName; | 
 | 63 |  | 
 | 64 |     virtual const char *getPassName() const { | 
 | 65 |       return "SparcV8 Assembly Printer"; | 
 | 66 |     } | 
 | 67 |  | 
 | 68 |     void emitConstantValueOnly(const Constant *CV); | 
 | 69 |     void emitGlobalConstant(const Constant *CV); | 
 | 70 |     void printConstantPool(MachineConstantPool *MCP); | 
| Brian Gaeke | 446ae11 | 2004-06-15 19:52:59 +0000 | [diff] [blame^] | 71 |     void printOperand(const MachineInstr *MI, int opNum); | 
| Brian Gaeke | 1c38175 | 2004-04-06 22:10:11 +0000 | [diff] [blame] | 72 |     void printBaseOffsetPair (const MachineInstr *MI, int i); | 
| Brian Gaeke | 4acfd03 | 2004-03-04 06:00:41 +0000 | [diff] [blame] | 73 |     void printMachineInstruction(const MachineInstr *MI); | 
 | 74 |     bool runOnMachineFunction(MachineFunction &F);     | 
 | 75 |     bool doInitialization(Module &M); | 
 | 76 |     bool doFinalization(Module &M); | 
 | 77 |   }; | 
 | 78 | } // end of anonymous namespace | 
 | 79 |  | 
 | 80 | /// createSparcV8CodePrinterPass - Returns a pass that prints the SparcV8 | 
 | 81 | /// assembly code for a MachineFunction to the given output stream, | 
 | 82 | /// using the given target machine description.  This should work | 
 | 83 | /// regardless of whether the function is in SSA form. | 
 | 84 | /// | 
 | 85 | FunctionPass *llvm::createSparcV8CodePrinterPass (std::ostream &o, | 
 | 86 |                                                   TargetMachine &tm) { | 
 | 87 |   return new V8Printer(o, tm); | 
 | 88 | } | 
 | 89 |  | 
 | 90 | /// toOctal - Convert the low order bits of X into an octal digit. | 
 | 91 | /// | 
 | 92 | static inline char toOctal(int X) { | 
 | 93 |   return (X&7)+'0'; | 
 | 94 | } | 
 | 95 |  | 
 | 96 | /// getAsCString - Return the specified array as a C compatible | 
 | 97 | /// string, only if the predicate isStringCompatible is true. | 
 | 98 | /// | 
 | 99 | static void printAsCString(std::ostream &O, const ConstantArray *CVA) { | 
 | 100 |   assert(CVA->isString() && "Array is not string compatible!"); | 
 | 101 |  | 
 | 102 |   O << "\""; | 
 | 103 |   for (unsigned i = 0; i != CVA->getNumOperands(); ++i) { | 
 | 104 |     unsigned char C = cast<ConstantInt>(CVA->getOperand(i))->getRawValue(); | 
 | 105 |  | 
 | 106 |     if (C == '"') { | 
 | 107 |       O << "\\\""; | 
 | 108 |     } else if (C == '\\') { | 
 | 109 |       O << "\\\\"; | 
 | 110 |     } else if (isprint(C)) { | 
 | 111 |       O << C; | 
 | 112 |     } else { | 
 | 113 |       switch(C) { | 
 | 114 |       case '\b': O << "\\b"; break; | 
 | 115 |       case '\f': O << "\\f"; break; | 
 | 116 |       case '\n': O << "\\n"; break; | 
 | 117 |       case '\r': O << "\\r"; break; | 
 | 118 |       case '\t': O << "\\t"; break; | 
 | 119 |       default: | 
 | 120 |         O << '\\'; | 
 | 121 |         O << toOctal(C >> 6); | 
 | 122 |         O << toOctal(C >> 3); | 
 | 123 |         O << toOctal(C >> 0); | 
 | 124 |         break; | 
 | 125 |       } | 
 | 126 |     } | 
 | 127 |   } | 
 | 128 |   O << "\""; | 
 | 129 | } | 
 | 130 |  | 
 | 131 | // Print out the specified constant, without a storage class.  Only the | 
 | 132 | // constants valid in constant expressions can occur here. | 
 | 133 | void V8Printer::emitConstantValueOnly(const Constant *CV) { | 
 | 134 |   if (CV->isNullValue()) | 
 | 135 |     O << "0"; | 
 | 136 |   else if (const ConstantBool *CB = dyn_cast<ConstantBool>(CV)) { | 
 | 137 |     assert(CB == ConstantBool::True); | 
 | 138 |     O << "1"; | 
 | 139 |   } else if (const ConstantSInt *CI = dyn_cast<ConstantSInt>(CV)) | 
 | 140 |     if (((CI->getValue() << 32) >> 32) == CI->getValue()) | 
 | 141 |       O << CI->getValue(); | 
 | 142 |     else | 
 | 143 |       O << (unsigned long long)CI->getValue(); | 
 | 144 |   else if (const ConstantUInt *CI = dyn_cast<ConstantUInt>(CV)) | 
 | 145 |     O << CI->getValue(); | 
 | 146 |   else if (const ConstantPointerRef *CPR = dyn_cast<ConstantPointerRef>(CV)) | 
 | 147 |     // This is a constant address for a global variable or function.  Use the | 
 | 148 |     // name of the variable or function as the address value. | 
 | 149 |     O << Mang->getValueName(CPR->getValue()); | 
 | 150 |   else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV)) { | 
 | 151 |     const TargetData &TD = TM.getTargetData(); | 
 | 152 |     switch(CE->getOpcode()) { | 
 | 153 |     case Instruction::GetElementPtr: { | 
 | 154 |       // generate a symbolic expression for the byte address | 
 | 155 |       const Constant *ptrVal = CE->getOperand(0); | 
 | 156 |       std::vector<Value*> idxVec(CE->op_begin()+1, CE->op_end()); | 
 | 157 |       if (unsigned Offset = TD.getIndexedOffset(ptrVal->getType(), idxVec)) { | 
 | 158 |         O << "("; | 
 | 159 |         emitConstantValueOnly(ptrVal); | 
 | 160 |         O << ") + " << Offset; | 
 | 161 |       } else { | 
 | 162 |         emitConstantValueOnly(ptrVal); | 
 | 163 |       } | 
 | 164 |       break; | 
 | 165 |     } | 
 | 166 |     case Instruction::Cast: { | 
 | 167 |       // Support only non-converting or widening casts for now, that is, ones | 
 | 168 |       // that do not involve a change in value.  This assertion is really gross, | 
 | 169 |       // and may not even be a complete check. | 
 | 170 |       Constant *Op = CE->getOperand(0); | 
 | 171 |       const Type *OpTy = Op->getType(), *Ty = CE->getType(); | 
 | 172 |  | 
 | 173 |       // Pointers on ILP32 machines can be losslessly converted back and | 
 | 174 |       // forth into 32-bit or wider integers, regardless of signedness. | 
 | 175 |       assert(((isa<PointerType>(OpTy) | 
 | 176 |                && (Ty == Type::LongTy || Ty == Type::ULongTy | 
 | 177 |                    || Ty == Type::IntTy || Ty == Type::UIntTy)) | 
 | 178 |               || (isa<PointerType>(Ty) | 
 | 179 |                   && (OpTy == Type::LongTy || OpTy == Type::ULongTy | 
 | 180 |                       || OpTy == Type::IntTy || OpTy == Type::UIntTy)) | 
 | 181 |               || (((TD.getTypeSize(Ty) >= TD.getTypeSize(OpTy)) | 
 | 182 |                    && OpTy->isLosslesslyConvertibleTo(Ty)))) | 
 | 183 |              && "FIXME: Don't yet support this kind of constant cast expr"); | 
 | 184 |       O << "("; | 
 | 185 |       emitConstantValueOnly(Op); | 
 | 186 |       O << ")"; | 
 | 187 |       break; | 
 | 188 |     } | 
 | 189 |     case Instruction::Add: | 
 | 190 |       O << "("; | 
 | 191 |       emitConstantValueOnly(CE->getOperand(0)); | 
 | 192 |       O << ") + ("; | 
 | 193 |       emitConstantValueOnly(CE->getOperand(1)); | 
 | 194 |       O << ")"; | 
 | 195 |       break; | 
 | 196 |     default: | 
 | 197 |       assert(0 && "Unsupported operator!"); | 
 | 198 |     } | 
 | 199 |   } else { | 
 | 200 |     assert(0 && "Unknown constant value!"); | 
 | 201 |   } | 
 | 202 | } | 
 | 203 |  | 
 | 204 | // Print a constant value or values, with the appropriate storage class as a | 
 | 205 | // prefix. | 
 | 206 | void V8Printer::emitGlobalConstant(const Constant *CV) {   | 
 | 207 |   const TargetData &TD = TM.getTargetData(); | 
 | 208 |  | 
 | 209 |   if (CV->isNullValue()) { | 
 | 210 |     O << "\t.zero\t " << TD.getTypeSize(CV->getType()) << "\n";       | 
 | 211 |     return; | 
 | 212 |   } else if (const ConstantArray *CVA = dyn_cast<ConstantArray>(CV)) { | 
 | 213 |     if (CVA->isString()) { | 
 | 214 |       O << "\t.ascii\t"; | 
 | 215 |       printAsCString(O, CVA); | 
 | 216 |       O << "\n"; | 
 | 217 |     } else { // Not a string.  Print the values in successive locations | 
 | 218 |       const std::vector<Use> &constValues = CVA->getValues(); | 
 | 219 |       for (unsigned i=0; i < constValues.size(); i++) | 
 | 220 |         emitGlobalConstant(cast<Constant>(constValues[i].get())); | 
 | 221 |     } | 
 | 222 |     return; | 
 | 223 |   } else if (const ConstantStruct *CVS = dyn_cast<ConstantStruct>(CV)) { | 
 | 224 |     // Print the fields in successive locations. Pad to align if needed! | 
 | 225 |     const StructLayout *cvsLayout = TD.getStructLayout(CVS->getType()); | 
 | 226 |     const std::vector<Use>& constValues = CVS->getValues(); | 
 | 227 |     unsigned sizeSoFar = 0; | 
 | 228 |     for (unsigned i=0, N = constValues.size(); i < N; i++) { | 
 | 229 |       const Constant* field = cast<Constant>(constValues[i].get()); | 
 | 230 |  | 
 | 231 |       // Check if padding is needed and insert one or more 0s. | 
 | 232 |       unsigned fieldSize = TD.getTypeSize(field->getType()); | 
 | 233 |       unsigned padSize = ((i == N-1? cvsLayout->StructSize | 
 | 234 |                            : cvsLayout->MemberOffsets[i+1]) | 
 | 235 |                           - cvsLayout->MemberOffsets[i]) - fieldSize; | 
 | 236 |       sizeSoFar += fieldSize + padSize; | 
 | 237 |  | 
 | 238 |       // Now print the actual field value | 
 | 239 |       emitGlobalConstant(field); | 
 | 240 |  | 
 | 241 |       // Insert the field padding unless it's zero bytes... | 
 | 242 |       if (padSize) | 
 | 243 |         O << "\t.zero\t " << padSize << "\n";       | 
 | 244 |     } | 
 | 245 |     assert(sizeSoFar == cvsLayout->StructSize && | 
 | 246 |            "Layout of constant struct may be incorrect!"); | 
 | 247 |     return; | 
 | 248 |   } else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV)) { | 
 | 249 |     // FP Constants are printed as integer constants to avoid losing | 
 | 250 |     // precision... | 
 | 251 |     double Val = CFP->getValue(); | 
 | 252 |     switch (CFP->getType()->getPrimitiveID()) { | 
 | 253 |     default: assert(0 && "Unknown floating point type!"); | 
 | 254 |     case Type::FloatTyID: { | 
 | 255 |       union FU {                            // Abide by C TBAA rules | 
 | 256 |         float FVal; | 
 | 257 |         unsigned UVal; | 
 | 258 |       } U; | 
 | 259 |       U.FVal = Val; | 
| Brian Gaeke | 79db740 | 2004-03-16 22:37:12 +0000 | [diff] [blame] | 260 |       O << ".long\t" << U.UVal << "\t! float " << Val << "\n"; | 
| Brian Gaeke | 4acfd03 | 2004-03-04 06:00:41 +0000 | [diff] [blame] | 261 |       return; | 
 | 262 |     } | 
 | 263 |     case Type::DoubleTyID: { | 
 | 264 |       union DU {                            // Abide by C TBAA rules | 
 | 265 |         double FVal; | 
 | 266 |         uint64_t UVal; | 
 | 267 |       } U; | 
 | 268 |       U.FVal = Val; | 
| Brian Gaeke | 79db740 | 2004-03-16 22:37:12 +0000 | [diff] [blame] | 269 |       O << ".quad\t" << U.UVal << "\t! double " << Val << "\n"; | 
| Brian Gaeke | 4acfd03 | 2004-03-04 06:00:41 +0000 | [diff] [blame] | 270 |       return; | 
 | 271 |     } | 
 | 272 |     } | 
 | 273 |   } | 
 | 274 |  | 
 | 275 |   const Type *type = CV->getType(); | 
 | 276 |   O << "\t"; | 
 | 277 |   switch (type->getPrimitiveID()) { | 
 | 278 |   case Type::BoolTyID: case Type::UByteTyID: case Type::SByteTyID: | 
 | 279 |     O << ".byte"; | 
 | 280 |     break; | 
 | 281 |   case Type::UShortTyID: case Type::ShortTyID: | 
 | 282 |     O << ".word"; | 
 | 283 |     break; | 
 | 284 |   case Type::FloatTyID: case Type::PointerTyID: | 
 | 285 |   case Type::UIntTyID: case Type::IntTyID: | 
 | 286 |     O << ".long"; | 
 | 287 |     break; | 
 | 288 |   case Type::DoubleTyID: | 
 | 289 |   case Type::ULongTyID: case Type::LongTyID: | 
 | 290 |     O << ".quad"; | 
 | 291 |     break; | 
 | 292 |   default: | 
 | 293 |     assert (0 && "Can't handle printing this type of thing"); | 
 | 294 |     break; | 
 | 295 |   } | 
 | 296 |   O << "\t"; | 
 | 297 |   emitConstantValueOnly(CV); | 
 | 298 |   O << "\n"; | 
 | 299 | } | 
 | 300 |  | 
 | 301 | /// printConstantPool - Print to the current output stream assembly | 
 | 302 | /// representations of the constants in the constant pool MCP. This is | 
 | 303 | /// used to print out constants which have been "spilled to memory" by | 
 | 304 | /// the code generator. | 
 | 305 | /// | 
 | 306 | void V8Printer::printConstantPool(MachineConstantPool *MCP) { | 
 | 307 |   const std::vector<Constant*> &CP = MCP->getConstants(); | 
 | 308 |   const TargetData &TD = TM.getTargetData(); | 
 | 309 |   | 
 | 310 |   if (CP.empty()) return; | 
 | 311 |  | 
 | 312 |   for (unsigned i = 0, e = CP.size(); i != e; ++i) { | 
 | 313 |     O << "\t.section .rodata\n"; | 
 | 314 |     O << "\t.align " << (unsigned)TD.getTypeAlignment(CP[i]->getType()) | 
 | 315 |       << "\n"; | 
| Brian Gaeke | 79db740 | 2004-03-16 22:37:12 +0000 | [diff] [blame] | 316 |     O << ".CPI" << CurrentFnName << "_" << i << ":\t\t\t\t\t!" | 
| Brian Gaeke | 4acfd03 | 2004-03-04 06:00:41 +0000 | [diff] [blame] | 317 |       << *CP[i] << "\n"; | 
 | 318 |     emitGlobalConstant(CP[i]); | 
 | 319 |   } | 
 | 320 | } | 
 | 321 |  | 
 | 322 | /// runOnMachineFunction - This uses the printMachineInstruction() | 
 | 323 | /// method to print assembly for each instruction. | 
 | 324 | /// | 
 | 325 | bool V8Printer::runOnMachineFunction(MachineFunction &MF) { | 
 | 326 |   // BBNumber is used here so that a given Printer will never give two | 
 | 327 |   // BBs the same name. (If you have a better way, please let me know!) | 
 | 328 |   static unsigned BBNumber = 0; | 
 | 329 |  | 
 | 330 |   O << "\n\n"; | 
 | 331 |   // What's my mangled name? | 
 | 332 |   CurrentFnName = Mang->getValueName(MF.getFunction()); | 
 | 333 |  | 
 | 334 |   // Print out constants referenced by the function | 
 | 335 |   printConstantPool(MF.getConstantPool()); | 
 | 336 |  | 
 | 337 |   // Print out labels for the function. | 
 | 338 |   O << "\t.text\n"; | 
 | 339 |   O << "\t.align 16\n"; | 
 | 340 |   O << "\t.globl\t" << CurrentFnName << "\n"; | 
| Brian Gaeke | 54cc3c2 | 2004-03-16 22:52:04 +0000 | [diff] [blame] | 341 |   O << "\t.type\t" << CurrentFnName << ", #function\n"; | 
| Brian Gaeke | 4acfd03 | 2004-03-04 06:00:41 +0000 | [diff] [blame] | 342 |   O << CurrentFnName << ":\n"; | 
 | 343 |  | 
 | 344 |   // Number each basic block so that we can consistently refer to them | 
 | 345 |   // in PC-relative references. | 
 | 346 |   NumberForBB.clear(); | 
 | 347 |   for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); | 
 | 348 |        I != E; ++I) { | 
 | 349 |     NumberForBB[I->getBasicBlock()] = BBNumber++; | 
 | 350 |   } | 
 | 351 |  | 
 | 352 |   // Print out code for the function. | 
 | 353 |   for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); | 
 | 354 |        I != E; ++I) { | 
 | 355 |     // Print a label for the basic block. | 
| Brian Gaeke | 79db740 | 2004-03-16 22:37:12 +0000 | [diff] [blame] | 356 |     O << ".LBB" << NumberForBB[I->getBasicBlock()] << ":\t! " | 
| Brian Gaeke | 4acfd03 | 2004-03-04 06:00:41 +0000 | [diff] [blame] | 357 |       << I->getBasicBlock()->getName() << "\n"; | 
 | 358 |     for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end(); | 
 | 359 | 	 II != E; ++II) { | 
 | 360 |       // Print the assembly for the instruction. | 
 | 361 |       O << "\t"; | 
 | 362 |       printMachineInstruction(II); | 
 | 363 |     } | 
 | 364 |   } | 
 | 365 |  | 
 | 366 |   // We didn't modify anything. | 
 | 367 |   return false; | 
 | 368 | } | 
 | 369 |  | 
| Brian Gaeke | a8b00ca | 2004-03-06 05:30:21 +0000 | [diff] [blame] | 370 |  | 
 | 371 | std::string LowercaseString (const std::string &S) { | 
 | 372 |   std::string result (S); | 
 | 373 |   for (unsigned i = 0; i < S.length(); ++i)  | 
 | 374 |     if (isupper (result[i])) | 
 | 375 |       result[i] = tolower(result[i]); | 
 | 376 |   return result; | 
 | 377 | } | 
 | 378 |  | 
| Brian Gaeke | 446ae11 | 2004-06-15 19:52:59 +0000 | [diff] [blame^] | 379 | void V8Printer::printOperand(const MachineInstr *MI, int opNum) { | 
 | 380 |   const MachineOperand &MO = MI->getOperand (opNum); | 
| Brian Gaeke | 62aa28a | 2004-03-05 08:39:09 +0000 | [diff] [blame] | 381 |   const MRegisterInfo &RI = *TM.getRegisterInfo(); | 
| Brian Gaeke | 446ae11 | 2004-06-15 19:52:59 +0000 | [diff] [blame^] | 382 |   bool CloseParen = false; | 
 | 383 |   if (MI->getOpcode() == V8::SETHIi && !MO.isRegister() && !MO.isImmediate()) { | 
 | 384 |     O << "%hi("; | 
 | 385 |     CloseParen = true; | 
 | 386 |   } else if (MI->getOpcode() ==V8::ORri &&!MO.isRegister() &&!MO.isImmediate()) { | 
 | 387 |     O << "%lo("; | 
 | 388 |     CloseParen = true; | 
 | 389 |   } | 
| Brian Gaeke | 62aa28a | 2004-03-05 08:39:09 +0000 | [diff] [blame] | 390 |   switch (MO.getType()) { | 
 | 391 |   case MachineOperand::MO_VirtualRegister: | 
 | 392 |     if (Value *V = MO.getVRegValueOrNull()) { | 
 | 393 |       O << "<" << V->getName() << ">"; | 
| Brian Gaeke | 446ae11 | 2004-06-15 19:52:59 +0000 | [diff] [blame^] | 394 |       break; | 
| Brian Gaeke | 62aa28a | 2004-03-05 08:39:09 +0000 | [diff] [blame] | 395 |     } | 
 | 396 |     // FALLTHROUGH | 
 | 397 |   case MachineOperand::MO_MachineRegister: | 
 | 398 |     if (MRegisterInfo::isPhysicalRegister(MO.getReg())) | 
| Brian Gaeke | a8b00ca | 2004-03-06 05:30:21 +0000 | [diff] [blame] | 399 |       O << "%" << LowercaseString (RI.get(MO.getReg()).Name); | 
| Brian Gaeke | 62aa28a | 2004-03-05 08:39:09 +0000 | [diff] [blame] | 400 |     else | 
 | 401 |       O << "%reg" << MO.getReg(); | 
| Brian Gaeke | 446ae11 | 2004-06-15 19:52:59 +0000 | [diff] [blame^] | 402 |     break; | 
| Brian Gaeke | 62aa28a | 2004-03-05 08:39:09 +0000 | [diff] [blame] | 403 |  | 
 | 404 |   case MachineOperand::MO_SignExtendedImmed: | 
 | 405 |   case MachineOperand::MO_UnextendedImmed: | 
 | 406 |     O << (int)MO.getImmedValue(); | 
| Brian Gaeke | 446ae11 | 2004-06-15 19:52:59 +0000 | [diff] [blame^] | 407 |     break; | 
| Brian Gaeke | 62aa28a | 2004-03-05 08:39:09 +0000 | [diff] [blame] | 408 |   case MachineOperand::MO_PCRelativeDisp: { | 
| Brian Gaeke | a778ca5 | 2004-04-02 20:53:35 +0000 | [diff] [blame] | 409 |     if (isa<GlobalValue> (MO.getVRegValue ())) { | 
 | 410 |       O << Mang->getValueName (MO.getVRegValue ()); | 
| Brian Gaeke | 446ae11 | 2004-06-15 19:52:59 +0000 | [diff] [blame^] | 411 |       break; | 
| Brian Gaeke | a778ca5 | 2004-04-02 20:53:35 +0000 | [diff] [blame] | 412 |     } | 
 | 413 |     assert (isa<BasicBlock> (MO.getVRegValue ()) | 
 | 414 |       && "Trying to look up something which is not a BB in the NumberForBB map"); | 
| Brian Gaeke | 62aa28a | 2004-03-05 08:39:09 +0000 | [diff] [blame] | 415 |     ValueMapTy::const_iterator i = NumberForBB.find(MO.getVRegValue()); | 
 | 416 |     assert (i != NumberForBB.end() | 
 | 417 |             && "Could not find a BB in the NumberForBB map!"); | 
| Brian Gaeke | 79db740 | 2004-03-16 22:37:12 +0000 | [diff] [blame] | 418 |     O << ".LBB" << i->second << " ! PC rel: " << MO.getVRegValue()->getName(); | 
| Brian Gaeke | 446ae11 | 2004-06-15 19:52:59 +0000 | [diff] [blame^] | 419 |     break; | 
| Brian Gaeke | 62aa28a | 2004-03-05 08:39:09 +0000 | [diff] [blame] | 420 |   } | 
 | 421 |   case MachineOperand::MO_GlobalAddress: | 
 | 422 |     O << Mang->getValueName(MO.getGlobal()); | 
| Brian Gaeke | 446ae11 | 2004-06-15 19:52:59 +0000 | [diff] [blame^] | 423 |     break; | 
| Brian Gaeke | 62aa28a | 2004-03-05 08:39:09 +0000 | [diff] [blame] | 424 |   case MachineOperand::MO_ExternalSymbol: | 
 | 425 |     O << MO.getSymbolName(); | 
| Brian Gaeke | 446ae11 | 2004-06-15 19:52:59 +0000 | [diff] [blame^] | 426 |     break; | 
| Brian Gaeke | 62aa28a | 2004-03-05 08:39:09 +0000 | [diff] [blame] | 427 |   default: | 
| Brian Gaeke | 446ae11 | 2004-06-15 19:52:59 +0000 | [diff] [blame^] | 428 |     O << "<unknown operand type>"; break;     | 
| Brian Gaeke | 62aa28a | 2004-03-05 08:39:09 +0000 | [diff] [blame] | 429 |   } | 
| Brian Gaeke | 446ae11 | 2004-06-15 19:52:59 +0000 | [diff] [blame^] | 430 |   if (CloseParen) O << ")"; | 
| Brian Gaeke | 62aa28a | 2004-03-05 08:39:09 +0000 | [diff] [blame] | 431 | } | 
 | 432 |  | 
| Brian Gaeke | 1c38175 | 2004-04-06 22:10:11 +0000 | [diff] [blame] | 433 | static bool isLoadInstruction (const MachineInstr *MI) { | 
 | 434 |   switch (MI->getOpcode ()) { | 
 | 435 |   case V8::LDSBmr: | 
 | 436 |   case V8::LDSHmr: | 
 | 437 |   case V8::LDUBmr: | 
 | 438 |   case V8::LDUHmr: | 
 | 439 |   case V8::LDmr: | 
 | 440 |   case V8::LDDmr: | 
 | 441 |     return true; | 
 | 442 |   default: | 
 | 443 |     return false; | 
 | 444 |   } | 
 | 445 | } | 
 | 446 |  | 
 | 447 | static bool isStoreInstruction (const MachineInstr *MI) { | 
 | 448 |   switch (MI->getOpcode ()) { | 
 | 449 |   case V8::STBrm: | 
 | 450 |   case V8::STHrm: | 
 | 451 |   case V8::STrm: | 
 | 452 |   case V8::STDrm: | 
 | 453 |     return true; | 
 | 454 |   default: | 
 | 455 |     return false; | 
 | 456 |   } | 
 | 457 | } | 
 | 458 |  | 
 | 459 | void V8Printer::printBaseOffsetPair (const MachineInstr *MI, int i) { | 
 | 460 |   O << "["; | 
| Brian Gaeke | 446ae11 | 2004-06-15 19:52:59 +0000 | [diff] [blame^] | 461 |   printOperand (MI, i); | 
| Brian Gaeke | 1c38175 | 2004-04-06 22:10:11 +0000 | [diff] [blame] | 462 |   assert (MI->getOperand (i + 1).isImmediate() | 
 | 463 |     && "2nd half of base-offset pair must be immediate-value machine operand"); | 
 | 464 |   int Val = (int) MI->getOperand (i + 1).getImmedValue (); | 
| Brian Gaeke | 8005ed3 | 2004-04-07 17:33:56 +0000 | [diff] [blame] | 465 |   if (Val != 0) { | 
 | 466 |     O << ((Val >= 0) ? " + " : " - "); | 
 | 467 |     O << ((Val >= 0) ? Val : -Val); | 
 | 468 |   } | 
| Brian Gaeke | 1c38175 | 2004-04-06 22:10:11 +0000 | [diff] [blame] | 469 |   O << "]"; | 
 | 470 | } | 
 | 471 |  | 
| Brian Gaeke | 4acfd03 | 2004-03-04 06:00:41 +0000 | [diff] [blame] | 472 | /// printMachineInstruction -- Print out a single SparcV8 LLVM instruction | 
 | 473 | /// MI in GAS syntax to the current output stream. | 
 | 474 | /// | 
 | 475 | void V8Printer::printMachineInstruction(const MachineInstr *MI) { | 
 | 476 |   unsigned Opcode = MI->getOpcode(); | 
| Chris Lattner | 143e0ea | 2004-06-02 05:47:26 +0000 | [diff] [blame] | 477 |   const TargetInstrInfo &TII = *TM.getInstrInfo(); | 
| Brian Gaeke | 4acfd03 | 2004-03-04 06:00:41 +0000 | [diff] [blame] | 478 |   const TargetInstrDescriptor &Desc = TII.get(Opcode); | 
| Brian Gaeke | 62aa28a | 2004-03-05 08:39:09 +0000 | [diff] [blame] | 479 |   O << Desc.Name << " "; | 
 | 480 |    | 
| Brian Gaeke | 1c38175 | 2004-04-06 22:10:11 +0000 | [diff] [blame] | 481 |   // Printing memory instructions is a special case. | 
| Brian Gaeke | fa4bb09 | 2004-04-07 04:29:03 +0000 | [diff] [blame] | 482 |   // for loads:  %dest = op %base, offset --> op [%base + offset], %dest | 
 | 483 |   // for stores: op %src, %base, offset   --> op %src, [%base + offset] | 
| Brian Gaeke | 1c38175 | 2004-04-06 22:10:11 +0000 | [diff] [blame] | 484 |   if (isLoadInstruction (MI)) { | 
| Brian Gaeke | fa4bb09 | 2004-04-07 04:29:03 +0000 | [diff] [blame] | 485 |     printBaseOffsetPair (MI, 1); | 
| Brian Gaeke | 1c38175 | 2004-04-06 22:10:11 +0000 | [diff] [blame] | 486 |     O << ", "; | 
| Brian Gaeke | 446ae11 | 2004-06-15 19:52:59 +0000 | [diff] [blame^] | 487 |     printOperand (MI, 0); | 
| Brian Gaeke | 1c38175 | 2004-04-06 22:10:11 +0000 | [diff] [blame] | 488 |     O << "\n"; | 
 | 489 |     return; | 
 | 490 |   } else if (isStoreInstruction (MI)) { | 
| Brian Gaeke | 446ae11 | 2004-06-15 19:52:59 +0000 | [diff] [blame^] | 491 |     printOperand (MI, 0); | 
| Brian Gaeke | 1c38175 | 2004-04-06 22:10:11 +0000 | [diff] [blame] | 492 |     O << ", "; | 
 | 493 |     printBaseOffsetPair (MI, 1); | 
 | 494 |     O << "\n"; | 
 | 495 |     return; | 
 | 496 |   } | 
 | 497 |  | 
| Brian Gaeke | 62aa28a | 2004-03-05 08:39:09 +0000 | [diff] [blame] | 498 |   // print non-immediate, non-register-def operands | 
 | 499 |   // then print immediate operands | 
 | 500 |   // then print register-def operands. | 
| Brian Gaeke | 446ae11 | 2004-06-15 19:52:59 +0000 | [diff] [blame^] | 501 |   std::vector<int> print_order; | 
| Brian Gaeke | 62aa28a | 2004-03-05 08:39:09 +0000 | [diff] [blame] | 502 |   for (unsigned i = 0; i < MI->getNumOperands (); ++i) | 
 | 503 |     if (!(MI->getOperand (i).isImmediate () | 
 | 504 |           || (MI->getOperand (i).isRegister () | 
 | 505 |               && MI->getOperand (i).isDef ()))) | 
| Brian Gaeke | 446ae11 | 2004-06-15 19:52:59 +0000 | [diff] [blame^] | 506 |       print_order.push_back (i); | 
| Brian Gaeke | 62aa28a | 2004-03-05 08:39:09 +0000 | [diff] [blame] | 507 |   for (unsigned i = 0; i < MI->getNumOperands (); ++i) | 
 | 508 |     if (MI->getOperand (i).isImmediate ()) | 
| Brian Gaeke | 446ae11 | 2004-06-15 19:52:59 +0000 | [diff] [blame^] | 509 |       print_order.push_back (i); | 
| Brian Gaeke | 62aa28a | 2004-03-05 08:39:09 +0000 | [diff] [blame] | 510 |   for (unsigned i = 0; i < MI->getNumOperands (); ++i) | 
 | 511 |     if (MI->getOperand (i).isRegister () && MI->getOperand (i).isDef ()) | 
| Brian Gaeke | 446ae11 | 2004-06-15 19:52:59 +0000 | [diff] [blame^] | 512 |       print_order.push_back (i); | 
| Brian Gaeke | 62aa28a | 2004-03-05 08:39:09 +0000 | [diff] [blame] | 513 |   for (unsigned i = 0, e = print_order.size (); i != e; ++i) {  | 
| Brian Gaeke | 446ae11 | 2004-06-15 19:52:59 +0000 | [diff] [blame^] | 514 |     printOperand (MI, print_order[i]); | 
| Brian Gaeke | 62aa28a | 2004-03-05 08:39:09 +0000 | [diff] [blame] | 515 |     if (i != (print_order.size () - 1)) | 
 | 516 |       O << ", "; | 
 | 517 |   } | 
 | 518 |   O << "\n"; | 
| Brian Gaeke | 4acfd03 | 2004-03-04 06:00:41 +0000 | [diff] [blame] | 519 | } | 
 | 520 |  | 
 | 521 | bool V8Printer::doInitialization(Module &M) { | 
 | 522 |   Mang = new Mangler(M); | 
 | 523 |   return false; // success | 
 | 524 | } | 
 | 525 |  | 
 | 526 | // SwitchSection - Switch to the specified section of the executable if we are | 
 | 527 | // not already in it! | 
 | 528 | // | 
 | 529 | static void SwitchSection(std::ostream &OS, std::string &CurSection, | 
 | 530 |                           const char *NewSection) { | 
 | 531 |   if (CurSection != NewSection) { | 
 | 532 |     CurSection = NewSection; | 
 | 533 |     if (!CurSection.empty()) | 
 | 534 |       OS << "\t" << NewSection << "\n"; | 
 | 535 |   } | 
 | 536 | } | 
 | 537 |  | 
 | 538 | bool V8Printer::doFinalization(Module &M) { | 
 | 539 |   const TargetData &TD = TM.getTargetData(); | 
 | 540 |   std::string CurSection; | 
 | 541 |  | 
 | 542 |   // Print out module-level global variables here. | 
 | 543 |   for (Module::const_giterator I = M.gbegin(), E = M.gend(); I != E; ++I) | 
 | 544 |     if (I->hasInitializer()) {   // External global require no code | 
 | 545 |       O << "\n\n"; | 
 | 546 |       std::string name = Mang->getValueName(I); | 
 | 547 |       Constant *C = I->getInitializer(); | 
 | 548 |       unsigned Size = TD.getTypeSize(C->getType()); | 
 | 549 |       unsigned Align = TD.getTypeAlignment(C->getType()); | 
 | 550 |  | 
 | 551 |       if (C->isNullValue() &&  | 
 | 552 |           (I->hasLinkOnceLinkage() || I->hasInternalLinkage() || | 
 | 553 |            I->hasWeakLinkage() /* FIXME: Verify correct */)) { | 
 | 554 |         SwitchSection(O, CurSection, ".data"); | 
 | 555 |         if (I->hasInternalLinkage()) | 
 | 556 |           O << "\t.local " << name << "\n"; | 
 | 557 |          | 
 | 558 |         O << "\t.comm " << name << "," << TD.getTypeSize(C->getType()) | 
 | 559 |           << "," << (unsigned)TD.getTypeAlignment(C->getType()); | 
| Brian Gaeke | 79db740 | 2004-03-16 22:37:12 +0000 | [diff] [blame] | 560 |         O << "\t\t! "; | 
| Brian Gaeke | 4acfd03 | 2004-03-04 06:00:41 +0000 | [diff] [blame] | 561 |         WriteAsOperand(O, I, true, true, &M); | 
 | 562 |         O << "\n"; | 
 | 563 |       } else { | 
 | 564 |         switch (I->getLinkage()) { | 
 | 565 |         case GlobalValue::LinkOnceLinkage: | 
 | 566 |         case GlobalValue::WeakLinkage:   // FIXME: Verify correct for weak. | 
 | 567 |           // Nonnull linkonce -> weak | 
 | 568 |           O << "\t.weak " << name << "\n"; | 
 | 569 |           SwitchSection(O, CurSection, ""); | 
 | 570 |           O << "\t.section\t.llvm.linkonce.d." << name << ",\"aw\",@progbits\n"; | 
 | 571 |           break; | 
 | 572 |          | 
 | 573 |         case GlobalValue::AppendingLinkage: | 
 | 574 |           // FIXME: appending linkage variables should go into a section of | 
 | 575 |           // their name or something.  For now, just emit them as external. | 
 | 576 |         case GlobalValue::ExternalLinkage: | 
 | 577 |           // If external or appending, declare as a global symbol | 
 | 578 |           O << "\t.globl " << name << "\n"; | 
 | 579 |           // FALL THROUGH | 
 | 580 |         case GlobalValue::InternalLinkage: | 
 | 581 |           if (C->isNullValue()) | 
 | 582 |             SwitchSection(O, CurSection, ".bss"); | 
 | 583 |           else | 
 | 584 |             SwitchSection(O, CurSection, ".data"); | 
 | 585 |           break; | 
 | 586 |         } | 
 | 587 |  | 
 | 588 |         O << "\t.align " << Align << "\n"; | 
| Brian Gaeke | 54cc3c2 | 2004-03-16 22:52:04 +0000 | [diff] [blame] | 589 |         O << "\t.type " << name << ",#object\n"; | 
| Brian Gaeke | 4acfd03 | 2004-03-04 06:00:41 +0000 | [diff] [blame] | 590 |         O << "\t.size " << name << "," << Size << "\n"; | 
| Brian Gaeke | 79db740 | 2004-03-16 22:37:12 +0000 | [diff] [blame] | 591 |         O << name << ":\t\t\t\t! "; | 
| Brian Gaeke | 4acfd03 | 2004-03-04 06:00:41 +0000 | [diff] [blame] | 592 |         WriteAsOperand(O, I, true, true, &M); | 
 | 593 |         O << " = "; | 
 | 594 |         WriteAsOperand(O, C, false, false, &M); | 
 | 595 |         O << "\n"; | 
 | 596 |         emitGlobalConstant(C); | 
 | 597 |       } | 
 | 598 |     } | 
 | 599 |  | 
 | 600 |   delete Mang; | 
 | 601 |   return false; // success | 
 | 602 | } |