AsmWriterEmitter.cpp revision 953c6fe11277c2511744440f5d8d90aca1354e18
12e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner//===- AsmWriterEmitter.cpp - Generate an assembly writer -----------------===//
22e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner//
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.
72e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner//
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"
182e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner#include <ostream>
192e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattnerusing namespace llvm;
202e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner
21076efa771aa634801202f7b8189e33ee79dfc4edChris Lattnerstatic bool isIdentChar(char C) {
22076efa771aa634801202f7b8189e33ee79dfc4edChris Lattner  return (C >= 'a' && C <= 'z') ||
23076efa771aa634801202f7b8189e33ee79dfc4edChris Lattner         (C >= 'A' && C <= 'Z') ||
24076efa771aa634801202f7b8189e33ee79dfc4edChris Lattner         (C >= '0' && C <= '9') ||
25076efa771aa634801202f7b8189e33ee79dfc4edChris Lattner         C == '_';
26076efa771aa634801202f7b8189e33ee79dfc4edChris Lattner}
27076efa771aa634801202f7b8189e33ee79dfc4edChris Lattner
282e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattnervoid AsmWriterEmitter::run(std::ostream &O) {
292e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner  EmitSourceFileHeader("Assembly Writer Source Fragment", O);
302c38413b3f5420f45f2f8220b21862246d446dd0Chris Lattner  O << "namespace llvm {\n\n";
312e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner
322e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner  CodeGenTarget Target;
33175580c0f36b026daf9de0adabdb7ddcf7619db6Chris Lattner  Record *AsmWriter = Target.getAsmWriter();
34953c6fe11277c2511744440f5d8d90aca1354e18Chris Lattner  std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName");
35953c6fe11277c2511744440f5d8d90aca1354e18Chris Lattner  unsigned Variant = AsmWriter->getValueAsInt("Variant");
36175580c0f36b026daf9de0adabdb7ddcf7619db6Chris Lattner
372e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner  O <<
382e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner  "/// printInstruction - This method is automatically generated by tablegen\n"
392e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner  "/// from the instruction set description.  This method returns true if the\n"
402e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner  "/// machine instruction was sufficiently described to print it, otherwise\n"
412e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner  "/// it returns false.\n"
42953c6fe11277c2511744440f5d8d90aca1354e18Chris Lattner    "bool " << Target.getName() << ClassName
43175580c0f36b026daf9de0adabdb7ddcf7619db6Chris Lattner            << "::printInstruction(const MachineInstr *MI) {\n";
442e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner  O << "  switch (MI->getOpcode()) {\n"
452e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner       "  default: return false;\n";
462e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner
472e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner  std::string Namespace = Target.inst_begin()->second.Namespace;
482e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner
49953c6fe11277c2511744440f5d8d90aca1354e18Chris Lattner  bool inVariant = false;  // True if we are inside a {.|.|.} region.
50953c6fe11277c2511744440f5d8d90aca1354e18Chris Lattner
512e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner  for (CodeGenTarget::inst_iterator I = Target.inst_begin(),
522e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner         E = Target.inst_end(); I != E; ++I)
532e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner    if (!I->second.AsmString.empty()) {
542e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner      const std::string &AsmString = I->second.AsmString;
55076efa771aa634801202f7b8189e33ee79dfc4edChris Lattner      O << "  case " << Namespace << "::" << I->first << ": O ";
56076efa771aa634801202f7b8189e33ee79dfc4edChris Lattner
57076efa771aa634801202f7b8189e33ee79dfc4edChris Lattner      std::string::size_type LastEmitted = 0;
58076efa771aa634801202f7b8189e33ee79dfc4edChris Lattner      while (LastEmitted != AsmString.size()) {
59953c6fe11277c2511744440f5d8d90aca1354e18Chris Lattner        std::string::size_type DollarPos =
60953c6fe11277c2511744440f5d8d90aca1354e18Chris Lattner          AsmString.find_first_of("${|}", LastEmitted);
61076efa771aa634801202f7b8189e33ee79dfc4edChris Lattner        if (DollarPos == std::string::npos) DollarPos = AsmString.size();
62076efa771aa634801202f7b8189e33ee79dfc4edChris Lattner
63076efa771aa634801202f7b8189e33ee79dfc4edChris Lattner        // Emit a constant string fragment.
64076efa771aa634801202f7b8189e33ee79dfc4edChris Lattner        if (DollarPos != LastEmitted) {
65076efa771aa634801202f7b8189e33ee79dfc4edChris Lattner          // TODO: this should eventually handle escaping.
66076efa771aa634801202f7b8189e33ee79dfc4edChris Lattner          O << " << \"" << std::string(AsmString.begin()+LastEmitted,
67076efa771aa634801202f7b8189e33ee79dfc4edChris Lattner                                       AsmString.begin()+DollarPos) << "\"";
68076efa771aa634801202f7b8189e33ee79dfc4edChris Lattner          LastEmitted = DollarPos;
69953c6fe11277c2511744440f5d8d90aca1354e18Chris Lattner        } else if (AsmString[DollarPos] == '{') {
70953c6fe11277c2511744440f5d8d90aca1354e18Chris Lattner          if (inVariant)
71953c6fe11277c2511744440f5d8d90aca1354e18Chris Lattner            throw "Nested variants found for instruction '" + I->first + "'!";
72953c6fe11277c2511744440f5d8d90aca1354e18Chris Lattner          LastEmitted = DollarPos+1;
73953c6fe11277c2511744440f5d8d90aca1354e18Chris Lattner          inVariant = true;   // We are now inside of the variant!
74953c6fe11277c2511744440f5d8d90aca1354e18Chris Lattner          for (unsigned i = 0; i != Variant; ++i) {
75953c6fe11277c2511744440f5d8d90aca1354e18Chris Lattner            // Skip over all of the text for an irrelevant variant here.  The
76953c6fe11277c2511744440f5d8d90aca1354e18Chris Lattner            // next variant starts at |, or there may not be text for this
77953c6fe11277c2511744440f5d8d90aca1354e18Chris Lattner            // variant if we see a }.
78953c6fe11277c2511744440f5d8d90aca1354e18Chris Lattner            std::string::size_type NP =
79953c6fe11277c2511744440f5d8d90aca1354e18Chris Lattner              AsmString.find_first_of("|}", LastEmitted);
80953c6fe11277c2511744440f5d8d90aca1354e18Chris Lattner            if (NP == std::string::npos)
81953c6fe11277c2511744440f5d8d90aca1354e18Chris Lattner              throw "Incomplete variant for instruction '" + I->first + "'!";
82953c6fe11277c2511744440f5d8d90aca1354e18Chris Lattner            LastEmitted = NP+1;
83953c6fe11277c2511744440f5d8d90aca1354e18Chris Lattner            if (AsmString[NP] == '}') {
84953c6fe11277c2511744440f5d8d90aca1354e18Chris Lattner              inVariant = false;        // No text for this variant.
85953c6fe11277c2511744440f5d8d90aca1354e18Chris Lattner              break;
86953c6fe11277c2511744440f5d8d90aca1354e18Chris Lattner            }
87953c6fe11277c2511744440f5d8d90aca1354e18Chris Lattner          }
88953c6fe11277c2511744440f5d8d90aca1354e18Chris Lattner        } else if (AsmString[DollarPos] == '|') {
89953c6fe11277c2511744440f5d8d90aca1354e18Chris Lattner          if (!inVariant)
90953c6fe11277c2511744440f5d8d90aca1354e18Chris Lattner            throw "'|' character found outside of a variant in instruction '"
91953c6fe11277c2511744440f5d8d90aca1354e18Chris Lattner                  + I->first + "'!";
92953c6fe11277c2511744440f5d8d90aca1354e18Chris Lattner          // Move to the end of variant list.
93953c6fe11277c2511744440f5d8d90aca1354e18Chris Lattner          std::string::size_type NP = AsmString.find('}', LastEmitted);
94953c6fe11277c2511744440f5d8d90aca1354e18Chris Lattner          if (NP == std::string::npos)
95953c6fe11277c2511744440f5d8d90aca1354e18Chris Lattner            throw "Incomplete variant for instruction '" + I->first + "'!";
96953c6fe11277c2511744440f5d8d90aca1354e18Chris Lattner          LastEmitted = NP+1;
97953c6fe11277c2511744440f5d8d90aca1354e18Chris Lattner          inVariant = false;
98953c6fe11277c2511744440f5d8d90aca1354e18Chris Lattner        } else if (AsmString[DollarPos] == '}') {
99953c6fe11277c2511744440f5d8d90aca1354e18Chris Lattner          if (!inVariant)
100953c6fe11277c2511744440f5d8d90aca1354e18Chris Lattner            throw "'}' character found outside of a variant in instruction '"
101953c6fe11277c2511744440f5d8d90aca1354e18Chris Lattner                  + I->first + "'!";
102953c6fe11277c2511744440f5d8d90aca1354e18Chris Lattner          LastEmitted = DollarPos+1;
103953c6fe11277c2511744440f5d8d90aca1354e18Chris Lattner          inVariant = false;
104076efa771aa634801202f7b8189e33ee79dfc4edChris Lattner        } else if (DollarPos+1 != AsmString.size() &&
105076efa771aa634801202f7b8189e33ee79dfc4edChris Lattner                   AsmString[DollarPos+1] == '$') {
106076efa771aa634801202f7b8189e33ee79dfc4edChris Lattner          O << " << '$'";         // "$$" -> $
107076efa771aa634801202f7b8189e33ee79dfc4edChris Lattner        } else {
108076efa771aa634801202f7b8189e33ee79dfc4edChris Lattner          // Get the name of the variable.
109076efa771aa634801202f7b8189e33ee79dfc4edChris Lattner          // TODO: should eventually handle ${foo}bar as $foo
110076efa771aa634801202f7b8189e33ee79dfc4edChris Lattner          std::string::size_type VarEnd = DollarPos+1;
111076efa771aa634801202f7b8189e33ee79dfc4edChris Lattner          while (VarEnd < AsmString.size() && isIdentChar(AsmString[VarEnd]))
112076efa771aa634801202f7b8189e33ee79dfc4edChris Lattner            ++VarEnd;
113076efa771aa634801202f7b8189e33ee79dfc4edChris Lattner          std::string VarName(AsmString.begin()+DollarPos+1,
114076efa771aa634801202f7b8189e33ee79dfc4edChris Lattner                              AsmString.begin()+VarEnd);
115076efa771aa634801202f7b8189e33ee79dfc4edChris Lattner          if (VarName.empty())
116076efa771aa634801202f7b8189e33ee79dfc4edChris Lattner            throw "Stray '$' in '" + I->first +
117076efa771aa634801202f7b8189e33ee79dfc4edChris Lattner                  "' asm string, maybe you want $$?";
118076efa771aa634801202f7b8189e33ee79dfc4edChris Lattner          unsigned OpNo = I->second.getOperandNamed(VarName);
119076efa771aa634801202f7b8189e33ee79dfc4edChris Lattner
120076efa771aa634801202f7b8189e33ee79dfc4edChris Lattner          // If this is a two-address instruction and we are not accessing the
121076efa771aa634801202f7b8189e33ee79dfc4edChris Lattner          // 0th operand, remove an operand.
1229302ba416b4b5291f4b3f123a47d47c9268573f9Chris Lattner          unsigned MIOp = I->second.OperandList[OpNo].MIOperandNo;
1239302ba416b4b5291f4b3f123a47d47c9268573f9Chris Lattner          if (I->second.isTwoAddress && MIOp != 0) {
1249302ba416b4b5291f4b3f123a47d47c9268573f9Chris Lattner            if (MIOp == 1)
125c3d5f3e12a19c75c483d3d2588842277937a851fChris Lattner              throw "Should refer to operand #0 instead of #1 for two-address"
126c3d5f3e12a19c75c483d3d2588842277937a851fChris Lattner                    " instruction '" + I->first + "'!";
1279302ba416b4b5291f4b3f123a47d47c9268573f9Chris Lattner            --MIOp;
128c3d5f3e12a19c75c483d3d2588842277937a851fChris Lattner          }
129076efa771aa634801202f7b8189e33ee79dfc4edChris Lattner
1301caef2c0a9df447d6bdcba329675e52c51f3642bChris Lattner          O << ";  " << I->second.OperandList[OpNo].PrinterMethodName
1319302ba416b4b5291f4b3f123a47d47c9268573f9Chris Lattner            << "(MI, " << MIOp << ", MVT::"
132076efa771aa634801202f7b8189e33ee79dfc4edChris Lattner            << getName(I->second.OperandList[OpNo].Ty) << "); O ";
133076efa771aa634801202f7b8189e33ee79dfc4edChris Lattner          LastEmitted = VarEnd;
134076efa771aa634801202f7b8189e33ee79dfc4edChris Lattner        }
135076efa771aa634801202f7b8189e33ee79dfc4edChris Lattner      }
136076efa771aa634801202f7b8189e33ee79dfc4edChris Lattner
137076efa771aa634801202f7b8189e33ee79dfc4edChris Lattner      O << " << '\\n'; break;\n";
1382e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner    }
1392e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner
1402e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner  O << "  }\n"
1412e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner       "  return true;\n"
1422e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner       "}\n";
1432c38413b3f5420f45f2f8220b21862246d446dd0Chris Lattner  O << "} // End llvm namespace \n";
1442e1f51b8a583649d74cb666ca5e4cf680cc1ced9Chris Lattner}
145