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