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