AsmWriterEmitter.cpp revision 3da94aec4d429b2ba0f65fa040c33650cade196b
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" 18615ed993e115f8bc97ff0678aa861629fec93880Jeff Cohen#include <algorithm> 192e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner#include <ostream> 202e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattnerusing namespace llvm; 212e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner 22076efa771aa634801202f7b8189e33ee79dfc4edChris Lattnerstatic bool isIdentChar(char C) { 23076efa771aa634801202f7b8189e33ee79dfc4edChris Lattner return (C >= 'a' && C <= 'z') || 24076efa771aa634801202f7b8189e33ee79dfc4edChris Lattner (C >= 'A' && C <= 'Z') || 25076efa771aa634801202f7b8189e33ee79dfc4edChris Lattner (C >= '0' && C <= '9') || 26076efa771aa634801202f7b8189e33ee79dfc4edChris Lattner C == '_'; 27076efa771aa634801202f7b8189e33ee79dfc4edChris Lattner} 28076efa771aa634801202f7b8189e33ee79dfc4edChris Lattner 29b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattnernamespace { 30b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner struct AsmWriterOperand { 31b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner enum { isLiteralTextOperand, isMachineInstrOperand } OperandType; 32b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner 33b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner /// Str - For isLiteralTextOperand, this IS the literal text. For 34b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner /// isMachineInstrOperand, this is the PrinterMethodName for the operand. 35b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner std::string Str; 36b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner 37b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner /// MiOpNo - For isMachineInstrOperand, this is the operand number of the 38b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner /// machine instruction. 39b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner unsigned MIOpNo; 40b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner 41b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner /// OpVT - For isMachineInstrOperand, this is the value type for the 42b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner /// operand. 43b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner MVT::ValueType OpVT; 44b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner 45b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner AsmWriterOperand(const std::string &LitStr) 46b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner : OperandType(isLiteralTextOperand), Str(LitStr) {} 47b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner 48b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner AsmWriterOperand(const std::string &Printer, unsigned OpNo, 49b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner MVT::ValueType VT) : OperandType(isMachineInstrOperand), 50b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner Str(Printer), MIOpNo(OpNo), OpVT(VT){} 51b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner 52870c016934bacf43995d89531b166ae095ee3675Chris Lattner bool operator!=(const AsmWriterOperand &Other) const { 53870c016934bacf43995d89531b166ae095ee3675Chris Lattner if (OperandType != Other.OperandType || Str != Other.Str) return true; 54870c016934bacf43995d89531b166ae095ee3675Chris Lattner if (OperandType == isMachineInstrOperand) 55870c016934bacf43995d89531b166ae095ee3675Chris Lattner return MIOpNo != Other.MIOpNo || OpVT != Other.OpVT; 56870c016934bacf43995d89531b166ae095ee3675Chris Lattner return false; 57870c016934bacf43995d89531b166ae095ee3675Chris Lattner } 5838c0751a128c0387c04c0f96a2f092340aaa7545Chris Lattner bool operator==(const AsmWriterOperand &Other) const { 5938c0751a128c0387c04c0f96a2f092340aaa7545Chris Lattner return !operator!=(Other); 6038c0751a128c0387c04c0f96a2f092340aaa7545Chris Lattner } 61b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner void EmitCode(std::ostream &OS) const; 62b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner }; 63b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner 64b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner struct AsmWriterInst { 65b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner std::vector<AsmWriterOperand> Operands; 665765dba5ce9f493f063a7caf1106e7db9b6693b6Chris Lattner const CodeGenInstruction *CGI; 673da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman 685765dba5ce9f493f063a7caf1106e7db9b6693b6Chris Lattner AsmWriterInst(const CodeGenInstruction &CGI, unsigned Variant); 69870c016934bacf43995d89531b166ae095ee3675Chris Lattner 70f876668518097413a904537ce9d249953987508cChris Lattner /// MatchesAllButOneOp - If this instruction is exactly identical to the 71f876668518097413a904537ce9d249953987508cChris Lattner /// specified instruction except for one differing operand, return the 72f876668518097413a904537ce9d249953987508cChris Lattner /// differing operand number. Otherwise return ~0. 73f876668518097413a904537ce9d249953987508cChris Lattner unsigned MatchesAllButOneOp(const AsmWriterInst &Other) const; 74870c016934bacf43995d89531b166ae095ee3675Chris Lattner 75b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner private: 76b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner void AddLiteralString(const std::string &Str) { 77b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner // If the last operand was already a literal text string, append this to 78b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner // it, otherwise add a new operand. 79b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner if (!Operands.empty() && 80b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner Operands.back().OperandType == AsmWriterOperand::isLiteralTextOperand) 81b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner Operands.back().Str.append(Str); 82b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner else 83b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner Operands.push_back(AsmWriterOperand(Str)); 84b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner } 85b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner }; 86b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner} 87b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner 88b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner 89b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattnervoid AsmWriterOperand::EmitCode(std::ostream &OS) const { 90b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner if (OperandType == isLiteralTextOperand) 91b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner OS << "O << \"" << Str << "\"; "; 92b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner else 93131ca38c600e2854510f7c4673258a3e878789e9Chris Lattner OS << Str << "(MI, " << MIOpNo << ", MVT::" << getEnumName(OpVT) << "); "; 94b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner} 95b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner 96b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner 97b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner/// ParseAsmString - Parse the specified Instruction's AsmString into this 98b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner/// AsmWriterInst. 99b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner/// 1005765dba5ce9f493f063a7caf1106e7db9b6693b6Chris LattnerAsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, unsigned Variant) { 1015765dba5ce9f493f063a7caf1106e7db9b6693b6Chris Lattner this->CGI = &CGI; 102b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner bool inVariant = false; // True if we are inside a {.|.|.} region. 103b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner 104b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner const std::string &AsmString = CGI.AsmString; 105b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner std::string::size_type LastEmitted = 0; 106b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner while (LastEmitted != AsmString.size()) { 107b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner std::string::size_type DollarPos = 108b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner AsmString.find_first_of("${|}", LastEmitted); 109b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner if (DollarPos == std::string::npos) DollarPos = AsmString.size(); 110b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner 111b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner // Emit a constant string fragment. 112b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner if (DollarPos != LastEmitted) { 113b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner // TODO: this should eventually handle escaping. 114b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner AddLiteralString(std::string(AsmString.begin()+LastEmitted, 115b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner AsmString.begin()+DollarPos)); 116b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner LastEmitted = DollarPos; 117b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner } else if (AsmString[DollarPos] == '{') { 118b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner if (inVariant) 119b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner throw "Nested variants found for instruction '" + CGI.Name + "'!"; 120b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner LastEmitted = DollarPos+1; 121b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner inVariant = true; // We are now inside of the variant! 122b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner for (unsigned i = 0; i != Variant; ++i) { 123b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner // Skip over all of the text for an irrelevant variant here. The 124b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner // next variant starts at |, or there may not be text for this 125b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner // variant if we see a }. 126b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner std::string::size_type NP = 127b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner AsmString.find_first_of("|}", LastEmitted); 128b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner if (NP == std::string::npos) 129b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner throw "Incomplete variant for instruction '" + CGI.Name + "'!"; 130b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner LastEmitted = NP+1; 131b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner if (AsmString[NP] == '}') { 132b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner inVariant = false; // No text for this variant. 133b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner break; 134b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner } 135b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner } 136b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner } else if (AsmString[DollarPos] == '|') { 137b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner if (!inVariant) 138b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner throw "'|' character found outside of a variant in instruction '" 139b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner + CGI.Name + "'!"; 140b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner // Move to the end of variant list. 141b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner std::string::size_type NP = AsmString.find('}', LastEmitted); 142b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner if (NP == std::string::npos) 143b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner throw "Incomplete variant for instruction '" + CGI.Name + "'!"; 144b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner LastEmitted = NP+1; 145b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner inVariant = false; 146b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner } else if (AsmString[DollarPos] == '}') { 147b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner if (!inVariant) 148b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner throw "'}' character found outside of a variant in instruction '" 149b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner + CGI.Name + "'!"; 150b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner LastEmitted = DollarPos+1; 151b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner inVariant = false; 152b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner } else if (DollarPos+1 != AsmString.size() && 153b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner AsmString[DollarPos+1] == '$') { 154b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner AddLiteralString("$"); // "$$" -> $ 155b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner LastEmitted = DollarPos+2; 156b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner } else { 157b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner // Get the name of the variable. 158b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner // TODO: should eventually handle ${foo}bar as $foo 159b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner std::string::size_type VarEnd = DollarPos+1; 160b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner while (VarEnd < AsmString.size() && isIdentChar(AsmString[VarEnd])) 161b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner ++VarEnd; 162b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner std::string VarName(AsmString.begin()+DollarPos+1, 163b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner AsmString.begin()+VarEnd); 164b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner if (VarName.empty()) 165b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner throw "Stray '$' in '" + CGI.Name + "' asm string, maybe you want $$?"; 166b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner 167b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner unsigned OpNo = CGI.getOperandNamed(VarName); 1685765dba5ce9f493f063a7caf1106e7db9b6693b6Chris Lattner CodeGenInstruction::OperandInfo OpInfo = CGI.OperandList[OpNo]; 169b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner 170b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner // If this is a two-address instruction and we are not accessing the 171b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner // 0th operand, remove an operand. 1725765dba5ce9f493f063a7caf1106e7db9b6693b6Chris Lattner unsigned MIOp = OpInfo.MIOperandNo; 173b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner if (CGI.isTwoAddress && MIOp != 0) { 174b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner if (MIOp == 1) 175b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner throw "Should refer to operand #0 instead of #1 for two-address" 176b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner " instruction '" + CGI.Name + "'!"; 177b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner --MIOp; 178b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner } 179b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner 1805765dba5ce9f493f063a7caf1106e7db9b6693b6Chris Lattner Operands.push_back(AsmWriterOperand(OpInfo.PrinterMethodName, 1815765dba5ce9f493f063a7caf1106e7db9b6693b6Chris Lattner MIOp, OpInfo.Ty)); 182b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner LastEmitted = VarEnd; 183b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner } 184b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner } 185b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner 186b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner AddLiteralString("\\n"); 187b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner} 188b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner 189f876668518097413a904537ce9d249953987508cChris Lattner/// MatchesAllButOneOp - If this instruction is exactly identical to the 190f876668518097413a904537ce9d249953987508cChris Lattner/// specified instruction except for one differing operand, return the differing 191f876668518097413a904537ce9d249953987508cChris Lattner/// operand number. If more than one operand mismatches, return ~1, otherwise 192f876668518097413a904537ce9d249953987508cChris Lattner/// if the instructions are identical return ~0. 193f876668518097413a904537ce9d249953987508cChris Lattnerunsigned AsmWriterInst::MatchesAllButOneOp(const AsmWriterInst &Other)const{ 194f876668518097413a904537ce9d249953987508cChris Lattner if (Operands.size() != Other.Operands.size()) return ~1; 195870c016934bacf43995d89531b166ae095ee3675Chris Lattner 196870c016934bacf43995d89531b166ae095ee3675Chris Lattner unsigned MismatchOperand = ~0U; 197870c016934bacf43995d89531b166ae095ee3675Chris Lattner for (unsigned i = 0, e = Operands.size(); i != e; ++i) { 198870c016934bacf43995d89531b166ae095ee3675Chris Lattner if (Operands[i] != Other.Operands[i]) 199f876668518097413a904537ce9d249953987508cChris Lattner if (MismatchOperand != ~0U) // Already have one mismatch? 200f876668518097413a904537ce9d249953987508cChris Lattner return ~1U; 2013da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman else 202870c016934bacf43995d89531b166ae095ee3675Chris Lattner MismatchOperand = i; 203870c016934bacf43995d89531b166ae095ee3675Chris Lattner } 204870c016934bacf43995d89531b166ae095ee3675Chris Lattner return MismatchOperand; 205870c016934bacf43995d89531b166ae095ee3675Chris Lattner} 206870c016934bacf43995d89531b166ae095ee3675Chris Lattner 20738c0751a128c0387c04c0f96a2f092340aaa7545Chris Lattnerstatic void PrintCases(std::vector<std::pair<std::string, 20838c0751a128c0387c04c0f96a2f092340aaa7545Chris Lattner AsmWriterOperand> > &OpsToPrint, std::ostream &O) { 20938c0751a128c0387c04c0f96a2f092340aaa7545Chris Lattner O << " case " << OpsToPrint.back().first << ": "; 21038c0751a128c0387c04c0f96a2f092340aaa7545Chris Lattner AsmWriterOperand TheOp = OpsToPrint.back().second; 21138c0751a128c0387c04c0f96a2f092340aaa7545Chris Lattner OpsToPrint.pop_back(); 21238c0751a128c0387c04c0f96a2f092340aaa7545Chris Lattner 21338c0751a128c0387c04c0f96a2f092340aaa7545Chris Lattner // Check to see if any other operands are identical in this list, and if so, 21438c0751a128c0387c04c0f96a2f092340aaa7545Chris Lattner // emit a case label for them. 21538c0751a128c0387c04c0f96a2f092340aaa7545Chris Lattner for (unsigned i = OpsToPrint.size(); i != 0; --i) 21638c0751a128c0387c04c0f96a2f092340aaa7545Chris Lattner if (OpsToPrint[i-1].second == TheOp) { 21738c0751a128c0387c04c0f96a2f092340aaa7545Chris Lattner O << "\n case " << OpsToPrint[i-1].first << ": "; 21838c0751a128c0387c04c0f96a2f092340aaa7545Chris Lattner OpsToPrint.erase(OpsToPrint.begin()+i-1); 21938c0751a128c0387c04c0f96a2f092340aaa7545Chris Lattner } 22038c0751a128c0387c04c0f96a2f092340aaa7545Chris Lattner 22138c0751a128c0387c04c0f96a2f092340aaa7545Chris Lattner // Finally, emit the code. 22238c0751a128c0387c04c0f96a2f092340aaa7545Chris Lattner TheOp.EmitCode(O); 22338c0751a128c0387c04c0f96a2f092340aaa7545Chris Lattner O << "break;\n"; 22438c0751a128c0387c04c0f96a2f092340aaa7545Chris Lattner} 22538c0751a128c0387c04c0f96a2f092340aaa7545Chris Lattner 226870c016934bacf43995d89531b166ae095ee3675Chris Lattner 227870c016934bacf43995d89531b166ae095ee3675Chris Lattner/// EmitInstructions - Emit the last instruction in the vector and any other 228870c016934bacf43995d89531b166ae095ee3675Chris Lattner/// instructions that are suitably similar to it. 229870c016934bacf43995d89531b166ae095ee3675Chris Lattnerstatic void EmitInstructions(std::vector<AsmWriterInst> &Insts, 230870c016934bacf43995d89531b166ae095ee3675Chris Lattner std::ostream &O) { 231870c016934bacf43995d89531b166ae095ee3675Chris Lattner AsmWriterInst FirstInst = Insts.back(); 232870c016934bacf43995d89531b166ae095ee3675Chris Lattner Insts.pop_back(); 233870c016934bacf43995d89531b166ae095ee3675Chris Lattner 234870c016934bacf43995d89531b166ae095ee3675Chris Lattner std::vector<AsmWriterInst> SimilarInsts; 235870c016934bacf43995d89531b166ae095ee3675Chris Lattner unsigned DifferingOperand = ~0; 236870c016934bacf43995d89531b166ae095ee3675Chris Lattner for (unsigned i = Insts.size(); i != 0; --i) { 237f876668518097413a904537ce9d249953987508cChris Lattner unsigned DiffOp = Insts[i-1].MatchesAllButOneOp(FirstInst); 238f876668518097413a904537ce9d249953987508cChris Lattner if (DiffOp != ~1U) { 239870c016934bacf43995d89531b166ae095ee3675Chris Lattner if (DifferingOperand == ~0U) // First match! 240870c016934bacf43995d89531b166ae095ee3675Chris Lattner DifferingOperand = DiffOp; 241870c016934bacf43995d89531b166ae095ee3675Chris Lattner 242870c016934bacf43995d89531b166ae095ee3675Chris Lattner // If this differs in the same operand as the rest of the instructions in 243870c016934bacf43995d89531b166ae095ee3675Chris Lattner // this class, move it to the SimilarInsts list. 244f876668518097413a904537ce9d249953987508cChris Lattner if (DifferingOperand == DiffOp || DiffOp == ~0U) { 245870c016934bacf43995d89531b166ae095ee3675Chris Lattner SimilarInsts.push_back(Insts[i-1]); 246870c016934bacf43995d89531b166ae095ee3675Chris Lattner Insts.erase(Insts.begin()+i-1); 247870c016934bacf43995d89531b166ae095ee3675Chris Lattner } 248870c016934bacf43995d89531b166ae095ee3675Chris Lattner } 249870c016934bacf43995d89531b166ae095ee3675Chris Lattner } 250870c016934bacf43995d89531b166ae095ee3675Chris Lattner 251870c016934bacf43995d89531b166ae095ee3675Chris Lattner std::string Namespace = FirstInst.CGI->Namespace; 252870c016934bacf43995d89531b166ae095ee3675Chris Lattner 253870c016934bacf43995d89531b166ae095ee3675Chris Lattner O << " case " << Namespace << "::" 254870c016934bacf43995d89531b166ae095ee3675Chris Lattner << FirstInst.CGI->TheDef->getName() << ":\n"; 255870c016934bacf43995d89531b166ae095ee3675Chris Lattner for (unsigned i = 0, e = SimilarInsts.size(); i != e; ++i) 256870c016934bacf43995d89531b166ae095ee3675Chris Lattner O << " case " << Namespace << "::" 257870c016934bacf43995d89531b166ae095ee3675Chris Lattner << SimilarInsts[i].CGI->TheDef->getName() << ":\n"; 258870c016934bacf43995d89531b166ae095ee3675Chris Lattner for (unsigned i = 0, e = FirstInst.Operands.size(); i != e; ++i) { 259870c016934bacf43995d89531b166ae095ee3675Chris Lattner if (i != DifferingOperand) { 260870c016934bacf43995d89531b166ae095ee3675Chris Lattner // If the operand is the same for all instructions, just print it. 261870c016934bacf43995d89531b166ae095ee3675Chris Lattner O << " "; 262870c016934bacf43995d89531b166ae095ee3675Chris Lattner FirstInst.Operands[i].EmitCode(O); 263870c016934bacf43995d89531b166ae095ee3675Chris Lattner } else { 264870c016934bacf43995d89531b166ae095ee3675Chris Lattner // If this is the operand that varies between all of the instructions, 265870c016934bacf43995d89531b166ae095ee3675Chris Lattner // emit a switch for just this operand now. 266870c016934bacf43995d89531b166ae095ee3675Chris Lattner O << " switch (MI->getOpcode()) {\n"; 26738c0751a128c0387c04c0f96a2f092340aaa7545Chris Lattner std::vector<std::pair<std::string, AsmWriterOperand> > OpsToPrint; 26838c0751a128c0387c04c0f96a2f092340aaa7545Chris Lattner OpsToPrint.push_back(std::make_pair(Namespace+"::"+ 26938c0751a128c0387c04c0f96a2f092340aaa7545Chris Lattner FirstInst.CGI->TheDef->getName(), 27038c0751a128c0387c04c0f96a2f092340aaa7545Chris Lattner FirstInst.Operands[i])); 2713da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman 272870c016934bacf43995d89531b166ae095ee3675Chris Lattner for (unsigned si = 0, e = SimilarInsts.size(); si != e; ++si) { 27338c0751a128c0387c04c0f96a2f092340aaa7545Chris Lattner AsmWriterInst &AWI = SimilarInsts[si]; 27438c0751a128c0387c04c0f96a2f092340aaa7545Chris Lattner OpsToPrint.push_back(std::make_pair(Namespace+"::"+ 27538c0751a128c0387c04c0f96a2f092340aaa7545Chris Lattner AWI.CGI->TheDef->getName(), 27638c0751a128c0387c04c0f96a2f092340aaa7545Chris Lattner AWI.Operands[i])); 277870c016934bacf43995d89531b166ae095ee3675Chris Lattner } 27838c0751a128c0387c04c0f96a2f092340aaa7545Chris Lattner std::reverse(OpsToPrint.begin(), OpsToPrint.end()); 27938c0751a128c0387c04c0f96a2f092340aaa7545Chris Lattner while (!OpsToPrint.empty()) 28038c0751a128c0387c04c0f96a2f092340aaa7545Chris Lattner PrintCases(OpsToPrint, O); 281870c016934bacf43995d89531b166ae095ee3675Chris Lattner O << " }"; 282870c016934bacf43995d89531b166ae095ee3675Chris Lattner } 283870c016934bacf43995d89531b166ae095ee3675Chris Lattner O << "\n"; 284870c016934bacf43995d89531b166ae095ee3675Chris Lattner } 285870c016934bacf43995d89531b166ae095ee3675Chris Lattner 286870c016934bacf43995d89531b166ae095ee3675Chris Lattner O << " break;\n"; 287870c016934bacf43995d89531b166ae095ee3675Chris Lattner} 288b0b55e74a090454711b1bb17e4f872d62d6e6b65Chris Lattner 2892e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattnervoid AsmWriterEmitter::run(std::ostream &O) { 2902e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner EmitSourceFileHeader("Assembly Writer Source Fragment", O); 2912e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner 2922e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner CodeGenTarget Target; 293175580c0f36b026daf9de0adabdb7ddcf7619db6Chris Lattner Record *AsmWriter = Target.getAsmWriter(); 294953c6fe11277c2511744440f5d8d90aca1354e18Chris Lattner std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName"); 295953c6fe11277c2511744440f5d8d90aca1354e18Chris Lattner unsigned Variant = AsmWriter->getValueAsInt("Variant"); 296175580c0f36b026daf9de0adabdb7ddcf7619db6Chris Lattner 2972e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner O << 2982e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner "/// printInstruction - This method is automatically generated by tablegen\n" 2992e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner "/// from the instruction set description. This method returns true if the\n" 3002e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner "/// machine instruction was sufficiently described to print it, otherwise\n" 3012e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner "/// it returns false.\n" 302953c6fe11277c2511744440f5d8d90aca1354e18Chris Lattner "bool " << Target.getName() << ClassName 303175580c0f36b026daf9de0adabdb7ddcf7619db6Chris Lattner << "::printInstruction(const MachineInstr *MI) {\n"; 3042e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner 3052e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner std::string Namespace = Target.inst_begin()->second.Namespace; 3062e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner 3075765dba5ce9f493f063a7caf1106e7db9b6693b6Chris Lattner std::vector<AsmWriterInst> Instructions; 3085765dba5ce9f493f063a7caf1106e7db9b6693b6Chris Lattner 3092e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner for (CodeGenTarget::inst_iterator I = Target.inst_begin(), 3102e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner E = Target.inst_end(); I != E; ++I) 3115765dba5ce9f493f063a7caf1106e7db9b6693b6Chris Lattner if (!I->second.AsmString.empty()) 3125765dba5ce9f493f063a7caf1106e7db9b6693b6Chris Lattner Instructions.push_back(AsmWriterInst(I->second, Variant)); 3135765dba5ce9f493f063a7caf1106e7db9b6693b6Chris Lattner 314f876668518097413a904537ce9d249953987508cChris Lattner // If all of the instructions start with a constant string (a very very common 315f876668518097413a904537ce9d249953987508cChris Lattner // occurance), emit all of the constant strings as a big table lookup instead 3163da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman // of requiring a switch for them. 317f876668518097413a904537ce9d249953987508cChris Lattner bool AllStartWithString = true; 318f876668518097413a904537ce9d249953987508cChris Lattner 319f876668518097413a904537ce9d249953987508cChris Lattner for (unsigned i = 0, e = Instructions.size(); i != e; ++i) 320f876668518097413a904537ce9d249953987508cChris Lattner if (Instructions[i].Operands.empty() || 321f876668518097413a904537ce9d249953987508cChris Lattner Instructions[i].Operands[0].OperandType != 322f876668518097413a904537ce9d249953987508cChris Lattner AsmWriterOperand::isLiteralTextOperand) { 323f876668518097413a904537ce9d249953987508cChris Lattner AllStartWithString = false; 324f876668518097413a904537ce9d249953987508cChris Lattner break; 325f876668518097413a904537ce9d249953987508cChris Lattner } 3263da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman 327f876668518097413a904537ce9d249953987508cChris Lattner if (AllStartWithString) { 328f876668518097413a904537ce9d249953987508cChris Lattner // Compute the CodeGenInstruction -> AsmWriterInst mapping. Note that not 329f876668518097413a904537ce9d249953987508cChris Lattner // all machine instructions are necessarily being printed, so there may be 330f876668518097413a904537ce9d249953987508cChris Lattner // target instructions not in this map. 331f876668518097413a904537ce9d249953987508cChris Lattner std::map<const CodeGenInstruction*, AsmWriterInst*> CGIAWIMap; 332f876668518097413a904537ce9d249953987508cChris Lattner for (unsigned i = 0, e = Instructions.size(); i != e; ++i) 333f876668518097413a904537ce9d249953987508cChris Lattner CGIAWIMap.insert(std::make_pair(Instructions[i].CGI, &Instructions[i])); 334f876668518097413a904537ce9d249953987508cChris Lattner 335f876668518097413a904537ce9d249953987508cChris Lattner // Emit a table of constant strings. 336f876668518097413a904537ce9d249953987508cChris Lattner std::vector<const CodeGenInstruction*> NumberedInstructions; 337f876668518097413a904537ce9d249953987508cChris Lattner Target.getInstructionsByEnumValue(NumberedInstructions); 338f876668518097413a904537ce9d249953987508cChris Lattner 339f876668518097413a904537ce9d249953987508cChris Lattner O << " static const char * const OpStrs[] = {\n"; 340f876668518097413a904537ce9d249953987508cChris Lattner for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) { 341f876668518097413a904537ce9d249953987508cChris Lattner AsmWriterInst *AWI = CGIAWIMap[NumberedInstructions[i]]; 342f876668518097413a904537ce9d249953987508cChris Lattner if (AWI == 0) { 343f876668518097413a904537ce9d249953987508cChris Lattner // Something not handled by the asmwriter printer. 344f876668518097413a904537ce9d249953987508cChris Lattner O << " 0,\t// "; 345f876668518097413a904537ce9d249953987508cChris Lattner } else { 346f876668518097413a904537ce9d249953987508cChris Lattner O << " \"" << AWI->Operands[0].Str << "\",\t// "; 347f876668518097413a904537ce9d249953987508cChris Lattner // Nuke the string from the operand list. It is now handled! 348f876668518097413a904537ce9d249953987508cChris Lattner AWI->Operands.erase(AWI->Operands.begin()); 349f876668518097413a904537ce9d249953987508cChris Lattner } 350f876668518097413a904537ce9d249953987508cChris Lattner O << NumberedInstructions[i]->TheDef->getName() << "\n"; 351f876668518097413a904537ce9d249953987508cChris Lattner } 352f876668518097413a904537ce9d249953987508cChris Lattner O << " };\n\n" 353f876668518097413a904537ce9d249953987508cChris Lattner << " // Emit the opcode for the instruction.\n" 354f876668518097413a904537ce9d249953987508cChris Lattner << " if (const char *AsmStr = OpStrs[MI->getOpcode()])\n" 355f876668518097413a904537ce9d249953987508cChris Lattner << " O << AsmStr;\n\n"; 356f876668518097413a904537ce9d249953987508cChris Lattner } 357f876668518097413a904537ce9d249953987508cChris Lattner 358870c016934bacf43995d89531b166ae095ee3675Chris Lattner // Because this is a vector we want to emit from the end. Reverse all of the 359870c016934bacf43995d89531b166ae095ee3675Chris Lattner // elements in the vector. 360870c016934bacf43995d89531b166ae095ee3675Chris Lattner std::reverse(Instructions.begin(), Instructions.end()); 361f876668518097413a904537ce9d249953987508cChris Lattner 362f876668518097413a904537ce9d249953987508cChris Lattner O << " switch (MI->getOpcode()) {\n" 363f876668518097413a904537ce9d249953987508cChris Lattner " default: return false;\n"; 3643da94aec4d429b2ba0f65fa040c33650cade196bMisha Brukman 365870c016934bacf43995d89531b166ae095ee3675Chris Lattner while (!Instructions.empty()) 366870c016934bacf43995d89531b166ae095ee3675Chris Lattner EmitInstructions(Instructions, O); 367870c016934bacf43995d89531b166ae095ee3675Chris Lattner 3682e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner O << " }\n" 3692e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner " return true;\n" 3702e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner "}\n"; 3712e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner} 372