1193323Sed//===- AsmWriterEmitter.cpp - Generate an assembly writer -----------------===// 2193323Sed// 3193323Sed// The LLVM Compiler Infrastructure 4193323Sed// 5193323Sed// This file is distributed under the University of Illinois Open Source 6193323Sed// License. See LICENSE.TXT for details. 7193323Sed// 8193323Sed//===----------------------------------------------------------------------===// 9193323Sed// 10193323Sed// This tablegen backend is emits an assembly printer for the current target. 11193323Sed// Note that this is currently fairly skeletal, but will grow over time. 12193323Sed// 13193323Sed//===----------------------------------------------------------------------===// 14193323Sed 15203954Srdivacky#include "AsmWriterInst.h" 16193323Sed#include "CodeGenTarget.h" 17234353Sdim#include "SequenceToOffsetTable.h" 18239462Sdim#include "llvm/ADT/StringExtras.h" 19224145Sdim#include "llvm/ADT/Twine.h" 20193323Sed#include "llvm/Support/Debug.h" 21263508Sdim#include "llvm/Support/Format.h" 22193323Sed#include "llvm/Support/MathExtras.h" 23226633Sdim#include "llvm/TableGen/Error.h" 24226633Sdim#include "llvm/TableGen/Record.h" 25239462Sdim#include "llvm/TableGen/TableGenBackend.h" 26193323Sed#include <algorithm> 27239462Sdim#include <cassert> 28239462Sdim#include <map> 29239462Sdim#include <vector> 30193323Sedusing namespace llvm; 31193323Sed 32239462Sdimnamespace { 33239462Sdimclass AsmWriterEmitter { 34239462Sdim RecordKeeper &Records; 35263508Sdim CodeGenTarget Target; 36239462Sdim std::map<const CodeGenInstruction*, AsmWriterInst*> CGIAWIMap; 37239462Sdim std::vector<const CodeGenInstruction*> NumberedInstructions; 38263508Sdim std::vector<AsmWriterInst> Instructions; 39239462Sdimpublic: 40263508Sdim AsmWriterEmitter(RecordKeeper &R); 41239462Sdim 42239462Sdim void run(raw_ostream &o); 43239462Sdim 44239462Sdimprivate: 45239462Sdim void EmitPrintInstruction(raw_ostream &o); 46239462Sdim void EmitGetRegisterName(raw_ostream &o); 47239462Sdim void EmitPrintAliasInstruction(raw_ostream &O); 48239462Sdim 49239462Sdim AsmWriterInst *getAsmWriterInstByID(unsigned ID) const { 50239462Sdim assert(ID < NumberedInstructions.size()); 51239462Sdim std::map<const CodeGenInstruction*, AsmWriterInst*>::const_iterator I = 52239462Sdim CGIAWIMap.find(NumberedInstructions[ID]); 53239462Sdim assert(I != CGIAWIMap.end() && "Didn't find inst!"); 54239462Sdim return I->second; 55239462Sdim } 56239462Sdim void FindUniqueOperandCommands(std::vector<std::string> &UOC, 57239462Sdim std::vector<unsigned> &InstIdxs, 58239462Sdim std::vector<unsigned> &InstOpsUsed) const; 59239462Sdim}; 60239462Sdim} // end anonymous namespace 61239462Sdim 62193323Sedstatic void PrintCases(std::vector<std::pair<std::string, 63195340Sed AsmWriterOperand> > &OpsToPrint, raw_ostream &O) { 64193323Sed O << " case " << OpsToPrint.back().first << ": "; 65193323Sed AsmWriterOperand TheOp = OpsToPrint.back().second; 66193323Sed OpsToPrint.pop_back(); 67193323Sed 68193323Sed // Check to see if any other operands are identical in this list, and if so, 69193323Sed // emit a case label for them. 70193323Sed for (unsigned i = OpsToPrint.size(); i != 0; --i) 71193323Sed if (OpsToPrint[i-1].second == TheOp) { 72193323Sed O << "\n case " << OpsToPrint[i-1].first << ": "; 73193323Sed OpsToPrint.erase(OpsToPrint.begin()+i-1); 74193323Sed } 75193323Sed 76193323Sed // Finally, emit the code. 77193323Sed O << TheOp.getCode(); 78193323Sed O << "break;\n"; 79193323Sed} 80193323Sed 81193323Sed 82193323Sed/// EmitInstructions - Emit the last instruction in the vector and any other 83193323Sed/// instructions that are suitably similar to it. 84193323Sedstatic void EmitInstructions(std::vector<AsmWriterInst> &Insts, 85195340Sed raw_ostream &O) { 86193323Sed AsmWriterInst FirstInst = Insts.back(); 87193323Sed Insts.pop_back(); 88193323Sed 89193323Sed std::vector<AsmWriterInst> SimilarInsts; 90193323Sed unsigned DifferingOperand = ~0; 91193323Sed for (unsigned i = Insts.size(); i != 0; --i) { 92193323Sed unsigned DiffOp = Insts[i-1].MatchesAllButOneOp(FirstInst); 93193323Sed if (DiffOp != ~1U) { 94193323Sed if (DifferingOperand == ~0U) // First match! 95193323Sed DifferingOperand = DiffOp; 96193323Sed 97193323Sed // If this differs in the same operand as the rest of the instructions in 98193323Sed // this class, move it to the SimilarInsts list. 99193323Sed if (DifferingOperand == DiffOp || DiffOp == ~0U) { 100193323Sed SimilarInsts.push_back(Insts[i-1]); 101193323Sed Insts.erase(Insts.begin()+i-1); 102193323Sed } 103193323Sed } 104193323Sed } 105193323Sed 106193323Sed O << " case " << FirstInst.CGI->Namespace << "::" 107193323Sed << FirstInst.CGI->TheDef->getName() << ":\n"; 108193323Sed for (unsigned i = 0, e = SimilarInsts.size(); i != e; ++i) 109193323Sed O << " case " << SimilarInsts[i].CGI->Namespace << "::" 110193323Sed << SimilarInsts[i].CGI->TheDef->getName() << ":\n"; 111193323Sed for (unsigned i = 0, e = FirstInst.Operands.size(); i != e; ++i) { 112193323Sed if (i != DifferingOperand) { 113193323Sed // If the operand is the same for all instructions, just print it. 114193323Sed O << " " << FirstInst.Operands[i].getCode(); 115193323Sed } else { 116193323Sed // If this is the operand that varies between all of the instructions, 117193323Sed // emit a switch for just this operand now. 118193323Sed O << " switch (MI->getOpcode()) {\n"; 119193323Sed std::vector<std::pair<std::string, AsmWriterOperand> > OpsToPrint; 120193323Sed OpsToPrint.push_back(std::make_pair(FirstInst.CGI->Namespace + "::" + 121193323Sed FirstInst.CGI->TheDef->getName(), 122193323Sed FirstInst.Operands[i])); 123193323Sed 124193323Sed for (unsigned si = 0, e = SimilarInsts.size(); si != e; ++si) { 125193323Sed AsmWriterInst &AWI = SimilarInsts[si]; 126193323Sed OpsToPrint.push_back(std::make_pair(AWI.CGI->Namespace+"::"+ 127193323Sed AWI.CGI->TheDef->getName(), 128193323Sed AWI.Operands[i])); 129193323Sed } 130193323Sed std::reverse(OpsToPrint.begin(), OpsToPrint.end()); 131193323Sed while (!OpsToPrint.empty()) 132193323Sed PrintCases(OpsToPrint, O); 133193323Sed O << " }"; 134193323Sed } 135193323Sed O << "\n"; 136193323Sed } 137193323Sed O << " break;\n"; 138193323Sed} 139193323Sed 140193323Sedvoid AsmWriterEmitter:: 141218893SdimFindUniqueOperandCommands(std::vector<std::string> &UniqueOperandCommands, 142193323Sed std::vector<unsigned> &InstIdxs, 143193323Sed std::vector<unsigned> &InstOpsUsed) const { 144193323Sed InstIdxs.assign(NumberedInstructions.size(), ~0U); 145218893Sdim 146193323Sed // This vector parallels UniqueOperandCommands, keeping track of which 147193323Sed // instructions each case are used for. It is a comma separated string of 148193323Sed // enums. 149193323Sed std::vector<std::string> InstrsForCase; 150193323Sed InstrsForCase.resize(UniqueOperandCommands.size()); 151193323Sed InstOpsUsed.assign(UniqueOperandCommands.size(), 0); 152218893Sdim 153193323Sed for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) { 154193323Sed const AsmWriterInst *Inst = getAsmWriterInstByID(i); 155212904Sdim if (Inst == 0) continue; // PHI, INLINEASM, PROLOG_LABEL, etc. 156218893Sdim 157193323Sed std::string Command; 158193323Sed if (Inst->Operands.empty()) 159193323Sed continue; // Instruction already done. 160193323Sed 161193323Sed Command = " " + Inst->Operands[0].getCode() + "\n"; 162193323Sed 163193323Sed // Check to see if we already have 'Command' in UniqueOperandCommands. 164193323Sed // If not, add it. 165193323Sed bool FoundIt = false; 166193323Sed for (unsigned idx = 0, e = UniqueOperandCommands.size(); idx != e; ++idx) 167193323Sed if (UniqueOperandCommands[idx] == Command) { 168193323Sed InstIdxs[i] = idx; 169193323Sed InstrsForCase[idx] += ", "; 170193323Sed InstrsForCase[idx] += Inst->CGI->TheDef->getName(); 171193323Sed FoundIt = true; 172193323Sed break; 173193323Sed } 174193323Sed if (!FoundIt) { 175193323Sed InstIdxs[i] = UniqueOperandCommands.size(); 176193323Sed UniqueOperandCommands.push_back(Command); 177193323Sed InstrsForCase.push_back(Inst->CGI->TheDef->getName()); 178193323Sed 179193323Sed // This command matches one operand so far. 180193323Sed InstOpsUsed.push_back(1); 181193323Sed } 182193323Sed } 183218893Sdim 184193323Sed // For each entry of UniqueOperandCommands, there is a set of instructions 185193323Sed // that uses it. If the next command of all instructions in the set are 186193323Sed // identical, fold it into the command. 187193323Sed for (unsigned CommandIdx = 0, e = UniqueOperandCommands.size(); 188193323Sed CommandIdx != e; ++CommandIdx) { 189218893Sdim 190193323Sed for (unsigned Op = 1; ; ++Op) { 191193323Sed // Scan for the first instruction in the set. 192193323Sed std::vector<unsigned>::iterator NIT = 193193323Sed std::find(InstIdxs.begin(), InstIdxs.end(), CommandIdx); 194193323Sed if (NIT == InstIdxs.end()) break; // No commonality. 195193323Sed 196193323Sed // If this instruction has no more operands, we isn't anything to merge 197193323Sed // into this command. 198218893Sdim const AsmWriterInst *FirstInst = 199193323Sed getAsmWriterInstByID(NIT-InstIdxs.begin()); 200193323Sed if (!FirstInst || FirstInst->Operands.size() == Op) 201193323Sed break; 202193323Sed 203193323Sed // Otherwise, scan to see if all of the other instructions in this command 204193323Sed // set share the operand. 205193323Sed bool AllSame = true; 206198090Srdivacky // Keep track of the maximum, number of operands or any 207198090Srdivacky // instruction we see in the group. 208198090Srdivacky size_t MaxSize = FirstInst->Operands.size(); 209198090Srdivacky 210193323Sed for (NIT = std::find(NIT+1, InstIdxs.end(), CommandIdx); 211193323Sed NIT != InstIdxs.end(); 212193323Sed NIT = std::find(NIT+1, InstIdxs.end(), CommandIdx)) { 213193323Sed // Okay, found another instruction in this command set. If the operand 214193323Sed // matches, we're ok, otherwise bail out. 215218893Sdim const AsmWriterInst *OtherInst = 216193323Sed getAsmWriterInstByID(NIT-InstIdxs.begin()); 217198090Srdivacky 218198090Srdivacky if (OtherInst && 219198090Srdivacky OtherInst->Operands.size() > FirstInst->Operands.size()) 220198090Srdivacky MaxSize = std::max(MaxSize, OtherInst->Operands.size()); 221198090Srdivacky 222193323Sed if (!OtherInst || OtherInst->Operands.size() == Op || 223193323Sed OtherInst->Operands[Op] != FirstInst->Operands[Op]) { 224193323Sed AllSame = false; 225193323Sed break; 226193323Sed } 227193323Sed } 228193323Sed if (!AllSame) break; 229218893Sdim 230193323Sed // Okay, everything in this command set has the same next operand. Add it 231193323Sed // to UniqueOperandCommands and remember that it was consumed. 232193323Sed std::string Command = " " + FirstInst->Operands[Op].getCode() + "\n"; 233218893Sdim 234193323Sed UniqueOperandCommands[CommandIdx] += Command; 235193323Sed InstOpsUsed[CommandIdx]++; 236193323Sed } 237193323Sed } 238218893Sdim 239193323Sed // Prepend some of the instructions each case is used for onto the case val. 240193323Sed for (unsigned i = 0, e = InstrsForCase.size(); i != e; ++i) { 241193323Sed std::string Instrs = InstrsForCase[i]; 242193323Sed if (Instrs.size() > 70) { 243193323Sed Instrs.erase(Instrs.begin()+70, Instrs.end()); 244193323Sed Instrs += "..."; 245193323Sed } 246218893Sdim 247193323Sed if (!Instrs.empty()) 248218893Sdim UniqueOperandCommands[i] = " // " + Instrs + "\n" + 249193323Sed UniqueOperandCommands[i]; 250193323Sed } 251193323Sed} 252193323Sed 253193323Sed 254198396Srdivackystatic void UnescapeString(std::string &Str) { 255198396Srdivacky for (unsigned i = 0; i != Str.size(); ++i) { 256198396Srdivacky if (Str[i] == '\\' && i != Str.size()-1) { 257198396Srdivacky switch (Str[i+1]) { 258198396Srdivacky default: continue; // Don't execute the code after the switch. 259198396Srdivacky case 'a': Str[i] = '\a'; break; 260198396Srdivacky case 'b': Str[i] = '\b'; break; 261198396Srdivacky case 'e': Str[i] = 27; break; 262198396Srdivacky case 'f': Str[i] = '\f'; break; 263198396Srdivacky case 'n': Str[i] = '\n'; break; 264198396Srdivacky case 'r': Str[i] = '\r'; break; 265198396Srdivacky case 't': Str[i] = '\t'; break; 266198396Srdivacky case 'v': Str[i] = '\v'; break; 267198396Srdivacky case '"': Str[i] = '\"'; break; 268198396Srdivacky case '\'': Str[i] = '\''; break; 269198396Srdivacky case '\\': Str[i] = '\\'; break; 270198396Srdivacky } 271198396Srdivacky // Nuke the second character. 272198396Srdivacky Str.erase(Str.begin()+i+1); 273198396Srdivacky } 274198396Srdivacky } 275198396Srdivacky} 276198396Srdivacky 277198090Srdivacky/// EmitPrintInstruction - Generate the code for the "printInstruction" method 278263508Sdim/// implementation. Destroys all instances of AsmWriterInst information, by 279263508Sdim/// clearing the Instructions vector. 280198090Srdivackyvoid AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) { 281193323Sed Record *AsmWriter = Target.getAsmWriter(); 282193323Sed std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName"); 283218893Sdim bool isMC = AsmWriter->getValueAsBit("isMCAsmWriter"); 284218893Sdim const char *MachineInstrClassName = isMC ? "MCInst" : "MachineInstr"; 285218893Sdim 286193323Sed O << 287193323Sed "/// printInstruction - This method is automatically generated by tablegen\n" 288198090Srdivacky "/// from the instruction set description.\n" 289198090Srdivacky "void " << Target.getName() << ClassName 290218893Sdim << "::printInstruction(const " << MachineInstrClassName 291218893Sdim << " *MI, raw_ostream &O) {\n"; 292193323Sed 293193323Sed // Build an aggregate string, and build a table of offsets into it. 294234353Sdim SequenceToOffsetTable<std::string> StringTable; 295218893Sdim 296193323Sed /// OpcodeInfo - This encodes the index of the string to use for the first 297193323Sed /// chunk of the output as well as indices used for operand printing. 298243830Sdim /// To reduce the number of unhandled cases, we expand the size from 32-bit 299243830Sdim /// to 32+16 = 48-bit. 300243830Sdim std::vector<uint64_t> OpcodeInfo; 301218893Sdim 302234353Sdim // Add all strings to the string table upfront so it can generate an optimized 303234353Sdim // representation. 304234353Sdim for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) { 305234353Sdim AsmWriterInst *AWI = CGIAWIMap[NumberedInstructions[i]]; 306234353Sdim if (AWI != 0 && 307234982Sdim AWI->Operands[0].OperandType == 308234982Sdim AsmWriterOperand::isLiteralTextOperand && 309234353Sdim !AWI->Operands[0].Str.empty()) { 310234353Sdim std::string Str = AWI->Operands[0].Str; 311234353Sdim UnescapeString(Str); 312234353Sdim StringTable.add(Str); 313234353Sdim } 314234353Sdim } 315234353Sdim 316234353Sdim StringTable.layout(); 317234353Sdim 318193323Sed unsigned MaxStringIdx = 0; 319193323Sed for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) { 320193323Sed AsmWriterInst *AWI = CGIAWIMap[NumberedInstructions[i]]; 321193323Sed unsigned Idx; 322193323Sed if (AWI == 0) { 323193323Sed // Something not handled by the asmwriter printer. 324198090Srdivacky Idx = ~0U; 325218893Sdim } else if (AWI->Operands[0].OperandType != 326193323Sed AsmWriterOperand::isLiteralTextOperand || 327193323Sed AWI->Operands[0].Str.empty()) { 328193323Sed // Something handled by the asmwriter printer, but with no leading string. 329234353Sdim Idx = StringTable.get(""); 330193323Sed } else { 331198090Srdivacky std::string Str = AWI->Operands[0].Str; 332198090Srdivacky UnescapeString(Str); 333234353Sdim Idx = StringTable.get(Str); 334198090Srdivacky MaxStringIdx = std::max(MaxStringIdx, Idx); 335218893Sdim 336193323Sed // Nuke the string from the operand list. It is now handled! 337193323Sed AWI->Operands.erase(AWI->Operands.begin()); 338193323Sed } 339218893Sdim 340198090Srdivacky // Bias offset by one since we want 0 as a sentinel. 341198090Srdivacky OpcodeInfo.push_back(Idx+1); 342193323Sed } 343218893Sdim 344193323Sed // Figure out how many bits we used for the string index. 345198090Srdivacky unsigned AsmStrBits = Log2_32_Ceil(MaxStringIdx+2); 346218893Sdim 347193323Sed // To reduce code size, we compactify common instructions into a few bits 348193323Sed // in the opcode-indexed table. 349243830Sdim unsigned BitsLeft = 64-AsmStrBits; 350193323Sed 351193323Sed std::vector<std::vector<std::string> > TableDrivenOperandPrinters; 352218893Sdim 353193323Sed while (1) { 354193323Sed std::vector<std::string> UniqueOperandCommands; 355193323Sed std::vector<unsigned> InstIdxs; 356193323Sed std::vector<unsigned> NumInstOpsHandled; 357193323Sed FindUniqueOperandCommands(UniqueOperandCommands, InstIdxs, 358193323Sed NumInstOpsHandled); 359218893Sdim 360193323Sed // If we ran out of operands to print, we're done. 361193323Sed if (UniqueOperandCommands.empty()) break; 362218893Sdim 363193323Sed // Compute the number of bits we need to represent these cases, this is 364193323Sed // ceil(log2(numentries)). 365193323Sed unsigned NumBits = Log2_32_Ceil(UniqueOperandCommands.size()); 366218893Sdim 367193323Sed // If we don't have enough bits for this operand, don't include it. 368193323Sed if (NumBits > BitsLeft) { 369198090Srdivacky DEBUG(errs() << "Not enough bits to densely encode " << NumBits 370198090Srdivacky << " more bits\n"); 371193323Sed break; 372193323Sed } 373218893Sdim 374193323Sed // Otherwise, we can include this in the initial lookup table. Add it in. 375243830Sdim for (unsigned i = 0, e = InstIdxs.size(); i != e; ++i) 376243830Sdim if (InstIdxs[i] != ~0U) { 377243830Sdim OpcodeInfo[i] |= (uint64_t)InstIdxs[i] << (64-BitsLeft); 378243830Sdim } 379193323Sed BitsLeft -= NumBits; 380218893Sdim 381193323Sed // Remove the info about this operand. 382193323Sed for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) { 383193323Sed if (AsmWriterInst *Inst = getAsmWriterInstByID(i)) 384193323Sed if (!Inst->Operands.empty()) { 385193323Sed unsigned NumOps = NumInstOpsHandled[InstIdxs[i]]; 386193323Sed assert(NumOps <= Inst->Operands.size() && 387193323Sed "Can't remove this many ops!"); 388193323Sed Inst->Operands.erase(Inst->Operands.begin(), 389193323Sed Inst->Operands.begin()+NumOps); 390193323Sed } 391193323Sed } 392218893Sdim 393193323Sed // Remember the handlers for this set of operands. 394193323Sed TableDrivenOperandPrinters.push_back(UniqueOperandCommands); 395193323Sed } 396218893Sdim 397218893Sdim 398243830Sdim // We always emit at least one 32-bit table. A second table is emitted if 399243830Sdim // more bits are needed. 400243830Sdim O<<" static const uint32_t OpInfo[] = {\n"; 401193323Sed for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) { 402243830Sdim O << " " << (OpcodeInfo[i] & 0xffffffff) << "U,\t// " 403193323Sed << NumberedInstructions[i]->TheDef->getName() << "\n"; 404193323Sed } 405193323Sed // Add a dummy entry so the array init doesn't end with a comma. 406193323Sed O << " 0U\n"; 407193323Sed O << " };\n\n"; 408218893Sdim 409243830Sdim if (BitsLeft < 32) { 410243830Sdim // Add a second OpInfo table only when it is necessary. 411243830Sdim // Adjust the type of the second table based on the number of bits needed. 412243830Sdim O << " static const uint" 413243830Sdim << ((BitsLeft < 16) ? "32" : (BitsLeft < 24) ? "16" : "8") 414243830Sdim << "_t OpInfo2[] = {\n"; 415243830Sdim for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) { 416243830Sdim O << " " << (OpcodeInfo[i] >> 32) << "U,\t// " 417243830Sdim << NumberedInstructions[i]->TheDef->getName() << "\n"; 418243830Sdim } 419243830Sdim // Add a dummy entry so the array init doesn't end with a comma. 420243830Sdim O << " 0U\n"; 421243830Sdim O << " };\n\n"; 422243830Sdim } 423243830Sdim 424193323Sed // Emit the string itself. 425234353Sdim O << " const char AsmStrs[] = {\n"; 426234353Sdim StringTable.emit(O, printChar); 427234353Sdim O << " };\n\n"; 428193323Sed 429193323Sed O << " O << \"\\t\";\n\n"; 430193323Sed 431243830Sdim O << " // Emit the opcode for the instruction.\n"; 432243830Sdim if (BitsLeft < 32) { 433243830Sdim // If we have two tables then we need to perform two lookups and combine 434243830Sdim // the results into a single 64-bit value. 435243830Sdim O << " uint64_t Bits1 = OpInfo[MI->getOpcode()];\n" 436243830Sdim << " uint64_t Bits2 = OpInfo2[MI->getOpcode()];\n" 437243830Sdim << " uint64_t Bits = (Bits2 << 32) | Bits1;\n"; 438243830Sdim } else { 439243830Sdim // If only one table is used we just need to perform a single lookup. 440243830Sdim O << " uint32_t Bits = OpInfo[MI->getOpcode()];\n"; 441243830Sdim } 442243830Sdim O << " assert(Bits != 0 && \"Cannot print this instruction.\");\n" 443198090Srdivacky << " O << AsmStrs+(Bits & " << (1 << AsmStrBits)-1 << ")-1;\n\n"; 444193323Sed 445193323Sed // Output the table driven operand information. 446243830Sdim BitsLeft = 64-AsmStrBits; 447193323Sed for (unsigned i = 0, e = TableDrivenOperandPrinters.size(); i != e; ++i) { 448193323Sed std::vector<std::string> &Commands = TableDrivenOperandPrinters[i]; 449193323Sed 450193323Sed // Compute the number of bits we need to represent these cases, this is 451193323Sed // ceil(log2(numentries)). 452193323Sed unsigned NumBits = Log2_32_Ceil(Commands.size()); 453193323Sed assert(NumBits <= BitsLeft && "consistency error"); 454218893Sdim 455193323Sed // Emit code to extract this field from Bits. 456193323Sed O << "\n // Fragment " << i << " encoded into " << NumBits 457193323Sed << " bits for " << Commands.size() << " unique commands.\n"; 458218893Sdim 459193323Sed if (Commands.size() == 2) { 460193323Sed // Emit two possibilitys with if/else. 461243830Sdim O << " if ((Bits >> " 462243830Sdim << (64-BitsLeft) << ") & " 463193323Sed << ((1 << NumBits)-1) << ") {\n" 464193323Sed << Commands[1] 465193323Sed << " } else {\n" 466193323Sed << Commands[0] 467193323Sed << " }\n\n"; 468218893Sdim } else if (Commands.size() == 1) { 469218893Sdim // Emit a single possibility. 470218893Sdim O << Commands[0] << "\n\n"; 471193323Sed } else { 472243830Sdim O << " switch ((Bits >> " 473243830Sdim << (64-BitsLeft) << ") & " 474193323Sed << ((1 << NumBits)-1) << ") {\n" 475193323Sed << " default: // unreachable.\n"; 476218893Sdim 477193323Sed // Print out all the cases. 478193323Sed for (unsigned i = 0, e = Commands.size(); i != e; ++i) { 479193323Sed O << " case " << i << ":\n"; 480193323Sed O << Commands[i]; 481193323Sed O << " break;\n"; 482193323Sed } 483193323Sed O << " }\n\n"; 484193323Sed } 485243830Sdim BitsLeft -= NumBits; 486193323Sed } 487218893Sdim 488193323Sed // Okay, delete instructions with no operand info left. 489193323Sed for (unsigned i = 0, e = Instructions.size(); i != e; ++i) { 490193323Sed // Entire instruction has been emitted? 491193323Sed AsmWriterInst &Inst = Instructions[i]; 492193323Sed if (Inst.Operands.empty()) { 493193323Sed Instructions.erase(Instructions.begin()+i); 494193323Sed --i; --e; 495193323Sed } 496193323Sed } 497193323Sed 498218893Sdim 499193323Sed // Because this is a vector, we want to emit from the end. Reverse all of the 500193323Sed // elements in the vector. 501193323Sed std::reverse(Instructions.begin(), Instructions.end()); 502218893Sdim 503218893Sdim 504198090Srdivacky // Now that we've emitted all of the operand info that fit into 32 bits, emit 505198090Srdivacky // information for those instructions that are left. This is a less dense 506198090Srdivacky // encoding, but we expect the main 32-bit table to handle the majority of 507198090Srdivacky // instructions. 508193323Sed if (!Instructions.empty()) { 509193323Sed // Find the opcode # of inline asm. 510193323Sed O << " switch (MI->getOpcode()) {\n"; 511193323Sed while (!Instructions.empty()) 512193323Sed EmitInstructions(Instructions, O); 513193323Sed 514193323Sed O << " }\n"; 515198090Srdivacky O << " return;\n"; 516193323Sed } 517198090Srdivacky 518193323Sed O << "}\n"; 519193323Sed} 520198090Srdivacky 521224145Sdimstatic void 522224145SdimemitRegisterNameString(raw_ostream &O, StringRef AltName, 523234353Sdim const std::vector<CodeGenRegister*> &Registers) { 524234353Sdim SequenceToOffsetTable<std::string> StringTable; 525234353Sdim SmallVector<std::string, 4> AsmNames(Registers.size()); 526224145Sdim for (unsigned i = 0, e = Registers.size(); i != e; ++i) { 527224145Sdim const CodeGenRegister &Reg = *Registers[i]; 528234353Sdim std::string &AsmName = AsmNames[i]; 529198090Srdivacky 530224145Sdim // "NoRegAltName" is special. We don't need to do a lookup for that, 531224145Sdim // as it's just a reference to the default register name. 532224145Sdim if (AltName == "" || AltName == "NoRegAltName") { 533224145Sdim AsmName = Reg.TheDef->getValueAsString("AsmName"); 534224145Sdim if (AsmName.empty()) 535224145Sdim AsmName = Reg.getName(); 536224145Sdim } else { 537224145Sdim // Make sure the register has an alternate name for this index. 538224145Sdim std::vector<Record*> AltNameList = 539224145Sdim Reg.TheDef->getValueAsListOfDefs("RegAltNameIndices"); 540224145Sdim unsigned Idx = 0, e; 541224145Sdim for (e = AltNameList.size(); 542224145Sdim Idx < e && (AltNameList[Idx]->getName() != AltName); 543224145Sdim ++Idx) 544224145Sdim ; 545224145Sdim // If the register has an alternate name for this index, use it. 546224145Sdim // Otherwise, leave it empty as an error flag. 547224145Sdim if (Idx < e) { 548224145Sdim std::vector<std::string> AltNames = 549224145Sdim Reg.TheDef->getValueAsListOfStrings("AltNames"); 550224145Sdim if (AltNames.size() <= Idx) 551243830Sdim PrintFatalError(Reg.TheDef->getLoc(), 552243830Sdim (Twine("Register definition missing alt name for '") + 553243830Sdim AltName + "'.").str()); 554224145Sdim AsmName = AltNames[Idx]; 555224145Sdim } 556224145Sdim } 557234353Sdim StringTable.add(AsmName); 558234353Sdim } 559224145Sdim 560234353Sdim StringTable.layout(); 561234353Sdim O << " static const char AsmStrs" << AltName << "[] = {\n"; 562234353Sdim StringTable.emit(O, printChar); 563234353Sdim O << " };\n\n"; 564224145Sdim 565243830Sdim O << " static const uint32_t RegAsmOffset" << AltName << "[] = {"; 566234353Sdim for (unsigned i = 0, e = Registers.size(); i != e; ++i) { 567234353Sdim if ((i % 14) == 0) 568234353Sdim O << "\n "; 569234353Sdim O << StringTable.get(AsmNames[i]) << ", "; 570224145Sdim } 571234353Sdim O << "\n };\n" 572224145Sdim << "\n"; 573224145Sdim} 574224145Sdim 575198090Srdivackyvoid AsmWriterEmitter::EmitGetRegisterName(raw_ostream &O) { 576198090Srdivacky Record *AsmWriter = Target.getAsmWriter(); 577198090Srdivacky std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName"); 578224145Sdim const std::vector<CodeGenRegister*> &Registers = 579224145Sdim Target.getRegBank().getRegisters(); 580224145Sdim std::vector<Record*> AltNameIndices = Target.getRegAltNameIndices(); 581224145Sdim bool hasAltNames = AltNameIndices.size() > 1; 582218893Sdim 583198090Srdivacky O << 584198090Srdivacky "\n\n/// getRegisterName - This method is automatically generated by tblgen\n" 585198090Srdivacky "/// from the register set description. This returns the assembler name\n" 586198090Srdivacky "/// for the specified register.\n" 587224145Sdim "const char *" << Target.getName() << ClassName << "::"; 588224145Sdim if (hasAltNames) 589224145Sdim O << "\ngetRegisterName(unsigned RegNo, unsigned AltIdx) {\n"; 590224145Sdim else 591224145Sdim O << "getRegisterName(unsigned RegNo) {\n"; 592224145Sdim O << " assert(RegNo && RegNo < " << (Registers.size()+1) 593224145Sdim << " && \"Invalid register number!\");\n" 594224145Sdim << "\n"; 595198090Srdivacky 596224145Sdim if (hasAltNames) { 597224145Sdim for (unsigned i = 0, e = AltNameIndices.size(); i < e; ++i) 598224145Sdim emitRegisterNameString(O, AltNameIndices[i]->getName(), Registers); 599224145Sdim } else 600224145Sdim emitRegisterNameString(O, "", Registers); 601218893Sdim 602224145Sdim if (hasAltNames) { 603243830Sdim O << " const uint32_t *RegAsmOffset;\n" 604224145Sdim << " const char *AsmStrs;\n" 605224145Sdim << " switch(AltIdx) {\n" 606234353Sdim << " default: llvm_unreachable(\"Invalid register alt name index!\");\n"; 607224145Sdim for (unsigned i = 0, e = AltNameIndices.size(); i < e; ++i) { 608224145Sdim StringRef Namespace = AltNameIndices[1]->getValueAsString("Namespace"); 609224145Sdim StringRef AltName(AltNameIndices[i]->getName()); 610224145Sdim O << " case " << Namespace << "::" << AltName 611224145Sdim << ":\n" 612224145Sdim << " AsmStrs = AsmStrs" << AltName << ";\n" 613224145Sdim << " RegAsmOffset = RegAsmOffset" << AltName << ";\n" 614224145Sdim << " break;\n"; 615224145Sdim } 616224145Sdim O << "}\n"; 617198090Srdivacky } 618218893Sdim 619224145Sdim O << " assert (*(AsmStrs+RegAsmOffset[RegNo-1]) &&\n" 620224145Sdim << " \"Invalid alt name index for register!\");\n" 621224145Sdim << " return AsmStrs+RegAsmOffset[RegNo-1];\n" 622198090Srdivacky << "}\n"; 623198090Srdivacky} 624198090Srdivacky 625221345Sdimnamespace { 626221345Sdim// IAPrinter - Holds information about an InstAlias. Two InstAliases match if 627221345Sdim// they both have the same conditionals. In which case, we cannot print out the 628221345Sdim// alias for that pattern. 629221345Sdimclass IAPrinter { 630221345Sdim std::vector<std::string> Conds; 631221345Sdim std::map<StringRef, unsigned> OpMap; 632221345Sdim std::string Result; 633221345Sdim std::string AsmString; 634234982Sdim SmallVector<Record*, 4> ReqFeatures; 635221345Sdimpublic: 636224145Sdim IAPrinter(std::string R, std::string AS) 637224145Sdim : Result(R), AsmString(AS) {} 638221345Sdim 639221345Sdim void addCond(const std::string &C) { Conds.push_back(C); } 640221345Sdim 641263508Sdim void addOperand(StringRef Op, unsigned Idx) { 642263508Sdim assert(Idx < 0xFF && "Index too large!"); 643263508Sdim OpMap[Op] = Idx; 644263508Sdim } 645221345Sdim unsigned getOpIndex(StringRef Op) { return OpMap[Op]; } 646221345Sdim bool isOpMapped(StringRef Op) { return OpMap.find(Op) != OpMap.end(); } 647221345Sdim 648224145Sdim void print(raw_ostream &O) { 649221345Sdim if (Conds.empty() && ReqFeatures.empty()) { 650221345Sdim O.indent(6) << "return true;\n"; 651224145Sdim return; 652221345Sdim } 653221345Sdim 654221345Sdim O << "if ("; 655221345Sdim 656221345Sdim for (std::vector<std::string>::iterator 657221345Sdim I = Conds.begin(), E = Conds.end(); I != E; ++I) { 658221345Sdim if (I != Conds.begin()) { 659221345Sdim O << " &&\n"; 660221345Sdim O.indent(8); 661221345Sdim } 662221345Sdim 663221345Sdim O << *I; 664221345Sdim } 665221345Sdim 666221345Sdim O << ") {\n"; 667221345Sdim O.indent(6) << "// " << Result << "\n"; 668221345Sdim 669263508Sdim // Directly mangle mapped operands into the string. Each operand is 670263508Sdim // identified by a '$' sign followed by a byte identifying the number of the 671263508Sdim // operand. We add one to the index to avoid zero bytes. 672263508Sdim std::pair<StringRef, StringRef> ASM = StringRef(AsmString).split(' '); 673263508Sdim SmallString<128> OutString = ASM.first; 674263508Sdim if (!ASM.second.empty()) { 675263508Sdim raw_svector_ostream OS(OutString); 676263508Sdim OS << ' '; 677263508Sdim for (StringRef::iterator I = ASM.second.begin(), E = ASM.second.end(); 678263508Sdim I != E;) { 679263508Sdim OS << *I; 680263508Sdim if (*I == '$') { 681263508Sdim StringRef::iterator Start = ++I; 682263508Sdim while (I != E && 683263508Sdim ((*I >= 'a' && *I <= 'z') || (*I >= 'A' && *I <= 'Z') || 684263508Sdim (*I >= '0' && *I <= '9') || *I == '_')) 685263508Sdim ++I; 686263508Sdim StringRef Name(Start, I - Start); 687263508Sdim assert(isOpMapped(Name) && "Unmapped operand!"); 688263508Sdim OS << format("\\x%02X", (unsigned char)getOpIndex(Name) + 1); 689263508Sdim } else { 690263508Sdim ++I; 691263508Sdim } 692263508Sdim } 693263508Sdim } 694221345Sdim 695263508Sdim // Emit the string. 696263508Sdim O.indent(6) << "AsmString = \"" << OutString.str() << "\";\n"; 697263508Sdim 698221345Sdim O.indent(6) << "break;\n"; 699221345Sdim O.indent(4) << '}'; 700221345Sdim } 701221345Sdim 702221345Sdim bool operator==(const IAPrinter &RHS) { 703221345Sdim if (Conds.size() != RHS.Conds.size()) 704221345Sdim return false; 705221345Sdim 706221345Sdim unsigned Idx = 0; 707221345Sdim for (std::vector<std::string>::iterator 708221345Sdim I = Conds.begin(), E = Conds.end(); I != E; ++I) 709221345Sdim if (*I != RHS.Conds[Idx++]) 710221345Sdim return false; 711221345Sdim 712221345Sdim return true; 713221345Sdim } 714221345Sdim 715221345Sdim bool operator()(const IAPrinter &RHS) { 716221345Sdim if (Conds.size() < RHS.Conds.size()) 717221345Sdim return true; 718221345Sdim 719221345Sdim unsigned Idx = 0; 720221345Sdim for (std::vector<std::string>::iterator 721221345Sdim I = Conds.begin(), E = Conds.end(); I != E; ++I) 722221345Sdim if (*I != RHS.Conds[Idx++]) 723221345Sdim return *I < RHS.Conds[Idx++]; 724221345Sdim 725221345Sdim return false; 726221345Sdim } 727221345Sdim}; 728221345Sdim 729221345Sdim} // end anonymous namespace 730221345Sdim 731224145Sdimstatic unsigned CountNumOperands(StringRef AsmString) { 732224145Sdim unsigned NumOps = 0; 733224145Sdim std::pair<StringRef, StringRef> ASM = AsmString.split(' '); 734224145Sdim 735224145Sdim while (!ASM.second.empty()) { 736224145Sdim ++NumOps; 737224145Sdim ASM = ASM.second.split(' '); 738224145Sdim } 739224145Sdim 740224145Sdim return NumOps; 741224145Sdim} 742224145Sdim 743224145Sdimstatic unsigned CountResultNumOperands(StringRef AsmString) { 744224145Sdim unsigned NumOps = 0; 745224145Sdim std::pair<StringRef, StringRef> ASM = AsmString.split('\t'); 746224145Sdim 747224145Sdim if (!ASM.second.empty()) { 748224145Sdim size_t I = ASM.second.find('{'); 749224145Sdim StringRef Str = ASM.second; 750224145Sdim if (I != StringRef::npos) 751224145Sdim Str = ASM.second.substr(I, ASM.second.find('|', I)); 752224145Sdim 753224145Sdim ASM = Str.split(' '); 754224145Sdim 755224145Sdim do { 756224145Sdim ++NumOps; 757224145Sdim ASM = ASM.second.split(' '); 758224145Sdim } while (!ASM.second.empty()); 759224145Sdim } 760224145Sdim 761224145Sdim return NumOps; 762224145Sdim} 763224145Sdim 764221345Sdimvoid AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) { 765221345Sdim Record *AsmWriter = Target.getAsmWriter(); 766221345Sdim 767224145Sdim if (!AsmWriter->getValueAsBit("isMCAsmWriter")) 768224145Sdim return; 769224145Sdim 770221345Sdim O << "\n#ifdef PRINT_ALIAS_INSTR\n"; 771221345Sdim O << "#undef PRINT_ALIAS_INSTR\n\n"; 772221345Sdim 773219077Sdim // Emit the method that prints the alias instruction. 774219077Sdim std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName"); 775219077Sdim 776219077Sdim std::vector<Record*> AllInstAliases = 777219077Sdim Records.getAllDerivedDefinitions("InstAlias"); 778219077Sdim 779219077Sdim // Create a map from the qualified name to a list of potential matches. 780219077Sdim std::map<std::string, std::vector<CodeGenInstAlias*> > AliasMap; 781219077Sdim for (std::vector<Record*>::iterator 782219077Sdim I = AllInstAliases.begin(), E = AllInstAliases.end(); I != E; ++I) { 783219077Sdim CodeGenInstAlias *Alias = new CodeGenInstAlias(*I, Target); 784219077Sdim const Record *R = *I; 785221345Sdim if (!R->getValueAsBit("EmitAlias")) 786221345Sdim continue; // We were told not to emit the alias, but to emit the aliasee. 787219077Sdim const DagInit *DI = R->getValueAsDag("ResultInst"); 788243830Sdim const DefInit *Op = cast<DefInit>(DI->getOperator()); 789219077Sdim AliasMap[getQualifiedName(Op->getDef())].push_back(Alias); 790219077Sdim } 791219077Sdim 792221345Sdim // A map of which conditions need to be met for each instruction operand 793221345Sdim // before it can be matched to the mnemonic. 794221345Sdim std::map<std::string, std::vector<IAPrinter*> > IAPrinterMap; 795219077Sdim 796219077Sdim for (std::map<std::string, std::vector<CodeGenInstAlias*> >::iterator 797219077Sdim I = AliasMap.begin(), E = AliasMap.end(); I != E; ++I) { 798219077Sdim std::vector<CodeGenInstAlias*> &Aliases = I->second; 799219077Sdim 800219077Sdim for (std::vector<CodeGenInstAlias*>::iterator 801219077Sdim II = Aliases.begin(), IE = Aliases.end(); II != IE; ++II) { 802219077Sdim const CodeGenInstAlias *CGA = *II; 803224145Sdim unsigned LastOpNo = CGA->ResultInstOperandIndex.size(); 804224145Sdim unsigned NumResultOps = 805224145Sdim CountResultNumOperands(CGA->ResultInst->AsmString); 806221345Sdim 807224145Sdim // Don't emit the alias if it has more operands than what it's aliasing. 808224145Sdim if (NumResultOps < CountNumOperands(CGA->AsmString)) 809224145Sdim continue; 810221345Sdim 811224145Sdim IAPrinter *IAP = new IAPrinter(CGA->Result->getAsString(), 812224145Sdim CGA->AsmString); 813219077Sdim 814219077Sdim std::string Cond; 815221345Sdim Cond = std::string("MI->getNumOperands() == ") + llvm::utostr(LastOpNo); 816221345Sdim IAP->addCond(Cond); 817219077Sdim 818219077Sdim bool CantHandle = false; 819219077Sdim 820219077Sdim for (unsigned i = 0, e = LastOpNo; i != e; ++i) { 821219077Sdim const CodeGenInstAlias::ResultOperand &RO = CGA->ResultOperands[i]; 822219077Sdim 823219077Sdim switch (RO.Kind) { 824219077Sdim case CodeGenInstAlias::ResultOperand::K_Record: { 825219077Sdim const Record *Rec = RO.getRecord(); 826219077Sdim StringRef ROName = RO.getName(); 827219077Sdim 828224145Sdim 829224145Sdim if (Rec->isSubClassOf("RegisterOperand")) 830224145Sdim Rec = Rec->getValueAsDef("RegClass"); 831219077Sdim if (Rec->isSubClassOf("RegisterClass")) { 832221345Sdim Cond = std::string("MI->getOperand(")+llvm::utostr(i)+").isReg()"; 833221345Sdim IAP->addCond(Cond); 834221345Sdim 835221345Sdim if (!IAP->isOpMapped(ROName)) { 836221345Sdim IAP->addOperand(ROName, i); 837249423Sdim Record *R = CGA->ResultOperands[i].getRecord(); 838249423Sdim if (R->isSubClassOf("RegisterOperand")) 839249423Sdim R = R->getValueAsDef("RegClass"); 840234353Sdim Cond = std::string("MRI.getRegClass(") + Target.getName() + "::" + 841249423Sdim R->getName() + "RegClassID)" 842234353Sdim ".contains(MI->getOperand(" + llvm::utostr(i) + ").getReg())"; 843221345Sdim IAP->addCond(Cond); 844219077Sdim } else { 845221345Sdim Cond = std::string("MI->getOperand(") + 846221345Sdim llvm::utostr(i) + ").getReg() == MI->getOperand(" + 847221345Sdim llvm::utostr(IAP->getOpIndex(ROName)) + ").getReg()"; 848221345Sdim IAP->addCond(Cond); 849219077Sdim } 850219077Sdim } else { 851219077Sdim assert(Rec->isSubClassOf("Operand") && "Unexpected operand!"); 852224145Sdim // FIXME: We may need to handle these situations. 853221345Sdim delete IAP; 854221345Sdim IAP = 0; 855219077Sdim CantHandle = true; 856219077Sdim break; 857219077Sdim } 858219077Sdim 859219077Sdim break; 860219077Sdim } 861249423Sdim case CodeGenInstAlias::ResultOperand::K_Imm: { 862249423Sdim std::string Op = "MI->getOperand(" + llvm::utostr(i) + ")"; 863249423Sdim 864249423Sdim // Just because the alias has an immediate result, doesn't mean the 865249423Sdim // MCInst will. An MCExpr could be present, for example. 866249423Sdim IAP->addCond(Op + ".isImm()"); 867249423Sdim 868249423Sdim Cond = Op + ".getImm() == " 869249423Sdim + llvm::utostr(CGA->ResultOperands[i].getImm()); 870221345Sdim IAP->addCond(Cond); 871219077Sdim break; 872249423Sdim } 873219077Sdim case CodeGenInstAlias::ResultOperand::K_Reg: 874234353Sdim // If this is zero_reg, something's playing tricks we're not 875234353Sdim // equipped to handle. 876234353Sdim if (!CGA->ResultOperands[i].getRegister()) { 877234353Sdim CantHandle = true; 878234353Sdim break; 879234353Sdim } 880234353Sdim 881221345Sdim Cond = std::string("MI->getOperand(") + 882221345Sdim llvm::utostr(i) + ").getReg() == " + Target.getName() + 883221345Sdim "::" + CGA->ResultOperands[i].getRegister()->getName(); 884221345Sdim IAP->addCond(Cond); 885219077Sdim break; 886219077Sdim } 887219077Sdim 888221345Sdim if (!IAP) break; 889219077Sdim } 890219077Sdim 891219077Sdim if (CantHandle) continue; 892221345Sdim IAPrinterMap[I->first].push_back(IAP); 893221345Sdim } 894221345Sdim } 895219077Sdim 896223017Sdim std::string Header; 897223017Sdim raw_string_ostream HeaderO(Header); 898219077Sdim 899223017Sdim HeaderO << "bool " << Target.getName() << ClassName 900224145Sdim << "::printAliasInstr(const MCInst" 901223017Sdim << " *MI, raw_ostream &OS) {\n"; 902223017Sdim 903221345Sdim std::string Cases; 904221345Sdim raw_string_ostream CasesO(Cases); 905219077Sdim 906221345Sdim for (std::map<std::string, std::vector<IAPrinter*> >::iterator 907221345Sdim I = IAPrinterMap.begin(), E = IAPrinterMap.end(); I != E; ++I) { 908221345Sdim std::vector<IAPrinter*> &IAPs = I->second; 909221345Sdim std::vector<IAPrinter*> UniqueIAPs; 910219077Sdim 911221345Sdim for (std::vector<IAPrinter*>::iterator 912221345Sdim II = IAPs.begin(), IE = IAPs.end(); II != IE; ++II) { 913221345Sdim IAPrinter *LHS = *II; 914221345Sdim bool IsDup = false; 915221345Sdim for (std::vector<IAPrinter*>::iterator 916221345Sdim III = IAPs.begin(), IIE = IAPs.end(); III != IIE; ++III) { 917221345Sdim IAPrinter *RHS = *III; 918221345Sdim if (LHS != RHS && *LHS == *RHS) { 919221345Sdim IsDup = true; 920221345Sdim break; 921221345Sdim } 922221345Sdim } 923221345Sdim 924221345Sdim if (!IsDup) UniqueIAPs.push_back(LHS); 925219077Sdim } 926219077Sdim 927221345Sdim if (UniqueIAPs.empty()) continue; 928219077Sdim 929221345Sdim CasesO.indent(2) << "case " << I->first << ":\n"; 930221345Sdim 931221345Sdim for (std::vector<IAPrinter*>::iterator 932221345Sdim II = UniqueIAPs.begin(), IE = UniqueIAPs.end(); II != IE; ++II) { 933221345Sdim IAPrinter *IAP = *II; 934221345Sdim CasesO.indent(4); 935224145Sdim IAP->print(CasesO); 936221345Sdim CasesO << '\n'; 937219077Sdim } 938219077Sdim 939221345Sdim CasesO.indent(4) << "return false;\n"; 940221345Sdim } 941219077Sdim 942224145Sdim if (CasesO.str().empty()) { 943223017Sdim O << HeaderO.str(); 944221345Sdim O << " return false;\n"; 945221345Sdim O << "}\n\n"; 946221345Sdim O << "#endif // PRINT_ALIAS_INSTR\n"; 947221345Sdim return; 948219077Sdim } 949219077Sdim 950223017Sdim O << HeaderO.str(); 951263508Sdim O.indent(2) << "const char *AsmString;\n"; 952221345Sdim O.indent(2) << "switch (MI->getOpcode()) {\n"; 953221345Sdim O.indent(2) << "default: return false;\n"; 954221345Sdim O << CasesO.str(); 955221345Sdim O.indent(2) << "}\n\n"; 956219077Sdim 957219077Sdim // Code that prints the alias, replacing the operands with the ones from the 958219077Sdim // MCInst. 959263508Sdim O << " unsigned I = 0;\n"; 960263508Sdim O << " while (AsmString[I] != ' ' && AsmString[I] != '\\0')\n"; 961263508Sdim O << " ++I;\n"; 962263508Sdim O << " OS << '\\t' << StringRef(AsmString, I);\n"; 963219077Sdim 964263508Sdim O << " if (AsmString[I] != '\\0') {\n"; 965219077Sdim O << " OS << '\\t';\n"; 966263508Sdim O << " do {\n"; 967263508Sdim O << " if (AsmString[I] == '$') {\n"; 968263508Sdim O << " ++I;\n"; 969263508Sdim O << " printOperand(MI, unsigned(AsmString[I++]) - 1, OS);\n"; 970219077Sdim O << " } else {\n"; 971263508Sdim O << " OS << AsmString[I++];\n"; 972219077Sdim O << " }\n"; 973263508Sdim O << " } while (AsmString[I] != '\\0');\n"; 974219077Sdim O << " }\n\n"; 975234982Sdim 976221345Sdim O << " return true;\n"; 977219077Sdim O << "}\n\n"; 978219077Sdim 979219077Sdim O << "#endif // PRINT_ALIAS_INSTR\n"; 980219077Sdim} 981219077Sdim 982263508SdimAsmWriterEmitter::AsmWriterEmitter(RecordKeeper &R) : Records(R), Target(R) { 983263508Sdim Record *AsmWriter = Target.getAsmWriter(); 984263508Sdim for (CodeGenTarget::inst_iterator I = Target.inst_begin(), 985263508Sdim E = Target.inst_end(); 986263508Sdim I != E; ++I) 987263508Sdim if (!(*I)->AsmString.empty() && (*I)->TheDef->getName() != "PHI") 988263508Sdim Instructions.push_back( 989263508Sdim AsmWriterInst(**I, AsmWriter->getValueAsInt("Variant"), 990263508Sdim AsmWriter->getValueAsInt("FirstOperandColumn"), 991263508Sdim AsmWriter->getValueAsInt("OperandSpacing"))); 992263508Sdim 993263508Sdim // Get the instruction numbering. 994263508Sdim NumberedInstructions = Target.getInstructionsByEnumValue(); 995263508Sdim 996263508Sdim // Compute the CodeGenInstruction -> AsmWriterInst mapping. Note that not 997263508Sdim // all machine instructions are necessarily being printed, so there may be 998263508Sdim // target instructions not in this map. 999263508Sdim for (unsigned i = 0, e = Instructions.size(); i != e; ++i) 1000263508Sdim CGIAWIMap.insert(std::make_pair(Instructions[i].CGI, &Instructions[i])); 1001263508Sdim} 1002263508Sdim 1003198090Srdivackyvoid AsmWriterEmitter::run(raw_ostream &O) { 1004198090Srdivacky EmitPrintInstruction(O); 1005198090Srdivacky EmitGetRegisterName(O); 1006219077Sdim EmitPrintAliasInstruction(O); 1007198090Srdivacky} 1008198090Srdivacky 1009239462Sdim 1010239462Sdimnamespace llvm { 1011239462Sdim 1012239462Sdimvoid EmitAsmWriter(RecordKeeper &RK, raw_ostream &OS) { 1013239462Sdim emitSourceFileHeader("Assembly Writer Source Fragment", OS); 1014239462Sdim AsmWriterEmitter(RK).run(OS); 1015239462Sdim} 1016239462Sdim 1017239462Sdim} // End llvm namespace 1018