blob: ca0fe0e6c832aa82507cc7227036acc69e40f7cc [file] [log] [blame]
Chris Lattner1c4ae852004-08-01 05:59:33 +00001//===- AsmWriterEmitter.cpp - Generate an assembly writer -----------------===//
Misha Brukman650ba8e2005-04-22 00:00:37 +00002//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Misha Brukman650ba8e2005-04-22 00:00:37 +00006//
Chris Lattner1c4ae852004-08-01 05:59:33 +00007//===----------------------------------------------------------------------===//
8//
Xinliang David Lib439c7a2016-02-23 19:18:21 +00009// This tablegen backend emits an assembly printer for the current target.
Chris Lattner1c4ae852004-08-01 05:59:33 +000010// Note that this is currently fairly skeletal, but will grow over time.
11//
12//===----------------------------------------------------------------------===//
13
Sean Callananb7e8f4a2010-02-09 21:50:41 +000014#include "AsmWriterInst.h"
Eugene Zelenkoa3fe70d2016-11-30 17:48:10 +000015#include "CodeGenInstruction.h"
16#include "CodeGenRegisters.h"
Chris Lattner1c4ae852004-08-01 05:59:33 +000017#include "CodeGenTarget.h"
Jakob Stoklund Olesen892f4802012-03-30 21:12:52 +000018#include "SequenceToOffsetTable.h"
Daniel Sandersca89f3a2016-11-19 12:21:34 +000019#include "Types.h"
Eugene Zelenkoa3fe70d2016-11-30 17:48:10 +000020#include "llvm/ADT/ArrayRef.h"
21#include "llvm/ADT/DenseMap.h"
Benjamin Kramerd59664f2014-04-29 23:26:49 +000022#include "llvm/ADT/SmallString.h"
Eugene Zelenkoa3fe70d2016-11-30 17:48:10 +000023#include "llvm/ADT/SmallVector.h"
24#include "llvm/ADT/STLExtras.h"
Craig Topperb6350132012-07-27 06:44:02 +000025#include "llvm/ADT/StringExtras.h"
Eugene Zelenkoa3fe70d2016-11-30 17:48:10 +000026#include "llvm/ADT/StringRef.h"
Owen Andersona84be6c2011-06-27 21:06:21 +000027#include "llvm/ADT/Twine.h"
Eugene Zelenkoa3fe70d2016-11-30 17:48:10 +000028#include "llvm/Support/Casting.h"
Chris Lattner692374c2006-07-18 17:18:03 +000029#include "llvm/Support/Debug.h"
Eugene Zelenkoa3fe70d2016-11-30 17:48:10 +000030#include "llvm/Support/ErrorHandling.h"
Benjamin Kramer17c17bc2013-09-11 15:42:16 +000031#include "llvm/Support/Format.h"
Reid Kleckner1d9291c2019-11-23 11:28:54 -080032#include "llvm/Support/FormatVariadic.h"
Chris Lattner692374c2006-07-18 17:18:03 +000033#include "llvm/Support/MathExtras.h"
Eugene Zelenkoa3fe70d2016-11-30 17:48:10 +000034#include "llvm/Support/raw_ostream.h"
Peter Collingbourne84c287e2011-10-01 16:41:13 +000035#include "llvm/TableGen/Error.h"
36#include "llvm/TableGen/Record.h"
Jakob Stoklund Olesene6aed132012-06-11 15:37:55 +000037#include "llvm/TableGen/TableGenBackend.h"
Jeff Cohenda636b32005-01-22 18:50:10 +000038#include <algorithm>
Jakob Stoklund Olesene6aed132012-06-11 15:37:55 +000039#include <cassert>
Eugene Zelenkoa3fe70d2016-11-30 17:48:10 +000040#include <cstddef>
41#include <cstdint>
42#include <deque>
43#include <iterator>
Jakob Stoklund Olesene6aed132012-06-11 15:37:55 +000044#include <map>
Eugene Zelenkoa3fe70d2016-11-30 17:48:10 +000045#include <set>
46#include <string>
47#include <tuple>
Benjamin Kramer82de7d32016-05-27 14:27:24 +000048#include <utility>
Jakob Stoklund Olesene6aed132012-06-11 15:37:55 +000049#include <vector>
Eugene Zelenkoa3fe70d2016-11-30 17:48:10 +000050
Chris Lattner1c4ae852004-08-01 05:59:33 +000051using namespace llvm;
52
Chandler Carruthe96dd892014-04-21 22:55:11 +000053#define DEBUG_TYPE "asm-writer-emitter"
54
Jakob Stoklund Olesene6aed132012-06-11 15:37:55 +000055namespace {
Eugene Zelenkoa3fe70d2016-11-30 17:48:10 +000056
Jakob Stoklund Olesene6aed132012-06-11 15:37:55 +000057class AsmWriterEmitter {
58 RecordKeeper &Records;
Ahmed Bougachabd214002013-10-28 18:07:17 +000059 CodeGenTarget Target;
Craig Topperf9265322016-01-17 20:38:14 +000060 ArrayRef<const CodeGenInstruction *> NumberedInstructions;
Ahmed Bougachabd214002013-10-28 18:07:17 +000061 std::vector<AsmWriterInst> Instructions;
Eugene Zelenkoa3fe70d2016-11-30 17:48:10 +000062
Jakob Stoklund Olesene6aed132012-06-11 15:37:55 +000063public:
Ahmed Bougachabd214002013-10-28 18:07:17 +000064 AsmWriterEmitter(RecordKeeper &R);
Jakob Stoklund Olesene6aed132012-06-11 15:37:55 +000065
66 void run(raw_ostream &o);
67
68private:
69 void EmitPrintInstruction(raw_ostream &o);
70 void EmitGetRegisterName(raw_ostream &o);
71 void EmitPrintAliasInstruction(raw_ostream &O);
72
Jakob Stoklund Olesene6aed132012-06-11 15:37:55 +000073 void FindUniqueOperandCommands(std::vector<std::string> &UOC,
Craig Topper5dd7a2c2016-01-24 07:13:28 +000074 std::vector<std::vector<unsigned>> &InstIdxs,
Craig Topperc24a4012016-01-14 06:15:07 +000075 std::vector<unsigned> &InstOpsUsed,
76 bool PassSubtarget) const;
Jakob Stoklund Olesene6aed132012-06-11 15:37:55 +000077};
Eugene Zelenkoa3fe70d2016-11-30 17:48:10 +000078
Jakob Stoklund Olesene6aed132012-06-11 15:37:55 +000079} // end anonymous namespace
80
Chris Lattner59a7f5c2005-01-22 20:31:17 +000081static void PrintCases(std::vector<std::pair<std::string,
Eugene Zelenkoa3fe70d2016-11-30 17:48:10 +000082 AsmWriterOperand>> &OpsToPrint, raw_ostream &O,
Craig Topperc24a4012016-01-14 06:15:07 +000083 bool PassSubtarget) {
Craig Topper0b271ad2016-01-13 07:20:13 +000084 O << " case " << OpsToPrint.back().first << ":";
Chris Lattner59a7f5c2005-01-22 20:31:17 +000085 AsmWriterOperand TheOp = OpsToPrint.back().second;
86 OpsToPrint.pop_back();
87
88 // Check to see if any other operands are identical in this list, and if so,
89 // emit a case label for them.
90 for (unsigned i = OpsToPrint.size(); i != 0; --i)
91 if (OpsToPrint[i-1].second == TheOp) {
Craig Topper0b271ad2016-01-13 07:20:13 +000092 O << "\n case " << OpsToPrint[i-1].first << ":";
Chris Lattner59a7f5c2005-01-22 20:31:17 +000093 OpsToPrint.erase(OpsToPrint.begin()+i-1);
94 }
95
96 // Finally, emit the code.
Craig Topperc24a4012016-01-14 06:15:07 +000097 O << "\n " << TheOp.getCode(PassSubtarget);
Craig Topper0b271ad2016-01-13 07:20:13 +000098 O << "\n break;\n";
Chris Lattner59a7f5c2005-01-22 20:31:17 +000099}
100
Chris Lattner9ceb7c82005-01-22 18:38:13 +0000101/// EmitInstructions - Emit the last instruction in the vector and any other
102/// instructions that are suitably similar to it.
103static void EmitInstructions(std::vector<AsmWriterInst> &Insts,
Craig Topperc24a4012016-01-14 06:15:07 +0000104 raw_ostream &O, bool PassSubtarget) {
Chris Lattner9ceb7c82005-01-22 18:38:13 +0000105 AsmWriterInst FirstInst = Insts.back();
106 Insts.pop_back();
107
108 std::vector<AsmWriterInst> SimilarInsts;
109 unsigned DifferingOperand = ~0;
110 for (unsigned i = Insts.size(); i != 0; --i) {
Chris Lattner92275bb2005-01-22 19:22:23 +0000111 unsigned DiffOp = Insts[i-1].MatchesAllButOneOp(FirstInst);
112 if (DiffOp != ~1U) {
Chris Lattner9ceb7c82005-01-22 18:38:13 +0000113 if (DifferingOperand == ~0U) // First match!
114 DifferingOperand = DiffOp;
115
116 // If this differs in the same operand as the rest of the instructions in
117 // this class, move it to the SimilarInsts list.
Chris Lattner92275bb2005-01-22 19:22:23 +0000118 if (DifferingOperand == DiffOp || DiffOp == ~0U) {
Chris Lattner9ceb7c82005-01-22 18:38:13 +0000119 SimilarInsts.push_back(Insts[i-1]);
120 Insts.erase(Insts.begin()+i-1);
121 }
122 }
123 }
124
Chris Lattner017b93d2006-05-01 17:01:17 +0000125 O << " case " << FirstInst.CGI->Namespace << "::"
Chris Lattner9ceb7c82005-01-22 18:38:13 +0000126 << FirstInst.CGI->TheDef->getName() << ":\n";
Craig Topper190ecd52016-01-08 07:06:32 +0000127 for (const AsmWriterInst &AWI : SimilarInsts)
128 O << " case " << AWI.CGI->Namespace << "::"
129 << AWI.CGI->TheDef->getName() << ":\n";
Chris Lattner9ceb7c82005-01-22 18:38:13 +0000130 for (unsigned i = 0, e = FirstInst.Operands.size(); i != e; ++i) {
131 if (i != DifferingOperand) {
132 // If the operand is the same for all instructions, just print it.
Craig Topperc24a4012016-01-14 06:15:07 +0000133 O << " " << FirstInst.Operands[i].getCode(PassSubtarget);
Chris Lattner9ceb7c82005-01-22 18:38:13 +0000134 } else {
135 // If this is the operand that varies between all of the instructions,
136 // emit a switch for just this operand now.
137 O << " switch (MI->getOpcode()) {\n";
Craig Topper0b271ad2016-01-13 07:20:13 +0000138 O << " default: llvm_unreachable(\"Unexpected opcode.\");\n";
Eugene Zelenkoa3fe70d2016-11-30 17:48:10 +0000139 std::vector<std::pair<std::string, AsmWriterOperand>> OpsToPrint;
Craig Topper86a9aee2017-07-07 06:22:35 +0000140 OpsToPrint.push_back(std::make_pair(FirstInst.CGI->Namespace.str() + "::" +
Matthias Braun4a86d452016-12-04 05:48:16 +0000141 FirstInst.CGI->TheDef->getName().str(),
Chris Lattner59a7f5c2005-01-22 20:31:17 +0000142 FirstInst.Operands[i]));
Misha Brukman650ba8e2005-04-22 00:00:37 +0000143
Craig Topper190ecd52016-01-08 07:06:32 +0000144 for (const AsmWriterInst &AWI : SimilarInsts) {
Craig Topper86a9aee2017-07-07 06:22:35 +0000145 OpsToPrint.push_back(std::make_pair(AWI.CGI->Namespace.str()+"::" +
Matthias Braun4a86d452016-12-04 05:48:16 +0000146 AWI.CGI->TheDef->getName().str(),
Chris Lattner59a7f5c2005-01-22 20:31:17 +0000147 AWI.Operands[i]));
Chris Lattner9ceb7c82005-01-22 18:38:13 +0000148 }
Chris Lattner59a7f5c2005-01-22 20:31:17 +0000149 std::reverse(OpsToPrint.begin(), OpsToPrint.end());
150 while (!OpsToPrint.empty())
Craig Topperc24a4012016-01-14 06:15:07 +0000151 PrintCases(OpsToPrint, O, PassSubtarget);
Chris Lattner9ceb7c82005-01-22 18:38:13 +0000152 O << " }";
153 }
154 O << "\n";
155 }
Chris Lattner9ceb7c82005-01-22 18:38:13 +0000156 O << " break;\n";
157}
Chris Lattner0c23ba52005-01-22 17:32:42 +0000158
Chris Lattner692374c2006-07-18 17:18:03 +0000159void AsmWriterEmitter::
Jim Grosbacha5497342010-09-29 22:32:50 +0000160FindUniqueOperandCommands(std::vector<std::string> &UniqueOperandCommands,
Craig Topper5dd7a2c2016-01-24 07:13:28 +0000161 std::vector<std::vector<unsigned>> &InstIdxs,
Craig Topperc24a4012016-01-14 06:15:07 +0000162 std::vector<unsigned> &InstOpsUsed,
163 bool PassSubtarget) const {
Chris Lattner692374c2006-07-18 17:18:03 +0000164 // This vector parallels UniqueOperandCommands, keeping track of which
165 // instructions each case are used for. It is a comma separated string of
166 // enums.
167 std::vector<std::string> InstrsForCase;
168 InstrsForCase.resize(UniqueOperandCommands.size());
Chris Lattneredee5252006-07-18 18:28:27 +0000169 InstOpsUsed.assign(UniqueOperandCommands.size(), 0);
Jim Grosbacha5497342010-09-29 22:32:50 +0000170
Craig Topper9e9ae602016-01-17 08:05:33 +0000171 for (size_t i = 0, e = Instructions.size(); i != e; ++i) {
172 const AsmWriterInst &Inst = Instructions[i];
173 if (Inst.Operands.empty())
Chris Lattner692374c2006-07-18 17:18:03 +0000174 continue; // Instruction already done.
Chris Lattner9d250692006-07-18 17:50:22 +0000175
Craig Topper9e9ae602016-01-17 08:05:33 +0000176 std::string Command = " "+Inst.Operands[0].getCode(PassSubtarget)+"\n";
Chris Lattner9d250692006-07-18 17:50:22 +0000177
Chris Lattner692374c2006-07-18 17:18:03 +0000178 // Check to see if we already have 'Command' in UniqueOperandCommands.
179 // If not, add it.
Eugene Zelenkoa3fe70d2016-11-30 17:48:10 +0000180 auto I = llvm::find(UniqueOperandCommands, Command);
Craig Toppera99859d2016-01-17 08:05:30 +0000181 if (I != UniqueOperandCommands.end()) {
182 size_t idx = I - UniqueOperandCommands.begin();
Craig Toppera99859d2016-01-17 08:05:30 +0000183 InstrsForCase[idx] += ", ";
Craig Topper9e9ae602016-01-17 08:05:33 +0000184 InstrsForCase[idx] += Inst.CGI->TheDef->getName();
Craig Topper5dd7a2c2016-01-24 07:13:28 +0000185 InstIdxs[idx].push_back(i);
Craig Toppera99859d2016-01-17 08:05:30 +0000186 } else {
Craig Topper1993e3b2016-01-08 07:06:29 +0000187 UniqueOperandCommands.push_back(std::move(Command));
Benjamin Krameradcd0262020-01-28 20:23:46 +0100188 InstrsForCase.push_back(std::string(Inst.CGI->TheDef->getName()));
Craig Topper5dd7a2c2016-01-24 07:13:28 +0000189 InstIdxs.emplace_back();
190 InstIdxs.back().push_back(i);
Chris Lattneredee5252006-07-18 18:28:27 +0000191
192 // This command matches one operand so far.
193 InstOpsUsed.push_back(1);
194 }
195 }
Jim Grosbacha5497342010-09-29 22:32:50 +0000196
Chris Lattneredee5252006-07-18 18:28:27 +0000197 // For each entry of UniqueOperandCommands, there is a set of instructions
198 // that uses it. If the next command of all instructions in the set are
199 // identical, fold it into the command.
Craig Topper5dd7a2c2016-01-24 07:13:28 +0000200 for (size_t CommandIdx = 0, e = UniqueOperandCommands.size();
Chris Lattneredee5252006-07-18 18:28:27 +0000201 CommandIdx != e; ++CommandIdx) {
Jim Grosbacha5497342010-09-29 22:32:50 +0000202
Craig Topper5dd7a2c2016-01-24 07:13:28 +0000203 const auto &Idxs = InstIdxs[CommandIdx];
Chris Lattneredee5252006-07-18 18:28:27 +0000204
Craig Topper5dd7a2c2016-01-24 07:13:28 +0000205 for (unsigned Op = 1; ; ++Op) {
206 // Find the first instruction in the set.
207 const AsmWriterInst &FirstInst = Instructions[Idxs.front()];
Chris Lattneredee5252006-07-18 18:28:27 +0000208 // If this instruction has no more operands, we isn't anything to merge
209 // into this command.
Craig Topper9e9ae602016-01-17 08:05:33 +0000210 if (FirstInst.Operands.size() == Op)
Chris Lattneredee5252006-07-18 18:28:27 +0000211 break;
212
213 // Otherwise, scan to see if all of the other instructions in this command
214 // set share the operand.
Craig Topper5dd7a2c2016-01-24 07:13:28 +0000215 if (std::any_of(Idxs.begin()+1, Idxs.end(),
216 [&](unsigned Idx) {
217 const AsmWriterInst &OtherInst = Instructions[Idx];
218 return OtherInst.Operands.size() == Op ||
219 OtherInst.Operands[Op] != FirstInst.Operands[Op];
220 }))
221 break;
Jim Grosbacha5497342010-09-29 22:32:50 +0000222
Chris Lattneredee5252006-07-18 18:28:27 +0000223 // Okay, everything in this command set has the same next operand. Add it
224 // to UniqueOperandCommands and remember that it was consumed.
Craig Topperc24a4012016-01-14 06:15:07 +0000225 std::string Command = " " +
Craig Topper9e9ae602016-01-17 08:05:33 +0000226 FirstInst.Operands[Op].getCode(PassSubtarget) + "\n";
Jim Grosbacha5497342010-09-29 22:32:50 +0000227
Chris Lattneredee5252006-07-18 18:28:27 +0000228 UniqueOperandCommands[CommandIdx] += Command;
229 InstOpsUsed[CommandIdx]++;
Chris Lattner692374c2006-07-18 17:18:03 +0000230 }
231 }
Jim Grosbacha5497342010-09-29 22:32:50 +0000232
Chris Lattner692374c2006-07-18 17:18:03 +0000233 // Prepend some of the instructions each case is used for onto the case val.
234 for (unsigned i = 0, e = InstrsForCase.size(); i != e; ++i) {
235 std::string Instrs = InstrsForCase[i];
236 if (Instrs.size() > 70) {
237 Instrs.erase(Instrs.begin()+70, Instrs.end());
238 Instrs += "...";
239 }
Jim Grosbacha5497342010-09-29 22:32:50 +0000240
Chris Lattner692374c2006-07-18 17:18:03 +0000241 if (!Instrs.empty())
Jim Grosbacha5497342010-09-29 22:32:50 +0000242 UniqueOperandCommands[i] = " // " + Instrs + "\n" +
Chris Lattner692374c2006-07-18 17:18:03 +0000243 UniqueOperandCommands[i];
244 }
245}
246
Daniel Dunbar04f049f2009-10-17 20:43:42 +0000247static void UnescapeString(std::string &Str) {
248 for (unsigned i = 0; i != Str.size(); ++i) {
249 if (Str[i] == '\\' && i != Str.size()-1) {
250 switch (Str[i+1]) {
251 default: continue; // Don't execute the code after the switch.
252 case 'a': Str[i] = '\a'; break;
253 case 'b': Str[i] = '\b'; break;
254 case 'e': Str[i] = 27; break;
255 case 'f': Str[i] = '\f'; break;
256 case 'n': Str[i] = '\n'; break;
257 case 'r': Str[i] = '\r'; break;
258 case 't': Str[i] = '\t'; break;
259 case 'v': Str[i] = '\v'; break;
260 case '"': Str[i] = '\"'; break;
261 case '\'': Str[i] = '\''; break;
262 case '\\': Str[i] = '\\'; break;
263 }
264 // Nuke the second character.
265 Str.erase(Str.begin()+i+1);
266 }
267 }
268}
269
Chris Lattner06c5eed2009-09-13 20:08:00 +0000270/// EmitPrintInstruction - Generate the code for the "printInstruction" method
Ahmed Bougachabd214002013-10-28 18:07:17 +0000271/// implementation. Destroys all instances of AsmWriterInst information, by
272/// clearing the Instructions vector.
Chris Lattner06c5eed2009-09-13 20:08:00 +0000273void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {
Chris Lattner6ffa5012004-08-14 22:50:53 +0000274 Record *AsmWriter = Target.getAsmWriter();
Craig Topperbcd3c372017-05-31 21:12:46 +0000275 StringRef ClassName = AsmWriter->getValueAsString("AsmWriterClassName");
Craig Topperc24a4012016-01-14 06:15:07 +0000276 bool PassSubtarget = AsmWriter->getValueAsInt("PassSubtarget");
Jim Grosbacha5497342010-09-29 22:32:50 +0000277
Fangrui Song3d87d0b2020-01-03 12:02:46 -0800278 O << "/// printInstruction - This method is automatically generated by "
279 "tablegen\n"
280 "/// from the instruction set description.\n"
281 "void "
282 << Target.getName() << ClassName
283 << "::printInstruction(const MCInst *MI, uint64_t Address, "
284 << (PassSubtarget ? "const MCSubtargetInfo &STI, " : "")
285 << "raw_ostream &O) {\n";
Chris Lattner1c4ae852004-08-01 05:59:33 +0000286
Chris Lattnere32982c2006-07-14 22:59:11 +0000287 // Build an aggregate string, and build a table of offsets into it.
Benjamin Kramer22d093e2012-04-02 09:13:46 +0000288 SequenceToOffsetTable<std::string> StringTable;
Jim Grosbacha5497342010-09-29 22:32:50 +0000289
Chris Lattner5d751b42006-09-27 16:44:09 +0000290 /// OpcodeInfo - This encodes the index of the string to use for the first
Chris Lattner1ac0eb72006-07-18 17:32:27 +0000291 /// chunk of the output as well as indices used for operand printing.
Craig Topperf9265322016-01-17 20:38:14 +0000292 std::vector<uint64_t> OpcodeInfo(NumberedInstructions.size());
Craig Topperd4f87a32016-01-13 07:20:12 +0000293 const unsigned OpcodeInfoBits = 64;
Jim Grosbacha5497342010-09-29 22:32:50 +0000294
Benjamin Kramer22d093e2012-04-02 09:13:46 +0000295 // Add all strings to the string table upfront so it can generate an optimized
296 // representation.
Craig Topper9e9ae602016-01-17 08:05:33 +0000297 for (AsmWriterInst &AWI : Instructions) {
298 if (AWI.Operands[0].OperandType ==
Jim Grosbachf4e67082012-04-18 18:56:33 +0000299 AsmWriterOperand::isLiteralTextOperand &&
Craig Topper9e9ae602016-01-17 08:05:33 +0000300 !AWI.Operands[0].Str.empty()) {
301 std::string Str = AWI.Operands[0].Str;
Benjamin Kramer22d093e2012-04-02 09:13:46 +0000302 UnescapeString(Str);
303 StringTable.add(Str);
304 }
305 }
306
307 StringTable.layout();
308
Chris Lattner1ac0eb72006-07-18 17:32:27 +0000309 unsigned MaxStringIdx = 0;
Craig Topper9e9ae602016-01-17 08:05:33 +0000310 for (AsmWriterInst &AWI : Instructions) {
Chris Lattnere32982c2006-07-14 22:59:11 +0000311 unsigned Idx;
Craig Topper9e9ae602016-01-17 08:05:33 +0000312 if (AWI.Operands[0].OperandType != AsmWriterOperand::isLiteralTextOperand ||
313 AWI.Operands[0].Str.empty()) {
Chris Lattner36504652006-07-19 01:39:06 +0000314 // Something handled by the asmwriter printer, but with no leading string.
Benjamin Kramer22d093e2012-04-02 09:13:46 +0000315 Idx = StringTable.get("");
Chris Lattnere32982c2006-07-14 22:59:11 +0000316 } else {
Craig Topper9e9ae602016-01-17 08:05:33 +0000317 std::string Str = AWI.Operands[0].Str;
Chris Lattnerb47ed612009-09-14 01:16:36 +0000318 UnescapeString(Str);
Benjamin Kramer22d093e2012-04-02 09:13:46 +0000319 Idx = StringTable.get(Str);
Chris Lattnerb47ed612009-09-14 01:16:36 +0000320 MaxStringIdx = std::max(MaxStringIdx, Idx);
Jim Grosbacha5497342010-09-29 22:32:50 +0000321
Chris Lattnere32982c2006-07-14 22:59:11 +0000322 // Nuke the string from the operand list. It is now handled!
Craig Topper9e9ae602016-01-17 08:05:33 +0000323 AWI.Operands.erase(AWI.Operands.begin());
Chris Lattner92275bb2005-01-22 19:22:23 +0000324 }
Jim Grosbacha5497342010-09-29 22:32:50 +0000325
Chris Lattnerb47ed612009-09-14 01:16:36 +0000326 // Bias offset by one since we want 0 as a sentinel.
Craig Topper9e9ae602016-01-17 08:05:33 +0000327 OpcodeInfo[AWI.CGIIndex] = Idx+1;
Chris Lattner92275bb2005-01-22 19:22:23 +0000328 }
Jim Grosbacha5497342010-09-29 22:32:50 +0000329
Chris Lattner1ac0eb72006-07-18 17:32:27 +0000330 // Figure out how many bits we used for the string index.
Chris Lattnerb47ed612009-09-14 01:16:36 +0000331 unsigned AsmStrBits = Log2_32_Ceil(MaxStringIdx+2);
Jim Grosbacha5497342010-09-29 22:32:50 +0000332
Chris Lattner692374c2006-07-18 17:18:03 +0000333 // To reduce code size, we compactify common instructions into a few bits
334 // in the opcode-indexed table.
Craig Topperd4f87a32016-01-13 07:20:12 +0000335 unsigned BitsLeft = OpcodeInfoBits-AsmStrBits;
Chris Lattner692374c2006-07-18 17:18:03 +0000336
Craig Topper1f387362014-11-25 20:11:25 +0000337 std::vector<std::vector<std::string>> TableDrivenOperandPrinters;
Jim Grosbacha5497342010-09-29 22:32:50 +0000338
Eugene Zelenkoa3fe70d2016-11-30 17:48:10 +0000339 while (true) {
Chris Lattner692374c2006-07-18 17:18:03 +0000340 std::vector<std::string> UniqueOperandCommands;
Craig Topper5dd7a2c2016-01-24 07:13:28 +0000341 std::vector<std::vector<unsigned>> InstIdxs;
Chris Lattneredee5252006-07-18 18:28:27 +0000342 std::vector<unsigned> NumInstOpsHandled;
343 FindUniqueOperandCommands(UniqueOperandCommands, InstIdxs,
Craig Topperc24a4012016-01-14 06:15:07 +0000344 NumInstOpsHandled, PassSubtarget);
Jim Grosbacha5497342010-09-29 22:32:50 +0000345
Chris Lattner692374c2006-07-18 17:18:03 +0000346 // If we ran out of operands to print, we're done.
347 if (UniqueOperandCommands.empty()) break;
Jim Grosbacha5497342010-09-29 22:32:50 +0000348
Chris Lattner692374c2006-07-18 17:18:03 +0000349 // Compute the number of bits we need to represent these cases, this is
350 // ceil(log2(numentries)).
351 unsigned NumBits = Log2_32_Ceil(UniqueOperandCommands.size());
Jim Grosbacha5497342010-09-29 22:32:50 +0000352
Chris Lattner692374c2006-07-18 17:18:03 +0000353 // If we don't have enough bits for this operand, don't include it.
354 if (NumBits > BitsLeft) {
Nicola Zaghend34e60c2018-05-14 12:53:11 +0000355 LLVM_DEBUG(errs() << "Not enough bits to densely encode " << NumBits
356 << " more bits\n");
Chris Lattner692374c2006-07-18 17:18:03 +0000357 break;
358 }
Jim Grosbacha5497342010-09-29 22:32:50 +0000359
Chris Lattner692374c2006-07-18 17:18:03 +0000360 // Otherwise, we can include this in the initial lookup table. Add it in.
Craig Topper5dd7a2c2016-01-24 07:13:28 +0000361 for (size_t i = 0, e = InstIdxs.size(); i != e; ++i) {
362 unsigned NumOps = NumInstOpsHandled[i];
363 for (unsigned Idx : InstIdxs[i]) {
364 OpcodeInfo[Instructions[Idx].CGIIndex] |=
365 (uint64_t)i << (OpcodeInfoBits-BitsLeft);
366 // Remove the info about this operand from the instruction.
367 AsmWriterInst &Inst = Instructions[Idx];
368 if (!Inst.Operands.empty()) {
369 assert(NumOps <= Inst.Operands.size() &&
370 "Can't remove this many ops!");
371 Inst.Operands.erase(Inst.Operands.begin(),
372 Inst.Operands.begin()+NumOps);
373 }
Craig Topper9e9ae602016-01-17 08:05:33 +0000374 }
Chris Lattnercb0c8482006-07-18 17:56:07 +0000375 }
Craig Topper5dd7a2c2016-01-24 07:13:28 +0000376 BitsLeft -= NumBits;
Jim Grosbacha5497342010-09-29 22:32:50 +0000377
Chris Lattnercb0c8482006-07-18 17:56:07 +0000378 // Remember the handlers for this set of operands.
Craig Topper1f387362014-11-25 20:11:25 +0000379 TableDrivenOperandPrinters.push_back(std::move(UniqueOperandCommands));
Chris Lattner692374c2006-07-18 17:18:03 +0000380 }
Jim Grosbacha5497342010-09-29 22:32:50 +0000381
Craig Topper14d91732016-01-11 05:13:41 +0000382 // Emit the string table itself.
Luke Drummond482e8902020-01-15 14:14:01 +0000383 StringTable.emitStringLiteralDef(O, " static const char AsmStrs[]");
Chris Lattnere32982c2006-07-14 22:59:11 +0000384
Craig Topper14d91732016-01-11 05:13:41 +0000385 // Emit the lookup tables in pieces to minimize wasted bytes.
Craig Topperd4f87a32016-01-13 07:20:12 +0000386 unsigned BytesNeeded = ((OpcodeInfoBits - BitsLeft) + 7) / 8;
Craig Topper14d91732016-01-11 05:13:41 +0000387 unsigned Table = 0, Shift = 0;
388 SmallString<128> BitsString;
389 raw_svector_ostream BitsOS(BitsString);
390 // If the total bits is more than 32-bits we need to use a 64-bit type.
Craig Topperd4f87a32016-01-13 07:20:12 +0000391 BitsOS << " uint" << ((BitsLeft < (OpcodeInfoBits - 32)) ? 64 : 32)
392 << "_t Bits = 0;\n";
Craig Topper14d91732016-01-11 05:13:41 +0000393 while (BytesNeeded != 0) {
394 // Figure out how big this table section needs to be, but no bigger than 4.
395 unsigned TableSize = std::min(1 << Log2_32(BytesNeeded), 4);
396 BytesNeeded -= TableSize;
397 TableSize *= 8; // Convert to bits;
398 uint64_t Mask = (1ULL << TableSize) - 1;
399 O << " static const uint" << TableSize << "_t OpInfo" << Table
400 << "[] = {\n";
Craig Topperf9265322016-01-17 20:38:14 +0000401 for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) {
Craig Topper14d91732016-01-11 05:13:41 +0000402 O << " " << ((OpcodeInfo[i] >> Shift) & Mask) << "U,\t// "
Craig Topperf9265322016-01-17 20:38:14 +0000403 << NumberedInstructions[i]->TheDef->getName() << "\n";
Craig Topper14d91732016-01-11 05:13:41 +0000404 }
405 O << " };\n\n";
406 // Emit string to combine the individual table lookups.
407 BitsOS << " Bits |= ";
408 // If the total bits is more than 32-bits we need to use a 64-bit type.
Craig Topperd4f87a32016-01-13 07:20:12 +0000409 if (BitsLeft < (OpcodeInfoBits - 32))
Craig Topper14d91732016-01-11 05:13:41 +0000410 BitsOS << "(uint64_t)";
411 BitsOS << "OpInfo" << Table << "[MI->getOpcode()] << " << Shift << ";\n";
412 // Prepare the shift for the next iteration and increment the table count.
413 Shift += TableSize;
414 ++Table;
415 }
416
417 // Emit the initial tab character.
Evan Cheng32e53472008-02-02 08:39:46 +0000418 O << " O << \"\\t\";\n\n";
419
Craig Topper06cec4c2012-09-14 08:33:11 +0000420 O << " // Emit the opcode for the instruction.\n";
Craig Topper14d91732016-01-11 05:13:41 +0000421 O << BitsString;
422
423 // Emit the starting string.
Manman Ren68cf9fc2012-09-13 17:43:46 +0000424 O << " assert(Bits != 0 && \"Cannot print this instruction.\");\n"
Chris Lattnerb47ed612009-09-14 01:16:36 +0000425 << " O << AsmStrs+(Bits & " << (1 << AsmStrBits)-1 << ")-1;\n\n";
David Greenefdd25192009-08-05 21:00:52 +0000426
Chris Lattner692374c2006-07-18 17:18:03 +0000427 // Output the table driven operand information.
Craig Topperd4f87a32016-01-13 07:20:12 +0000428 BitsLeft = OpcodeInfoBits-AsmStrBits;
Chris Lattner692374c2006-07-18 17:18:03 +0000429 for (unsigned i = 0, e = TableDrivenOperandPrinters.size(); i != e; ++i) {
430 std::vector<std::string> &Commands = TableDrivenOperandPrinters[i];
431
432 // Compute the number of bits we need to represent these cases, this is
433 // ceil(log2(numentries)).
434 unsigned NumBits = Log2_32_Ceil(Commands.size());
435 assert(NumBits <= BitsLeft && "consistency error");
Jim Grosbacha5497342010-09-29 22:32:50 +0000436
Chris Lattner692374c2006-07-18 17:18:03 +0000437 // Emit code to extract this field from Bits.
Chris Lattner692374c2006-07-18 17:18:03 +0000438 O << "\n // Fragment " << i << " encoded into " << NumBits
Chris Lattner75dcf6c2006-07-18 17:43:54 +0000439 << " bits for " << Commands.size() << " unique commands.\n";
Jim Grosbacha5497342010-09-29 22:32:50 +0000440
Chris Lattneredee5252006-07-18 18:28:27 +0000441 if (Commands.size() == 2) {
Chris Lattner75dcf6c2006-07-18 17:43:54 +0000442 // Emit two possibilitys with if/else.
Craig Topper06cec4c2012-09-14 08:33:11 +0000443 O << " if ((Bits >> "
Craig Topperd4f87a32016-01-13 07:20:12 +0000444 << (OpcodeInfoBits-BitsLeft) << ") & "
Chris Lattner75dcf6c2006-07-18 17:43:54 +0000445 << ((1 << NumBits)-1) << ") {\n"
446 << Commands[1]
447 << " } else {\n"
448 << Commands[0]
449 << " }\n\n";
Eric Christophera573d192010-09-18 18:50:27 +0000450 } else if (Commands.size() == 1) {
451 // Emit a single possibility.
452 O << Commands[0] << "\n\n";
Chris Lattner75dcf6c2006-07-18 17:43:54 +0000453 } else {
Craig Topper06cec4c2012-09-14 08:33:11 +0000454 O << " switch ((Bits >> "
Craig Topperd4f87a32016-01-13 07:20:12 +0000455 << (OpcodeInfoBits-BitsLeft) << ") & "
Chris Lattner75dcf6c2006-07-18 17:43:54 +0000456 << ((1 << NumBits)-1) << ") {\n"
Craig Toppera4ff6ae2014-11-24 14:09:52 +0000457 << " default: llvm_unreachable(\"Invalid command number.\");\n";
Jim Grosbacha5497342010-09-29 22:32:50 +0000458
Chris Lattner75dcf6c2006-07-18 17:43:54 +0000459 // Print out all the cases.
Craig Topper190ecd52016-01-08 07:06:32 +0000460 for (unsigned j = 0, e = Commands.size(); j != e; ++j) {
461 O << " case " << j << ":\n";
462 O << Commands[j];
Chris Lattner75dcf6c2006-07-18 17:43:54 +0000463 O << " break;\n";
464 }
465 O << " }\n\n";
Chris Lattner692374c2006-07-18 17:18:03 +0000466 }
Craig Topper06cec4c2012-09-14 08:33:11 +0000467 BitsLeft -= NumBits;
Chris Lattner692374c2006-07-18 17:18:03 +0000468 }
Jim Grosbacha5497342010-09-29 22:32:50 +0000469
Chris Lattnercb0c8482006-07-18 17:56:07 +0000470 // Okay, delete instructions with no operand info left.
Eugene Zelenkoa3fe70d2016-11-30 17:48:10 +0000471 auto I = llvm::remove_if(Instructions,
David Majnemerc7004902016-08-12 04:32:37 +0000472 [](AsmWriterInst &Inst) { return Inst.Operands.empty(); });
Craig Topper4f1f1152016-01-13 07:20:10 +0000473 Instructions.erase(I, Instructions.end());
Chris Lattner692374c2006-07-18 17:18:03 +0000474
Jim Grosbacha5497342010-09-29 22:32:50 +0000475
Chris Lattner692374c2006-07-18 17:18:03 +0000476 // Because this is a vector, we want to emit from the end. Reverse all of the
Chris Lattner9ceb7c82005-01-22 18:38:13 +0000477 // elements in the vector.
478 std::reverse(Instructions.begin(), Instructions.end());
Jim Grosbacha5497342010-09-29 22:32:50 +0000479
480
Craig Topperdf390602016-01-13 07:20:07 +0000481 // Now that we've emitted all of the operand info that fit into 64 bits, emit
Chris Lattnerbf1a7692009-09-18 18:10:19 +0000482 // information for those instructions that are left. This is a less dense
Craig Topperdf390602016-01-13 07:20:07 +0000483 // encoding, but we expect the main 64-bit table to handle the majority of
Chris Lattnerbf1a7692009-09-18 18:10:19 +0000484 // instructions.
Chris Lattner66e288b2006-07-18 17:38:46 +0000485 if (!Instructions.empty()) {
486 // Find the opcode # of inline asm.
487 O << " switch (MI->getOpcode()) {\n";
Craig Topper0b271ad2016-01-13 07:20:13 +0000488 O << " default: llvm_unreachable(\"Unexpected opcode.\");\n";
Chris Lattner66e288b2006-07-18 17:38:46 +0000489 while (!Instructions.empty())
Craig Topperc24a4012016-01-14 06:15:07 +0000490 EmitInstructions(Instructions, O, PassSubtarget);
Chris Lattner9ceb7c82005-01-22 18:38:13 +0000491
Chris Lattner66e288b2006-07-18 17:38:46 +0000492 O << " }\n";
493 }
David Greene5b4bc262009-07-29 20:10:24 +0000494
Chris Lattner6e172082006-07-18 19:06:01 +0000495 O << "}\n";
Chris Lattner1c4ae852004-08-01 05:59:33 +0000496}
Chris Lattner06c5eed2009-09-13 20:08:00 +0000497
Owen Andersona84be6c2011-06-27 21:06:21 +0000498static void
499emitRegisterNameString(raw_ostream &O, StringRef AltName,
David Blaikie9b613db2014-11-29 18:13:39 +0000500 const std::deque<CodeGenRegister> &Registers) {
Jakob Stoklund Olesen892f4802012-03-30 21:12:52 +0000501 SequenceToOffsetTable<std::string> StringTable;
502 SmallVector<std::string, 4> AsmNames(Registers.size());
David Blaikie9b613db2014-11-29 18:13:39 +0000503 unsigned i = 0;
504 for (const auto &Reg : Registers) {
505 std::string &AsmName = AsmNames[i++];
Owen Andersona84be6c2011-06-27 21:06:21 +0000506
Owen Andersona84be6c2011-06-27 21:06:21 +0000507 // "NoRegAltName" is special. We don't need to do a lookup for that,
508 // as it's just a reference to the default register name.
509 if (AltName == "" || AltName == "NoRegAltName") {
Benjamin Krameradcd0262020-01-28 20:23:46 +0100510 AsmName = std::string(Reg.TheDef->getValueAsString("AsmName"));
Owen Andersona84be6c2011-06-27 21:06:21 +0000511 if (AsmName.empty())
Benjamin Krameradcd0262020-01-28 20:23:46 +0100512 AsmName = std::string(Reg.getName());
Owen Andersona84be6c2011-06-27 21:06:21 +0000513 } else {
514 // Make sure the register has an alternate name for this index.
515 std::vector<Record*> AltNameList =
516 Reg.TheDef->getValueAsListOfDefs("RegAltNameIndices");
517 unsigned Idx = 0, e;
518 for (e = AltNameList.size();
519 Idx < e && (AltNameList[Idx]->getName() != AltName);
520 ++Idx)
521 ;
522 // If the register has an alternate name for this index, use it.
523 // Otherwise, leave it empty as an error flag.
524 if (Idx < e) {
Craig Topper2b8419a2017-05-31 19:01:11 +0000525 std::vector<StringRef> AltNames =
Owen Andersona84be6c2011-06-27 21:06:21 +0000526 Reg.TheDef->getValueAsListOfStrings("AltNames");
527 if (AltNames.size() <= Idx)
Joerg Sonnenberger635debe2012-10-25 20:33:17 +0000528 PrintFatalError(Reg.TheDef->getLoc(),
Benjamin Kramer48e7e852014-03-29 17:17:15 +0000529 "Register definition missing alt name for '" +
530 AltName + "'.");
Benjamin Krameradcd0262020-01-28 20:23:46 +0100531 AsmName = std::string(AltNames[Idx]);
Owen Andersona84be6c2011-06-27 21:06:21 +0000532 }
533 }
Jakob Stoklund Olesen892f4802012-03-30 21:12:52 +0000534 StringTable.add(AsmName);
535 }
Owen Andersona84be6c2011-06-27 21:06:21 +0000536
Craig Topperf8f0a232012-09-15 01:22:42 +0000537 StringTable.layout();
Luke Drummond482e8902020-01-15 14:14:01 +0000538 StringTable.emitStringLiteralDef(O, Twine(" static const char AsmStrs") +
539 AltName + "[]");
Jakob Stoklund Olesen892f4802012-03-30 21:12:52 +0000540
Daniel Sandersca89f3a2016-11-19 12:21:34 +0000541 O << " static const " << getMinimalTypeForRange(StringTable.size() - 1, 32)
Craig Topperba6d83e2014-11-24 02:08:35 +0000542 << " RegAsmOffset" << AltName << "[] = {";
Jakob Stoklund Olesen892f4802012-03-30 21:12:52 +0000543 for (unsigned i = 0, e = Registers.size(); i != e; ++i) {
Craig Topper7a2cea12012-04-02 00:47:39 +0000544 if ((i % 14) == 0)
545 O << "\n ";
546 O << StringTable.get(AsmNames[i]) << ", ";
Owen Andersona84be6c2011-06-27 21:06:21 +0000547 }
Craig Topper9c252eb2012-04-03 06:52:47 +0000548 O << "\n };\n"
Owen Andersona84be6c2011-06-27 21:06:21 +0000549 << "\n";
Owen Andersona84be6c2011-06-27 21:06:21 +0000550}
Chris Lattner06c5eed2009-09-13 20:08:00 +0000551
552void AsmWriterEmitter::EmitGetRegisterName(raw_ostream &O) {
Chris Lattner06c5eed2009-09-13 20:08:00 +0000553 Record *AsmWriter = Target.getAsmWriter();
Craig Topperbcd3c372017-05-31 21:12:46 +0000554 StringRef ClassName = AsmWriter->getValueAsString("AsmWriterClassName");
David Blaikie9b613db2014-11-29 18:13:39 +0000555 const auto &Registers = Target.getRegBank().getRegisters();
Craig Topper83421ec2016-01-17 20:38:21 +0000556 const std::vector<Record*> &AltNameIndices = Target.getRegAltNameIndices();
Owen Andersona84be6c2011-06-27 21:06:21 +0000557 bool hasAltNames = AltNameIndices.size() > 1;
Craig Topperbcd3c372017-05-31 21:12:46 +0000558 StringRef Namespace = Registers.front().TheDef->getValueAsString("Namespace");
Jim Grosbacha5497342010-09-29 22:32:50 +0000559
Chris Lattner06c5eed2009-09-13 20:08:00 +0000560 O <<
561 "\n\n/// getRegisterName - This method is automatically generated by tblgen\n"
562 "/// from the register set description. This returns the assembler name\n"
563 "/// for the specified register.\n"
Owen Andersona84be6c2011-06-27 21:06:21 +0000564 "const char *" << Target.getName() << ClassName << "::";
565 if (hasAltNames)
566 O << "\ngetRegisterName(unsigned RegNo, unsigned AltIdx) {\n";
567 else
568 O << "getRegisterName(unsigned RegNo) {\n";
569 O << " assert(RegNo && RegNo < " << (Registers.size()+1)
570 << " && \"Invalid register number!\");\n"
Chris Lattnera7e8ae42009-09-14 01:26:18 +0000571 << "\n";
Jim Grosbacha5497342010-09-29 22:32:50 +0000572
Owen Andersona84be6c2011-06-27 21:06:21 +0000573 if (hasAltNames) {
Craig Topper190ecd52016-01-08 07:06:32 +0000574 for (const Record *R : AltNameIndices)
575 emitRegisterNameString(O, R->getName(), Registers);
Owen Andersona84be6c2011-06-27 21:06:21 +0000576 } else
577 emitRegisterNameString(O, "", Registers);
Jim Grosbacha5497342010-09-29 22:32:50 +0000578
Owen Andersona84be6c2011-06-27 21:06:21 +0000579 if (hasAltNames) {
Craig Topperba6d83e2014-11-24 02:08:35 +0000580 O << " switch(AltIdx) {\n"
Craig Topperc4965bc2012-02-05 07:21:30 +0000581 << " default: llvm_unreachable(\"Invalid register alt name index!\");\n";
Craig Topper190ecd52016-01-08 07:06:32 +0000582 for (const Record *R : AltNameIndices) {
Craig Topperbcd3c372017-05-31 21:12:46 +0000583 StringRef AltName = R->getName();
584 O << " case ";
585 if (!Namespace.empty())
586 O << Namespace << "::";
Igor Kudrin2d3faad2019-02-26 12:15:14 +0000587 O << AltName << ":\n";
588 if (R->isValueUnset("FallbackRegAltNameIndex"))
589 O << " assert(*(AsmStrs" << AltName << "+RegAsmOffset" << AltName
590 << "[RegNo-1]) &&\n"
591 << " \"Invalid alt name index for register!\");\n";
592 else {
593 O << " if (!*(AsmStrs" << AltName << "+RegAsmOffset" << AltName
594 << "[RegNo-1]))\n"
595 << " return getRegisterName(RegNo, ";
596 if (!Namespace.empty())
597 O << Namespace << "::";
598 O << R->getValueAsDef("FallbackRegAltNameIndex")->getName() << ");\n";
599 }
600 O << " return AsmStrs" << AltName << "+RegAsmOffset" << AltName
Craig Topperbcd3c372017-05-31 21:12:46 +0000601 << "[RegNo-1];\n";
Owen Andersona84be6c2011-06-27 21:06:21 +0000602 }
Craig Topperba6d83e2014-11-24 02:08:35 +0000603 O << " }\n";
604 } else {
605 O << " assert (*(AsmStrs+RegAsmOffset[RegNo-1]) &&\n"
606 << " \"Invalid alt name index for register!\");\n"
607 << " return AsmStrs+RegAsmOffset[RegNo-1];\n";
Owen Andersona84be6c2011-06-27 21:06:21 +0000608 }
Craig Topperba6d83e2014-11-24 02:08:35 +0000609 O << "}\n";
Chris Lattner06c5eed2009-09-13 20:08:00 +0000610}
611
Bill Wendling7e5771d2011-03-21 08:31:53 +0000612namespace {
Eugene Zelenkoa3fe70d2016-11-30 17:48:10 +0000613
Bill Wendling5d3174c2011-03-21 08:40:31 +0000614// IAPrinter - Holds information about an InstAlias. Two InstAliases match if
615// they both have the same conditionals. In which case, we cannot print out the
616// alias for that pattern.
617class IAPrinter {
Tim Northoveree20caa2014-05-12 18:04:06 +0000618 std::map<StringRef, std::pair<int, int>> OpMap;
Tim Northoveree20caa2014-05-12 18:04:06 +0000619
Reid Kleckner1d9291c2019-11-23 11:28:54 -0800620 std::vector<std::string> Conds;
621
Bill Wendling5d3174c2011-03-21 08:40:31 +0000622 std::string Result;
623 std::string AsmString;
Eugene Zelenkoa3fe70d2016-11-30 17:48:10 +0000624
Reid Kleckner1d9291c2019-11-23 11:28:54 -0800625 unsigned NumMIOps;
Bill Wendling5d3174c2011-03-21 08:40:31 +0000626
Reid Kleckner1d9291c2019-11-23 11:28:54 -0800627public:
628 IAPrinter(std::string R, std::string AS, unsigned NumMIOps)
629 : Result(std::move(R)), AsmString(std::move(AS)), NumMIOps(NumMIOps) {}
630
631 void addCond(std::string C) { Conds.push_back(std::move(C)); }
632 ArrayRef<std::string> getConds() const { return Conds; }
633 size_t getCondCount() const { return Conds.size(); }
Bill Wendling5d3174c2011-03-21 08:40:31 +0000634
Tim Northoveree20caa2014-05-12 18:04:06 +0000635 void addOperand(StringRef Op, int OpIdx, int PrintMethodIdx = -1) {
636 assert(OpIdx >= 0 && OpIdx < 0xFE && "Idx out of range");
Tim Northover0ee9e7e2014-05-13 09:37:41 +0000637 assert(PrintMethodIdx >= -1 && PrintMethodIdx < 0xFF &&
Jay Foadb3590512014-05-13 08:26:53 +0000638 "Idx out of range");
Tim Northoveree20caa2014-05-12 18:04:06 +0000639 OpMap[Op] = std::make_pair(OpIdx, PrintMethodIdx);
Benjamin Kramer17c17bc2013-09-11 15:42:16 +0000640 }
Tim Northoveree20caa2014-05-12 18:04:06 +0000641
Reid Kleckner1d9291c2019-11-23 11:28:54 -0800642 unsigned getNumMIOps() { return NumMIOps; }
643
644 StringRef getResult() { return Result; }
645
Bill Wendling5d3174c2011-03-21 08:40:31 +0000646 bool isOpMapped(StringRef Op) { return OpMap.find(Op) != OpMap.end(); }
Tim Northoveree20caa2014-05-12 18:04:06 +0000647 int getOpIndex(StringRef Op) { return OpMap[Op].first; }
648 std::pair<int, int> &getOpData(StringRef Op) { return OpMap[Op]; }
Bill Wendling5d3174c2011-03-21 08:40:31 +0000649
Tim Northoverd8d65a62014-05-15 11:16:32 +0000650 std::pair<StringRef, StringRef::iterator> parseName(StringRef::iterator Start,
651 StringRef::iterator End) {
652 StringRef::iterator I = Start;
Evgeny Astigeevichb42003d2014-12-16 18:16:17 +0000653 StringRef::iterator Next;
Tim Northoverd8d65a62014-05-15 11:16:32 +0000654 if (*I == '{') {
655 // ${some_name}
656 Start = ++I;
657 while (I != End && *I != '}')
658 ++I;
Evgeny Astigeevichb42003d2014-12-16 18:16:17 +0000659 Next = I;
660 // eat the final '}'
661 if (Next != End)
662 ++Next;
Tim Northoverd8d65a62014-05-15 11:16:32 +0000663 } else {
664 // $name, just eat the usual suspects.
665 while (I != End &&
666 ((*I >= 'a' && *I <= 'z') || (*I >= 'A' && *I <= 'Z') ||
667 (*I >= '0' && *I <= '9') || *I == '_'))
668 ++I;
Evgeny Astigeevichb42003d2014-12-16 18:16:17 +0000669 Next = I;
Tim Northoverd8d65a62014-05-15 11:16:32 +0000670 }
671
Evgeny Astigeevichb42003d2014-12-16 18:16:17 +0000672 return std::make_pair(StringRef(Start, I - Start), Next);
Tim Northoverd8d65a62014-05-15 11:16:32 +0000673 }
674
Reid Kleckner1d9291c2019-11-23 11:28:54 -0800675 std::string formatAliasString(uint32_t &UnescapedSize) {
Benjamin Kramer17c17bc2013-09-11 15:42:16 +0000676 // Directly mangle mapped operands into the string. Each operand is
677 // identified by a '$' sign followed by a byte identifying the number of the
678 // operand. We add one to the index to avoid zero bytes.
Tim Northoverd8d65a62014-05-15 11:16:32 +0000679 StringRef ASM(AsmString);
Reid Kleckner1d9291c2019-11-23 11:28:54 -0800680 std::string OutString;
681 raw_string_ostream OS(OutString);
Tim Northoverd8d65a62014-05-15 11:16:32 +0000682 for (StringRef::iterator I = ASM.begin(), E = ASM.end(); I != E;) {
683 OS << *I;
Reid Kleckner1d9291c2019-11-23 11:28:54 -0800684 ++UnescapedSize;
Tim Northoverd8d65a62014-05-15 11:16:32 +0000685 if (*I == '$') {
686 StringRef Name;
687 std::tie(Name, I) = parseName(++I, E);
688 assert(isOpMapped(Name) && "Unmapped operand!");
Tim Northoveree20caa2014-05-12 18:04:06 +0000689
Tim Northoverd8d65a62014-05-15 11:16:32 +0000690 int OpIndex, PrintIndex;
691 std::tie(OpIndex, PrintIndex) = getOpData(Name);
692 if (PrintIndex == -1) {
693 // Can use the default printOperand route.
694 OS << format("\\x%02X", (unsigned char)OpIndex + 1);
Reid Kleckner1d9291c2019-11-23 11:28:54 -0800695 ++UnescapedSize;
696 } else {
Tim Northoverd8d65a62014-05-15 11:16:32 +0000697 // 3 bytes if a PrintMethod is needed: 0xFF, the MCInst operand
698 // number, and which of our pre-detected Methods to call.
699 OS << format("\\xFF\\x%02X\\x%02X", OpIndex + 1, PrintIndex + 1);
Reid Kleckner1d9291c2019-11-23 11:28:54 -0800700 UnescapedSize += 3;
701 }
Tim Northoverd8d65a62014-05-15 11:16:32 +0000702 } else {
703 ++I;
Benjamin Kramer17c17bc2013-09-11 15:42:16 +0000704 }
705 }
706
Reid Kleckner1d9291c2019-11-23 11:28:54 -0800707 OS.flush();
708 return OutString;
Bill Wendling5d3174c2011-03-21 08:40:31 +0000709 }
710
David Blaikie4ab57cd2015-08-06 19:23:33 +0000711 bool operator==(const IAPrinter &RHS) const {
Reid Kleckner1d9291c2019-11-23 11:28:54 -0800712 if (NumMIOps != RHS.NumMIOps)
713 return false;
Bill Wendling5d3174c2011-03-21 08:40:31 +0000714 if (Conds.size() != RHS.Conds.size())
715 return false;
716
717 unsigned Idx = 0;
David Blaikie4ab57cd2015-08-06 19:23:33 +0000718 for (const auto &str : Conds)
719 if (str != RHS.Conds[Idx++])
Bill Wendling5d3174c2011-03-21 08:40:31 +0000720 return false;
721
722 return true;
723 }
Bill Wendling5d3174c2011-03-21 08:40:31 +0000724};
725
Bill Wendling7e5771d2011-03-21 08:31:53 +0000726} // end anonymous namespace
727
Tim Northover5896b062014-05-16 09:42:04 +0000728static unsigned CountNumOperands(StringRef AsmString, unsigned Variant) {
Tim Northover5896b062014-05-16 09:42:04 +0000729 return AsmString.count(' ') + AsmString.count('\t');
Bill Wendling36c0c6d2011-06-15 04:31:19 +0000730}
Bill Wendlinge7124492011-06-14 03:17:20 +0000731
Tim Northover9a24f882014-05-20 09:17:16 +0000732namespace {
Eugene Zelenkoa3fe70d2016-11-30 17:48:10 +0000733
Tim Northover9a24f882014-05-20 09:17:16 +0000734struct AliasPriorityComparator {
David Blaikie4ab57cd2015-08-06 19:23:33 +0000735 typedef std::pair<CodeGenInstAlias, int> ValueType;
Eric Fiselieraa54e502016-12-27 23:15:58 +0000736 bool operator()(const ValueType &LHS, const ValueType &RHS) const {
Tim Northover9a24f882014-05-20 09:17:16 +0000737 if (LHS.second == RHS.second) {
738 // We don't actually care about the order, but for consistency it
739 // shouldn't depend on pointer comparisons.
Quentin Colombet21136c02017-02-10 02:43:09 +0000740 return LessRecordByID()(LHS.first.TheDef, RHS.first.TheDef);
Tim Northover9a24f882014-05-20 09:17:16 +0000741 }
742
743 // Aliases with larger priorities should be considered first.
744 return LHS.second > RHS.second;
745 }
746};
Tim Northover9a24f882014-05-20 09:17:16 +0000747
Eugene Zelenkoa3fe70d2016-11-30 17:48:10 +0000748} // end anonymous namespace
Tim Northover9a24f882014-05-20 09:17:16 +0000749
Bill Wendling7e5771d2011-03-21 08:31:53 +0000750void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
Bill Wendling7e5771d2011-03-21 08:31:53 +0000751 Record *AsmWriter = Target.getAsmWriter();
752
753 O << "\n#ifdef PRINT_ALIAS_INSTR\n";
754 O << "#undef PRINT_ALIAS_INSTR\n\n";
755
Tim Northoveree20caa2014-05-12 18:04:06 +0000756 //////////////////////////////
757 // Gather information about aliases we need to print
758 //////////////////////////////
759
Bill Wendling31ca7ef2011-02-26 03:09:12 +0000760 // Emit the method that prints the alias instruction.
Craig Topperbcd3c372017-05-31 21:12:46 +0000761 StringRef ClassName = AsmWriter->getValueAsString("AsmWriterClassName");
Tim Northover9a24f882014-05-20 09:17:16 +0000762 unsigned Variant = AsmWriter->getValueAsInt("Variant");
Craig Topperc24a4012016-01-14 06:15:07 +0000763 bool PassSubtarget = AsmWriter->getValueAsInt("PassSubtarget");
Bill Wendling31ca7ef2011-02-26 03:09:12 +0000764
Bill Wendling31ca7ef2011-02-26 03:09:12 +0000765 std::vector<Record*> AllInstAliases =
766 Records.getAllDerivedDefinitions("InstAlias");
767
768 // Create a map from the qualified name to a list of potential matches.
David Blaikie4ab57cd2015-08-06 19:23:33 +0000769 typedef std::set<std::pair<CodeGenInstAlias, int>, AliasPriorityComparator>
Tim Northover9a24f882014-05-20 09:17:16 +0000770 AliasWithPriority;
771 std::map<std::string, AliasWithPriority> AliasMap;
Craig Topper190ecd52016-01-08 07:06:32 +0000772 for (Record *R : AllInstAliases) {
Tim Northover9a24f882014-05-20 09:17:16 +0000773 int Priority = R->getValueAsInt("EmitPriority");
774 if (Priority < 1)
775 continue; // Aliases with priority 0 are never emitted.
776
Bill Wendling31ca7ef2011-02-26 03:09:12 +0000777 const DagInit *DI = R->getValueAsDag("ResultInst");
Daniel Sanders4b7cabf2019-10-08 18:41:32 +0000778 AliasMap[getQualifiedName(DI->getOperatorAsDef(R->getLoc()))].insert(
Craig Topper2be74392018-06-18 01:28:01 +0000779 std::make_pair(CodeGenInstAlias(R, Target), Priority));
Bill Wendling31ca7ef2011-02-26 03:09:12 +0000780 }
781
Bill Wendling7e570b52011-03-21 08:59:17 +0000782 // A map of which conditions need to be met for each instruction operand
783 // before it can be matched to the mnemonic.
David Blaikie4ab57cd2015-08-06 19:23:33 +0000784 std::map<std::string, std::vector<IAPrinter>> IAPrinterMap;
Bill Wendling7e570b52011-03-21 08:59:17 +0000785
Craig Topper674d2382016-01-22 05:59:43 +0000786 std::vector<std::string> PrintMethods;
787
Artyom Skrobov6c8682e2014-06-10 13:11:35 +0000788 // A list of MCOperandPredicates for all operands in use, and the reverse map
789 std::vector<const Record*> MCOpPredicates;
790 DenseMap<const Record*, unsigned> MCOpPredicateMap;
791
Tim Northover9a24f882014-05-20 09:17:16 +0000792 for (auto &Aliases : AliasMap) {
Reid Kleckner1d9291c2019-11-23 11:28:54 -0800793 // Collection of instruction alias rules. May contain ambiguous rules.
794 std::vector<IAPrinter> IAPs;
795
Tim Northover9a24f882014-05-20 09:17:16 +0000796 for (auto &Alias : Aliases.second) {
David Blaikie4ab57cd2015-08-06 19:23:33 +0000797 const CodeGenInstAlias &CGA = Alias.first;
798 unsigned LastOpNo = CGA.ResultInstOperandIndex.size();
Craig Topper2be74392018-06-18 01:28:01 +0000799 std::string FlatInstAsmString =
800 CodeGenInstruction::FlattenAsmStringVariants(CGA.ResultInst->AsmString,
801 Variant);
802 unsigned NumResultOps = CountNumOperands(FlatInstAsmString, Variant);
803
804 std::string FlatAliasAsmString =
Reid Kleckner1d9291c2019-11-23 11:28:54 -0800805 CodeGenInstruction::FlattenAsmStringVariants(CGA.AsmString, Variant);
Bill Wendlinge7124492011-06-14 03:17:20 +0000806
807 // Don't emit the alias if it has more operands than what it's aliasing.
Craig Topper2be74392018-06-18 01:28:01 +0000808 if (NumResultOps < CountNumOperands(FlatAliasAsmString, Variant))
Bill Wendlinge7124492011-06-14 03:17:20 +0000809 continue;
810
Craig Topperbcd3c372017-05-31 21:12:46 +0000811 StringRef Namespace = Target.getName();
Tim Northover60091cf2014-05-15 13:36:01 +0000812 unsigned NumMIOps = 0;
Sander de Smalen0c5a29b2017-11-20 14:36:40 +0000813 for (auto &ResultInstOpnd : CGA.ResultInst->Operands)
814 NumMIOps += ResultInstOpnd.MINumOperands;
Tim Northover60091cf2014-05-15 13:36:01 +0000815
Reid Kleckner1d9291c2019-11-23 11:28:54 -0800816 IAPrinter IAP(CGA.Result->getAsString(), FlatAliasAsmString, NumMIOps);
Bill Wendling7e570b52011-03-21 08:59:17 +0000817
Bill Wendling7e570b52011-03-21 08:59:17 +0000818 bool CantHandle = false;
819
Tim Northover60091cf2014-05-15 13:36:01 +0000820 unsigned MIOpNum = 0;
Bill Wendling7e570b52011-03-21 08:59:17 +0000821 for (unsigned i = 0, e = LastOpNo; i != e; ++i) {
Sander de Smalen0c5a29b2017-11-20 14:36:40 +0000822 // Skip over tied operands as they're not part of an alias declaration.
823 auto &Operands = CGA.ResultInst->Operands;
Simon Tatham80391d62018-12-14 11:39:55 +0000824 while (true) {
825 unsigned OpNum = Operands.getSubOperandNumber(MIOpNum).first;
826 if (Operands[OpNum].MINumOperands == 1 &&
827 Operands[OpNum].getTiedRegister() != -1) {
828 // Tied operands of different RegisterClass should be explicit within
829 // an instruction's syntax and so cannot be skipped.
830 int TiedOpNum = Operands[OpNum].getTiedRegister();
831 if (Operands[OpNum].Rec->getName() ==
832 Operands[TiedOpNum].Rec->getName()) {
833 ++MIOpNum;
834 continue;
835 }
836 }
837 break;
Sander de Smalen0c5a29b2017-11-20 14:36:40 +0000838 }
839
Reid Kleckner1d9291c2019-11-23 11:28:54 -0800840 // Ignore unchecked result operands.
841 while (IAP.getCondCount() < MIOpNum)
842 IAP.addCond("AliasPatternCond::K_Ignore, 0");
Artyom Skrobovaf3c20f2014-06-10 12:47:23 +0000843
David Blaikie4ab57cd2015-08-06 19:23:33 +0000844 const CodeGenInstAlias::ResultOperand &RO = CGA.ResultOperands[i];
Bill Wendling7e570b52011-03-21 08:59:17 +0000845
846 switch (RO.Kind) {
Bill Wendling7e570b52011-03-21 08:59:17 +0000847 case CodeGenInstAlias::ResultOperand::K_Record: {
848 const Record *Rec = RO.getRecord();
849 StringRef ROName = RO.getName();
Tim Northoveree20caa2014-05-12 18:04:06 +0000850 int PrintMethodIdx = -1;
Bill Wendling7e570b52011-03-21 08:59:17 +0000851
Tim Northoveree20caa2014-05-12 18:04:06 +0000852 // These two may have a PrintMethod, which we want to record (if it's
853 // the first time we've seen it) and provide an index for the aliasing
854 // code to use.
855 if (Rec->isSubClassOf("RegisterOperand") ||
856 Rec->isSubClassOf("Operand")) {
Craig Topperbcd3c372017-05-31 21:12:46 +0000857 StringRef PrintMethod = Rec->getValueAsString("PrintMethod");
Tim Northoveree20caa2014-05-12 18:04:06 +0000858 if (PrintMethod != "" && PrintMethod != "printOperand") {
David Majnemer42531262016-08-12 03:55:06 +0000859 PrintMethodIdx =
Eugene Zelenkoa3fe70d2016-11-30 17:48:10 +0000860 llvm::find(PrintMethods, PrintMethod) - PrintMethods.begin();
Tim Northoveree20caa2014-05-12 18:04:06 +0000861 if (static_cast<unsigned>(PrintMethodIdx) == PrintMethods.size())
Benjamin Krameradcd0262020-01-28 20:23:46 +0100862 PrintMethods.push_back(std::string(PrintMethod));
Tim Northoveree20caa2014-05-12 18:04:06 +0000863 }
864 }
Owen Andersona84be6c2011-06-27 21:06:21 +0000865
866 if (Rec->isSubClassOf("RegisterOperand"))
867 Rec = Rec->getValueAsDef("RegClass");
Bill Wendling7e570b52011-03-21 08:59:17 +0000868 if (Rec->isSubClassOf("RegisterClass")) {
David Blaikie4ab57cd2015-08-06 19:23:33 +0000869 if (!IAP.isOpMapped(ROName)) {
870 IAP.addOperand(ROName, MIOpNum, PrintMethodIdx);
871 Record *R = CGA.ResultOperands[i].getRecord();
Jack Carter9c1a0272013-02-05 08:32:10 +0000872 if (R->isSubClassOf("RegisterOperand"))
873 R = R->getValueAsDef("RegClass");
Benjamin Krameradcd0262020-01-28 20:23:46 +0100874 IAP.addCond(std::string(
875 formatv("AliasPatternCond::K_RegClass, {0}::{1}RegClassID",
876 Namespace, R->getName())));
Bill Wendling7e570b52011-03-21 08:59:17 +0000877 } else {
Benjamin Krameradcd0262020-01-28 20:23:46 +0100878 IAP.addCond(std::string(formatv(
879 "AliasPatternCond::K_TiedReg, {0}", IAP.getOpIndex(ROName))));
Bill Wendling7e570b52011-03-21 08:59:17 +0000880 }
881 } else {
Tim Northoveree20caa2014-05-12 18:04:06 +0000882 // Assume all printable operands are desired for now. This can be
Alp Tokerbeaca192014-05-15 01:52:21 +0000883 // overridden in the InstAlias instantiation if necessary.
David Blaikie4ab57cd2015-08-06 19:23:33 +0000884 IAP.addOperand(ROName, MIOpNum, PrintMethodIdx);
Bill Wendling7e570b52011-03-21 08:59:17 +0000885
Artyom Skrobov6c8682e2014-06-10 13:11:35 +0000886 // There might be an additional predicate on the MCOperand
887 unsigned Entry = MCOpPredicateMap[Rec];
888 if (!Entry) {
889 if (!Rec->isValueUnset("MCOperandPredicate")) {
890 MCOpPredicates.push_back(Rec);
891 Entry = MCOpPredicates.size();
892 MCOpPredicateMap[Rec] = Entry;
893 } else
894 break; // No conditions on this operand at all
895 }
Benjamin Krameradcd0262020-01-28 20:23:46 +0100896 IAP.addCond(
897 std::string(formatv("AliasPatternCond::K_Custom, {0}", Entry)));
Artyom Skrobov6c8682e2014-06-10 13:11:35 +0000898 }
Bill Wendling7e570b52011-03-21 08:59:17 +0000899 break;
900 }
Tim Northoverab7689e2013-01-09 13:32:04 +0000901 case CodeGenInstAlias::ResultOperand::K_Imm: {
Tim Northoverab7689e2013-01-09 13:32:04 +0000902 // Just because the alias has an immediate result, doesn't mean the
903 // MCInst will. An MCExpr could be present, for example.
Reid Kleckner1d9291c2019-11-23 11:28:54 -0800904 auto Imm = CGA.ResultOperands[i].getImm();
905 int32_t Imm32 = int32_t(Imm);
906 if (Imm != Imm32)
907 PrintFatalError("Matching an alias with an immediate out of the "
908 "range of int32_t is not supported");
Benjamin Krameradcd0262020-01-28 20:23:46 +0100909 IAP.addCond(std::string(
910 formatv("AliasPatternCond::K_Imm, uint32_t({0})", Imm32)));
Bill Wendling7e570b52011-03-21 08:59:17 +0000911 break;
Tim Northoverab7689e2013-01-09 13:32:04 +0000912 }
Bill Wendling7e570b52011-03-21 08:59:17 +0000913 case CodeGenInstAlias::ResultOperand::K_Reg:
Jim Grosbach29cdcda2011-11-15 01:46:57 +0000914 // If this is zero_reg, something's playing tricks we're not
915 // equipped to handle.
David Blaikie4ab57cd2015-08-06 19:23:33 +0000916 if (!CGA.ResultOperands[i].getRegister()) {
Jim Grosbach29cdcda2011-11-15 01:46:57 +0000917 CantHandle = true;
918 break;
919 }
920
Reid Kleckner1d9291c2019-11-23 11:28:54 -0800921 StringRef Reg = CGA.ResultOperands[i].getRegister()->getName();
Benjamin Krameradcd0262020-01-28 20:23:46 +0100922 IAP.addCond(std::string(
923 formatv("AliasPatternCond::K_Reg, {0}::{1}", Namespace, Reg)));
Bill Wendling7e570b52011-03-21 08:59:17 +0000924 break;
925 }
926
Tim Northover60091cf2014-05-15 13:36:01 +0000927 MIOpNum += RO.getMINumOperands();
Bill Wendling7e570b52011-03-21 08:59:17 +0000928 }
929
930 if (CantHandle) continue;
Sjoerd Meijer84e2f692016-06-03 13:14:19 +0000931
Reid Kleckner1d9291c2019-11-23 11:28:54 -0800932 std::vector<Record *> ReqFeatures;
933 if (PassSubtarget) {
934 // We only consider ReqFeatures predicates if PassSubtarget
935 std::vector<Record *> RF =
936 CGA.TheDef->getValueAsListOfDefs("Predicates");
937 copy_if(RF, std::back_inserter(ReqFeatures), [](Record *R) {
938 return R->getValueAsBit("AssemblerMatcherPredicate");
939 });
940 }
941
Sjoerd Meijer84e2f692016-06-03 13:14:19 +0000942 for (auto I = ReqFeatures.cbegin(); I != ReqFeatures.cend(); I++) {
943 Record *R = *I;
Simon Cooka26bd4e2020-03-13 17:13:51 +0000944 const DagInit *D = R->getValueAsDag("AssemblerCondDag");
945 std::string CombineType = D->getOperator()->getAsString();
946 if (CombineType != "any_of" && CombineType != "all_of")
947 PrintFatalError(R->getLoc(), "Invalid AssemblerCondDag!");
948 if (D->getNumArgs() == 0)
949 PrintFatalError(R->getLoc(), "Invalid AssemblerCondDag!");
950 bool IsOr = CombineType == "any_of";
Sjoerd Meijer84e2f692016-06-03 13:14:19 +0000951
Simon Cooka26bd4e2020-03-13 17:13:51 +0000952 for (auto *Arg : D->getArgs()) {
953 bool IsNeg = false;
954 if (auto *NotArg = dyn_cast<DagInit>(Arg)) {
955 if (NotArg->getOperator()->getAsString() != "not" ||
956 NotArg->getNumArgs() != 1)
957 PrintFatalError(R->getLoc(), "Invalid AssemblerCondDag!");
958 Arg = NotArg->getArg(0);
959 IsNeg = true;
960 }
961 if (!isa<DefInit>(Arg) ||
962 !cast<DefInit>(Arg)->getDef()->isSubClassOf("SubtargetFeature"))
963 PrintFatalError(R->getLoc(), "Invalid AssemblerCondDag!");
Sjoerd Meijer84e2f692016-06-03 13:14:19 +0000964
Simon Cooka26bd4e2020-03-13 17:13:51 +0000965 IAP.addCond(std::string(formatv(
966 "AliasPatternCond::K_{0}{1}Feature, {2}::{3}", IsOr ? "Or" : "",
967 IsNeg ? "Neg" : "", Namespace, Arg->getAsString())));
Sjoerd Meijer84e2f692016-06-03 13:14:19 +0000968 }
Simon Cooka26bd4e2020-03-13 17:13:51 +0000969 // If an AssemblerPredicate with ors is used, note end of list should
970 // these be combined.
971 if (IsOr)
972 IAP.addCond("AliasPatternCond::K_EndOrFeatures, 0");
Sjoerd Meijer84e2f692016-06-03 13:14:19 +0000973 }
974
David Blaikie4ab57cd2015-08-06 19:23:33 +0000975 IAPrinterMap[Aliases.first].push_back(std::move(IAP));
Bill Wendling7e570b52011-03-21 08:59:17 +0000976 }
977 }
978
Tim Northoveree20caa2014-05-12 18:04:06 +0000979 //////////////////////////////
980 // Write out the printAliasInstr function
981 //////////////////////////////
982
Bill Wendlingf5199de2011-05-23 00:18:33 +0000983 std::string Header;
984 raw_string_ostream HeaderO(Header);
985
986 HeaderO << "bool " << Target.getName() << ClassName
Bill Wendlinge7124492011-06-14 03:17:20 +0000987 << "::printAliasInstr(const MCInst"
Fangrui Songb3cc5dc2020-03-26 23:55:43 -0700988 << " *MI, uint64_t Address, "
989 << (PassSubtarget ? "const MCSubtargetInfo &STI, " : "")
Akira Hatanakab46d0232015-03-27 20:36:02 +0000990 << "raw_ostream &OS) {\n";
Bill Wendling7e570b52011-03-21 08:59:17 +0000991
Reid Kleckner1d9291c2019-11-23 11:28:54 -0800992 std::string PatternsForOpcode;
993 raw_string_ostream OpcodeO(PatternsForOpcode);
Bill Wendlingbc3f7902011-04-07 21:20:06 +0000994
Reid Kleckner1d9291c2019-11-23 11:28:54 -0800995 unsigned PatternCount = 0;
996 std::string Patterns;
997 raw_string_ostream PatternO(Patterns);
998
999 unsigned CondCount = 0;
1000 std::string Conds;
1001 raw_string_ostream CondO(Conds);
1002
1003 // All flattened alias strings.
1004 std::map<std::string, uint32_t> AsmStringOffsets;
1005 std::vector<std::pair<uint32_t, std::string>> AsmStrings;
1006 size_t AsmStringsSize = 0;
1007
1008 // Iterate over the opcodes in enum order so they are sorted by opcode for
1009 // binary search.
1010 for (const CodeGenInstruction *Inst : NumberedInstructions) {
1011 auto It = IAPrinterMap.find(getQualifiedName(Inst->TheDef));
1012 if (It == IAPrinterMap.end())
1013 continue;
1014 std::vector<IAPrinter> &IAPs = It->second;
Bill Wendlingbc3f7902011-04-07 21:20:06 +00001015 std::vector<IAPrinter*> UniqueIAPs;
1016
Reid Kleckner1d9291c2019-11-23 11:28:54 -08001017 // Remove any ambiguous alias rules.
David Blaikie4ab57cd2015-08-06 19:23:33 +00001018 for (auto &LHS : IAPs) {
Bill Wendlingbc3f7902011-04-07 21:20:06 +00001019 bool IsDup = false;
David Blaikie4ab57cd2015-08-06 19:23:33 +00001020 for (const auto &RHS : IAPs) {
1021 if (&LHS != &RHS && LHS == RHS) {
Bill Wendlingbc3f7902011-04-07 21:20:06 +00001022 IsDup = true;
1023 break;
1024 }
1025 }
1026
David Blaikie4ab57cd2015-08-06 19:23:33 +00001027 if (!IsDup)
1028 UniqueIAPs.push_back(&LHS);
Bill Wendlingbc3f7902011-04-07 21:20:06 +00001029 }
1030
1031 if (UniqueIAPs.empty()) continue;
1032
Reid Kleckner1d9291c2019-11-23 11:28:54 -08001033 unsigned PatternStart = PatternCount;
1034
1035 // Insert the pattern start and opcode in the pattern list for debugging.
1036 PatternO << formatv(" // {0} - {1}\n", It->first, PatternStart);
Bill Wendlingbc3f7902011-04-07 21:20:06 +00001037
Craig Topper190ecd52016-01-08 07:06:32 +00001038 for (IAPrinter *IAP : UniqueIAPs) {
Reid Kleckner1d9291c2019-11-23 11:28:54 -08001039 // Start each condition list with a comment of the resulting pattern that
1040 // we're trying to match.
1041 unsigned CondStart = CondCount;
1042 CondO << formatv(" // {0} - {1}\n", IAP->getResult(), CondStart);
1043 for (const auto &Cond : IAP->getConds())
1044 CondO << " {" << Cond << "},\n";
1045 CondCount += IAP->getCondCount();
1046
1047 // After operands have been examined, re-encode the alias string with
1048 // escapes indicating how operands should be printed.
1049 uint32_t UnescapedSize = 0;
1050 std::string EncodedAsmString = IAP->formatAliasString(UnescapedSize);
1051 auto Insertion =
1052 AsmStringOffsets.insert({EncodedAsmString, AsmStringsSize});
1053 if (Insertion.second) {
1054 // If the string is new, add it to the vector.
1055 AsmStrings.push_back({AsmStringsSize, EncodedAsmString});
1056 AsmStringsSize += UnescapedSize + 1;
1057 }
1058 unsigned AsmStrOffset = Insertion.first->second;
1059
1060 PatternO << formatv(" {{{0}, {1}, {2}, {3} },\n", AsmStrOffset,
1061 CondStart, IAP->getNumMIOps(), IAP->getCondCount());
1062 ++PatternCount;
Bill Wendlingbc3f7902011-04-07 21:20:06 +00001063 }
1064
Reid Kleckner1d9291c2019-11-23 11:28:54 -08001065 OpcodeO << formatv(" {{{0}, {1}, {2} },\n", It->first, PatternStart,
1066 PatternCount - PatternStart);
Bill Wendlingbc3f7902011-04-07 21:20:06 +00001067 }
1068
Reid Kleckner1d9291c2019-11-23 11:28:54 -08001069 if (OpcodeO.str().empty()) {
Bill Wendlingf5199de2011-05-23 00:18:33 +00001070 O << HeaderO.str();
Eric Christopher2e3fbaa2011-04-18 21:28:11 +00001071 O << " return false;\n";
Bill Wendling31ca7ef2011-02-26 03:09:12 +00001072 O << "}\n\n";
1073 O << "#endif // PRINT_ALIAS_INSTR\n";
1074 return;
1075 }
1076
Reid Kleckner1d9291c2019-11-23 11:28:54 -08001077 // Forward declare the validation method if needed.
Alexander Kornienko8c0809c2015-01-15 11:41:30 +00001078 if (!MCOpPredicates.empty())
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00001079 O << "static bool " << Target.getName() << ClassName
Oliver Stannarda34e4702015-12-01 10:48:51 +00001080 << "ValidateMCOperand(const MCOperand &MCOp,\n"
1081 << " const MCSubtargetInfo &STI,\n"
1082 << " unsigned PredicateIndex);\n";
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00001083
Bill Wendlingf5199de2011-05-23 00:18:33 +00001084 O << HeaderO.str();
Reid Kleckner1d9291c2019-11-23 11:28:54 -08001085 O.indent(2) << "static const PatternsForOpcode OpToPatterns[] = {\n";
1086 O << OpcodeO.str();
1087 O.indent(2) << "};\n\n";
1088 O.indent(2) << "static const AliasPattern Patterns[] = {\n";
1089 O << PatternO.str();
1090 O.indent(2) << "};\n\n";
1091 O.indent(2) << "static const AliasPatternCond Conds[] = {\n";
1092 O << CondO.str();
1093 O.indent(2) << "};\n\n";
1094 O.indent(2) << "static const char AsmStrings[] =\n";
1095 for (const auto &P : AsmStrings) {
1096 O.indent(4) << "/* " << P.first << " */ \"" << P.second << "\\0\"\n";
1097 }
1098
1099 O.indent(2) << ";\n\n";
1100
1101 // Assert that the opcode table is sorted. Use a static local constructor to
1102 // ensure that the check only happens once on first run.
1103 O << "#ifndef NDEBUG\n";
1104 O.indent(2) << "static struct SortCheck {\n";
1105 O.indent(2) << " SortCheck(ArrayRef<PatternsForOpcode> OpToPatterns) {\n";
1106 O.indent(2) << " assert(std::is_sorted(\n";
1107 O.indent(2) << " OpToPatterns.begin(), OpToPatterns.end(),\n";
1108 O.indent(2) << " [](const PatternsForOpcode &L, const "
1109 "PatternsForOpcode &R) {\n";
1110 O.indent(2) << " return L.Opcode < R.Opcode;\n";
1111 O.indent(2) << " }) &&\n";
1112 O.indent(2) << " \"tablegen failed to sort opcode patterns\");\n";
1113 O.indent(2) << " }\n";
1114 O.indent(2) << "} sortCheckVar(OpToPatterns);\n";
1115 O << "#endif\n\n";
1116
1117 O.indent(2) << "AliasMatchingData M {\n";
1118 O.indent(2) << " makeArrayRef(OpToPatterns),\n";
1119 O.indent(2) << " makeArrayRef(Patterns),\n";
1120 O.indent(2) << " makeArrayRef(Conds),\n";
1121 O.indent(2) << " StringRef(AsmStrings, array_lengthof(AsmStrings)),\n";
1122 if (MCOpPredicates.empty())
1123 O.indent(2) << " nullptr,\n";
1124 else
1125 O.indent(2) << " &" << Target.getName() << ClassName << "ValidateMCOperand,\n";
1126 O.indent(2) << "};\n";
1127
1128 O.indent(2) << "const char *AsmString = matchAliasPatterns(MI, "
1129 << (PassSubtarget ? "&STI" : "nullptr") << ", M);\n";
1130 O.indent(2) << "if (!AsmString) return false;\n\n";
Bill Wendling31ca7ef2011-02-26 03:09:12 +00001131
1132 // Code that prints the alias, replacing the operands with the ones from the
1133 // MCInst.
Benjamin Kramer17c17bc2013-09-11 15:42:16 +00001134 O << " unsigned I = 0;\n";
Sjoerd Meijer3c2f7852016-06-03 13:17:37 +00001135 O << " while (AsmString[I] != ' ' && AsmString[I] != '\\t' &&\n";
1136 O << " AsmString[I] != '$' && AsmString[I] != '\\0')\n";
Benjamin Kramer17c17bc2013-09-11 15:42:16 +00001137 O << " ++I;\n";
1138 O << " OS << '\\t' << StringRef(AsmString, I);\n";
Bill Wendling31ca7ef2011-02-26 03:09:12 +00001139
Benjamin Kramer17c17bc2013-09-11 15:42:16 +00001140 O << " if (AsmString[I] != '\\0') {\n";
Petar Jovanovicbd57b8b2017-11-13 18:00:24 +00001141 O << " if (AsmString[I] == ' ' || AsmString[I] == '\\t') {\n";
Sjoerd Meijer3c2f7852016-06-03 13:17:37 +00001142 O << " OS << '\\t';\n";
Petar Jovanovicbd57b8b2017-11-13 18:00:24 +00001143 O << " ++I;\n";
1144 O << " }\n";
Benjamin Kramer17c17bc2013-09-11 15:42:16 +00001145 O << " do {\n";
1146 O << " if (AsmString[I] == '$') {\n";
1147 O << " ++I;\n";
Tim Northoveree20caa2014-05-12 18:04:06 +00001148 O << " if (AsmString[I] == (char)0xff) {\n";
1149 O << " ++I;\n";
1150 O << " int OpIdx = AsmString[I++] - 1;\n";
1151 O << " int PrintMethodIdx = AsmString[I++] - 1;\n";
Akira Hatanakab46d0232015-03-27 20:36:02 +00001152 O << " printCustomAliasOperand(MI, OpIdx, PrintMethodIdx, ";
1153 O << (PassSubtarget ? "STI, " : "");
1154 O << "OS);\n";
Tim Northoveree20caa2014-05-12 18:04:06 +00001155 O << " } else\n";
Akira Hatanakab46d0232015-03-27 20:36:02 +00001156 O << " printOperand(MI, unsigned(AsmString[I++]) - 1, ";
1157 O << (PassSubtarget ? "STI, " : "");
1158 O << "OS);\n";
Bill Wendling31ca7ef2011-02-26 03:09:12 +00001159 O << " } else {\n";
Benjamin Kramer17c17bc2013-09-11 15:42:16 +00001160 O << " OS << AsmString[I++];\n";
Bill Wendling31ca7ef2011-02-26 03:09:12 +00001161 O << " }\n";
Benjamin Kramer17c17bc2013-09-11 15:42:16 +00001162 O << " } while (AsmString[I] != '\\0');\n";
Bill Wendling31ca7ef2011-02-26 03:09:12 +00001163 O << " }\n\n";
Jim Grosbachf4e67082012-04-18 18:56:33 +00001164
Eric Christopher2e3fbaa2011-04-18 21:28:11 +00001165 O << " return true;\n";
Bill Wendling31ca7ef2011-02-26 03:09:12 +00001166 O << "}\n\n";
1167
Tim Northoveree20caa2014-05-12 18:04:06 +00001168 //////////////////////////////
1169 // Write out the printCustomAliasOperand function
1170 //////////////////////////////
1171
1172 O << "void " << Target.getName() << ClassName << "::"
1173 << "printCustomAliasOperand(\n"
1174 << " const MCInst *MI, unsigned OpIdx,\n"
Akira Hatanakab46d0232015-03-27 20:36:02 +00001175 << " unsigned PrintMethodIdx,\n"
1176 << (PassSubtarget ? " const MCSubtargetInfo &STI,\n" : "")
1177 << " raw_ostream &OS) {\n";
Aaron Ballmane58a5702014-05-13 12:52:35 +00001178 if (PrintMethods.empty())
1179 O << " llvm_unreachable(\"Unknown PrintMethod kind\");\n";
1180 else {
1181 O << " switch (PrintMethodIdx) {\n"
1182 << " default:\n"
1183 << " llvm_unreachable(\"Unknown PrintMethod kind\");\n"
Tim Northoveree20caa2014-05-12 18:04:06 +00001184 << " break;\n";
Tim Northoveree20caa2014-05-12 18:04:06 +00001185
Aaron Ballmane58a5702014-05-13 12:52:35 +00001186 for (unsigned i = 0; i < PrintMethods.size(); ++i) {
1187 O << " case " << i << ":\n"
Akira Hatanakab46d0232015-03-27 20:36:02 +00001188 << " " << PrintMethods[i] << "(MI, OpIdx, "
1189 << (PassSubtarget ? "STI, " : "") << "OS);\n"
Aaron Ballmane58a5702014-05-13 12:52:35 +00001190 << " break;\n";
1191 }
1192 O << " }\n";
1193 }
1194 O << "}\n\n";
Tim Northoveree20caa2014-05-12 18:04:06 +00001195
Alexander Kornienko8c0809c2015-01-15 11:41:30 +00001196 if (!MCOpPredicates.empty()) {
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00001197 O << "static bool " << Target.getName() << ClassName
Oliver Stannarda34e4702015-12-01 10:48:51 +00001198 << "ValidateMCOperand(const MCOperand &MCOp,\n"
1199 << " const MCSubtargetInfo &STI,\n"
1200 << " unsigned PredicateIndex) {\n"
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00001201 << " switch (PredicateIndex) {\n"
1202 << " default:\n"
1203 << " llvm_unreachable(\"Unknown MCOperandPredicate kind\");\n"
1204 << " break;\n";
1205
1206 for (unsigned i = 0; i < MCOpPredicates.size(); ++i) {
1207 Init *MCOpPred = MCOpPredicates[i]->getValueInit("MCOperandPredicate");
Tim Northover88403d72016-07-05 21:22:55 +00001208 if (CodeInit *SI = dyn_cast<CodeInit>(MCOpPred)) {
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00001209 O << " case " << i + 1 << ": {\n"
1210 << SI->getValue() << "\n"
1211 << " }\n";
1212 } else
1213 llvm_unreachable("Unexpected MCOperandPredicate field!");
1214 }
1215 O << " }\n"
1216 << "}\n\n";
1217 }
1218
Bill Wendling31ca7ef2011-02-26 03:09:12 +00001219 O << "#endif // PRINT_ALIAS_INSTR\n";
1220}
Chris Lattner06c5eed2009-09-13 20:08:00 +00001221
Ahmed Bougachabd214002013-10-28 18:07:17 +00001222AsmWriterEmitter::AsmWriterEmitter(RecordKeeper &R) : Records(R), Target(R) {
1223 Record *AsmWriter = Target.getAsmWriter();
Craig Topper0bd58742016-01-13 07:20:05 +00001224 unsigned Variant = AsmWriter->getValueAsInt("Variant");
Ahmed Bougachabd214002013-10-28 18:07:17 +00001225
1226 // Get the instruction numbering.
Craig Topperf9265322016-01-17 20:38:14 +00001227 NumberedInstructions = Target.getInstructionsByEnumValue();
Ahmed Bougachabd214002013-10-28 18:07:17 +00001228
Craig Topperf9265322016-01-17 20:38:14 +00001229 for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) {
1230 const CodeGenInstruction *I = NumberedInstructions[i];
Craig Topper9e9ae602016-01-17 08:05:33 +00001231 if (!I->AsmString.empty() && I->TheDef->getName() != "PHI")
1232 Instructions.emplace_back(*I, i, Variant);
1233 }
Ahmed Bougachabd214002013-10-28 18:07:17 +00001234}
1235
Chris Lattner06c5eed2009-09-13 20:08:00 +00001236void AsmWriterEmitter::run(raw_ostream &O) {
Chris Lattner06c5eed2009-09-13 20:08:00 +00001237 EmitPrintInstruction(O);
1238 EmitGetRegisterName(O);
Bill Wendling31ca7ef2011-02-26 03:09:12 +00001239 EmitPrintAliasInstruction(O);
Chris Lattner06c5eed2009-09-13 20:08:00 +00001240}
1241
Jakob Stoklund Olesene6aed132012-06-11 15:37:55 +00001242namespace llvm {
1243
1244void EmitAsmWriter(RecordKeeper &RK, raw_ostream &OS) {
1245 emitSourceFileHeader("Assembly Writer Source Fragment", OS);
1246 AsmWriterEmitter(RK).run(OS);
1247}
1248
Eugene Zelenkoa3fe70d2016-11-30 17:48:10 +00001249} // end namespace llvm