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