xref: /llvm-project/llvm/utils/TableGen/Common/CodeGenInstAlias.cpp (revision 4e8c9d28132039a98feb97cec2759cddeb37d934)
1fa3d789dSPierre van Houtryve //===- CodeGenInstAlias.cpp - CodeGen InstAlias Class Wrapper -------------===//
2fa3d789dSPierre van Houtryve //
3fa3d789dSPierre van Houtryve // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4fa3d789dSPierre van Houtryve // See https://llvm.org/LICENSE.txt for license information.
5fa3d789dSPierre van Houtryve // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6fa3d789dSPierre van Houtryve //
7fa3d789dSPierre van Houtryve //===----------------------------------------------------------------------===//
8fa3d789dSPierre van Houtryve //
9fa3d789dSPierre van Houtryve // This file implements the CodeGenInstAlias class.
10fa3d789dSPierre van Houtryve //
11fa3d789dSPierre van Houtryve //===----------------------------------------------------------------------===//
12fa3d789dSPierre van Houtryve 
13fa3d789dSPierre van Houtryve #include "CodeGenInstAlias.h"
14fa3d789dSPierre van Houtryve #include "CodeGenInstruction.h"
15fa3d789dSPierre van Houtryve #include "CodeGenRegisters.h"
16fa3d789dSPierre van Houtryve #include "CodeGenTarget.h"
17fa3d789dSPierre van Houtryve #include "llvm/ADT/StringMap.h"
18fa3d789dSPierre van Houtryve #include "llvm/TableGen/Error.h"
19fa3d789dSPierre van Houtryve #include "llvm/TableGen/Record.h"
20fa3d789dSPierre van Houtryve 
21fa3d789dSPierre van Houtryve using namespace llvm;
22fa3d789dSPierre van Houtryve 
23fa3d789dSPierre van Houtryve /// tryAliasOpMatch - This is a helper function for the CodeGenInstAlias
24fa3d789dSPierre van Houtryve /// constructor.  It checks if an argument in an InstAlias pattern matches
25fa3d789dSPierre van Houtryve /// the corresponding operand of the instruction.  It returns true on a
26fa3d789dSPierre van Houtryve /// successful match, with ResOp set to the result operand to be used.
278783bd5fSRahul Joshi bool CodeGenInstAlias::tryAliasOpMatch(const DagInit *Result,
288783bd5fSRahul Joshi                                        unsigned AliasOpNo,
29bdf02249SRahul Joshi                                        const Record *InstOpRec, bool hasSubOps,
308783bd5fSRahul Joshi                                        ArrayRef<SMLoc> Loc,
318783bd5fSRahul Joshi                                        const CodeGenTarget &T,
32fa3d789dSPierre van Houtryve                                        ResultOperand &ResOp) {
333138eb50SRahul Joshi   const Init *Arg = Result->getArg(AliasOpNo);
343138eb50SRahul Joshi   const DefInit *ADI = dyn_cast<DefInit>(Arg);
353138eb50SRahul Joshi   const Record *ResultRecord = ADI ? ADI->getDef() : nullptr;
36fa3d789dSPierre van Houtryve 
37fa3d789dSPierre van Houtryve   if (ADI && ADI->getDef() == InstOpRec) {
38fa3d789dSPierre van Houtryve     // If the operand is a record, it must have a name, and the record type
39fa3d789dSPierre van Houtryve     // must match up with the instruction's argument type.
40fa3d789dSPierre van Houtryve     if (!Result->getArgName(AliasOpNo))
41fa3d789dSPierre van Houtryve       PrintFatalError(Loc, "result argument #" + Twine(AliasOpNo) +
42fa3d789dSPierre van Houtryve                                " must have a name!");
43fa3d789dSPierre van Houtryve     ResOp = ResultOperand(std::string(Result->getArgNameStr(AliasOpNo)),
44fa3d789dSPierre van Houtryve                           ResultRecord);
45fa3d789dSPierre van Houtryve     return true;
46fa3d789dSPierre van Houtryve   }
47fa3d789dSPierre van Houtryve 
48fa3d789dSPierre van Houtryve   // For register operands, the source register class can be a subclass
49fa3d789dSPierre van Houtryve   // of the instruction register class, not just an exact match.
50fa3d789dSPierre van Houtryve   if (InstOpRec->isSubClassOf("RegisterOperand"))
51fa3d789dSPierre van Houtryve     InstOpRec = InstOpRec->getValueAsDef("RegClass");
52fa3d789dSPierre van Houtryve 
53fa3d789dSPierre van Houtryve   if (ADI && ADI->getDef()->isSubClassOf("RegisterOperand"))
54fa3d789dSPierre van Houtryve     ADI = ADI->getDef()->getValueAsDef("RegClass")->getDefInit();
55fa3d789dSPierre van Houtryve 
56fa3d789dSPierre van Houtryve   if (ADI && ADI->getDef()->isSubClassOf("RegisterClass")) {
57fa3d789dSPierre van Houtryve     if (!InstOpRec->isSubClassOf("RegisterClass"))
58fa3d789dSPierre van Houtryve       return false;
59fa3d789dSPierre van Houtryve     if (!T.getRegisterClass(InstOpRec).hasSubClass(
60fa3d789dSPierre van Houtryve             &T.getRegisterClass(ADI->getDef())))
61fa3d789dSPierre van Houtryve       return false;
62fa3d789dSPierre van Houtryve     ResOp = ResultOperand(std::string(Result->getArgNameStr(AliasOpNo)),
63fa3d789dSPierre van Houtryve                           ResultRecord);
64fa3d789dSPierre van Houtryve     return true;
65fa3d789dSPierre van Houtryve   }
66fa3d789dSPierre van Houtryve 
67fa3d789dSPierre van Houtryve   // Handle explicit registers.
68fa3d789dSPierre van Houtryve   if (ADI && ADI->getDef()->isSubClassOf("Register")) {
69fa3d789dSPierre van Houtryve     if (InstOpRec->isSubClassOf("OptionalDefOperand")) {
7062e2c7fbSRahul Joshi       const DagInit *DI = InstOpRec->getValueAsDag("MIOperandInfo");
71fa3d789dSPierre van Houtryve       // The operand info should only have a single (register) entry. We
72fa3d789dSPierre van Houtryve       // want the register class of it.
73fa3d789dSPierre van Houtryve       InstOpRec = cast<DefInit>(DI->getArg(0))->getDef();
74fa3d789dSPierre van Houtryve     }
75fa3d789dSPierre van Houtryve 
76fa3d789dSPierre van Houtryve     if (!InstOpRec->isSubClassOf("RegisterClass"))
77fa3d789dSPierre van Houtryve       return false;
78fa3d789dSPierre van Houtryve 
79fa3d789dSPierre van Houtryve     if (!T.getRegisterClass(InstOpRec).contains(
80fa3d789dSPierre van Houtryve             T.getRegBank().getReg(ADI->getDef())))
81fa3d789dSPierre van Houtryve       PrintFatalError(Loc, "fixed register " + ADI->getDef()->getName() +
82fa3d789dSPierre van Houtryve                                " is not a member of the " +
83fa3d789dSPierre van Houtryve                                InstOpRec->getName() + " register class!");
84fa3d789dSPierre van Houtryve 
85fa3d789dSPierre van Houtryve     if (Result->getArgName(AliasOpNo))
86fa3d789dSPierre van Houtryve       PrintFatalError(Loc, "result fixed register argument must "
87fa3d789dSPierre van Houtryve                            "not have a name!");
88fa3d789dSPierre van Houtryve 
89fa3d789dSPierre van Houtryve     ResOp = ResultOperand(ResultRecord);
90fa3d789dSPierre van Houtryve     return true;
91fa3d789dSPierre van Houtryve   }
92fa3d789dSPierre van Houtryve 
93fa3d789dSPierre van Houtryve   // Handle "zero_reg" for optional def operands.
94fa3d789dSPierre van Houtryve   if (ADI && ADI->getDef()->getName() == "zero_reg") {
95fa3d789dSPierre van Houtryve 
96fa3d789dSPierre van Houtryve     // Check if this is an optional def.
97fa3d789dSPierre van Houtryve     // Tied operands where the source is a sub-operand of a complex operand
98fa3d789dSPierre van Houtryve     // need to represent both operands in the alias destination instruction.
99fa3d789dSPierre van Houtryve     // Allow zero_reg for the tied portion. This can and should go away once
100fa3d789dSPierre van Houtryve     // the MC representation of things doesn't use tied operands at all.
101fa3d789dSPierre van Houtryve     // if (!InstOpRec->isSubClassOf("OptionalDefOperand"))
102fa3d789dSPierre van Houtryve     //  throw TGError(Loc, "reg0 used for result that is not an "
103fa3d789dSPierre van Houtryve     //                "OptionalDefOperand!");
104fa3d789dSPierre van Houtryve 
1053138eb50SRahul Joshi     ResOp = ResultOperand(nullptr);
106fa3d789dSPierre van Houtryve     return true;
107fa3d789dSPierre van Houtryve   }
108fa3d789dSPierre van Houtryve 
109fa3d789dSPierre van Houtryve   // Literal integers.
1103138eb50SRahul Joshi   if (const IntInit *II = dyn_cast<IntInit>(Arg)) {
111fa3d789dSPierre van Houtryve     if (hasSubOps || !InstOpRec->isSubClassOf("Operand"))
112fa3d789dSPierre van Houtryve       return false;
113fa3d789dSPierre van Houtryve     // Integer arguments can't have names.
114fa3d789dSPierre van Houtryve     if (Result->getArgName(AliasOpNo))
115fa3d789dSPierre van Houtryve       PrintFatalError(Loc, "result argument #" + Twine(AliasOpNo) +
116fa3d789dSPierre van Houtryve                                " must not have a name!");
117fa3d789dSPierre van Houtryve     ResOp = ResultOperand(II->getValue());
118fa3d789dSPierre van Houtryve     return true;
119fa3d789dSPierre van Houtryve   }
120fa3d789dSPierre van Houtryve 
121fa3d789dSPierre van Houtryve   // Bits<n> (also used for 0bxx literals)
1223138eb50SRahul Joshi   if (const BitsInit *BI = dyn_cast<BitsInit>(Arg)) {
123fa3d789dSPierre van Houtryve     if (hasSubOps || !InstOpRec->isSubClassOf("Operand"))
124fa3d789dSPierre van Houtryve       return false;
125fa3d789dSPierre van Houtryve     if (!BI->isComplete())
126fa3d789dSPierre van Houtryve       return false;
127fa3d789dSPierre van Houtryve     // Convert the bits init to an integer and use that for the result.
1283138eb50SRahul Joshi     std::optional<int64_t> Value = BI->convertInitializerToInt();
1293138eb50SRahul Joshi     if (!Value)
130fa3d789dSPierre van Houtryve       return false;
1313138eb50SRahul Joshi     ResOp = ResultOperand(*Value);
132fa3d789dSPierre van Houtryve     return true;
133fa3d789dSPierre van Houtryve   }
134fa3d789dSPierre van Houtryve 
135fa3d789dSPierre van Houtryve   // If both are Operands with the same MVT, allow the conversion. It's
136fa3d789dSPierre van Houtryve   // up to the user to make sure the values are appropriate, just like
137fa3d789dSPierre van Houtryve   // for isel Pat's.
138fa3d789dSPierre van Houtryve   if (InstOpRec->isSubClassOf("Operand") && ADI &&
139fa3d789dSPierre van Houtryve       ADI->getDef()->isSubClassOf("Operand")) {
140fa3d789dSPierre van Houtryve     // FIXME: What other attributes should we check here? Identical
141fa3d789dSPierre van Houtryve     // MIOperandInfo perhaps?
142fa3d789dSPierre van Houtryve     if (InstOpRec->getValueInit("Type") != ADI->getDef()->getValueInit("Type"))
143fa3d789dSPierre van Houtryve       return false;
144fa3d789dSPierre van Houtryve     ResOp = ResultOperand(std::string(Result->getArgNameStr(AliasOpNo)),
145fa3d789dSPierre van Houtryve                           ADI->getDef());
146fa3d789dSPierre van Houtryve     return true;
147fa3d789dSPierre van Houtryve   }
148fa3d789dSPierre van Houtryve 
149fa3d789dSPierre van Houtryve   return false;
150fa3d789dSPierre van Houtryve }
151fa3d789dSPierre van Houtryve 
152fa3d789dSPierre van Houtryve unsigned CodeGenInstAlias::ResultOperand::getMINumOperands() const {
153fa3d789dSPierre van Houtryve   if (!isRecord())
154fa3d789dSPierre van Houtryve     return 1;
155fa3d789dSPierre van Houtryve 
1568783bd5fSRahul Joshi   const Record *Rec = getRecord();
157fa3d789dSPierre van Houtryve   if (!Rec->isSubClassOf("Operand"))
158fa3d789dSPierre van Houtryve     return 1;
159fa3d789dSPierre van Houtryve 
1608783bd5fSRahul Joshi   const DagInit *MIOpInfo = Rec->getValueAsDag("MIOperandInfo");
161fa3d789dSPierre van Houtryve   if (MIOpInfo->getNumArgs() == 0) {
162fa3d789dSPierre van Houtryve     // Unspecified, so it defaults to 1
163fa3d789dSPierre van Houtryve     return 1;
164fa3d789dSPierre van Houtryve   }
165fa3d789dSPierre van Houtryve 
166fa3d789dSPierre van Houtryve   return MIOpInfo->getNumArgs();
167fa3d789dSPierre van Houtryve }
168fa3d789dSPierre van Houtryve 
1698783bd5fSRahul Joshi CodeGenInstAlias::CodeGenInstAlias(const Record *R, const CodeGenTarget &T)
1708783bd5fSRahul Joshi     : TheDef(R) {
171fa3d789dSPierre van Houtryve   Result = R->getValueAsDag("ResultInst");
172fa3d789dSPierre van Houtryve   AsmString = std::string(R->getValueAsString("AsmString"));
173fa3d789dSPierre van Houtryve 
174fa3d789dSPierre van Houtryve   // Verify that the root of the result is an instruction.
17562e2c7fbSRahul Joshi   const DefInit *DI = dyn_cast<DefInit>(Result->getOperator());
176fa3d789dSPierre van Houtryve   if (!DI || !DI->getDef()->isSubClassOf("Instruction"))
177fa3d789dSPierre van Houtryve     PrintFatalError(R->getLoc(),
178fa3d789dSPierre van Houtryve                     "result of inst alias should be an instruction");
179fa3d789dSPierre van Houtryve 
180fa3d789dSPierre van Houtryve   ResultInst = &T.getInstruction(DI->getDef());
181fa3d789dSPierre van Houtryve 
182fa3d789dSPierre van Houtryve   // NameClass - If argument names are repeated, we need to verify they have
183fa3d789dSPierre van Houtryve   // the same class.
1843138eb50SRahul Joshi   StringMap<const Record *> NameClass;
185fa3d789dSPierre van Houtryve   for (unsigned i = 0, e = Result->getNumArgs(); i != e; ++i) {
1863138eb50SRahul Joshi     const DefInit *ADI = dyn_cast<DefInit>(Result->getArg(i));
187fa3d789dSPierre van Houtryve     if (!ADI || !Result->getArgName(i))
188fa3d789dSPierre van Houtryve       continue;
189fa3d789dSPierre van Houtryve     // Verify we don't have something like: (someinst GR16:$foo, GR32:$foo)
190fa3d789dSPierre van Houtryve     // $foo can exist multiple times in the result list, but it must have the
191fa3d789dSPierre van Houtryve     // same type.
1923138eb50SRahul Joshi     const Record *&Entry = NameClass[Result->getArgNameStr(i)];
193fa3d789dSPierre van Houtryve     if (Entry && Entry != ADI->getDef())
194fa3d789dSPierre van Houtryve       PrintFatalError(R->getLoc(), "result value $" + Result->getArgNameStr(i) +
195fa3d789dSPierre van Houtryve                                        " is both " + Entry->getName() +
196fa3d789dSPierre van Houtryve                                        " and " + ADI->getDef()->getName() +
197fa3d789dSPierre van Houtryve                                        "!");
198fa3d789dSPierre van Houtryve     Entry = ADI->getDef();
199fa3d789dSPierre van Houtryve   }
200fa3d789dSPierre van Houtryve 
201fa3d789dSPierre van Houtryve   // Decode and validate the arguments of the result.
202fa3d789dSPierre van Houtryve   unsigned AliasOpNo = 0;
203fa3d789dSPierre van Houtryve   for (unsigned i = 0, e = ResultInst->Operands.size(); i != e; ++i) {
204fa3d789dSPierre van Houtryve 
205fa3d789dSPierre van Houtryve     // Tied registers don't have an entry in the result dag unless they're part
206fa3d789dSPierre van Houtryve     // of a complex operand, in which case we include them anyways, as we
207fa3d789dSPierre van Houtryve     // don't have any other way to specify the whole operand.
208fa3d789dSPierre van Houtryve     if (ResultInst->Operands[i].MINumOperands == 1 &&
209fa3d789dSPierre van Houtryve         ResultInst->Operands[i].getTiedRegister() != -1) {
210fa3d789dSPierre van Houtryve       // Tied operands of different RegisterClass should be explicit within an
211fa3d789dSPierre van Houtryve       // instruction's syntax and so cannot be skipped.
212fa3d789dSPierre van Houtryve       int TiedOpNum = ResultInst->Operands[i].getTiedRegister();
213fa3d789dSPierre van Houtryve       if (ResultInst->Operands[i].Rec->getName() ==
214fa3d789dSPierre van Houtryve           ResultInst->Operands[TiedOpNum].Rec->getName())
215fa3d789dSPierre van Houtryve         continue;
216fa3d789dSPierre van Houtryve     }
217fa3d789dSPierre van Houtryve 
218fa3d789dSPierre van Houtryve     if (AliasOpNo >= Result->getNumArgs())
219fa3d789dSPierre van Houtryve       PrintFatalError(R->getLoc(), "not enough arguments for instruction!");
220fa3d789dSPierre van Houtryve 
221bdf02249SRahul Joshi     const Record *InstOpRec = ResultInst->Operands[i].Rec;
222fa3d789dSPierre van Houtryve     unsigned NumSubOps = ResultInst->Operands[i].MINumOperands;
223fa3d789dSPierre van Houtryve     ResultOperand ResOp(static_cast<int64_t>(0));
224fa3d789dSPierre van Houtryve     if (tryAliasOpMatch(Result, AliasOpNo, InstOpRec, (NumSubOps > 1),
225fa3d789dSPierre van Houtryve                         R->getLoc(), T, ResOp)) {
226fa3d789dSPierre van Houtryve       // If this is a simple operand, or a complex operand with a custom match
227fa3d789dSPierre van Houtryve       // class, then we can match is verbatim.
228fa3d789dSPierre van Houtryve       if (NumSubOps == 1 || (InstOpRec->getValue("ParserMatchClass") &&
229fa3d789dSPierre van Houtryve                              InstOpRec->getValueAsDef("ParserMatchClass")
230fa3d789dSPierre van Houtryve                                      ->getValueAsString("Name") != "Imm")) {
23131ce47b5Sabhishek-kaushik22         ResultOperands.push_back(std::move(ResOp));
232*4e8c9d28SJay Foad         ResultInstOperandIndex.emplace_back(i, -1);
233fa3d789dSPierre van Houtryve         ++AliasOpNo;
234fa3d789dSPierre van Houtryve 
235fa3d789dSPierre van Houtryve         // Otherwise, we need to match each of the suboperands individually.
236fa3d789dSPierre van Houtryve       } else {
2373138eb50SRahul Joshi         const DagInit *MIOI = ResultInst->Operands[i].MIOperandInfo;
238fa3d789dSPierre van Houtryve         for (unsigned SubOp = 0; SubOp != NumSubOps; ++SubOp) {
2393138eb50SRahul Joshi           const Record *SubRec = cast<DefInit>(MIOI->getArg(SubOp))->getDef();
240fa3d789dSPierre van Houtryve 
241fa3d789dSPierre van Houtryve           // Take care to instantiate each of the suboperands with the correct
242fa3d789dSPierre van Houtryve           // nomenclature: $foo.bar
243fa3d789dSPierre van Houtryve           ResultOperands.emplace_back(
244fa3d789dSPierre van Houtryve               Result->getArgName(AliasOpNo)->getAsUnquotedString() + "." +
245fa3d789dSPierre van Houtryve                   MIOI->getArgName(SubOp)->getAsUnquotedString(),
246fa3d789dSPierre van Houtryve               SubRec);
247*4e8c9d28SJay Foad           ResultInstOperandIndex.emplace_back(i, SubOp);
248fa3d789dSPierre van Houtryve         }
249fa3d789dSPierre van Houtryve         ++AliasOpNo;
250fa3d789dSPierre van Houtryve       }
251fa3d789dSPierre van Houtryve       continue;
252fa3d789dSPierre van Houtryve     }
253fa3d789dSPierre van Houtryve 
254fa3d789dSPierre van Houtryve     // If the argument did not match the instruction operand, and the operand
255fa3d789dSPierre van Houtryve     // is composed of multiple suboperands, try matching the suboperands.
256fa3d789dSPierre van Houtryve     if (NumSubOps > 1) {
2573138eb50SRahul Joshi       const DagInit *MIOI = ResultInst->Operands[i].MIOperandInfo;
258fa3d789dSPierre van Houtryve       for (unsigned SubOp = 0; SubOp != NumSubOps; ++SubOp) {
259fa3d789dSPierre van Houtryve         if (AliasOpNo >= Result->getNumArgs())
260fa3d789dSPierre van Houtryve           PrintFatalError(R->getLoc(), "not enough arguments for instruction!");
2613138eb50SRahul Joshi         const Record *SubRec = cast<DefInit>(MIOI->getArg(SubOp))->getDef();
262fa3d789dSPierre van Houtryve         if (tryAliasOpMatch(Result, AliasOpNo, SubRec, false, R->getLoc(), T,
263fa3d789dSPierre van Houtryve                             ResOp)) {
264fa3d789dSPierre van Houtryve           ResultOperands.push_back(ResOp);
265*4e8c9d28SJay Foad           ResultInstOperandIndex.emplace_back(i, SubOp);
266fa3d789dSPierre van Houtryve           ++AliasOpNo;
267fa3d789dSPierre van Houtryve         } else {
268fa3d789dSPierre van Houtryve           PrintFatalError(
269fa3d789dSPierre van Houtryve               R->getLoc(),
270fa3d789dSPierre van Houtryve               "result argument #" + Twine(AliasOpNo) +
271fa3d789dSPierre van Houtryve                   " does not match instruction operand class " +
272fa3d789dSPierre van Houtryve                   (SubOp == 0 ? InstOpRec->getName() : SubRec->getName()));
273fa3d789dSPierre van Houtryve         }
274fa3d789dSPierre van Houtryve       }
275fa3d789dSPierre van Houtryve       continue;
276fa3d789dSPierre van Houtryve     }
277fa3d789dSPierre van Houtryve     PrintFatalError(R->getLoc(),
278fa3d789dSPierre van Houtryve                     "result argument #" + Twine(AliasOpNo) +
279fa3d789dSPierre van Houtryve                         " does not match instruction operand class " +
280fa3d789dSPierre van Houtryve                         InstOpRec->getName());
281fa3d789dSPierre van Houtryve   }
282fa3d789dSPierre van Houtryve 
283fa3d789dSPierre van Houtryve   if (AliasOpNo != Result->getNumArgs())
284fa3d789dSPierre van Houtryve     PrintFatalError(R->getLoc(), "too many operands for instruction!");
285fa3d789dSPierre van Houtryve }
286