SparcAsmPrinter.cpp revision b5e9eb6089676ba807da70348079fb6e8df3e40e
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/AsmPrinter.h" 22#include "llvm/CodeGen/MachineFunctionPass.h" 23#include "llvm/CodeGen/MachineConstantPool.h" 24#include "llvm/CodeGen/MachineInstr.h" 25#include "llvm/Target/TargetMachine.h" 26#include "llvm/Support/Mangler.h" 27#include "llvm/ADT/Statistic.h" 28#include "llvm/ADT/StringExtras.h" 29#include "llvm/Support/CommandLine.h" 30#include "llvm/Support/MathExtras.h" 31#include <cctype> 32using namespace llvm; 33 34namespace { 35 Statistic<> EmittedInsts("asm-printer", "Number of machine instrs printed"); 36 37 struct SparcV8AsmPrinter : public AsmPrinter { 38 SparcV8AsmPrinter(std::ostream &O, TargetMachine &TM) : AsmPrinter(O, TM) { 39 Data16bitsDirective = "\t.half\t"; 40 Data32bitsDirective = "\t.word\t"; 41 Data64bitsDirective = "\t.xword\t"; 42 } 43 44 /// We name each basic block in a Function with a unique number, so 45 /// that we can consistently refer to them later. This is cleared 46 /// at the beginning of each call to runOnMachineFunction(). 47 /// 48 typedef std::map<const Value *, unsigned> ValueMapTy; 49 ValueMapTy NumberForBB; 50 51 virtual const char *getPassName() const { 52 return "SparcV8 Assembly Printer"; 53 } 54 55 void emitConstantValueOnly(const Constant *CV); 56 void emitGlobalConstant(const Constant *CV); 57 void printOperand(const MachineInstr *MI, int opNum); 58 bool printInstruction(const MachineInstr *MI); // autogenerated. 59 bool runOnMachineFunction(MachineFunction &F); 60 bool doInitialization(Module &M); 61 bool doFinalization(Module &M); 62 }; 63} // end of anonymous namespace 64 65#include "SparcV8GenAsmWriter.inc" 66 67/// createSparcV8CodePrinterPass - Returns a pass that prints the SparcV8 68/// assembly code for a MachineFunction to the given output stream, 69/// using the given target machine description. This should work 70/// regardless of whether the function is in SSA form. 71/// 72FunctionPass *llvm::createSparcV8CodePrinterPass (std::ostream &o, 73 TargetMachine &tm) { 74 return new SparcV8AsmPrinter(o, tm); 75} 76 77/// toOctal - Convert the low order bits of X into an octal digit. 78/// 79static inline char toOctal(int X) { 80 return (X&7)+'0'; 81} 82 83/// getAsCString - Return the specified array as a C compatible 84/// string, only if the predicate isStringCompatible is true. 85/// 86static void printAsCString(std::ostream &O, const ConstantArray *CVA) { 87 assert(CVA->isString() && "Array is not string compatible!"); 88 89 O << "\""; 90 for (unsigned i = 0; i != CVA->getNumOperands(); ++i) { 91 unsigned char C = cast<ConstantInt>(CVA->getOperand(i))->getRawValue(); 92 93 if (C == '"') { 94 O << "\\\""; 95 } else if (C == '\\') { 96 O << "\\\\"; 97 } else if (isprint(C)) { 98 O << C; 99 } else { 100 switch(C) { 101 case '\b': O << "\\b"; break; 102 case '\f': O << "\\f"; break; 103 case '\n': O << "\\n"; break; 104 case '\r': O << "\\r"; break; 105 case '\t': O << "\\t"; break; 106 default: 107 O << '\\'; 108 O << toOctal(C >> 6); 109 O << toOctal(C >> 3); 110 O << toOctal(C >> 0); 111 break; 112 } 113 } 114 } 115 O << "\""; 116} 117 118// Print out the specified constant, without a storage class. Only the 119// constants valid in constant expressions can occur here. 120void SparcV8AsmPrinter::emitConstantValueOnly(const Constant *CV) { 121 if (CV->isNullValue() || isa<UndefValue> (CV)) 122 O << "0"; 123 else if (const ConstantBool *CB = dyn_cast<ConstantBool>(CV)) { 124 assert(CB == ConstantBool::True); 125 O << "1"; 126 } else if (const ConstantSInt *CI = dyn_cast<ConstantSInt>(CV)) 127 if (((CI->getValue() << 32) >> 32) == CI->getValue()) 128 O << CI->getValue(); 129 else 130 O << (unsigned long long)CI->getValue(); 131 else if (const ConstantUInt *CI = dyn_cast<ConstantUInt>(CV)) 132 O << CI->getValue(); 133 else if (const GlobalValue *GV = dyn_cast<GlobalValue>(CV)) 134 // This is a constant address for a global variable or function. Use the 135 // name of the variable or function as the address value. 136 O << Mang->getValueName(GV); 137 else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV)) { 138 const TargetData &TD = TM.getTargetData(); 139 switch(CE->getOpcode()) { 140 case Instruction::GetElementPtr: { 141 // generate a symbolic expression for the byte address 142 const Constant *ptrVal = CE->getOperand(0); 143 std::vector<Value*> idxVec(CE->op_begin()+1, CE->op_end()); 144 if (unsigned Offset = TD.getIndexedOffset(ptrVal->getType(), idxVec)) { 145 O << "("; 146 emitConstantValueOnly(ptrVal); 147 O << ") + " << Offset; 148 } else { 149 emitConstantValueOnly(ptrVal); 150 } 151 break; 152 } 153 case Instruction::Cast: { 154 // Support only non-converting or widening casts for now, that is, ones 155 // that do not involve a change in value. This assertion is really gross, 156 // and may not even be a complete check. 157 Constant *Op = CE->getOperand(0); 158 const Type *OpTy = Op->getType(), *Ty = CE->getType(); 159 160 // Pointers on ILP32 machines can be losslessly converted back and 161 // forth into 32-bit or wider integers, regardless of signedness. 162 assert(((isa<PointerType>(OpTy) 163 && (Ty == Type::LongTy || Ty == Type::ULongTy 164 || Ty == Type::IntTy || Ty == Type::UIntTy)) 165 || (isa<PointerType>(Ty) 166 && (OpTy == Type::LongTy || OpTy == Type::ULongTy 167 || OpTy == Type::IntTy || OpTy == Type::UIntTy)) 168 || (((TD.getTypeSize(Ty) >= TD.getTypeSize(OpTy)) 169 && OpTy->isLosslesslyConvertibleTo(Ty)))) 170 && "FIXME: Don't yet support this kind of constant cast expr"); 171 O << "("; 172 emitConstantValueOnly(Op); 173 O << ")"; 174 break; 175 } 176 case Instruction::Add: 177 O << "("; 178 emitConstantValueOnly(CE->getOperand(0)); 179 O << ") + ("; 180 emitConstantValueOnly(CE->getOperand(1)); 181 O << ")"; 182 break; 183 default: 184 assert(0 && "Unsupported operator!"); 185 } 186 } else { 187 assert(0 && "Unknown constant value!"); 188 } 189} 190 191// Print a constant value or values, with the appropriate storage class as a 192// prefix. 193void SparcV8AsmPrinter::emitGlobalConstant(const Constant *CV) { 194 const TargetData &TD = TM.getTargetData(); 195 196 if (const ConstantArray *CVA = dyn_cast<ConstantArray>(CV)) { 197 if (CVA->isString()) { 198 O << "\t.ascii\t"; 199 printAsCString(O, CVA); 200 O << "\n"; 201 } else { // Not a string. Print the values in successive locations 202 for (unsigned i = 0, e = CVA->getNumOperands(); i != e; i++) 203 emitGlobalConstant(CVA->getOperand(i)); 204 } 205 return; 206 } else if (const ConstantStruct *CVS = dyn_cast<ConstantStruct>(CV)) { 207 // Print the fields in successive locations. Pad to align if needed! 208 const StructLayout *cvsLayout = TD.getStructLayout(CVS->getType()); 209 unsigned sizeSoFar = 0; 210 for (unsigned i = 0, e = CVS->getNumOperands(); i != e; i++) { 211 const Constant* field = CVS->getOperand(i); 212 213 // Check if padding is needed and insert one or more 0s. 214 unsigned fieldSize = TD.getTypeSize(field->getType()); 215 unsigned padSize = ((i == e-1? cvsLayout->StructSize 216 : cvsLayout->MemberOffsets[i+1]) 217 - cvsLayout->MemberOffsets[i]) - fieldSize; 218 sizeSoFar += fieldSize + padSize; 219 220 // Now print the actual field value 221 emitGlobalConstant(field); 222 223 // Insert the field padding unless it's zero bytes... 224 if (padSize) 225 O << "\t.skip\t " << padSize << "\n"; 226 } 227 assert(sizeSoFar == cvsLayout->StructSize && 228 "Layout of constant struct may be incorrect!"); 229 return; 230 } else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV)) { 231 // FP Constants are printed as integer constants to avoid losing 232 // precision... 233 double Val = CFP->getValue(); 234 switch (CFP->getType()->getTypeID()) { 235 default: assert(0 && "Unknown floating point type!"); 236 case Type::FloatTyID: { 237 O << ".long\t" << FloatToBits(Val) << "\t! float " << Val << "\n"; 238 return; 239 } 240 case Type::DoubleTyID: { 241 O << ".word\t0x" << std::hex << (DoubleToBits(Val) >> 32) << std::dec << "\t! double " << Val << "\n"; 242 O << ".word\t0x" << std::hex << (DoubleToBits(Val) & 0xffffffffUL) << std::dec << "\t! double " << Val << "\n"; 243 return; 244 } 245 } 246 } else if (isa<UndefValue> (CV)) { 247 unsigned size = TD.getTypeSize (CV->getType ()); 248 O << "\t.skip\t " << size << "\n"; 249 return; 250 } else if (isa<ConstantAggregateZero> (CV)) { 251 unsigned size = TD.getTypeSize (CV->getType ()); 252 for (unsigned i = 0; i < size; ++i) 253 O << "\t.byte 0\n"; 254 return; 255 } 256 257 const Type *type = CV->getType(); 258 O << "\t"; 259 switch (type->getTypeID()) { 260 case Type::BoolTyID: case Type::UByteTyID: case Type::SByteTyID: 261 O << ".byte"; 262 break; 263 case Type::UShortTyID: case Type::ShortTyID: 264 O << ".half"; 265 break; 266 case Type::FloatTyID: case Type::PointerTyID: 267 case Type::UIntTyID: case Type::IntTyID: 268 O << ".word"; 269 break; 270 case Type::DoubleTyID: 271 case Type::ULongTyID: case Type::LongTyID: 272 O << ".xword"; 273 break; 274 default: 275 assert (0 && "Can't handle printing this type of thing"); 276 break; 277 } 278 O << "\t"; 279 emitConstantValueOnly(CV); 280 O << "\n"; 281} 282 283/// runOnMachineFunction - This uses the printMachineInstruction() 284/// method to print assembly for each instruction. 285/// 286bool SparcV8AsmPrinter::runOnMachineFunction(MachineFunction &MF) { 287 SetupMachineFunction(MF); 288 289 // Print out constants referenced by the function 290 EmitConstantPool(MF.getConstantPool()); 291 292 // BBNumber is used here so that a given Printer will never give two 293 // BBs the same name. (If you have a better way, please let me know!) 294 static unsigned BBNumber = 0; 295 296 O << "\n\n"; 297 // What's my mangled name? 298 CurrentFnName = Mang->getValueName(MF.getFunction()); 299 300 // Print out labels for the function. 301 O << "\t.text\n"; 302 O << "\t.align 16\n"; 303 O << "\t.globl\t" << CurrentFnName << "\n"; 304 O << "\t.type\t" << CurrentFnName << ", #function\n"; 305 O << CurrentFnName << ":\n"; 306 307 // Number each basic block so that we can consistently refer to them 308 // in PC-relative references. 309 NumberForBB.clear(); 310 for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); 311 I != E; ++I) { 312 NumberForBB[I->getBasicBlock()] = BBNumber++; 313 } 314 315 // Print out code for the function. 316 for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); 317 I != E; ++I) { 318 // Print a label for the basic block. 319 O << ".LBB" << Mang->getValueName(MF.getFunction ()) 320 << "_" << I->getNumber () << ":\t! " 321 << I->getBasicBlock ()->getName () << "\n"; 322 for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end(); 323 II != E; ++II) { 324 // Print the assembly for the instruction. 325 O << "\t"; 326 printInstruction(II); 327 ++EmittedInsts; 328 } 329 } 330 331 // We didn't modify anything. 332 return false; 333} 334 335void SparcV8AsmPrinter::printOperand(const MachineInstr *MI, int opNum) { 336 const MachineOperand &MO = MI->getOperand (opNum); 337 const MRegisterInfo &RI = *TM.getRegisterInfo(); 338 bool CloseParen = false; 339 if (MI->getOpcode() == V8::SETHIi && !MO.isRegister() && !MO.isImmediate()) { 340 O << "%hi("; 341 CloseParen = true; 342 } else if (MI->getOpcode() ==V8::ORri &&!MO.isRegister() &&!MO.isImmediate()) 343 { 344 O << "%lo("; 345 CloseParen = true; 346 } 347 switch (MO.getType()) { 348 case MachineOperand::MO_VirtualRegister: 349 if (Value *V = MO.getVRegValueOrNull()) { 350 O << "<" << V->getName() << ">"; 351 break; 352 } 353 // FALLTHROUGH 354 case MachineOperand::MO_MachineRegister: 355 if (MRegisterInfo::isPhysicalRegister(MO.getReg())) 356 O << "%" << LowercaseString (RI.get(MO.getReg()).Name); 357 else 358 O << "%reg" << MO.getReg(); 359 break; 360 361 case MachineOperand::MO_SignExtendedImmed: 362 case MachineOperand::MO_UnextendedImmed: 363 O << (int)MO.getImmedValue(); 364 break; 365 case MachineOperand::MO_MachineBasicBlock: { 366 MachineBasicBlock *MBBOp = MO.getMachineBasicBlock(); 367 O << ".LBB" << Mang->getValueName(MBBOp->getParent()->getFunction()) 368 << "_" << MBBOp->getNumber () << "\t! " 369 << MBBOp->getBasicBlock ()->getName (); 370 return; 371 } 372 case MachineOperand::MO_PCRelativeDisp: 373 std::cerr << "Shouldn't use addPCDisp() when building SparcV8 MachineInstrs"; 374 abort (); 375 return; 376 case MachineOperand::MO_GlobalAddress: 377 O << Mang->getValueName(MO.getGlobal()); 378 break; 379 case MachineOperand::MO_ExternalSymbol: 380 O << MO.getSymbolName(); 381 break; 382 case MachineOperand::MO_ConstantPoolIndex: 383 O << PrivateGlobalPrefix << "CPI" << getFunctionNumber() << "_" 384 << MO.getConstantPoolIndex(); 385 break; 386 default: 387 O << "<unknown operand type>"; abort (); break; 388 } 389 if (CloseParen) O << ")"; 390} 391 392bool SparcV8AsmPrinter::doInitialization(Module &M) { 393 Mang = new Mangler(M); 394 return false; // success 395} 396 397bool SparcV8AsmPrinter::doFinalization(Module &M) { 398 const TargetData &TD = TM.getTargetData(); 399 400 // Print out module-level global variables here. 401 for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) 402 if (I->hasInitializer()) { // External global require no code 403 O << "\n\n"; 404 std::string name = Mang->getValueName(I); 405 Constant *C = I->getInitializer(); 406 unsigned Size = TD.getTypeSize(C->getType()); 407 unsigned Align = TD.getTypeAlignment(C->getType()); 408 409 if (C->isNullValue() && 410 (I->hasLinkOnceLinkage() || I->hasInternalLinkage() || 411 I->hasWeakLinkage() /* FIXME: Verify correct */)) { 412 SwitchSection(".data", I); 413 if (I->hasInternalLinkage()) 414 O << "\t.local " << name << "\n"; 415 416 O << "\t.comm " << name << "," << TD.getTypeSize(C->getType()) 417 << "," << (unsigned)TD.getTypeAlignment(C->getType()); 418 O << "\t\t! "; 419 WriteAsOperand(O, I, true, true, &M); 420 O << "\n"; 421 } else { 422 switch (I->getLinkage()) { 423 case GlobalValue::LinkOnceLinkage: 424 case GlobalValue::WeakLinkage: // FIXME: Verify correct for weak. 425 // Nonnull linkonce -> weak 426 O << "\t.weak " << name << "\n"; 427 SwitchSection("", I); 428 O << "\t.section\t\".llvm.linkonce.d." << name 429 << "\",\"aw\",@progbits\n"; 430 break; 431 432 case GlobalValue::AppendingLinkage: 433 // FIXME: appending linkage variables should go into a section of 434 // their name or something. For now, just emit them as external. 435 case GlobalValue::ExternalLinkage: 436 // If external or appending, declare as a global symbol 437 O << "\t.globl " << name << "\n"; 438 // FALL THROUGH 439 case GlobalValue::InternalLinkage: 440 if (C->isNullValue()) 441 SwitchSection(".bss", I); 442 else 443 SwitchSection(".data", I); 444 break; 445 case GlobalValue::GhostLinkage: 446 std::cerr << "Should not have any unmaterialized functions!\n"; 447 abort(); 448 } 449 450 O << "\t.align " << Align << "\n"; 451 O << "\t.type " << name << ",#object\n"; 452 O << "\t.size " << name << "," << Size << "\n"; 453 O << name << ":\t\t\t\t! "; 454 WriteAsOperand(O, I, true, true, &M); 455 O << " = "; 456 WriteAsOperand(O, C, false, false, &M); 457 O << "\n"; 458 emitGlobalConstant(C); 459 } 460 } 461 462 AsmPrinter::doFinalization(M); 463 return false; // success 464} 465