AsmWriterEmitter.cpp revision f64f9a4b75d07819866bfcf918b922a76d3e1600
1//===- AsmWriterEmitter.cpp - Generate an 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 tablegen backend is emits an assembly printer for the current target. 11// Note that this is currently fairly skeletal, but will grow over time. 12// 13//===----------------------------------------------------------------------===// 14 15#include "AsmWriterEmitter.h" 16#include "CodeGenTarget.h" 17#include "Record.h" 18#include "llvm/ADT/StringExtras.h" 19#include "llvm/Support/Debug.h" 20#include "llvm/Support/MathExtras.h" 21#include <algorithm> 22#include <ostream> 23using namespace llvm; 24 25static bool isIdentChar(char C) { 26 return (C >= 'a' && C <= 'z') || 27 (C >= 'A' && C <= 'Z') || 28 (C >= '0' && C <= '9') || 29 C == '_'; 30} 31 32namespace { 33 struct AsmWriterOperand { 34 enum { isLiteralTextOperand, isMachineInstrOperand } OperandType; 35 36 /// Str - For isLiteralTextOperand, this IS the literal text. For 37 /// isMachineInstrOperand, this is the PrinterMethodName for the operand. 38 std::string Str; 39 40 /// MiOpNo - For isMachineInstrOperand, this is the operand number of the 41 /// machine instruction. 42 unsigned MIOpNo; 43 44 /// MiModifier - For isMachineInstrOperand, this is the modifier string for 45 /// an operand, specified with syntax like ${opname:modifier}. 46 std::string MiModifier; 47 48 AsmWriterOperand(const std::string &LitStr) 49 : OperandType(isLiteralTextOperand), Str(LitStr) {} 50 51 AsmWriterOperand(const std::string &Printer, unsigned OpNo, 52 const std::string &Modifier) 53 : OperandType(isMachineInstrOperand), Str(Printer), MIOpNo(OpNo), 54 MiModifier(Modifier) {} 55 56 bool operator!=(const AsmWriterOperand &Other) const { 57 if (OperandType != Other.OperandType || Str != Other.Str) return true; 58 if (OperandType == isMachineInstrOperand) 59 return MIOpNo != Other.MIOpNo || MiModifier != Other.MiModifier; 60 return false; 61 } 62 bool operator==(const AsmWriterOperand &Other) const { 63 return !operator!=(Other); 64 } 65 66 /// getCode - Return the code that prints this operand. 67 std::string getCode() const; 68 }; 69} 70 71namespace llvm { 72 class AsmWriterInst { 73 public: 74 std::vector<AsmWriterOperand> Operands; 75 const CodeGenInstruction *CGI; 76 77 AsmWriterInst(const CodeGenInstruction &CGI, unsigned Variant); 78 79 /// MatchesAllButOneOp - If this instruction is exactly identical to the 80 /// specified instruction except for one differing operand, return the 81 /// differing operand number. Otherwise return ~0. 82 unsigned MatchesAllButOneOp(const AsmWriterInst &Other) const; 83 84 private: 85 void AddLiteralString(const std::string &Str) { 86 // If the last operand was already a literal text string, append this to 87 // it, otherwise add a new operand. 88 if (!Operands.empty() && 89 Operands.back().OperandType == AsmWriterOperand::isLiteralTextOperand) 90 Operands.back().Str.append(Str); 91 else 92 Operands.push_back(AsmWriterOperand(Str)); 93 } 94 }; 95} 96 97 98std::string AsmWriterOperand::getCode() const { 99 if (OperandType == isLiteralTextOperand) 100 return "O << \"" + Str + "\"; "; 101 102 std::string Result = Str + "(MI"; 103 if (MIOpNo != ~0U) 104 Result += ", " + utostr(MIOpNo); 105 if (!MiModifier.empty()) 106 Result += ", \"" + MiModifier + '"'; 107 return Result + "); "; 108} 109 110 111/// ParseAsmString - Parse the specified Instruction's AsmString into this 112/// AsmWriterInst. 113/// 114AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, unsigned Variant) { 115 this->CGI = &CGI; 116 unsigned CurVariant = ~0U; // ~0 if we are outside a {.|.|.} region, other #. 117 118 // NOTE: Any extensions to this code need to be mirrored in the 119 // AsmPrinter::printInlineAsm code that executes as compile time (assuming 120 // that inline asm strings should also get the new feature)! 121 const std::string &AsmString = CGI.AsmString; 122 std::string::size_type LastEmitted = 0; 123 while (LastEmitted != AsmString.size()) { 124 std::string::size_type DollarPos = 125 AsmString.find_first_of("${|}", LastEmitted); 126 if (DollarPos == std::string::npos) DollarPos = AsmString.size(); 127 128 // Emit a constant string fragment. 129 if (DollarPos != LastEmitted) { 130 // TODO: this should eventually handle escaping. 131 if (CurVariant == Variant || CurVariant == ~0U) 132 AddLiteralString(std::string(AsmString.begin()+LastEmitted, 133 AsmString.begin()+DollarPos)); 134 LastEmitted = DollarPos; 135 } else if (AsmString[DollarPos] == '{') { 136 if (CurVariant != ~0U) 137 throw "Nested variants found for instruction '" + 138 CGI.TheDef->getName() + "'!"; 139 LastEmitted = DollarPos+1; 140 CurVariant = 0; // We are now inside of the variant! 141 } else if (AsmString[DollarPos] == '|') { 142 if (CurVariant == ~0U) 143 throw "'|' character found outside of a variant in instruction '" 144 + CGI.TheDef->getName() + "'!"; 145 ++CurVariant; 146 ++LastEmitted; 147 } else if (AsmString[DollarPos] == '}') { 148 if (CurVariant == ~0U) 149 throw "'}' character found outside of a variant in instruction '" 150 + CGI.TheDef->getName() + "'!"; 151 ++LastEmitted; 152 CurVariant = ~0U; 153 } else if (DollarPos+1 != AsmString.size() && 154 AsmString[DollarPos+1] == '$') { 155 if (CurVariant == Variant || CurVariant == ~0U) 156 AddLiteralString("$"); // "$$" -> $ 157 LastEmitted = DollarPos+2; 158 } else { 159 // Get the name of the variable. 160 std::string::size_type VarEnd = DollarPos+1; 161 162 // handle ${foo}bar as $foo by detecting whether the character following 163 // the dollar sign is a curly brace. If so, advance VarEnd and DollarPos 164 // so the variable name does not contain the leading curly brace. 165 bool hasCurlyBraces = false; 166 if (VarEnd < AsmString.size() && '{' == AsmString[VarEnd]) { 167 hasCurlyBraces = true; 168 ++DollarPos; 169 ++VarEnd; 170 } 171 172 while (VarEnd < AsmString.size() && isIdentChar(AsmString[VarEnd])) 173 ++VarEnd; 174 std::string VarName(AsmString.begin()+DollarPos+1, 175 AsmString.begin()+VarEnd); 176 177 // Modifier - Support ${foo:modifier} syntax, where "modifier" is passed 178 // into printOperand. Also support ${:feature}, which is passed into 179 // PrintSpecial. 180 std::string Modifier; 181 182 // In order to avoid starting the next string at the terminating curly 183 // brace, advance the end position past it if we found an opening curly 184 // brace. 185 if (hasCurlyBraces) { 186 if (VarEnd >= AsmString.size()) 187 throw "Reached end of string before terminating curly brace in '" 188 + CGI.TheDef->getName() + "'"; 189 190 // Look for a modifier string. 191 if (AsmString[VarEnd] == ':') { 192 ++VarEnd; 193 if (VarEnd >= AsmString.size()) 194 throw "Reached end of string before terminating curly brace in '" 195 + CGI.TheDef->getName() + "'"; 196 197 unsigned ModifierStart = VarEnd; 198 while (VarEnd < AsmString.size() && isIdentChar(AsmString[VarEnd])) 199 ++VarEnd; 200 Modifier = std::string(AsmString.begin()+ModifierStart, 201 AsmString.begin()+VarEnd); 202 if (Modifier.empty()) 203 throw "Bad operand modifier name in '"+ CGI.TheDef->getName() + "'"; 204 } 205 206 if (AsmString[VarEnd] != '}') 207 throw "Variable name beginning with '{' did not end with '}' in '" 208 + CGI.TheDef->getName() + "'"; 209 ++VarEnd; 210 } 211 if (VarName.empty() && Modifier.empty()) 212 throw "Stray '$' in '" + CGI.TheDef->getName() + 213 "' asm string, maybe you want $$?"; 214 215 if (VarName.empty()) { 216 // Just a modifier, pass this into PrintSpecial. 217 Operands.push_back(AsmWriterOperand("PrintSpecial", ~0U, Modifier)); 218 } else { 219 // Otherwise, normal operand. 220 unsigned OpNo = CGI.getOperandNamed(VarName); 221 CodeGenInstruction::OperandInfo OpInfo = CGI.OperandList[OpNo]; 222 223 if (CurVariant == Variant || CurVariant == ~0U) { 224 unsigned MIOp = OpInfo.MIOperandNo; 225 Operands.push_back(AsmWriterOperand(OpInfo.PrinterMethodName, MIOp, 226 Modifier)); 227 } 228 } 229 LastEmitted = VarEnd; 230 } 231 } 232 233 AddLiteralString("\\n"); 234} 235 236/// MatchesAllButOneOp - If this instruction is exactly identical to the 237/// specified instruction except for one differing operand, return the differing 238/// operand number. If more than one operand mismatches, return ~1, otherwise 239/// if the instructions are identical return ~0. 240unsigned AsmWriterInst::MatchesAllButOneOp(const AsmWriterInst &Other)const{ 241 if (Operands.size() != Other.Operands.size()) return ~1; 242 243 unsigned MismatchOperand = ~0U; 244 for (unsigned i = 0, e = Operands.size(); i != e; ++i) { 245 if (Operands[i] != Other.Operands[i]) 246 if (MismatchOperand != ~0U) // Already have one mismatch? 247 return ~1U; 248 else 249 MismatchOperand = i; 250 } 251 return MismatchOperand; 252} 253 254static void PrintCases(std::vector<std::pair<std::string, 255 AsmWriterOperand> > &OpsToPrint, std::ostream &O) { 256 O << " case " << OpsToPrint.back().first << ": "; 257 AsmWriterOperand TheOp = OpsToPrint.back().second; 258 OpsToPrint.pop_back(); 259 260 // Check to see if any other operands are identical in this list, and if so, 261 // emit a case label for them. 262 for (unsigned i = OpsToPrint.size(); i != 0; --i) 263 if (OpsToPrint[i-1].second == TheOp) { 264 O << "\n case " << OpsToPrint[i-1].first << ": "; 265 OpsToPrint.erase(OpsToPrint.begin()+i-1); 266 } 267 268 // Finally, emit the code. 269 O << TheOp.getCode(); 270 O << "break;\n"; 271} 272 273 274/// EmitInstructions - Emit the last instruction in the vector and any other 275/// instructions that are suitably similar to it. 276static void EmitInstructions(std::vector<AsmWriterInst> &Insts, 277 std::ostream &O) { 278 AsmWriterInst FirstInst = Insts.back(); 279 Insts.pop_back(); 280 281 std::vector<AsmWriterInst> SimilarInsts; 282 unsigned DifferingOperand = ~0; 283 for (unsigned i = Insts.size(); i != 0; --i) { 284 unsigned DiffOp = Insts[i-1].MatchesAllButOneOp(FirstInst); 285 if (DiffOp != ~1U) { 286 if (DifferingOperand == ~0U) // First match! 287 DifferingOperand = DiffOp; 288 289 // If this differs in the same operand as the rest of the instructions in 290 // this class, move it to the SimilarInsts list. 291 if (DifferingOperand == DiffOp || DiffOp == ~0U) { 292 SimilarInsts.push_back(Insts[i-1]); 293 Insts.erase(Insts.begin()+i-1); 294 } 295 } 296 } 297 298 O << " case " << FirstInst.CGI->Namespace << "::" 299 << FirstInst.CGI->TheDef->getName() << ":\n"; 300 for (unsigned i = 0, e = SimilarInsts.size(); i != e; ++i) 301 O << " case " << SimilarInsts[i].CGI->Namespace << "::" 302 << SimilarInsts[i].CGI->TheDef->getName() << ":\n"; 303 for (unsigned i = 0, e = FirstInst.Operands.size(); i != e; ++i) { 304 if (i != DifferingOperand) { 305 // If the operand is the same for all instructions, just print it. 306 O << " " << FirstInst.Operands[i].getCode(); 307 } else { 308 // If this is the operand that varies between all of the instructions, 309 // emit a switch for just this operand now. 310 O << " switch (MI->getOpcode()) {\n"; 311 std::vector<std::pair<std::string, AsmWriterOperand> > OpsToPrint; 312 OpsToPrint.push_back(std::make_pair(FirstInst.CGI->Namespace + "::" + 313 FirstInst.CGI->TheDef->getName(), 314 FirstInst.Operands[i])); 315 316 for (unsigned si = 0, e = SimilarInsts.size(); si != e; ++si) { 317 AsmWriterInst &AWI = SimilarInsts[si]; 318 OpsToPrint.push_back(std::make_pair(AWI.CGI->Namespace+"::"+ 319 AWI.CGI->TheDef->getName(), 320 AWI.Operands[i])); 321 } 322 std::reverse(OpsToPrint.begin(), OpsToPrint.end()); 323 while (!OpsToPrint.empty()) 324 PrintCases(OpsToPrint, O); 325 O << " }"; 326 } 327 O << "\n"; 328 } 329 330 O << " break;\n"; 331} 332 333void AsmWriterEmitter:: 334FindUniqueOperandCommands(std::vector<std::string> &UniqueOperandCommands, 335 std::vector<unsigned> &InstIdxs, 336 std::vector<unsigned> &InstOpsUsed) const { 337 InstIdxs.assign(NumberedInstructions.size(), ~0U); 338 339 // This vector parallels UniqueOperandCommands, keeping track of which 340 // instructions each case are used for. It is a comma separated string of 341 // enums. 342 std::vector<std::string> InstrsForCase; 343 InstrsForCase.resize(UniqueOperandCommands.size()); 344 InstOpsUsed.assign(UniqueOperandCommands.size(), 0); 345 346 for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) { 347 const AsmWriterInst *Inst = getAsmWriterInstByID(i); 348 if (Inst == 0) continue; // PHI, INLINEASM, etc. 349 350 std::string Command; 351 if (Inst->Operands.empty()) 352 continue; // Instruction already done. 353 354 Command = " " + Inst->Operands[0].getCode() + "\n"; 355 356 // If this is the last operand, emit a return. 357 if (Inst->Operands.size() == 1) 358 Command += " return true;\n"; 359 360 // Check to see if we already have 'Command' in UniqueOperandCommands. 361 // If not, add it. 362 bool FoundIt = false; 363 for (unsigned idx = 0, e = UniqueOperandCommands.size(); idx != e; ++idx) 364 if (UniqueOperandCommands[idx] == Command) { 365 InstIdxs[i] = idx; 366 InstrsForCase[idx] += ", "; 367 InstrsForCase[idx] += Inst->CGI->TheDef->getName(); 368 FoundIt = true; 369 break; 370 } 371 if (!FoundIt) { 372 InstIdxs[i] = UniqueOperandCommands.size(); 373 UniqueOperandCommands.push_back(Command); 374 InstrsForCase.push_back(Inst->CGI->TheDef->getName()); 375 376 // This command matches one operand so far. 377 InstOpsUsed.push_back(1); 378 } 379 } 380 381 // For each entry of UniqueOperandCommands, there is a set of instructions 382 // that uses it. If the next command of all instructions in the set are 383 // identical, fold it into the command. 384 for (unsigned CommandIdx = 0, e = UniqueOperandCommands.size(); 385 CommandIdx != e; ++CommandIdx) { 386 387 for (unsigned Op = 1; ; ++Op) { 388 // Scan for the first instruction in the set. 389 std::vector<unsigned>::iterator NIT = 390 std::find(InstIdxs.begin(), InstIdxs.end(), CommandIdx); 391 if (NIT == InstIdxs.end()) break; // No commonality. 392 393 // If this instruction has no more operands, we isn't anything to merge 394 // into this command. 395 const AsmWriterInst *FirstInst = 396 getAsmWriterInstByID(NIT-InstIdxs.begin()); 397 if (!FirstInst || FirstInst->Operands.size() == Op) 398 break; 399 400 // Otherwise, scan to see if all of the other instructions in this command 401 // set share the operand. 402 bool AllSame = true; 403 404 for (NIT = std::find(NIT+1, InstIdxs.end(), CommandIdx); 405 NIT != InstIdxs.end(); 406 NIT = std::find(NIT+1, InstIdxs.end(), CommandIdx)) { 407 // Okay, found another instruction in this command set. If the operand 408 // matches, we're ok, otherwise bail out. 409 const AsmWriterInst *OtherInst = 410 getAsmWriterInstByID(NIT-InstIdxs.begin()); 411 if (!OtherInst || OtherInst->Operands.size() == Op || 412 OtherInst->Operands[Op] != FirstInst->Operands[Op]) { 413 AllSame = false; 414 break; 415 } 416 } 417 if (!AllSame) break; 418 419 // Okay, everything in this command set has the same next operand. Add it 420 // to UniqueOperandCommands and remember that it was consumed. 421 std::string Command = " " + FirstInst->Operands[Op].getCode() + "\n"; 422 423 // If this is the last operand, emit a return after the code. 424 if (FirstInst->Operands.size() == Op+1) 425 Command += " return true;\n"; 426 427 UniqueOperandCommands[CommandIdx] += Command; 428 InstOpsUsed[CommandIdx]++; 429 } 430 } 431 432 // Prepend some of the instructions each case is used for onto the case val. 433 for (unsigned i = 0, e = InstrsForCase.size(); i != e; ++i) { 434 std::string Instrs = InstrsForCase[i]; 435 if (Instrs.size() > 70) { 436 Instrs.erase(Instrs.begin()+70, Instrs.end()); 437 Instrs += "..."; 438 } 439 440 if (!Instrs.empty()) 441 UniqueOperandCommands[i] = " // " + Instrs + "\n" + 442 UniqueOperandCommands[i]; 443 } 444} 445 446 447 448void AsmWriterEmitter::run(std::ostream &O) { 449 EmitSourceFileHeader("Assembly Writer Source Fragment", O); 450 451 CodeGenTarget Target; 452 Record *AsmWriter = Target.getAsmWriter(); 453 std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName"); 454 unsigned Variant = AsmWriter->getValueAsInt("Variant"); 455 456 O << 457 "/// printInstruction - This method is automatically generated by tablegen\n" 458 "/// from the instruction set description. This method returns true if the\n" 459 "/// machine instruction was sufficiently described to print it, otherwise\n" 460 "/// it returns false.\n" 461 "bool " << Target.getName() << ClassName 462 << "::printInstruction(const MachineInstr *MI) {\n"; 463 464 std::vector<AsmWriterInst> Instructions; 465 466 for (CodeGenTarget::inst_iterator I = Target.inst_begin(), 467 E = Target.inst_end(); I != E; ++I) 468 if (!I->second.AsmString.empty()) 469 Instructions.push_back(AsmWriterInst(I->second, Variant)); 470 471 // Get the instruction numbering. 472 Target.getInstructionsByEnumValue(NumberedInstructions); 473 474 // Compute the CodeGenInstruction -> AsmWriterInst mapping. Note that not 475 // all machine instructions are necessarily being printed, so there may be 476 // target instructions not in this map. 477 for (unsigned i = 0, e = Instructions.size(); i != e; ++i) 478 CGIAWIMap.insert(std::make_pair(Instructions[i].CGI, &Instructions[i])); 479 480 // Build an aggregate string, and build a table of offsets into it. 481 std::map<std::string, unsigned> StringOffset; 482 std::string AggregateString; 483 AggregateString.push_back(0); // "\0" 484 AggregateString.push_back(0); // "\0" 485 486 /// OpcodeInfo - This encodes the index of the string to use for the first 487 /// chunk of the output as well as indices used for operand printing. 488 std::vector<unsigned> OpcodeInfo; 489 490 unsigned MaxStringIdx = 0; 491 for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) { 492 AsmWriterInst *AWI = CGIAWIMap[NumberedInstructions[i]]; 493 unsigned Idx; 494 if (AWI == 0) { 495 // Something not handled by the asmwriter printer. 496 Idx = 0; 497 } else if (AWI->Operands[0].OperandType != 498 AsmWriterOperand::isLiteralTextOperand || 499 AWI->Operands[0].Str.empty()) { 500 // Something handled by the asmwriter printer, but with no leading string. 501 Idx = 1; 502 } else { 503 unsigned &Entry = StringOffset[AWI->Operands[0].Str]; 504 if (Entry == 0) { 505 // Add the string to the aggregate if this is the first time found. 506 MaxStringIdx = Entry = AggregateString.size(); 507 std::string Str = AWI->Operands[0].Str; 508 UnescapeString(Str); 509 AggregateString += Str; 510 AggregateString += '\0'; 511 } 512 Idx = Entry; 513 514 // Nuke the string from the operand list. It is now handled! 515 AWI->Operands.erase(AWI->Operands.begin()); 516 } 517 OpcodeInfo.push_back(Idx); 518 } 519 520 // Figure out how many bits we used for the string index. 521 unsigned AsmStrBits = Log2_32_Ceil(MaxStringIdx); 522 523 // To reduce code size, we compactify common instructions into a few bits 524 // in the opcode-indexed table. 525 unsigned BitsLeft = 32-AsmStrBits; 526 527 std::vector<std::vector<std::string> > TableDrivenOperandPrinters; 528 529 bool isFirst = true; 530 while (1) { 531 std::vector<std::string> UniqueOperandCommands; 532 533 // For the first operand check, add a default value for instructions with 534 // just opcode strings to use. 535 if (isFirst) { 536 UniqueOperandCommands.push_back(" return true;\n"); 537 isFirst = false; 538 } 539 540 std::vector<unsigned> InstIdxs; 541 std::vector<unsigned> NumInstOpsHandled; 542 FindUniqueOperandCommands(UniqueOperandCommands, InstIdxs, 543 NumInstOpsHandled); 544 545 // If we ran out of operands to print, we're done. 546 if (UniqueOperandCommands.empty()) break; 547 548 // Compute the number of bits we need to represent these cases, this is 549 // ceil(log2(numentries)). 550 unsigned NumBits = Log2_32_Ceil(UniqueOperandCommands.size()); 551 552 // If we don't have enough bits for this operand, don't include it. 553 if (NumBits > BitsLeft) { 554 DEBUG(std::cerr << "Not enough bits to densely encode " << NumBits 555 << " more bits\n"); 556 break; 557 } 558 559 // Otherwise, we can include this in the initial lookup table. Add it in. 560 BitsLeft -= NumBits; 561 for (unsigned i = 0, e = InstIdxs.size(); i != e; ++i) 562 if (InstIdxs[i] != ~0U) 563 OpcodeInfo[i] |= InstIdxs[i] << (BitsLeft+AsmStrBits); 564 565 // Remove the info about this operand. 566 for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) { 567 if (AsmWriterInst *Inst = getAsmWriterInstByID(i)) 568 if (!Inst->Operands.empty()) { 569 unsigned NumOps = NumInstOpsHandled[InstIdxs[i]]; 570 assert(NumOps <= Inst->Operands.size() && 571 "Can't remove this many ops!"); 572 Inst->Operands.erase(Inst->Operands.begin(), 573 Inst->Operands.begin()+NumOps); 574 } 575 } 576 577 // Remember the handlers for this set of operands. 578 TableDrivenOperandPrinters.push_back(UniqueOperandCommands); 579 } 580 581 582 583 O<<" static const unsigned OpInfo[] = {\n"; 584 for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) { 585 O << " " << OpcodeInfo[i] << "U,\t// " 586 << NumberedInstructions[i]->TheDef->getName() << "\n"; 587 } 588 // Add a dummy entry so the array init doesn't end with a comma. 589 O << " 0U\n"; 590 O << " };\n\n"; 591 592 // Emit the string itself. 593 O << " const char *AsmStrs = \n \""; 594 unsigned CharsPrinted = 0; 595 EscapeString(AggregateString); 596 for (unsigned i = 0, e = AggregateString.size(); i != e; ++i) { 597 if (CharsPrinted > 70) { 598 O << "\"\n \""; 599 CharsPrinted = 0; 600 } 601 O << AggregateString[i]; 602 ++CharsPrinted; 603 604 // Print escape sequences all together. 605 if (AggregateString[i] == '\\') { 606 assert(i+1 < AggregateString.size() && "Incomplete escape sequence!"); 607 if (isdigit(AggregateString[i+1])) { 608 assert(isdigit(AggregateString[i+2]) && isdigit(AggregateString[i+3]) && 609 "Expected 3 digit octal escape!"); 610 O << AggregateString[++i]; 611 O << AggregateString[++i]; 612 O << AggregateString[++i]; 613 CharsPrinted += 3; 614 } else { 615 O << AggregateString[++i]; 616 ++CharsPrinted; 617 } 618 } 619 } 620 O << "\";\n\n"; 621 622 O << " if (MI->getOpcode() == TargetInstrInfo::INLINEASM) {\n" 623 << " printInlineAsm(MI);\n" 624 << " return true;\n" 625 << " }\n\n"; 626 627 O << " // Emit the opcode for the instruction.\n" 628 << " unsigned Bits = OpInfo[MI->getOpcode()];\n" 629 << " if (Bits == 0) return false;\n" 630 << " O << AsmStrs+(Bits & " << (1 << AsmStrBits)-1 << ");\n\n"; 631 632 // Output the table driven operand information. 633 BitsLeft = 32-AsmStrBits; 634 for (unsigned i = 0, e = TableDrivenOperandPrinters.size(); i != e; ++i) { 635 std::vector<std::string> &Commands = TableDrivenOperandPrinters[i]; 636 637 // Compute the number of bits we need to represent these cases, this is 638 // ceil(log2(numentries)). 639 unsigned NumBits = Log2_32_Ceil(Commands.size()); 640 assert(NumBits <= BitsLeft && "consistency error"); 641 642 // Emit code to extract this field from Bits. 643 BitsLeft -= NumBits; 644 645 O << "\n // Fragment " << i << " encoded into " << NumBits 646 << " bits for " << Commands.size() << " unique commands.\n"; 647 648 if (Commands.size() == 2) { 649 // Emit two possibilitys with if/else. 650 O << " if ((Bits >> " << (BitsLeft+AsmStrBits) << ") & " 651 << ((1 << NumBits)-1) << ") {\n" 652 << Commands[1] 653 << " } else {\n" 654 << Commands[0] 655 << " }\n\n"; 656 } else { 657 O << " switch ((Bits >> " << (BitsLeft+AsmStrBits) << ") & " 658 << ((1 << NumBits)-1) << ") {\n" 659 << " default: // unreachable.\n"; 660 661 // Print out all the cases. 662 for (unsigned i = 0, e = Commands.size(); i != e; ++i) { 663 O << " case " << i << ":\n"; 664 O << Commands[i]; 665 O << " break;\n"; 666 } 667 O << " }\n\n"; 668 } 669 } 670 671 // Okay, delete instructions with no operand info left. 672 for (unsigned i = 0, e = Instructions.size(); i != e; ++i) { 673 // Entire instruction has been emitted? 674 AsmWriterInst &Inst = Instructions[i]; 675 if (Inst.Operands.empty()) { 676 Instructions.erase(Instructions.begin()+i); 677 --i; --e; 678 } 679 } 680 681 682 // Because this is a vector, we want to emit from the end. Reverse all of the 683 // elements in the vector. 684 std::reverse(Instructions.begin(), Instructions.end()); 685 686 if (!Instructions.empty()) { 687 // Find the opcode # of inline asm. 688 O << " switch (MI->getOpcode()) {\n"; 689 while (!Instructions.empty()) 690 EmitInstructions(Instructions, O); 691 692 O << " }\n"; 693 O << " return true;\n"; 694 } 695 696 O << "}\n"; 697} 698