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