blob: c168a914ec72e1b57af42cb8266990d615b6878e [file] [log] [blame]
Chris Lattner2e1f51b2004-08-01 05:59:33 +00001//===- AsmWriterEmitter.cpp - Generate an assembly writer -----------------===//
Misha Brukman3da94ae2005-04-22 00:00:37 +00002//
Chris Lattner2e1f51b2004-08-01 05:59:33 +00003// The LLVM Compiler Infrastructure
4//
5// This file was developed by the LLVM research group and is distributed under
6// the University of Illinois Open Source License. See LICENSE.TXT for details.
Misha Brukman3da94ae2005-04-22 00:00:37 +00007//
Chris Lattner2e1f51b2004-08-01 05:59:33 +00008//===----------------------------------------------------------------------===//
9//
10// This tablegen backend is emits an assembly printer for the current target.
11// Note that this is currently fairly skeletal, but will grow over time.
12//
13//===----------------------------------------------------------------------===//
14
15#include "AsmWriterEmitter.h"
16#include "CodeGenTarget.h"
Chris Lattner175580c2004-08-14 22:50:53 +000017#include "Record.h"
Chris Lattner6af022f2006-07-14 22:59:11 +000018#include "llvm/ADT/StringExtras.h"
Jeff Cohen615ed992005-01-22 18:50:10 +000019#include <algorithm>
Chris Lattner2e1f51b2004-08-01 05:59:33 +000020#include <ostream>
21using namespace llvm;
22
Chris Lattner076efa72004-08-01 07:43:02 +000023static bool isIdentChar(char C) {
24 return (C >= 'a' && C <= 'z') ||
25 (C >= 'A' && C <= 'Z') ||
26 (C >= '0' && C <= '9') ||
27 C == '_';
28}
29
Chris Lattnerb0b55e72005-01-22 17:32:42 +000030namespace {
31 struct AsmWriterOperand {
32 enum { isLiteralTextOperand, isMachineInstrOperand } OperandType;
33
34 /// Str - For isLiteralTextOperand, this IS the literal text. For
35 /// isMachineInstrOperand, this is the PrinterMethodName for the operand.
36 std::string Str;
37
38 /// MiOpNo - For isMachineInstrOperand, this is the operand number of the
39 /// machine instruction.
40 unsigned MIOpNo;
Chris Lattner04cadb32006-02-06 23:40:48 +000041
42 /// MiModifier - For isMachineInstrOperand, this is the modifier string for
43 /// an operand, specified with syntax like ${opname:modifier}.
44 std::string MiModifier;
Chris Lattnerb0b55e72005-01-22 17:32:42 +000045
Chris Lattnerb0b55e72005-01-22 17:32:42 +000046 AsmWriterOperand(const std::string &LitStr)
Nate Begeman391c5d22005-11-30 18:54:35 +000047 : OperandType(isLiteralTextOperand), Str(LitStr) {}
Chris Lattnerb0b55e72005-01-22 17:32:42 +000048
Chris Lattner04cadb32006-02-06 23:40:48 +000049 AsmWriterOperand(const std::string &Printer, unsigned OpNo,
50 const std::string &Modifier)
51 : OperandType(isMachineInstrOperand), Str(Printer), MIOpNo(OpNo),
52 MiModifier(Modifier) {}
Chris Lattnerb0b55e72005-01-22 17:32:42 +000053
Chris Lattner870c0162005-01-22 18:38:13 +000054 bool operator!=(const AsmWriterOperand &Other) const {
55 if (OperandType != Other.OperandType || Str != Other.Str) return true;
56 if (OperandType == isMachineInstrOperand)
Chris Lattner04cadb32006-02-06 23:40:48 +000057 return MIOpNo != Other.MIOpNo || MiModifier != Other.MiModifier;
Chris Lattner870c0162005-01-22 18:38:13 +000058 return false;
59 }
Chris Lattner38c07512005-01-22 20:31:17 +000060 bool operator==(const AsmWriterOperand &Other) const {
61 return !operator!=(Other);
62 }
Chris Lattnerb0b55e72005-01-22 17:32:42 +000063 void EmitCode(std::ostream &OS) const;
64 };
65
66 struct AsmWriterInst {
67 std::vector<AsmWriterOperand> Operands;
Chris Lattner5765dba2005-01-22 17:40:38 +000068 const CodeGenInstruction *CGI;
Misha Brukman3da94ae2005-04-22 00:00:37 +000069
Chris Lattner5765dba2005-01-22 17:40:38 +000070 AsmWriterInst(const CodeGenInstruction &CGI, unsigned Variant);
Chris Lattner870c0162005-01-22 18:38:13 +000071
Chris Lattnerf8766682005-01-22 19:22:23 +000072 /// MatchesAllButOneOp - If this instruction is exactly identical to the
73 /// specified instruction except for one differing operand, return the
74 /// differing operand number. Otherwise return ~0.
75 unsigned MatchesAllButOneOp(const AsmWriterInst &Other) const;
Chris Lattner870c0162005-01-22 18:38:13 +000076
Chris Lattnerb0b55e72005-01-22 17:32:42 +000077 private:
78 void AddLiteralString(const std::string &Str) {
79 // If the last operand was already a literal text string, append this to
80 // it, otherwise add a new operand.
81 if (!Operands.empty() &&
82 Operands.back().OperandType == AsmWriterOperand::isLiteralTextOperand)
83 Operands.back().Str.append(Str);
84 else
85 Operands.push_back(AsmWriterOperand(Str));
86 }
87 };
88}
89
90
91void AsmWriterOperand::EmitCode(std::ostream &OS) const {
92 if (OperandType == isLiteralTextOperand)
93 OS << "O << \"" << Str << "\"; ";
Chris Lattner04cadb32006-02-06 23:40:48 +000094 else {
95 OS << Str << "(MI, " << MIOpNo;
96 if (!MiModifier.empty())
97 OS << ", \"" << MiModifier << '"';
98 OS << "); ";
99 }
Chris Lattnerb0b55e72005-01-22 17:32:42 +0000100}
101
102
103/// ParseAsmString - Parse the specified Instruction's AsmString into this
104/// AsmWriterInst.
105///
Chris Lattner5765dba2005-01-22 17:40:38 +0000106AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, unsigned Variant) {
107 this->CGI = &CGI;
Chris Lattnerb03b0802006-02-06 22:43:28 +0000108 unsigned CurVariant = ~0U; // ~0 if we are outside a {.|.|.} region, other #.
Chris Lattnerb0b55e72005-01-22 17:32:42 +0000109
Chris Lattner1cf9d962006-02-01 19:12:23 +0000110 // NOTE: Any extensions to this code need to be mirrored in the
111 // AsmPrinter::printInlineAsm code that executes as compile time (assuming
112 // that inline asm strings should also get the new feature)!
Chris Lattnerb0b55e72005-01-22 17:32:42 +0000113 const std::string &AsmString = CGI.AsmString;
114 std::string::size_type LastEmitted = 0;
115 while (LastEmitted != AsmString.size()) {
116 std::string::size_type DollarPos =
117 AsmString.find_first_of("${|}", LastEmitted);
118 if (DollarPos == std::string::npos) DollarPos = AsmString.size();
119
120 // Emit a constant string fragment.
121 if (DollarPos != LastEmitted) {
122 // TODO: this should eventually handle escaping.
Chris Lattnerb03b0802006-02-06 22:43:28 +0000123 if (CurVariant == Variant || CurVariant == ~0U)
124 AddLiteralString(std::string(AsmString.begin()+LastEmitted,
125 AsmString.begin()+DollarPos));
Chris Lattnerb0b55e72005-01-22 17:32:42 +0000126 LastEmitted = DollarPos;
127 } else if (AsmString[DollarPos] == '{') {
Chris Lattnerb03b0802006-02-06 22:43:28 +0000128 if (CurVariant != ~0U)
Jeff Cohen00b168892005-07-27 06:12:32 +0000129 throw "Nested variants found for instruction '" +
Chris Lattner3e3def92005-07-15 22:43:04 +0000130 CGI.TheDef->getName() + "'!";
Chris Lattnerb0b55e72005-01-22 17:32:42 +0000131 LastEmitted = DollarPos+1;
Chris Lattnerb03b0802006-02-06 22:43:28 +0000132 CurVariant = 0; // We are now inside of the variant!
Chris Lattnerb0b55e72005-01-22 17:32:42 +0000133 } else if (AsmString[DollarPos] == '|') {
Chris Lattnerb03b0802006-02-06 22:43:28 +0000134 if (CurVariant == ~0U)
Chris Lattnerb0b55e72005-01-22 17:32:42 +0000135 throw "'|' character found outside of a variant in instruction '"
Chris Lattner3e3def92005-07-15 22:43:04 +0000136 + CGI.TheDef->getName() + "'!";
Chris Lattnerb03b0802006-02-06 22:43:28 +0000137 ++CurVariant;
138 ++LastEmitted;
Chris Lattnerb0b55e72005-01-22 17:32:42 +0000139 } else if (AsmString[DollarPos] == '}') {
Chris Lattnerb03b0802006-02-06 22:43:28 +0000140 if (CurVariant == ~0U)
Chris Lattnerb0b55e72005-01-22 17:32:42 +0000141 throw "'}' character found outside of a variant in instruction '"
Chris Lattner3e3def92005-07-15 22:43:04 +0000142 + CGI.TheDef->getName() + "'!";
Chris Lattnerb03b0802006-02-06 22:43:28 +0000143 ++LastEmitted;
144 CurVariant = ~0U;
Chris Lattnerb0b55e72005-01-22 17:32:42 +0000145 } else if (DollarPos+1 != AsmString.size() &&
146 AsmString[DollarPos+1] == '$') {
Chris Lattnerb03b0802006-02-06 22:43:28 +0000147 if (CurVariant == Variant || CurVariant == ~0U)
148 AddLiteralString("$"); // "$$" -> $
Chris Lattnerb0b55e72005-01-22 17:32:42 +0000149 LastEmitted = DollarPos+2;
150 } else {
151 // Get the name of the variable.
Chris Lattnerb0b55e72005-01-22 17:32:42 +0000152 std::string::size_type VarEnd = DollarPos+1;
Nate Begemanafc54562005-07-14 22:50:30 +0000153
154 // handle ${foo}bar as $foo by detecting whether the character following
155 // the dollar sign is a curly brace. If so, advance VarEnd and DollarPos
156 // so the variable name does not contain the leading curly brace.
157 bool hasCurlyBraces = false;
158 if (VarEnd < AsmString.size() && '{' == AsmString[VarEnd]) {
159 hasCurlyBraces = true;
160 ++DollarPos;
161 ++VarEnd;
162 }
163
Chris Lattnerb0b55e72005-01-22 17:32:42 +0000164 while (VarEnd < AsmString.size() && isIdentChar(AsmString[VarEnd]))
165 ++VarEnd;
166 std::string VarName(AsmString.begin()+DollarPos+1,
167 AsmString.begin()+VarEnd);
Nate Begemanafc54562005-07-14 22:50:30 +0000168
Chris Lattner04cadb32006-02-06 23:40:48 +0000169 // Modifier - Support ${foo:modifier} syntax, where "modifier" is passed
170 // into printOperand.
171 std::string Modifier;
172
Nate Begemanafc54562005-07-14 22:50:30 +0000173 // In order to avoid starting the next string at the terminating curly
174 // brace, advance the end position past it if we found an opening curly
175 // brace.
176 if (hasCurlyBraces) {
177 if (VarEnd >= AsmString.size())
178 throw "Reached end of string before terminating curly brace in '"
Chris Lattner3e3def92005-07-15 22:43:04 +0000179 + CGI.TheDef->getName() + "'";
Chris Lattner04cadb32006-02-06 23:40:48 +0000180
181 // Look for a modifier string.
182 if (AsmString[VarEnd] == ':') {
183 ++VarEnd;
184 if (VarEnd >= AsmString.size())
185 throw "Reached end of string before terminating curly brace in '"
186 + CGI.TheDef->getName() + "'";
187
188 unsigned ModifierStart = VarEnd;
189 while (VarEnd < AsmString.size() && isIdentChar(AsmString[VarEnd]))
190 ++VarEnd;
191 Modifier = std::string(AsmString.begin()+ModifierStart,
192 AsmString.begin()+VarEnd);
193 if (Modifier.empty())
194 throw "Bad operand modifier name in '"+ CGI.TheDef->getName() + "'";
195 }
196
Nate Begemanafc54562005-07-14 22:50:30 +0000197 if (AsmString[VarEnd] != '}')
Chris Lattnerb03b0802006-02-06 22:43:28 +0000198 throw "Variable name beginning with '{' did not end with '}' in '"
Chris Lattner3e3def92005-07-15 22:43:04 +0000199 + CGI.TheDef->getName() + "'";
Nate Begemanafc54562005-07-14 22:50:30 +0000200 ++VarEnd;
201 }
Chris Lattnerb0b55e72005-01-22 17:32:42 +0000202 if (VarName.empty())
Jeff Cohen00b168892005-07-27 06:12:32 +0000203 throw "Stray '$' in '" + CGI.TheDef->getName() +
Chris Lattner3e3def92005-07-15 22:43:04 +0000204 "' asm string, maybe you want $$?";
Chris Lattnerb0b55e72005-01-22 17:32:42 +0000205
206 unsigned OpNo = CGI.getOperandNamed(VarName);
Chris Lattner5765dba2005-01-22 17:40:38 +0000207 CodeGenInstruction::OperandInfo OpInfo = CGI.OperandList[OpNo];
Chris Lattnerb0b55e72005-01-22 17:32:42 +0000208
209 // If this is a two-address instruction and we are not accessing the
210 // 0th operand, remove an operand.
Chris Lattner5765dba2005-01-22 17:40:38 +0000211 unsigned MIOp = OpInfo.MIOperandNo;
Chris Lattnerb0b55e72005-01-22 17:32:42 +0000212 if (CGI.isTwoAddress && MIOp != 0) {
213 if (MIOp == 1)
214 throw "Should refer to operand #0 instead of #1 for two-address"
Chris Lattner3e3def92005-07-15 22:43:04 +0000215 " instruction '" + CGI.TheDef->getName() + "'!";
Chris Lattnerb0b55e72005-01-22 17:32:42 +0000216 --MIOp;
217 }
218
Chris Lattnerb03b0802006-02-06 22:43:28 +0000219 if (CurVariant == Variant || CurVariant == ~0U)
Chris Lattner04cadb32006-02-06 23:40:48 +0000220 Operands.push_back(AsmWriterOperand(OpInfo.PrinterMethodName, MIOp,
221 Modifier));
Chris Lattnerb0b55e72005-01-22 17:32:42 +0000222 LastEmitted = VarEnd;
223 }
224 }
225
226 AddLiteralString("\\n");
227}
228
Chris Lattnerf8766682005-01-22 19:22:23 +0000229/// MatchesAllButOneOp - If this instruction is exactly identical to the
230/// specified instruction except for one differing operand, return the differing
231/// operand number. If more than one operand mismatches, return ~1, otherwise
232/// if the instructions are identical return ~0.
233unsigned AsmWriterInst::MatchesAllButOneOp(const AsmWriterInst &Other)const{
234 if (Operands.size() != Other.Operands.size()) return ~1;
Chris Lattner870c0162005-01-22 18:38:13 +0000235
236 unsigned MismatchOperand = ~0U;
237 for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
Chris Lattner870c0162005-01-22 18:38:13 +0000238 if (Operands[i] != Other.Operands[i])
Chris Lattnerf8766682005-01-22 19:22:23 +0000239 if (MismatchOperand != ~0U) // Already have one mismatch?
240 return ~1U;
Misha Brukman3da94ae2005-04-22 00:00:37 +0000241 else
Chris Lattner870c0162005-01-22 18:38:13 +0000242 MismatchOperand = i;
243 }
244 return MismatchOperand;
245}
246
Chris Lattner38c07512005-01-22 20:31:17 +0000247static void PrintCases(std::vector<std::pair<std::string,
248 AsmWriterOperand> > &OpsToPrint, std::ostream &O) {
249 O << " case " << OpsToPrint.back().first << ": ";
250 AsmWriterOperand TheOp = OpsToPrint.back().second;
251 OpsToPrint.pop_back();
252
253 // Check to see if any other operands are identical in this list, and if so,
254 // emit a case label for them.
255 for (unsigned i = OpsToPrint.size(); i != 0; --i)
256 if (OpsToPrint[i-1].second == TheOp) {
257 O << "\n case " << OpsToPrint[i-1].first << ": ";
258 OpsToPrint.erase(OpsToPrint.begin()+i-1);
259 }
260
261 // Finally, emit the code.
262 TheOp.EmitCode(O);
263 O << "break;\n";
264}
265
Chris Lattner870c0162005-01-22 18:38:13 +0000266
267/// EmitInstructions - Emit the last instruction in the vector and any other
268/// instructions that are suitably similar to it.
269static void EmitInstructions(std::vector<AsmWriterInst> &Insts,
270 std::ostream &O) {
271 AsmWriterInst FirstInst = Insts.back();
272 Insts.pop_back();
273
274 std::vector<AsmWriterInst> SimilarInsts;
275 unsigned DifferingOperand = ~0;
276 for (unsigned i = Insts.size(); i != 0; --i) {
Chris Lattnerf8766682005-01-22 19:22:23 +0000277 unsigned DiffOp = Insts[i-1].MatchesAllButOneOp(FirstInst);
278 if (DiffOp != ~1U) {
Chris Lattner870c0162005-01-22 18:38:13 +0000279 if (DifferingOperand == ~0U) // First match!
280 DifferingOperand = DiffOp;
281
282 // If this differs in the same operand as the rest of the instructions in
283 // this class, move it to the SimilarInsts list.
Chris Lattnerf8766682005-01-22 19:22:23 +0000284 if (DifferingOperand == DiffOp || DiffOp == ~0U) {
Chris Lattner870c0162005-01-22 18:38:13 +0000285 SimilarInsts.push_back(Insts[i-1]);
286 Insts.erase(Insts.begin()+i-1);
287 }
288 }
289 }
290
Chris Lattnera1e8a802006-05-01 17:01:17 +0000291 O << " case " << FirstInst.CGI->Namespace << "::"
Chris Lattner870c0162005-01-22 18:38:13 +0000292 << FirstInst.CGI->TheDef->getName() << ":\n";
293 for (unsigned i = 0, e = SimilarInsts.size(); i != e; ++i)
Chris Lattnera1e8a802006-05-01 17:01:17 +0000294 O << " case " << SimilarInsts[i].CGI->Namespace << "::"
Chris Lattner870c0162005-01-22 18:38:13 +0000295 << SimilarInsts[i].CGI->TheDef->getName() << ":\n";
296 for (unsigned i = 0, e = FirstInst.Operands.size(); i != e; ++i) {
297 if (i != DifferingOperand) {
298 // If the operand is the same for all instructions, just print it.
299 O << " ";
300 FirstInst.Operands[i].EmitCode(O);
301 } else {
302 // If this is the operand that varies between all of the instructions,
303 // emit a switch for just this operand now.
304 O << " switch (MI->getOpcode()) {\n";
Chris Lattner38c07512005-01-22 20:31:17 +0000305 std::vector<std::pair<std::string, AsmWriterOperand> > OpsToPrint;
Chris Lattnera1e8a802006-05-01 17:01:17 +0000306 OpsToPrint.push_back(std::make_pair(FirstInst.CGI->Namespace + "::" +
Chris Lattner38c07512005-01-22 20:31:17 +0000307 FirstInst.CGI->TheDef->getName(),
308 FirstInst.Operands[i]));
Misha Brukman3da94ae2005-04-22 00:00:37 +0000309
Chris Lattner870c0162005-01-22 18:38:13 +0000310 for (unsigned si = 0, e = SimilarInsts.size(); si != e; ++si) {
Chris Lattner38c07512005-01-22 20:31:17 +0000311 AsmWriterInst &AWI = SimilarInsts[si];
Chris Lattnera1e8a802006-05-01 17:01:17 +0000312 OpsToPrint.push_back(std::make_pair(AWI.CGI->Namespace+"::"+
Chris Lattner38c07512005-01-22 20:31:17 +0000313 AWI.CGI->TheDef->getName(),
314 AWI.Operands[i]));
Chris Lattner870c0162005-01-22 18:38:13 +0000315 }
Chris Lattner38c07512005-01-22 20:31:17 +0000316 std::reverse(OpsToPrint.begin(), OpsToPrint.end());
317 while (!OpsToPrint.empty())
318 PrintCases(OpsToPrint, O);
Chris Lattner870c0162005-01-22 18:38:13 +0000319 O << " }";
320 }
321 O << "\n";
322 }
323
324 O << " break;\n";
325}
Chris Lattnerb0b55e72005-01-22 17:32:42 +0000326
Chris Lattner2e1f51b2004-08-01 05:59:33 +0000327void AsmWriterEmitter::run(std::ostream &O) {
328 EmitSourceFileHeader("Assembly Writer Source Fragment", O);
329
330 CodeGenTarget Target;
Chris Lattner175580c2004-08-14 22:50:53 +0000331 Record *AsmWriter = Target.getAsmWriter();
Chris Lattner953c6fe2004-10-03 20:19:02 +0000332 std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName");
333 unsigned Variant = AsmWriter->getValueAsInt("Variant");
Chris Lattner175580c2004-08-14 22:50:53 +0000334
Chris Lattner2e1f51b2004-08-01 05:59:33 +0000335 O <<
336 "/// printInstruction - This method is automatically generated by tablegen\n"
337 "/// from the instruction set description. This method returns true if the\n"
338 "/// machine instruction was sufficiently described to print it, otherwise\n"
339 "/// it returns false.\n"
Chris Lattner953c6fe2004-10-03 20:19:02 +0000340 "bool " << Target.getName() << ClassName
Chris Lattner175580c2004-08-14 22:50:53 +0000341 << "::printInstruction(const MachineInstr *MI) {\n";
Chris Lattner2e1f51b2004-08-01 05:59:33 +0000342
Chris Lattner5765dba2005-01-22 17:40:38 +0000343 std::vector<AsmWriterInst> Instructions;
344
Chris Lattner2e1f51b2004-08-01 05:59:33 +0000345 for (CodeGenTarget::inst_iterator I = Target.inst_begin(),
346 E = Target.inst_end(); I != E; ++I)
Chris Lattner5765dba2005-01-22 17:40:38 +0000347 if (!I->second.AsmString.empty())
348 Instructions.push_back(AsmWriterInst(I->second, Variant));
Chris Lattner076efa72004-08-01 07:43:02 +0000349
Chris Lattner0cfcc1e2006-01-27 02:10:50 +0000350 std::vector<const CodeGenInstruction*> NumberedInstructions;
351 Target.getInstructionsByEnumValue(NumberedInstructions);
352
Chris Lattner6af022f2006-07-14 22:59:11 +0000353 // Compute the CodeGenInstruction -> AsmWriterInst mapping. Note that not
354 // all machine instructions are necessarily being printed, so there may be
355 // target instructions not in this map.
356 std::map<const CodeGenInstruction*, AsmWriterInst*> CGIAWIMap;
357 for (unsigned i = 0, e = Instructions.size(); i != e; ++i)
358 CGIAWIMap.insert(std::make_pair(Instructions[i].CGI, &Instructions[i]));
Chris Lattnerf8766682005-01-22 19:22:23 +0000359
Chris Lattner6af022f2006-07-14 22:59:11 +0000360 // Build an aggregate string, and build a table of offsets into it.
361 std::map<std::string, unsigned> StringOffset;
362 std::string AggregateString;
363 AggregateString += '\0';
364
Chris Lattnerfb5115e2006-07-14 23:14:02 +0000365 O << " static const unsigned short OpStrIdxs[] = {\n";
Chris Lattner6af022f2006-07-14 22:59:11 +0000366 for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) {
367 AsmWriterInst *AWI = CGIAWIMap[NumberedInstructions[i]];
368 unsigned Idx;
369 if (AWI == 0 || AWI->Operands[0].Str.empty()) {
370 // Something not handled by the asmwriter printer.
371 Idx = 0;
372 } else {
373 unsigned &Entry = StringOffset[AWI->Operands[0].Str];
374 if (Entry == 0) {
375 // Add the string to the aggregate if this is the first time found.
376 Entry = AggregateString.size();
377 std::string Str = AWI->Operands[0].Str;
378 UnescapeString(Str);
379 AggregateString += Str;
380 AggregateString += '\0';
Chris Lattnerf8766682005-01-22 19:22:23 +0000381 }
Chris Lattner6af022f2006-07-14 22:59:11 +0000382 Idx = Entry;
383 assert(Entry < 65536 && "Must not use unsigned short for table idx!");
384
385 // Nuke the string from the operand list. It is now handled!
386 AWI->Operands.erase(AWI->Operands.begin());
Chris Lattnerf8766682005-01-22 19:22:23 +0000387 }
Chris Lattner6af022f2006-07-14 22:59:11 +0000388 O << " " << Idx << ",\t// " << NumberedInstructions[i]->TheDef->getName()
389 << "\n";
Chris Lattnerf8766682005-01-22 19:22:23 +0000390 }
Chris Lattner6af022f2006-07-14 22:59:11 +0000391 O << " };\n\n";
392
393 // Emit the string itself.
394 O << " const char *AsmStrs = \n \"";
395 unsigned CharsPrinted = 0;
396 EscapeString(AggregateString);
397 for (unsigned i = 0, e = AggregateString.size(); i != e; ++i) {
398 if (CharsPrinted > 70) {
399 O << "\"\n \"";
400 CharsPrinted = 0;
401 }
402 O << AggregateString[i];
403 ++CharsPrinted;
404
405 // Print escape sequences all together.
406 if (AggregateString[i] == '\\') {
407 assert(i+1 < AggregateString.size() && "Incomplete escape sequence!");
408 if (isdigit(AggregateString[i+1])) {
409 assert(isdigit(AggregateString[i+2]) && isdigit(AggregateString[i+3]) &&
410 "Expected 3 digit octal escape!");
411 O << AggregateString[++i];
412 O << AggregateString[++i];
413 O << AggregateString[++i];
414 CharsPrinted += 3;
415 } else {
416 O << AggregateString[++i];
417 ++CharsPrinted;
418 }
419 }
420 }
421 O << "\";\n\n";
422
423 O << " // Emit the opcode for the instruction.\n"
424 << " O << AsmStrs+OpStrIdxs[MI->getOpcode()];\n\n";
Chris Lattnerf8766682005-01-22 19:22:23 +0000425
Chris Lattner870c0162005-01-22 18:38:13 +0000426 // Because this is a vector we want to emit from the end. Reverse all of the
427 // elements in the vector.
428 std::reverse(Instructions.begin(), Instructions.end());
Chris Lattnerf8766682005-01-22 19:22:23 +0000429
Chris Lattner0cfcc1e2006-01-27 02:10:50 +0000430 // Find the opcode # of inline asm
Chris Lattnerf8766682005-01-22 19:22:23 +0000431 O << " switch (MI->getOpcode()) {\n"
Chris Lattner0cfcc1e2006-01-27 02:10:50 +0000432 " default: return false;\n"
433 " case " << NumberedInstructions.back()->Namespace
434 << "::INLINEASM: printInlineAsm(MI); break;\n";
Misha Brukman3da94ae2005-04-22 00:00:37 +0000435
Chris Lattner870c0162005-01-22 18:38:13 +0000436 while (!Instructions.empty())
437 EmitInstructions(Instructions, O);
438
Chris Lattner2e1f51b2004-08-01 05:59:33 +0000439 O << " }\n"
440 " return true;\n"
441 "}\n";
Chris Lattner2e1f51b2004-08-01 05:59:33 +0000442}