AsmWriterEmitter.cpp revision a6dc9fb745962564fac3b18da28736b2e094c417
12e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner//===- AsmWriterEmitter.cpp - Generate an assembly writer -----------------===// 23da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman// 32e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner// The LLVM Compiler Infrastructure 42e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner// 52e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner// This file was developed by the LLVM research group and is distributed under 62e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner// the University of Illinois Open Source License. See LICENSE.TXT for details. 73da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman// 82e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner//===----------------------------------------------------------------------===// 92e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner// 102e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner// This tablegen backend is emits an assembly printer for the current target. 112e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner// Note that this is currently fairly skeletal, but will grow over time. 122e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner// 132e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner//===----------------------------------------------------------------------===// 142e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner 152e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner#include "AsmWriterEmitter.h" 162e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner#include "CodeGenTarget.h" 17175580c0f36b026daf9de0adabdb7ddcf7619db6Chris Lattner#include "Record.h" 186af022f255257bee7c6d6903ff4caa2217d51502Chris Lattner#include "llvm/ADT/StringExtras.h" 19bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner#include "llvm/Support/Debug.h" 20bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner#include "llvm/Support/MathExtras.h" 21615ed993e115f8bc97ff0678aa861629fec93880Jeff Cohen#include <algorithm> 222e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner#include <ostream> 232e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattnerusing namespace llvm; 242e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner 25076efa771aa634801202f7b8189e33ee79dfc4edChris Lattnerstatic bool isIdentChar(char C) { 26076efa771aa634801202f7b8189e33ee79dfc4edChris Lattner return (C >= 'a' && C <= 'z') || 27076efa771aa634801202f7b8189e33ee79dfc4edChris Lattner (C >= 'A' && C <= 'Z') || 28076efa771aa634801202f7b8189e33ee79dfc4edChris Lattner (C >= '0' && C <= '9') || 29076efa771aa634801202f7b8189e33ee79dfc4edChris Lattner C == '_'; 30076efa771aa634801202f7b8189e33ee79dfc4edChris Lattner} 31076efa771aa634801202f7b8189e33ee79dfc4edChris Lattner 32b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattnernamespace { 33b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner struct AsmWriterOperand { 34b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner enum { isLiteralTextOperand, isMachineInstrOperand } OperandType; 35b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner 36b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner /// Str - For isLiteralTextOperand, this IS the literal text. For 37b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner /// isMachineInstrOperand, this is the PrinterMethodName for the operand. 38b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner std::string Str; 39b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner 40b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner /// MiOpNo - For isMachineInstrOperand, this is the operand number of the 41b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner /// machine instruction. 42b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner unsigned MIOpNo; 4304cadb3684b14e4aad19f9f29e6c14539866bd56Chris Lattner 4404cadb3684b14e4aad19f9f29e6c14539866bd56Chris Lattner /// MiModifier - For isMachineInstrOperand, this is the modifier string for 4504cadb3684b14e4aad19f9f29e6c14539866bd56Chris Lattner /// an operand, specified with syntax like ${opname:modifier}. 4604cadb3684b14e4aad19f9f29e6c14539866bd56Chris Lattner std::string MiModifier; 47b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner 48b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner AsmWriterOperand(const std::string &LitStr) 49391c5d231a1d251ea9dc3d8745547c957db94ca4Nate Begeman : OperandType(isLiteralTextOperand), Str(LitStr) {} 50b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner 5104cadb3684b14e4aad19f9f29e6c14539866bd56Chris Lattner AsmWriterOperand(const std::string &Printer, unsigned OpNo, 5204cadb3684b14e4aad19f9f29e6c14539866bd56Chris Lattner const std::string &Modifier) 5304cadb3684b14e4aad19f9f29e6c14539866bd56Chris Lattner : OperandType(isMachineInstrOperand), Str(Printer), MIOpNo(OpNo), 5404cadb3684b14e4aad19f9f29e6c14539866bd56Chris Lattner MiModifier(Modifier) {} 55b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner 56870c016934bacf43995d89531b166ae095ee3675Chris Lattner bool operator!=(const AsmWriterOperand &Other) const { 57870c016934bacf43995d89531b166ae095ee3675Chris Lattner if (OperandType != Other.OperandType || Str != Other.Str) return true; 58870c016934bacf43995d89531b166ae095ee3675Chris Lattner if (OperandType == isMachineInstrOperand) 5904cadb3684b14e4aad19f9f29e6c14539866bd56Chris Lattner return MIOpNo != Other.MIOpNo || MiModifier != Other.MiModifier; 60870c016934bacf43995d89531b166ae095ee3675Chris Lattner return false; 61870c016934bacf43995d89531b166ae095ee3675Chris Lattner } 6238c0751a128c0387c04c0f96a2f092340aaa7545Chris Lattner bool operator==(const AsmWriterOperand &Other) const { 6338c0751a128c0387c04c0f96a2f092340aaa7545Chris Lattner return !operator!=(Other); 6438c0751a128c0387c04c0f96a2f092340aaa7545Chris Lattner } 65bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner 66bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner /// getCode - Return the code that prints this operand. 67bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner std::string getCode() const; 68b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner }; 69bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner} 70b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner 71bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattnernamespace llvm { 72b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner struct AsmWriterInst { 73b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner std::vector<AsmWriterOperand> Operands; 745765dba5ce9f493f063a7caf1106e7db9b6693b6Chris Lattner const CodeGenInstruction *CGI; 753da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman 765765dba5ce9f493f063a7caf1106e7db9b6693b6Chris Lattner AsmWriterInst(const CodeGenInstruction &CGI, unsigned Variant); 77870c016934bacf43995d89531b166ae095ee3675Chris Lattner 78f876668518097413a904537ce9d249953987508cChris Lattner /// MatchesAllButOneOp - If this instruction is exactly identical to the 79f876668518097413a904537ce9d249953987508cChris Lattner /// specified instruction except for one differing operand, return the 80f876668518097413a904537ce9d249953987508cChris Lattner /// differing operand number. Otherwise return ~0. 81f876668518097413a904537ce9d249953987508cChris Lattner unsigned MatchesAllButOneOp(const AsmWriterInst &Other) const; 82870c016934bacf43995d89531b166ae095ee3675Chris Lattner 83b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner private: 84b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner void AddLiteralString(const std::string &Str) { 85b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner // If the last operand was already a literal text string, append this to 86b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner // it, otherwise add a new operand. 87b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner if (!Operands.empty() && 88b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner Operands.back().OperandType == AsmWriterOperand::isLiteralTextOperand) 89b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner Operands.back().Str.append(Str); 90b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner else 91b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner Operands.push_back(AsmWriterOperand(Str)); 92b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner } 93b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner }; 94b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner} 95b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner 96b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner 97bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattnerstd::string AsmWriterOperand::getCode() const { 98b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner if (OperandType == isLiteralTextOperand) 99bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner return "O << \"" + Str + "\"; "; 100bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner 101bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner std::string Result = Str + "(MI, " + utostr(MIOpNo); 102bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner if (!MiModifier.empty()) 103bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner Result += ", \"" + MiModifier + '"'; 104bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner return Result + "); "; 105b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner} 106b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner 107b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner 108b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner/// ParseAsmString - Parse the specified Instruction's AsmString into this 109b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner/// AsmWriterInst. 110b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner/// 1115765dba5ce9f493f063a7caf1106e7db9b6693b6Chris LattnerAsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, unsigned Variant) { 1125765dba5ce9f493f063a7caf1106e7db9b6693b6Chris Lattner this->CGI = &CGI; 113b03b080a8208b25946bcb96c2a10661b53547ff6Chris Lattner unsigned CurVariant = ~0U; // ~0 if we are outside a {.|.|.} region, other #. 114b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner 1151cf9d961b2fc35c8ba67f20fd36c2b5fb51c9709Chris Lattner // NOTE: Any extensions to this code need to be mirrored in the 1161cf9d961b2fc35c8ba67f20fd36c2b5fb51c9709Chris Lattner // AsmPrinter::printInlineAsm code that executes as compile time (assuming 1171cf9d961b2fc35c8ba67f20fd36c2b5fb51c9709Chris Lattner // that inline asm strings should also get the new feature)! 118b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner const std::string &AsmString = CGI.AsmString; 119b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner std::string::size_type LastEmitted = 0; 120b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner while (LastEmitted != AsmString.size()) { 121b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner std::string::size_type DollarPos = 122b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner AsmString.find_first_of("${|}", LastEmitted); 123b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner if (DollarPos == std::string::npos) DollarPos = AsmString.size(); 124b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner 125b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner // Emit a constant string fragment. 126b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner if (DollarPos != LastEmitted) { 127b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner // TODO: this should eventually handle escaping. 128b03b080a8208b25946bcb96c2a10661b53547ff6Chris Lattner if (CurVariant == Variant || CurVariant == ~0U) 129b03b080a8208b25946bcb96c2a10661b53547ff6Chris Lattner AddLiteralString(std::string(AsmString.begin()+LastEmitted, 130b03b080a8208b25946bcb96c2a10661b53547ff6Chris Lattner AsmString.begin()+DollarPos)); 131b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner LastEmitted = DollarPos; 132b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner } else if (AsmString[DollarPos] == '{') { 133b03b080a8208b25946bcb96c2a10661b53547ff6Chris Lattner if (CurVariant != ~0U) 13400b16889ab461b7ecef1c91ade101186b7f1fce2Jeff Cohen throw "Nested variants found for instruction '" + 1353e3def9c1955ab061575eb9a99aa4297a4de5299Chris Lattner CGI.TheDef->getName() + "'!"; 136b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner LastEmitted = DollarPos+1; 137b03b080a8208b25946bcb96c2a10661b53547ff6Chris Lattner CurVariant = 0; // We are now inside of the variant! 138b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner } else if (AsmString[DollarPos] == '|') { 139b03b080a8208b25946bcb96c2a10661b53547ff6Chris Lattner if (CurVariant == ~0U) 140b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner throw "'|' character found outside of a variant in instruction '" 1413e3def9c1955ab061575eb9a99aa4297a4de5299Chris Lattner + CGI.TheDef->getName() + "'!"; 142b03b080a8208b25946bcb96c2a10661b53547ff6Chris Lattner ++CurVariant; 143b03b080a8208b25946bcb96c2a10661b53547ff6Chris Lattner ++LastEmitted; 144b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner } else if (AsmString[DollarPos] == '}') { 145b03b080a8208b25946bcb96c2a10661b53547ff6Chris Lattner if (CurVariant == ~0U) 146b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner throw "'}' character found outside of a variant in instruction '" 1473e3def9c1955ab061575eb9a99aa4297a4de5299Chris Lattner + CGI.TheDef->getName() + "'!"; 148b03b080a8208b25946bcb96c2a10661b53547ff6Chris Lattner ++LastEmitted; 149b03b080a8208b25946bcb96c2a10661b53547ff6Chris Lattner CurVariant = ~0U; 150b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner } else if (DollarPos+1 != AsmString.size() && 151b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner AsmString[DollarPos+1] == '$') { 152b03b080a8208b25946bcb96c2a10661b53547ff6Chris Lattner if (CurVariant == Variant || CurVariant == ~0U) 153b03b080a8208b25946bcb96c2a10661b53547ff6Chris Lattner AddLiteralString("$"); // "$$" -> $ 154b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner LastEmitted = DollarPos+2; 155b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner } else { 156b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner // Get the name of the variable. 157b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner std::string::size_type VarEnd = DollarPos+1; 158afc545616a5a062e6872114f9f1c23070e5e753bNate Begeman 159afc545616a5a062e6872114f9f1c23070e5e753bNate Begeman // handle ${foo}bar as $foo by detecting whether the character following 160afc545616a5a062e6872114f9f1c23070e5e753bNate Begeman // the dollar sign is a curly brace. If so, advance VarEnd and DollarPos 161afc545616a5a062e6872114f9f1c23070e5e753bNate Begeman // so the variable name does not contain the leading curly brace. 162afc545616a5a062e6872114f9f1c23070e5e753bNate Begeman bool hasCurlyBraces = false; 163afc545616a5a062e6872114f9f1c23070e5e753bNate Begeman if (VarEnd < AsmString.size() && '{' == AsmString[VarEnd]) { 164afc545616a5a062e6872114f9f1c23070e5e753bNate Begeman hasCurlyBraces = true; 165afc545616a5a062e6872114f9f1c23070e5e753bNate Begeman ++DollarPos; 166afc545616a5a062e6872114f9f1c23070e5e753bNate Begeman ++VarEnd; 167afc545616a5a062e6872114f9f1c23070e5e753bNate Begeman } 168afc545616a5a062e6872114f9f1c23070e5e753bNate Begeman 169b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner while (VarEnd < AsmString.size() && isIdentChar(AsmString[VarEnd])) 170b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner ++VarEnd; 171b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner std::string VarName(AsmString.begin()+DollarPos+1, 172b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner AsmString.begin()+VarEnd); 173afc545616a5a062e6872114f9f1c23070e5e753bNate Begeman 17404cadb3684b14e4aad19f9f29e6c14539866bd56Chris Lattner // Modifier - Support ${foo:modifier} syntax, where "modifier" is passed 17504cadb3684b14e4aad19f9f29e6c14539866bd56Chris Lattner // into printOperand. 17604cadb3684b14e4aad19f9f29e6c14539866bd56Chris Lattner std::string Modifier; 17704cadb3684b14e4aad19f9f29e6c14539866bd56Chris Lattner 178afc545616a5a062e6872114f9f1c23070e5e753bNate Begeman // In order to avoid starting the next string at the terminating curly 179afc545616a5a062e6872114f9f1c23070e5e753bNate Begeman // brace, advance the end position past it if we found an opening curly 180afc545616a5a062e6872114f9f1c23070e5e753bNate Begeman // brace. 181afc545616a5a062e6872114f9f1c23070e5e753bNate Begeman if (hasCurlyBraces) { 182afc545616a5a062e6872114f9f1c23070e5e753bNate Begeman if (VarEnd >= AsmString.size()) 183afc545616a5a062e6872114f9f1c23070e5e753bNate Begeman throw "Reached end of string before terminating curly brace in '" 1843e3def9c1955ab061575eb9a99aa4297a4de5299Chris Lattner + CGI.TheDef->getName() + "'"; 18504cadb3684b14e4aad19f9f29e6c14539866bd56Chris Lattner 18604cadb3684b14e4aad19f9f29e6c14539866bd56Chris Lattner // Look for a modifier string. 18704cadb3684b14e4aad19f9f29e6c14539866bd56Chris Lattner if (AsmString[VarEnd] == ':') { 18804cadb3684b14e4aad19f9f29e6c14539866bd56Chris Lattner ++VarEnd; 18904cadb3684b14e4aad19f9f29e6c14539866bd56Chris Lattner if (VarEnd >= AsmString.size()) 19004cadb3684b14e4aad19f9f29e6c14539866bd56Chris Lattner throw "Reached end of string before terminating curly brace in '" 19104cadb3684b14e4aad19f9f29e6c14539866bd56Chris Lattner + CGI.TheDef->getName() + "'"; 19204cadb3684b14e4aad19f9f29e6c14539866bd56Chris Lattner 19304cadb3684b14e4aad19f9f29e6c14539866bd56Chris Lattner unsigned ModifierStart = VarEnd; 19404cadb3684b14e4aad19f9f29e6c14539866bd56Chris Lattner while (VarEnd < AsmString.size() && isIdentChar(AsmString[VarEnd])) 19504cadb3684b14e4aad19f9f29e6c14539866bd56Chris Lattner ++VarEnd; 19604cadb3684b14e4aad19f9f29e6c14539866bd56Chris Lattner Modifier = std::string(AsmString.begin()+ModifierStart, 19704cadb3684b14e4aad19f9f29e6c14539866bd56Chris Lattner AsmString.begin()+VarEnd); 19804cadb3684b14e4aad19f9f29e6c14539866bd56Chris Lattner if (Modifier.empty()) 19904cadb3684b14e4aad19f9f29e6c14539866bd56Chris Lattner throw "Bad operand modifier name in '"+ CGI.TheDef->getName() + "'"; 20004cadb3684b14e4aad19f9f29e6c14539866bd56Chris Lattner } 20104cadb3684b14e4aad19f9f29e6c14539866bd56Chris Lattner 202afc545616a5a062e6872114f9f1c23070e5e753bNate Begeman if (AsmString[VarEnd] != '}') 203b03b080a8208b25946bcb96c2a10661b53547ff6Chris Lattner throw "Variable name beginning with '{' did not end with '}' in '" 2043e3def9c1955ab061575eb9a99aa4297a4de5299Chris Lattner + CGI.TheDef->getName() + "'"; 205afc545616a5a062e6872114f9f1c23070e5e753bNate Begeman ++VarEnd; 206afc545616a5a062e6872114f9f1c23070e5e753bNate Begeman } 207b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner if (VarName.empty()) 20800b16889ab461b7ecef1c91ade101186b7f1fce2Jeff Cohen throw "Stray '$' in '" + CGI.TheDef->getName() + 2093e3def9c1955ab061575eb9a99aa4297a4de5299Chris Lattner "' asm string, maybe you want $$?"; 210b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner 211b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner unsigned OpNo = CGI.getOperandNamed(VarName); 2125765dba5ce9f493f063a7caf1106e7db9b6693b6Chris Lattner CodeGenInstruction::OperandInfo OpInfo = CGI.OperandList[OpNo]; 213b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner 214b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner // If this is a two-address instruction and we are not accessing the 215b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner // 0th operand, remove an operand. 2165765dba5ce9f493f063a7caf1106e7db9b6693b6Chris Lattner unsigned MIOp = OpInfo.MIOperandNo; 217b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner if (CGI.isTwoAddress && MIOp != 0) { 218b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner if (MIOp == 1) 219b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner throw "Should refer to operand #0 instead of #1 for two-address" 2203e3def9c1955ab061575eb9a99aa4297a4de5299Chris Lattner " instruction '" + CGI.TheDef->getName() + "'!"; 221b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner --MIOp; 222b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner } 223b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner 224b03b080a8208b25946bcb96c2a10661b53547ff6Chris Lattner if (CurVariant == Variant || CurVariant == ~0U) 22504cadb3684b14e4aad19f9f29e6c14539866bd56Chris Lattner Operands.push_back(AsmWriterOperand(OpInfo.PrinterMethodName, MIOp, 22604cadb3684b14e4aad19f9f29e6c14539866bd56Chris Lattner Modifier)); 227b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner LastEmitted = VarEnd; 228b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner } 229b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner } 230b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner 231b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner AddLiteralString("\\n"); 232b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner} 233b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner 234f876668518097413a904537ce9d249953987508cChris Lattner/// MatchesAllButOneOp - If this instruction is exactly identical to the 235f876668518097413a904537ce9d249953987508cChris Lattner/// specified instruction except for one differing operand, return the differing 236f876668518097413a904537ce9d249953987508cChris Lattner/// operand number. If more than one operand mismatches, return ~1, otherwise 237f876668518097413a904537ce9d249953987508cChris Lattner/// if the instructions are identical return ~0. 238f876668518097413a904537ce9d249953987508cChris Lattnerunsigned AsmWriterInst::MatchesAllButOneOp(const AsmWriterInst &Other)const{ 239f876668518097413a904537ce9d249953987508cChris Lattner if (Operands.size() != Other.Operands.size()) return ~1; 240870c016934bacf43995d89531b166ae095ee3675Chris Lattner 241870c016934bacf43995d89531b166ae095ee3675Chris Lattner unsigned MismatchOperand = ~0U; 242870c016934bacf43995d89531b166ae095ee3675Chris Lattner for (unsigned i = 0, e = Operands.size(); i != e; ++i) { 243870c016934bacf43995d89531b166ae095ee3675Chris Lattner if (Operands[i] != Other.Operands[i]) 244f876668518097413a904537ce9d249953987508cChris Lattner if (MismatchOperand != ~0U) // Already have one mismatch? 245f876668518097413a904537ce9d249953987508cChris Lattner return ~1U; 2463da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman else 247870c016934bacf43995d89531b166ae095ee3675Chris Lattner MismatchOperand = i; 248870c016934bacf43995d89531b166ae095ee3675Chris Lattner } 249870c016934bacf43995d89531b166ae095ee3675Chris Lattner return MismatchOperand; 250870c016934bacf43995d89531b166ae095ee3675Chris Lattner} 251870c016934bacf43995d89531b166ae095ee3675Chris Lattner 25238c0751a128c0387c04c0f96a2f092340aaa7545Chris Lattnerstatic void PrintCases(std::vector<std::pair<std::string, 25338c0751a128c0387c04c0f96a2f092340aaa7545Chris Lattner AsmWriterOperand> > &OpsToPrint, std::ostream &O) { 25438c0751a128c0387c04c0f96a2f092340aaa7545Chris Lattner O << " case " << OpsToPrint.back().first << ": "; 25538c0751a128c0387c04c0f96a2f092340aaa7545Chris Lattner AsmWriterOperand TheOp = OpsToPrint.back().second; 25638c0751a128c0387c04c0f96a2f092340aaa7545Chris Lattner OpsToPrint.pop_back(); 25738c0751a128c0387c04c0f96a2f092340aaa7545Chris Lattner 25838c0751a128c0387c04c0f96a2f092340aaa7545Chris Lattner // Check to see if any other operands are identical in this list, and if so, 25938c0751a128c0387c04c0f96a2f092340aaa7545Chris Lattner // emit a case label for them. 26038c0751a128c0387c04c0f96a2f092340aaa7545Chris Lattner for (unsigned i = OpsToPrint.size(); i != 0; --i) 26138c0751a128c0387c04c0f96a2f092340aaa7545Chris Lattner if (OpsToPrint[i-1].second == TheOp) { 26238c0751a128c0387c04c0f96a2f092340aaa7545Chris Lattner O << "\n case " << OpsToPrint[i-1].first << ": "; 26338c0751a128c0387c04c0f96a2f092340aaa7545Chris Lattner OpsToPrint.erase(OpsToPrint.begin()+i-1); 26438c0751a128c0387c04c0f96a2f092340aaa7545Chris Lattner } 26538c0751a128c0387c04c0f96a2f092340aaa7545Chris Lattner 26638c0751a128c0387c04c0f96a2f092340aaa7545Chris Lattner // Finally, emit the code. 267bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner O << TheOp.getCode(); 26838c0751a128c0387c04c0f96a2f092340aaa7545Chris Lattner O << "break;\n"; 26938c0751a128c0387c04c0f96a2f092340aaa7545Chris Lattner} 27038c0751a128c0387c04c0f96a2f092340aaa7545Chris Lattner 271870c016934bacf43995d89531b166ae095ee3675Chris Lattner 272870c016934bacf43995d89531b166ae095ee3675Chris Lattner/// EmitInstructions - Emit the last instruction in the vector and any other 273870c016934bacf43995d89531b166ae095ee3675Chris Lattner/// instructions that are suitably similar to it. 274870c016934bacf43995d89531b166ae095ee3675Chris Lattnerstatic void EmitInstructions(std::vector<AsmWriterInst> &Insts, 275870c016934bacf43995d89531b166ae095ee3675Chris Lattner std::ostream &O) { 276870c016934bacf43995d89531b166ae095ee3675Chris Lattner AsmWriterInst FirstInst = Insts.back(); 277870c016934bacf43995d89531b166ae095ee3675Chris Lattner Insts.pop_back(); 278870c016934bacf43995d89531b166ae095ee3675Chris Lattner 279870c016934bacf43995d89531b166ae095ee3675Chris Lattner std::vector<AsmWriterInst> SimilarInsts; 280870c016934bacf43995d89531b166ae095ee3675Chris Lattner unsigned DifferingOperand = ~0; 281870c016934bacf43995d89531b166ae095ee3675Chris Lattner for (unsigned i = Insts.size(); i != 0; --i) { 282f876668518097413a904537ce9d249953987508cChris Lattner unsigned DiffOp = Insts[i-1].MatchesAllButOneOp(FirstInst); 283f876668518097413a904537ce9d249953987508cChris Lattner if (DiffOp != ~1U) { 284870c016934bacf43995d89531b166ae095ee3675Chris Lattner if (DifferingOperand == ~0U) // First match! 285870c016934bacf43995d89531b166ae095ee3675Chris Lattner DifferingOperand = DiffOp; 286870c016934bacf43995d89531b166ae095ee3675Chris Lattner 287870c016934bacf43995d89531b166ae095ee3675Chris Lattner // If this differs in the same operand as the rest of the instructions in 288870c016934bacf43995d89531b166ae095ee3675Chris Lattner // this class, move it to the SimilarInsts list. 289f876668518097413a904537ce9d249953987508cChris Lattner if (DifferingOperand == DiffOp || DiffOp == ~0U) { 290870c016934bacf43995d89531b166ae095ee3675Chris Lattner SimilarInsts.push_back(Insts[i-1]); 291870c016934bacf43995d89531b166ae095ee3675Chris Lattner Insts.erase(Insts.begin()+i-1); 292870c016934bacf43995d89531b166ae095ee3675Chris Lattner } 293870c016934bacf43995d89531b166ae095ee3675Chris Lattner } 294870c016934bacf43995d89531b166ae095ee3675Chris Lattner } 295870c016934bacf43995d89531b166ae095ee3675Chris Lattner 296a1e8a80b96d02c8667021049e7fba9050658f39bChris Lattner O << " case " << FirstInst.CGI->Namespace << "::" 297870c016934bacf43995d89531b166ae095ee3675Chris Lattner << FirstInst.CGI->TheDef->getName() << ":\n"; 298870c016934bacf43995d89531b166ae095ee3675Chris Lattner for (unsigned i = 0, e = SimilarInsts.size(); i != e; ++i) 299a1e8a80b96d02c8667021049e7fba9050658f39bChris Lattner O << " case " << SimilarInsts[i].CGI->Namespace << "::" 300870c016934bacf43995d89531b166ae095ee3675Chris Lattner << SimilarInsts[i].CGI->TheDef->getName() << ":\n"; 301870c016934bacf43995d89531b166ae095ee3675Chris Lattner for (unsigned i = 0, e = FirstInst.Operands.size(); i != e; ++i) { 302870c016934bacf43995d89531b166ae095ee3675Chris Lattner if (i != DifferingOperand) { 303870c016934bacf43995d89531b166ae095ee3675Chris Lattner // If the operand is the same for all instructions, just print it. 304bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner O << " " << FirstInst.Operands[i].getCode(); 305870c016934bacf43995d89531b166ae095ee3675Chris Lattner } else { 306870c016934bacf43995d89531b166ae095ee3675Chris Lattner // If this is the operand that varies between all of the instructions, 307870c016934bacf43995d89531b166ae095ee3675Chris Lattner // emit a switch for just this operand now. 308870c016934bacf43995d89531b166ae095ee3675Chris Lattner O << " switch (MI->getOpcode()) {\n"; 30938c0751a128c0387c04c0f96a2f092340aaa7545Chris Lattner std::vector<std::pair<std::string, AsmWriterOperand> > OpsToPrint; 310a1e8a80b96d02c8667021049e7fba9050658f39bChris Lattner OpsToPrint.push_back(std::make_pair(FirstInst.CGI->Namespace + "::" + 31138c0751a128c0387c04c0f96a2f092340aaa7545Chris Lattner FirstInst.CGI->TheDef->getName(), 31238c0751a128c0387c04c0f96a2f092340aaa7545Chris Lattner FirstInst.Operands[i])); 3133da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman 314870c016934bacf43995d89531b166ae095ee3675Chris Lattner for (unsigned si = 0, e = SimilarInsts.size(); si != e; ++si) { 31538c0751a128c0387c04c0f96a2f092340aaa7545Chris Lattner AsmWriterInst &AWI = SimilarInsts[si]; 316a1e8a80b96d02c8667021049e7fba9050658f39bChris Lattner OpsToPrint.push_back(std::make_pair(AWI.CGI->Namespace+"::"+ 31738c0751a128c0387c04c0f96a2f092340aaa7545Chris Lattner AWI.CGI->TheDef->getName(), 31838c0751a128c0387c04c0f96a2f092340aaa7545Chris Lattner AWI.Operands[i])); 319870c016934bacf43995d89531b166ae095ee3675Chris Lattner } 32038c0751a128c0387c04c0f96a2f092340aaa7545Chris Lattner std::reverse(OpsToPrint.begin(), OpsToPrint.end()); 32138c0751a128c0387c04c0f96a2f092340aaa7545Chris Lattner while (!OpsToPrint.empty()) 32238c0751a128c0387c04c0f96a2f092340aaa7545Chris Lattner PrintCases(OpsToPrint, O); 323870c016934bacf43995d89531b166ae095ee3675Chris Lattner O << " }"; 324870c016934bacf43995d89531b166ae095ee3675Chris Lattner } 325870c016934bacf43995d89531b166ae095ee3675Chris Lattner O << "\n"; 326870c016934bacf43995d89531b166ae095ee3675Chris Lattner } 327870c016934bacf43995d89531b166ae095ee3675Chris Lattner 328870c016934bacf43995d89531b166ae095ee3675Chris Lattner O << " break;\n"; 329870c016934bacf43995d89531b166ae095ee3675Chris Lattner} 330b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner 331bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattnervoid AsmWriterEmitter:: 332bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris LattnerFindUniqueOperandCommands(std::vector<std::string> &UniqueOperandCommands, 33396c1ade5c3927cb0e835af721cbf37f9605cc678Chris Lattner std::vector<unsigned> &InstIdxs, 33496c1ade5c3927cb0e835af721cbf37f9605cc678Chris Lattner std::vector<unsigned> &InstOpsUsed) const { 335195bb4a7b0de2bb76ae064a5ab8776094d4fccbbChris Lattner InstIdxs.assign(NumberedInstructions.size(), ~0U); 336bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner 337bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner // This vector parallels UniqueOperandCommands, keeping track of which 338bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner // instructions each case are used for. It is a comma separated string of 339bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner // enums. 340bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner std::vector<std::string> InstrsForCase; 341bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner InstrsForCase.resize(UniqueOperandCommands.size()); 34296c1ade5c3927cb0e835af721cbf37f9605cc678Chris Lattner InstOpsUsed.assign(UniqueOperandCommands.size(), 0); 343bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner 344bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) { 345bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner const AsmWriterInst *Inst = getAsmWriterInstByID(i); 346bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner if (Inst == 0) continue; // PHI, INLINEASM, etc. 347bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner 348bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner std::string Command; 349b84628679ad7240a63d267fc6388efbc1e91f588Chris Lattner if (Inst->Operands.empty()) 350bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner continue; // Instruction already done. 351191dd1f1860661f2e0bb99432d10da9b2aff1fc7Chris Lattner 352b84628679ad7240a63d267fc6388efbc1e91f588Chris Lattner Command = " " + Inst->Operands[0].getCode() + "\n"; 353191dd1f1860661f2e0bb99432d10da9b2aff1fc7Chris Lattner 354191dd1f1860661f2e0bb99432d10da9b2aff1fc7Chris Lattner // If this is the last operand, emit a return. 355b84628679ad7240a63d267fc6388efbc1e91f588Chris Lattner if (Inst->Operands.size() == 1) 356191dd1f1860661f2e0bb99432d10da9b2aff1fc7Chris Lattner Command += " return true;\n"; 357bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner 358bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner // Check to see if we already have 'Command' in UniqueOperandCommands. 359bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner // If not, add it. 360bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner bool FoundIt = false; 361bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner for (unsigned idx = 0, e = UniqueOperandCommands.size(); idx != e; ++idx) 362bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner if (UniqueOperandCommands[idx] == Command) { 363bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner InstIdxs[i] = idx; 364bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner InstrsForCase[idx] += ", "; 365bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner InstrsForCase[idx] += Inst->CGI->TheDef->getName(); 366bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner FoundIt = true; 367bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner break; 368bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner } 369bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner if (!FoundIt) { 370bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner InstIdxs[i] = UniqueOperandCommands.size(); 371bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner UniqueOperandCommands.push_back(Command); 372bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner InstrsForCase.push_back(Inst->CGI->TheDef->getName()); 37396c1ade5c3927cb0e835af721cbf37f9605cc678Chris Lattner 37496c1ade5c3927cb0e835af721cbf37f9605cc678Chris Lattner // This command matches one operand so far. 37596c1ade5c3927cb0e835af721cbf37f9605cc678Chris Lattner InstOpsUsed.push_back(1); 37696c1ade5c3927cb0e835af721cbf37f9605cc678Chris Lattner } 37796c1ade5c3927cb0e835af721cbf37f9605cc678Chris Lattner } 37896c1ade5c3927cb0e835af721cbf37f9605cc678Chris Lattner 37996c1ade5c3927cb0e835af721cbf37f9605cc678Chris Lattner // For each entry of UniqueOperandCommands, there is a set of instructions 38096c1ade5c3927cb0e835af721cbf37f9605cc678Chris Lattner // that uses it. If the next command of all instructions in the set are 38196c1ade5c3927cb0e835af721cbf37f9605cc678Chris Lattner // identical, fold it into the command. 38296c1ade5c3927cb0e835af721cbf37f9605cc678Chris Lattner for (unsigned CommandIdx = 0, e = UniqueOperandCommands.size(); 38396c1ade5c3927cb0e835af721cbf37f9605cc678Chris Lattner CommandIdx != e; ++CommandIdx) { 38496c1ade5c3927cb0e835af721cbf37f9605cc678Chris Lattner 38596c1ade5c3927cb0e835af721cbf37f9605cc678Chris Lattner for (unsigned Op = 1; ; ++Op) { 38696c1ade5c3927cb0e835af721cbf37f9605cc678Chris Lattner // Scan for the first instruction in the set. 38796c1ade5c3927cb0e835af721cbf37f9605cc678Chris Lattner std::vector<unsigned>::iterator NIT = 38896c1ade5c3927cb0e835af721cbf37f9605cc678Chris Lattner std::find(InstIdxs.begin(), InstIdxs.end(), CommandIdx); 38996c1ade5c3927cb0e835af721cbf37f9605cc678Chris Lattner if (NIT == InstIdxs.end()) break; // No commonality. 39096c1ade5c3927cb0e835af721cbf37f9605cc678Chris Lattner 39196c1ade5c3927cb0e835af721cbf37f9605cc678Chris Lattner // If this instruction has no more operands, we isn't anything to merge 39296c1ade5c3927cb0e835af721cbf37f9605cc678Chris Lattner // into this command. 39396c1ade5c3927cb0e835af721cbf37f9605cc678Chris Lattner const AsmWriterInst *FirstInst = 39496c1ade5c3927cb0e835af721cbf37f9605cc678Chris Lattner getAsmWriterInstByID(NIT-InstIdxs.begin()); 39596c1ade5c3927cb0e835af721cbf37f9605cc678Chris Lattner if (!FirstInst || FirstInst->Operands.size() == Op) 39696c1ade5c3927cb0e835af721cbf37f9605cc678Chris Lattner break; 39796c1ade5c3927cb0e835af721cbf37f9605cc678Chris Lattner 39896c1ade5c3927cb0e835af721cbf37f9605cc678Chris Lattner // Otherwise, scan to see if all of the other instructions in this command 39996c1ade5c3927cb0e835af721cbf37f9605cc678Chris Lattner // set share the operand. 40096c1ade5c3927cb0e835af721cbf37f9605cc678Chris Lattner bool AllSame = true; 40196c1ade5c3927cb0e835af721cbf37f9605cc678Chris Lattner 40296c1ade5c3927cb0e835af721cbf37f9605cc678Chris Lattner for (NIT = std::find(NIT+1, InstIdxs.end(), CommandIdx); 40396c1ade5c3927cb0e835af721cbf37f9605cc678Chris Lattner NIT != InstIdxs.end(); 40496c1ade5c3927cb0e835af721cbf37f9605cc678Chris Lattner NIT = std::find(NIT+1, InstIdxs.end(), CommandIdx)) { 40596c1ade5c3927cb0e835af721cbf37f9605cc678Chris Lattner // Okay, found another instruction in this command set. If the operand 40696c1ade5c3927cb0e835af721cbf37f9605cc678Chris Lattner // matches, we're ok, otherwise bail out. 40796c1ade5c3927cb0e835af721cbf37f9605cc678Chris Lattner const AsmWriterInst *OtherInst = 40896c1ade5c3927cb0e835af721cbf37f9605cc678Chris Lattner getAsmWriterInstByID(NIT-InstIdxs.begin()); 40996c1ade5c3927cb0e835af721cbf37f9605cc678Chris Lattner if (!OtherInst || OtherInst->Operands.size() == Op || 41096c1ade5c3927cb0e835af721cbf37f9605cc678Chris Lattner OtherInst->Operands[Op] != FirstInst->Operands[Op]) { 41196c1ade5c3927cb0e835af721cbf37f9605cc678Chris Lattner AllSame = false; 41296c1ade5c3927cb0e835af721cbf37f9605cc678Chris Lattner break; 41396c1ade5c3927cb0e835af721cbf37f9605cc678Chris Lattner } 41496c1ade5c3927cb0e835af721cbf37f9605cc678Chris Lattner } 41596c1ade5c3927cb0e835af721cbf37f9605cc678Chris Lattner if (!AllSame) break; 41696c1ade5c3927cb0e835af721cbf37f9605cc678Chris Lattner 41796c1ade5c3927cb0e835af721cbf37f9605cc678Chris Lattner // Okay, everything in this command set has the same next operand. Add it 41896c1ade5c3927cb0e835af721cbf37f9605cc678Chris Lattner // to UniqueOperandCommands and remember that it was consumed. 41996c1ade5c3927cb0e835af721cbf37f9605cc678Chris Lattner std::string Command = " " + FirstInst->Operands[Op].getCode() + "\n"; 42096c1ade5c3927cb0e835af721cbf37f9605cc678Chris Lattner 42196c1ade5c3927cb0e835af721cbf37f9605cc678Chris Lattner // If this is the last operand, emit a return after the code. 42296c1ade5c3927cb0e835af721cbf37f9605cc678Chris Lattner if (FirstInst->Operands.size() == Op+1) 42396c1ade5c3927cb0e835af721cbf37f9605cc678Chris Lattner Command += " return true;\n"; 42496c1ade5c3927cb0e835af721cbf37f9605cc678Chris Lattner 42596c1ade5c3927cb0e835af721cbf37f9605cc678Chris Lattner UniqueOperandCommands[CommandIdx] += Command; 42696c1ade5c3927cb0e835af721cbf37f9605cc678Chris Lattner InstOpsUsed[CommandIdx]++; 427bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner } 428bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner } 429bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner 430bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner // Prepend some of the instructions each case is used for onto the case val. 431bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner for (unsigned i = 0, e = InstrsForCase.size(); i != e; ++i) { 432bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner std::string Instrs = InstrsForCase[i]; 433bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner if (Instrs.size() > 70) { 434bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner Instrs.erase(Instrs.begin()+70, Instrs.end()); 435bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner Instrs += "..."; 436bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner } 437bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner 438bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner if (!Instrs.empty()) 439bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner UniqueOperandCommands[i] = " // " + Instrs + "\n" + 440bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner UniqueOperandCommands[i]; 441bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner } 442bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner} 443bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner 444bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner 445bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner 4462e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattnervoid AsmWriterEmitter::run(std::ostream &O) { 4472e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner EmitSourceFileHeader("Assembly Writer Source Fragment", O); 4482e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner 4492e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner CodeGenTarget Target; 450175580c0f36b026daf9de0adabdb7ddcf7619db6Chris Lattner Record *AsmWriter = Target.getAsmWriter(); 451953c6fe11277c2511744440f5d8d90aca1354e18Chris Lattner std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName"); 452953c6fe11277c2511744440f5d8d90aca1354e18Chris Lattner unsigned Variant = AsmWriter->getValueAsInt("Variant"); 453175580c0f36b026daf9de0adabdb7ddcf7619db6Chris Lattner 4542e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner O << 4552e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner "/// printInstruction - This method is automatically generated by tablegen\n" 4562e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner "/// from the instruction set description. This method returns true if the\n" 4572e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner "/// machine instruction was sufficiently described to print it, otherwise\n" 4582e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner "/// it returns false.\n" 459953c6fe11277c2511744440f5d8d90aca1354e18Chris Lattner "bool " << Target.getName() << ClassName 460175580c0f36b026daf9de0adabdb7ddcf7619db6Chris Lattner << "::printInstruction(const MachineInstr *MI) {\n"; 4612e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner 4625765dba5ce9f493f063a7caf1106e7db9b6693b6Chris Lattner std::vector<AsmWriterInst> Instructions; 4635765dba5ce9f493f063a7caf1106e7db9b6693b6Chris Lattner 4642e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner for (CodeGenTarget::inst_iterator I = Target.inst_begin(), 4652e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner E = Target.inst_end(); I != E; ++I) 4665765dba5ce9f493f063a7caf1106e7db9b6693b6Chris Lattner if (!I->second.AsmString.empty()) 4675765dba5ce9f493f063a7caf1106e7db9b6693b6Chris Lattner Instructions.push_back(AsmWriterInst(I->second, Variant)); 4685765dba5ce9f493f063a7caf1106e7db9b6693b6Chris Lattner 469bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner // Get the instruction numbering. 4700cfcc1e8072af7f3d92bbcdba48da551cccd90beChris Lattner Target.getInstructionsByEnumValue(NumberedInstructions); 4710cfcc1e8072af7f3d92bbcdba48da551cccd90beChris Lattner 4726af022f255257bee7c6d6903ff4caa2217d51502Chris Lattner // Compute the CodeGenInstruction -> AsmWriterInst mapping. Note that not 4736af022f255257bee7c6d6903ff4caa2217d51502Chris Lattner // all machine instructions are necessarily being printed, so there may be 4746af022f255257bee7c6d6903ff4caa2217d51502Chris Lattner // target instructions not in this map. 4756af022f255257bee7c6d6903ff4caa2217d51502Chris Lattner for (unsigned i = 0, e = Instructions.size(); i != e; ++i) 4766af022f255257bee7c6d6903ff4caa2217d51502Chris Lattner CGIAWIMap.insert(std::make_pair(Instructions[i].CGI, &Instructions[i])); 4776af022f255257bee7c6d6903ff4caa2217d51502Chris Lattner 4786af022f255257bee7c6d6903ff4caa2217d51502Chris Lattner // Build an aggregate string, and build a table of offsets into it. 4796af022f255257bee7c6d6903ff4caa2217d51502Chris Lattner std::map<std::string, unsigned> StringOffset; 4806af022f255257bee7c6d6903ff4caa2217d51502Chris Lattner std::string AggregateString; 481a6dc9fb745962564fac3b18da28736b2e094c417Chris Lattner AggregateString += "\0\0"; 4826af022f255257bee7c6d6903ff4caa2217d51502Chris Lattner 4835561640043666174a1e4d828107702a8992e59f6Chris Lattner /// OpcodeInfo - Theis encodes the index of the string to use for the first 4845561640043666174a1e4d828107702a8992e59f6Chris Lattner /// chunk of the output as well as indices used for operand printing. 4855561640043666174a1e4d828107702a8992e59f6Chris Lattner std::vector<unsigned> OpcodeInfo; 486bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner 4875561640043666174a1e4d828107702a8992e59f6Chris Lattner unsigned MaxStringIdx = 0; 4886af022f255257bee7c6d6903ff4caa2217d51502Chris Lattner for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) { 4896af022f255257bee7c6d6903ff4caa2217d51502Chris Lattner AsmWriterInst *AWI = CGIAWIMap[NumberedInstructions[i]]; 4906af022f255257bee7c6d6903ff4caa2217d51502Chris Lattner unsigned Idx; 491a6dc9fb745962564fac3b18da28736b2e094c417Chris Lattner if (AWI == 0) { 4926af022f255257bee7c6d6903ff4caa2217d51502Chris Lattner // Something not handled by the asmwriter printer. 4936af022f255257bee7c6d6903ff4caa2217d51502Chris Lattner Idx = 0; 494a6dc9fb745962564fac3b18da28736b2e094c417Chris Lattner } else if (AWI->Operands[0].OperandType != 495a6dc9fb745962564fac3b18da28736b2e094c417Chris Lattner AsmWriterOperand::isLiteralTextOperand || 496a6dc9fb745962564fac3b18da28736b2e094c417Chris Lattner AWI->Operands[0].Str.empty()) { 497a6dc9fb745962564fac3b18da28736b2e094c417Chris Lattner // Something handled by the asmwriter printer, but with no leading string. 498a6dc9fb745962564fac3b18da28736b2e094c417Chris Lattner Idx = 1; 4996af022f255257bee7c6d6903ff4caa2217d51502Chris Lattner } else { 5006af022f255257bee7c6d6903ff4caa2217d51502Chris Lattner unsigned &Entry = StringOffset[AWI->Operands[0].Str]; 5016af022f255257bee7c6d6903ff4caa2217d51502Chris Lattner if (Entry == 0) { 5026af022f255257bee7c6d6903ff4caa2217d51502Chris Lattner // Add the string to the aggregate if this is the first time found. 5035561640043666174a1e4d828107702a8992e59f6Chris Lattner MaxStringIdx = Entry = AggregateString.size(); 5046af022f255257bee7c6d6903ff4caa2217d51502Chris Lattner std::string Str = AWI->Operands[0].Str; 5056af022f255257bee7c6d6903ff4caa2217d51502Chris Lattner UnescapeString(Str); 5066af022f255257bee7c6d6903ff4caa2217d51502Chris Lattner AggregateString += Str; 5076af022f255257bee7c6d6903ff4caa2217d51502Chris Lattner AggregateString += '\0'; 5086af022f255257bee7c6d6903ff4caa2217d51502Chris Lattner } 5096af022f255257bee7c6d6903ff4caa2217d51502Chris Lattner Idx = Entry; 5106af022f255257bee7c6d6903ff4caa2217d51502Chris Lattner 5116af022f255257bee7c6d6903ff4caa2217d51502Chris Lattner // Nuke the string from the operand list. It is now handled! 5126af022f255257bee7c6d6903ff4caa2217d51502Chris Lattner AWI->Operands.erase(AWI->Operands.begin()); 5136af022f255257bee7c6d6903ff4caa2217d51502Chris Lattner } 5145561640043666174a1e4d828107702a8992e59f6Chris Lattner OpcodeInfo.push_back(Idx); 515bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner } 516bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner 5175561640043666174a1e4d828107702a8992e59f6Chris Lattner // Figure out how many bits we used for the string index. 5185561640043666174a1e4d828107702a8992e59f6Chris Lattner unsigned AsmStrBits = Log2_32_Ceil(MaxStringIdx); 5195561640043666174a1e4d828107702a8992e59f6Chris Lattner 520bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner // To reduce code size, we compactify common instructions into a few bits 521bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner // in the opcode-indexed table. 522b51ecd4dd93b8eccf2cba3d541cff0f7cdbf7e1cChris Lattner unsigned BitsLeft = 32-AsmStrBits; 523bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner 524bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner std::vector<std::vector<std::string> > TableDrivenOperandPrinters; 525bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner 526b84628679ad7240a63d267fc6388efbc1e91f588Chris Lattner bool isFirst = true; 527b84628679ad7240a63d267fc6388efbc1e91f588Chris Lattner while (1) { 528bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner std::vector<std::string> UniqueOperandCommands; 529bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner 530a6dc9fb745962564fac3b18da28736b2e094c417Chris Lattner // For the first operand check, add a default value for instructions with 531a6dc9fb745962564fac3b18da28736b2e094c417Chris Lattner // just opcode strings to use. 532b84628679ad7240a63d267fc6388efbc1e91f588Chris Lattner if (isFirst) { 533a6dc9fb745962564fac3b18da28736b2e094c417Chris Lattner UniqueOperandCommands.push_back(" return true;\n"); 534b84628679ad7240a63d267fc6388efbc1e91f588Chris Lattner isFirst = false; 535b84628679ad7240a63d267fc6388efbc1e91f588Chris Lattner } 536bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner 537bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner std::vector<unsigned> InstIdxs; 53896c1ade5c3927cb0e835af721cbf37f9605cc678Chris Lattner std::vector<unsigned> NumInstOpsHandled; 53996c1ade5c3927cb0e835af721cbf37f9605cc678Chris Lattner FindUniqueOperandCommands(UniqueOperandCommands, InstIdxs, 54096c1ade5c3927cb0e835af721cbf37f9605cc678Chris Lattner NumInstOpsHandled); 541bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner 542bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner // If we ran out of operands to print, we're done. 543bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner if (UniqueOperandCommands.empty()) break; 544bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner 545bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner // Compute the number of bits we need to represent these cases, this is 546bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner // ceil(log2(numentries)). 547bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner unsigned NumBits = Log2_32_Ceil(UniqueOperandCommands.size()); 548bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner 549bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner // If we don't have enough bits for this operand, don't include it. 550bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner if (NumBits > BitsLeft) { 551bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner DEBUG(std::cerr << "Not enough bits to densely encode " << NumBits 552bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner << " more bits\n"); 553bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner break; 554bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner } 555bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner 556bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner // Otherwise, we can include this in the initial lookup table. Add it in. 557bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner BitsLeft -= NumBits; 558bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner for (unsigned i = 0, e = InstIdxs.size(); i != e; ++i) 559195bb4a7b0de2bb76ae064a5ab8776094d4fccbbChris Lattner if (InstIdxs[i] != ~0U) 560195bb4a7b0de2bb76ae064a5ab8776094d4fccbbChris Lattner OpcodeInfo[i] |= InstIdxs[i] << (BitsLeft+AsmStrBits); 561bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner 562b84628679ad7240a63d267fc6388efbc1e91f588Chris Lattner // Remove the info about this operand. 563b84628679ad7240a63d267fc6388efbc1e91f588Chris Lattner for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) { 564b84628679ad7240a63d267fc6388efbc1e91f588Chris Lattner if (AsmWriterInst *Inst = getAsmWriterInstByID(i)) 56596c1ade5c3927cb0e835af721cbf37f9605cc678Chris Lattner if (!Inst->Operands.empty()) { 56696c1ade5c3927cb0e835af721cbf37f9605cc678Chris Lattner unsigned NumOps = NumInstOpsHandled[InstIdxs[i]]; 5670a012128574c93d5b85adffd14eb4b07883fba4cChris Lattner assert(NumOps <= Inst->Operands.size() && 5680a012128574c93d5b85adffd14eb4b07883fba4cChris Lattner "Can't remove this many ops!"); 56996c1ade5c3927cb0e835af721cbf37f9605cc678Chris Lattner Inst->Operands.erase(Inst->Operands.begin(), 57096c1ade5c3927cb0e835af721cbf37f9605cc678Chris Lattner Inst->Operands.begin()+NumOps); 57196c1ade5c3927cb0e835af721cbf37f9605cc678Chris Lattner } 572b84628679ad7240a63d267fc6388efbc1e91f588Chris Lattner } 573b84628679ad7240a63d267fc6388efbc1e91f588Chris Lattner 574b84628679ad7240a63d267fc6388efbc1e91f588Chris Lattner // Remember the handlers for this set of operands. 575bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner TableDrivenOperandPrinters.push_back(UniqueOperandCommands); 576bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner } 577bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner 578bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner 579bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner 5805561640043666174a1e4d828107702a8992e59f6Chris Lattner O<<" static const unsigned OpInfo[] = {\n"; 581bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) { 582b51ecd4dd93b8eccf2cba3d541cff0f7cdbf7e1cChris Lattner O << " " << OpcodeInfo[i] << "U,\t// " 5835561640043666174a1e4d828107702a8992e59f6Chris Lattner << NumberedInstructions[i]->TheDef->getName() << "\n"; 5846af022f255257bee7c6d6903ff4caa2217d51502Chris Lattner } 585bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner // Add a dummy entry so the array init doesn't end with a comma. 5865561640043666174a1e4d828107702a8992e59f6Chris Lattner O << " 0U\n"; 5876af022f255257bee7c6d6903ff4caa2217d51502Chris Lattner O << " };\n\n"; 5886af022f255257bee7c6d6903ff4caa2217d51502Chris Lattner 5896af022f255257bee7c6d6903ff4caa2217d51502Chris Lattner // Emit the string itself. 5906af022f255257bee7c6d6903ff4caa2217d51502Chris Lattner O << " const char *AsmStrs = \n \""; 5916af022f255257bee7c6d6903ff4caa2217d51502Chris Lattner unsigned CharsPrinted = 0; 5926af022f255257bee7c6d6903ff4caa2217d51502Chris Lattner EscapeString(AggregateString); 5936af022f255257bee7c6d6903ff4caa2217d51502Chris Lattner for (unsigned i = 0, e = AggregateString.size(); i != e; ++i) { 5946af022f255257bee7c6d6903ff4caa2217d51502Chris Lattner if (CharsPrinted > 70) { 5956af022f255257bee7c6d6903ff4caa2217d51502Chris Lattner O << "\"\n \""; 5966af022f255257bee7c6d6903ff4caa2217d51502Chris Lattner CharsPrinted = 0; 5976af022f255257bee7c6d6903ff4caa2217d51502Chris Lattner } 5986af022f255257bee7c6d6903ff4caa2217d51502Chris Lattner O << AggregateString[i]; 5996af022f255257bee7c6d6903ff4caa2217d51502Chris Lattner ++CharsPrinted; 6006af022f255257bee7c6d6903ff4caa2217d51502Chris Lattner 6016af022f255257bee7c6d6903ff4caa2217d51502Chris Lattner // Print escape sequences all together. 6026af022f255257bee7c6d6903ff4caa2217d51502Chris Lattner if (AggregateString[i] == '\\') { 6036af022f255257bee7c6d6903ff4caa2217d51502Chris Lattner assert(i+1 < AggregateString.size() && "Incomplete escape sequence!"); 6046af022f255257bee7c6d6903ff4caa2217d51502Chris Lattner if (isdigit(AggregateString[i+1])) { 6056af022f255257bee7c6d6903ff4caa2217d51502Chris Lattner assert(isdigit(AggregateString[i+2]) && isdigit(AggregateString[i+3]) && 6066af022f255257bee7c6d6903ff4caa2217d51502Chris Lattner "Expected 3 digit octal escape!"); 6076af022f255257bee7c6d6903ff4caa2217d51502Chris Lattner O << AggregateString[++i]; 6086af022f255257bee7c6d6903ff4caa2217d51502Chris Lattner O << AggregateString[++i]; 6096af022f255257bee7c6d6903ff4caa2217d51502Chris Lattner O << AggregateString[++i]; 6106af022f255257bee7c6d6903ff4caa2217d51502Chris Lattner CharsPrinted += 3; 611f876668518097413a904537ce9d249953987508cChris Lattner } else { 6126af022f255257bee7c6d6903ff4caa2217d51502Chris Lattner O << AggregateString[++i]; 6136af022f255257bee7c6d6903ff4caa2217d51502Chris Lattner ++CharsPrinted; 614f876668518097413a904537ce9d249953987508cChris Lattner } 615f876668518097413a904537ce9d249953987508cChris Lattner } 616f876668518097413a904537ce9d249953987508cChris Lattner } 6176af022f255257bee7c6d6903ff4caa2217d51502Chris Lattner O << "\";\n\n"; 6186af022f255257bee7c6d6903ff4caa2217d51502Chris Lattner 619bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner O << " if (MI->getOpcode() == TargetInstrInfo::INLINEASM) {\n" 620bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner << " printInlineAsm(MI);\n" 621bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner << " return true;\n" 622bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner << " }\n\n"; 623bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner 6246af022f255257bee7c6d6903ff4caa2217d51502Chris Lattner O << " // Emit the opcode for the instruction.\n" 6255561640043666174a1e4d828107702a8992e59f6Chris Lattner << " unsigned Bits = OpInfo[MI->getOpcode()];\n" 626a6dc9fb745962564fac3b18da28736b2e094c417Chris Lattner << " if (Bits == 0) return false;\n" 6275561640043666174a1e4d828107702a8992e59f6Chris Lattner << " O << AsmStrs+(Bits & " << (1 << AsmStrBits)-1 << ");\n\n"; 628bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner 629bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner // Output the table driven operand information. 630b51ecd4dd93b8eccf2cba3d541cff0f7cdbf7e1cChris Lattner BitsLeft = 32-AsmStrBits; 631bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner for (unsigned i = 0, e = TableDrivenOperandPrinters.size(); i != e; ++i) { 632bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner std::vector<std::string> &Commands = TableDrivenOperandPrinters[i]; 633f876668518097413a904537ce9d249953987508cChris Lattner 634bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner // Compute the number of bits we need to represent these cases, this is 635bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner // ceil(log2(numentries)). 636bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner unsigned NumBits = Log2_32_Ceil(Commands.size()); 637bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner assert(NumBits <= BitsLeft && "consistency error"); 638bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner 639bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner // Emit code to extract this field from Bits. 640bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner BitsLeft -= NumBits; 641bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner 642bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner O << "\n // Fragment " << i << " encoded into " << NumBits 643e7a589df09ed4d1f0853fb586609b00357a34ac2Chris Lattner << " bits for " << Commands.size() << " unique commands.\n"; 644bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner 64596c1ade5c3927cb0e835af721cbf37f9605cc678Chris Lattner if (Commands.size() == 2) { 646e7a589df09ed4d1f0853fb586609b00357a34ac2Chris Lattner // Emit two possibilitys with if/else. 647e7a589df09ed4d1f0853fb586609b00357a34ac2Chris Lattner O << " if ((Bits >> " << (BitsLeft+AsmStrBits) << ") & " 648e7a589df09ed4d1f0853fb586609b00357a34ac2Chris Lattner << ((1 << NumBits)-1) << ") {\n" 649e7a589df09ed4d1f0853fb586609b00357a34ac2Chris Lattner << Commands[1] 650e7a589df09ed4d1f0853fb586609b00357a34ac2Chris Lattner << " } else {\n" 651e7a589df09ed4d1f0853fb586609b00357a34ac2Chris Lattner << Commands[0] 652e7a589df09ed4d1f0853fb586609b00357a34ac2Chris Lattner << " }\n\n"; 653e7a589df09ed4d1f0853fb586609b00357a34ac2Chris Lattner } else { 654e7a589df09ed4d1f0853fb586609b00357a34ac2Chris Lattner O << " switch ((Bits >> " << (BitsLeft+AsmStrBits) << ") & " 655e7a589df09ed4d1f0853fb586609b00357a34ac2Chris Lattner << ((1 << NumBits)-1) << ") {\n" 656e7a589df09ed4d1f0853fb586609b00357a34ac2Chris Lattner << " default: // unreachable.\n"; 657e7a589df09ed4d1f0853fb586609b00357a34ac2Chris Lattner 658e7a589df09ed4d1f0853fb586609b00357a34ac2Chris Lattner // Print out all the cases. 659e7a589df09ed4d1f0853fb586609b00357a34ac2Chris Lattner for (unsigned i = 0, e = Commands.size(); i != e; ++i) { 660e7a589df09ed4d1f0853fb586609b00357a34ac2Chris Lattner O << " case " << i << ":\n"; 661e7a589df09ed4d1f0853fb586609b00357a34ac2Chris Lattner O << Commands[i]; 662e7a589df09ed4d1f0853fb586609b00357a34ac2Chris Lattner O << " break;\n"; 663e7a589df09ed4d1f0853fb586609b00357a34ac2Chris Lattner } 664e7a589df09ed4d1f0853fb586609b00357a34ac2Chris Lattner O << " }\n\n"; 665bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner } 666bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner } 667bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner 668b84628679ad7240a63d267fc6388efbc1e91f588Chris Lattner // Okay, delete instructions with no operand info left. 669bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner for (unsigned i = 0, e = Instructions.size(); i != e; ++i) { 670bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner // Entire instruction has been emitted? 671bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner AsmWriterInst &Inst = Instructions[i]; 672b84628679ad7240a63d267fc6388efbc1e91f588Chris Lattner if (Inst.Operands.empty()) { 673bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner Instructions.erase(Instructions.begin()+i); 674b84628679ad7240a63d267fc6388efbc1e91f588Chris Lattner --i; --e; 675bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner } 676bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner } 677bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner 678bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner 679bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner // Because this is a vector, we want to emit from the end. Reverse all of the 680870c016934bacf43995d89531b166ae095ee3675Chris Lattner // elements in the vector. 681870c016934bacf43995d89531b166ae095ee3675Chris Lattner std::reverse(Instructions.begin(), Instructions.end()); 682bdff5f95b9cda9a6d24104201fa53204bd0c5a75Chris Lattner 683b51ecd4dd93b8eccf2cba3d541cff0f7cdbf7e1cChris Lattner if (!Instructions.empty()) { 684b51ecd4dd93b8eccf2cba3d541cff0f7cdbf7e1cChris Lattner // Find the opcode # of inline asm. 685b51ecd4dd93b8eccf2cba3d541cff0f7cdbf7e1cChris Lattner O << " switch (MI->getOpcode()) {\n"; 686b51ecd4dd93b8eccf2cba3d541cff0f7cdbf7e1cChris Lattner while (!Instructions.empty()) 687b51ecd4dd93b8eccf2cba3d541cff0f7cdbf7e1cChris Lattner EmitInstructions(Instructions, O); 688870c016934bacf43995d89531b166ae095ee3675Chris Lattner 689b51ecd4dd93b8eccf2cba3d541cff0f7cdbf7e1cChris Lattner O << " }\n"; 6900a012128574c93d5b85adffd14eb4b07883fba4cChris Lattner O << " return true;\n"; 691b51ecd4dd93b8eccf2cba3d541cff0f7cdbf7e1cChris Lattner } 692b51ecd4dd93b8eccf2cba3d541cff0f7cdbf7e1cChris Lattner 6930a012128574c93d5b85adffd14eb4b07883fba4cChris Lattner O << "}\n"; 6942e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner} 695