xref: /src/contrib/llvm-project/llvm/utils/TableGen/Common/CodeGenInstAlias.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
17fa27ce4SDimitry Andric //===- CodeGenInstAlias.cpp - CodeGen InstAlias Class Wrapper -------------===//
27fa27ce4SDimitry Andric //
37fa27ce4SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47fa27ce4SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
57fa27ce4SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67fa27ce4SDimitry Andric //
77fa27ce4SDimitry Andric //===----------------------------------------------------------------------===//
87fa27ce4SDimitry Andric //
97fa27ce4SDimitry Andric // This file implements the CodeGenInstAlias class.
107fa27ce4SDimitry Andric //
117fa27ce4SDimitry Andric //===----------------------------------------------------------------------===//
127fa27ce4SDimitry Andric 
137fa27ce4SDimitry Andric #include "CodeGenInstAlias.h"
147fa27ce4SDimitry Andric #include "CodeGenInstruction.h"
157fa27ce4SDimitry Andric #include "CodeGenRegisters.h"
167fa27ce4SDimitry Andric #include "CodeGenTarget.h"
177fa27ce4SDimitry Andric #include "llvm/ADT/StringMap.h"
187fa27ce4SDimitry Andric #include "llvm/TableGen/Error.h"
197fa27ce4SDimitry Andric #include "llvm/TableGen/Record.h"
207fa27ce4SDimitry Andric 
217fa27ce4SDimitry Andric using namespace llvm;
227fa27ce4SDimitry Andric 
237fa27ce4SDimitry Andric /// tryAliasOpMatch - This is a helper function for the CodeGenInstAlias
247fa27ce4SDimitry Andric /// constructor.  It checks if an argument in an InstAlias pattern matches
257fa27ce4SDimitry Andric /// the corresponding operand of the instruction.  It returns true on a
267fa27ce4SDimitry Andric /// successful match, with ResOp set to the result operand to be used.
tryAliasOpMatch(DagInit * Result,unsigned AliasOpNo,Record * InstOpRec,bool hasSubOps,ArrayRef<SMLoc> Loc,CodeGenTarget & T,ResultOperand & ResOp)277fa27ce4SDimitry Andric bool CodeGenInstAlias::tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo,
287fa27ce4SDimitry Andric                                        Record *InstOpRec, bool hasSubOps,
297fa27ce4SDimitry Andric                                        ArrayRef<SMLoc> Loc, CodeGenTarget &T,
307fa27ce4SDimitry Andric                                        ResultOperand &ResOp) {
317fa27ce4SDimitry Andric   Init *Arg = Result->getArg(AliasOpNo);
327fa27ce4SDimitry Andric   DefInit *ADI = dyn_cast<DefInit>(Arg);
337fa27ce4SDimitry Andric   Record *ResultRecord = ADI ? ADI->getDef() : nullptr;
347fa27ce4SDimitry Andric 
357fa27ce4SDimitry Andric   if (ADI && ADI->getDef() == InstOpRec) {
367fa27ce4SDimitry Andric     // If the operand is a record, it must have a name, and the record type
377fa27ce4SDimitry Andric     // must match up with the instruction's argument type.
387fa27ce4SDimitry Andric     if (!Result->getArgName(AliasOpNo))
397fa27ce4SDimitry Andric       PrintFatalError(Loc, "result argument #" + Twine(AliasOpNo) +
407fa27ce4SDimitry Andric                                " must have a name!");
417fa27ce4SDimitry Andric     ResOp = ResultOperand(std::string(Result->getArgNameStr(AliasOpNo)),
427fa27ce4SDimitry Andric                           ResultRecord);
437fa27ce4SDimitry Andric     return true;
447fa27ce4SDimitry Andric   }
457fa27ce4SDimitry Andric 
467fa27ce4SDimitry Andric   // For register operands, the source register class can be a subclass
477fa27ce4SDimitry Andric   // of the instruction register class, not just an exact match.
487fa27ce4SDimitry Andric   if (InstOpRec->isSubClassOf("RegisterOperand"))
497fa27ce4SDimitry Andric     InstOpRec = InstOpRec->getValueAsDef("RegClass");
507fa27ce4SDimitry Andric 
517fa27ce4SDimitry Andric   if (ADI && ADI->getDef()->isSubClassOf("RegisterOperand"))
527fa27ce4SDimitry Andric     ADI = ADI->getDef()->getValueAsDef("RegClass")->getDefInit();
537fa27ce4SDimitry Andric 
547fa27ce4SDimitry Andric   if (ADI && ADI->getDef()->isSubClassOf("RegisterClass")) {
557fa27ce4SDimitry Andric     if (!InstOpRec->isSubClassOf("RegisterClass"))
567fa27ce4SDimitry Andric       return false;
577fa27ce4SDimitry Andric     if (!T.getRegisterClass(InstOpRec).hasSubClass(
587fa27ce4SDimitry Andric             &T.getRegisterClass(ADI->getDef())))
597fa27ce4SDimitry Andric       return false;
607fa27ce4SDimitry Andric     ResOp = ResultOperand(std::string(Result->getArgNameStr(AliasOpNo)),
617fa27ce4SDimitry Andric                           ResultRecord);
627fa27ce4SDimitry Andric     return true;
637fa27ce4SDimitry Andric   }
647fa27ce4SDimitry Andric 
657fa27ce4SDimitry Andric   // Handle explicit registers.
667fa27ce4SDimitry Andric   if (ADI && ADI->getDef()->isSubClassOf("Register")) {
677fa27ce4SDimitry Andric     if (InstOpRec->isSubClassOf("OptionalDefOperand")) {
687fa27ce4SDimitry Andric       DagInit *DI = InstOpRec->getValueAsDag("MIOperandInfo");
697fa27ce4SDimitry Andric       // The operand info should only have a single (register) entry. We
707fa27ce4SDimitry Andric       // want the register class of it.
717fa27ce4SDimitry Andric       InstOpRec = cast<DefInit>(DI->getArg(0))->getDef();
727fa27ce4SDimitry Andric     }
737fa27ce4SDimitry Andric 
747fa27ce4SDimitry Andric     if (!InstOpRec->isSubClassOf("RegisterClass"))
757fa27ce4SDimitry Andric       return false;
767fa27ce4SDimitry Andric 
777fa27ce4SDimitry Andric     if (!T.getRegisterClass(InstOpRec).contains(
787fa27ce4SDimitry Andric             T.getRegBank().getReg(ADI->getDef())))
797fa27ce4SDimitry Andric       PrintFatalError(Loc, "fixed register " + ADI->getDef()->getName() +
807fa27ce4SDimitry Andric                                " is not a member of the " +
817fa27ce4SDimitry Andric                                InstOpRec->getName() + " register class!");
827fa27ce4SDimitry Andric 
837fa27ce4SDimitry Andric     if (Result->getArgName(AliasOpNo))
847fa27ce4SDimitry Andric       PrintFatalError(Loc, "result fixed register argument must "
857fa27ce4SDimitry Andric                            "not have a name!");
867fa27ce4SDimitry Andric 
877fa27ce4SDimitry Andric     ResOp = ResultOperand(ResultRecord);
887fa27ce4SDimitry Andric     return true;
897fa27ce4SDimitry Andric   }
907fa27ce4SDimitry Andric 
917fa27ce4SDimitry Andric   // Handle "zero_reg" for optional def operands.
927fa27ce4SDimitry Andric   if (ADI && ADI->getDef()->getName() == "zero_reg") {
937fa27ce4SDimitry Andric 
947fa27ce4SDimitry Andric     // Check if this is an optional def.
957fa27ce4SDimitry Andric     // Tied operands where the source is a sub-operand of a complex operand
967fa27ce4SDimitry Andric     // need to represent both operands in the alias destination instruction.
977fa27ce4SDimitry Andric     // Allow zero_reg for the tied portion. This can and should go away once
987fa27ce4SDimitry Andric     // the MC representation of things doesn't use tied operands at all.
997fa27ce4SDimitry Andric     // if (!InstOpRec->isSubClassOf("OptionalDefOperand"))
1007fa27ce4SDimitry Andric     //  throw TGError(Loc, "reg0 used for result that is not an "
1017fa27ce4SDimitry Andric     //                "OptionalDefOperand!");
1027fa27ce4SDimitry Andric 
1037fa27ce4SDimitry Andric     ResOp = ResultOperand(static_cast<Record *>(nullptr));
1047fa27ce4SDimitry Andric     return true;
1057fa27ce4SDimitry Andric   }
1067fa27ce4SDimitry Andric 
1077fa27ce4SDimitry Andric   // Literal integers.
1087fa27ce4SDimitry Andric   if (IntInit *II = dyn_cast<IntInit>(Arg)) {
1097fa27ce4SDimitry Andric     if (hasSubOps || !InstOpRec->isSubClassOf("Operand"))
1107fa27ce4SDimitry Andric       return false;
1117fa27ce4SDimitry Andric     // Integer arguments can't have names.
1127fa27ce4SDimitry Andric     if (Result->getArgName(AliasOpNo))
1137fa27ce4SDimitry Andric       PrintFatalError(Loc, "result argument #" + Twine(AliasOpNo) +
1147fa27ce4SDimitry Andric                                " must not have a name!");
1157fa27ce4SDimitry Andric     ResOp = ResultOperand(II->getValue());
1167fa27ce4SDimitry Andric     return true;
1177fa27ce4SDimitry Andric   }
1187fa27ce4SDimitry Andric 
1197fa27ce4SDimitry Andric   // Bits<n> (also used for 0bxx literals)
1207fa27ce4SDimitry Andric   if (BitsInit *BI = dyn_cast<BitsInit>(Arg)) {
1217fa27ce4SDimitry Andric     if (hasSubOps || !InstOpRec->isSubClassOf("Operand"))
1227fa27ce4SDimitry Andric       return false;
1237fa27ce4SDimitry Andric     if (!BI->isComplete())
1247fa27ce4SDimitry Andric       return false;
1257fa27ce4SDimitry Andric     // Convert the bits init to an integer and use that for the result.
1267fa27ce4SDimitry Andric     IntInit *II = dyn_cast_or_null<IntInit>(
1277fa27ce4SDimitry Andric         BI->convertInitializerTo(IntRecTy::get(BI->getRecordKeeper())));
1287fa27ce4SDimitry Andric     if (!II)
1297fa27ce4SDimitry Andric       return false;
1307fa27ce4SDimitry Andric     ResOp = ResultOperand(II->getValue());
1317fa27ce4SDimitry Andric     return true;
1327fa27ce4SDimitry Andric   }
1337fa27ce4SDimitry Andric 
1347fa27ce4SDimitry Andric   // If both are Operands with the same MVT, allow the conversion. It's
1357fa27ce4SDimitry Andric   // up to the user to make sure the values are appropriate, just like
1367fa27ce4SDimitry Andric   // for isel Pat's.
1377fa27ce4SDimitry Andric   if (InstOpRec->isSubClassOf("Operand") && ADI &&
1387fa27ce4SDimitry Andric       ADI->getDef()->isSubClassOf("Operand")) {
1397fa27ce4SDimitry Andric     // FIXME: What other attributes should we check here? Identical
1407fa27ce4SDimitry Andric     // MIOperandInfo perhaps?
1417fa27ce4SDimitry Andric     if (InstOpRec->getValueInit("Type") != ADI->getDef()->getValueInit("Type"))
1427fa27ce4SDimitry Andric       return false;
1437fa27ce4SDimitry Andric     ResOp = ResultOperand(std::string(Result->getArgNameStr(AliasOpNo)),
1447fa27ce4SDimitry Andric                           ADI->getDef());
1457fa27ce4SDimitry Andric     return true;
1467fa27ce4SDimitry Andric   }
1477fa27ce4SDimitry Andric 
1487fa27ce4SDimitry Andric   return false;
1497fa27ce4SDimitry Andric }
1507fa27ce4SDimitry Andric 
getMINumOperands() const1517fa27ce4SDimitry Andric unsigned CodeGenInstAlias::ResultOperand::getMINumOperands() const {
1527fa27ce4SDimitry Andric   if (!isRecord())
1537fa27ce4SDimitry Andric     return 1;
1547fa27ce4SDimitry Andric 
1557fa27ce4SDimitry Andric   Record *Rec = getRecord();
1567fa27ce4SDimitry Andric   if (!Rec->isSubClassOf("Operand"))
1577fa27ce4SDimitry Andric     return 1;
1587fa27ce4SDimitry Andric 
1597fa27ce4SDimitry Andric   DagInit *MIOpInfo = Rec->getValueAsDag("MIOperandInfo");
1607fa27ce4SDimitry Andric   if (MIOpInfo->getNumArgs() == 0) {
1617fa27ce4SDimitry Andric     // Unspecified, so it defaults to 1
1627fa27ce4SDimitry Andric     return 1;
1637fa27ce4SDimitry Andric   }
1647fa27ce4SDimitry Andric 
1657fa27ce4SDimitry Andric   return MIOpInfo->getNumArgs();
1667fa27ce4SDimitry Andric }
1677fa27ce4SDimitry Andric 
CodeGenInstAlias(Record * R,CodeGenTarget & T)1687fa27ce4SDimitry Andric CodeGenInstAlias::CodeGenInstAlias(Record *R, CodeGenTarget &T) : TheDef(R) {
1697fa27ce4SDimitry Andric   Result = R->getValueAsDag("ResultInst");
1707fa27ce4SDimitry Andric   AsmString = std::string(R->getValueAsString("AsmString"));
1717fa27ce4SDimitry Andric 
1727fa27ce4SDimitry Andric   // Verify that the root of the result is an instruction.
1737fa27ce4SDimitry Andric   DefInit *DI = dyn_cast<DefInit>(Result->getOperator());
1747fa27ce4SDimitry Andric   if (!DI || !DI->getDef()->isSubClassOf("Instruction"))
1757fa27ce4SDimitry Andric     PrintFatalError(R->getLoc(),
1767fa27ce4SDimitry Andric                     "result of inst alias should be an instruction");
1777fa27ce4SDimitry Andric 
1787fa27ce4SDimitry Andric   ResultInst = &T.getInstruction(DI->getDef());
1797fa27ce4SDimitry Andric 
1807fa27ce4SDimitry Andric   // NameClass - If argument names are repeated, we need to verify they have
1817fa27ce4SDimitry Andric   // the same class.
1827fa27ce4SDimitry Andric   StringMap<Record *> NameClass;
1837fa27ce4SDimitry Andric   for (unsigned i = 0, e = Result->getNumArgs(); i != e; ++i) {
1847fa27ce4SDimitry Andric     DefInit *ADI = dyn_cast<DefInit>(Result->getArg(i));
1857fa27ce4SDimitry Andric     if (!ADI || !Result->getArgName(i))
1867fa27ce4SDimitry Andric       continue;
1877fa27ce4SDimitry Andric     // Verify we don't have something like: (someinst GR16:$foo, GR32:$foo)
1887fa27ce4SDimitry Andric     // $foo can exist multiple times in the result list, but it must have the
1897fa27ce4SDimitry Andric     // same type.
1907fa27ce4SDimitry Andric     Record *&Entry = NameClass[Result->getArgNameStr(i)];
1917fa27ce4SDimitry Andric     if (Entry && Entry != ADI->getDef())
1927fa27ce4SDimitry Andric       PrintFatalError(R->getLoc(), "result value $" + Result->getArgNameStr(i) +
1937fa27ce4SDimitry Andric                                        " is both " + Entry->getName() +
1947fa27ce4SDimitry Andric                                        " and " + ADI->getDef()->getName() +
1957fa27ce4SDimitry Andric                                        "!");
1967fa27ce4SDimitry Andric     Entry = ADI->getDef();
1977fa27ce4SDimitry Andric   }
1987fa27ce4SDimitry Andric 
1997fa27ce4SDimitry Andric   // Decode and validate the arguments of the result.
2007fa27ce4SDimitry Andric   unsigned AliasOpNo = 0;
2017fa27ce4SDimitry Andric   for (unsigned i = 0, e = ResultInst->Operands.size(); i != e; ++i) {
2027fa27ce4SDimitry Andric 
2037fa27ce4SDimitry Andric     // Tied registers don't have an entry in the result dag unless they're part
2047fa27ce4SDimitry Andric     // of a complex operand, in which case we include them anyways, as we
2057fa27ce4SDimitry Andric     // don't have any other way to specify the whole operand.
2067fa27ce4SDimitry Andric     if (ResultInst->Operands[i].MINumOperands == 1 &&
2077fa27ce4SDimitry Andric         ResultInst->Operands[i].getTiedRegister() != -1) {
2087fa27ce4SDimitry Andric       // Tied operands of different RegisterClass should be explicit within an
2097fa27ce4SDimitry Andric       // instruction's syntax and so cannot be skipped.
2107fa27ce4SDimitry Andric       int TiedOpNum = ResultInst->Operands[i].getTiedRegister();
2117fa27ce4SDimitry Andric       if (ResultInst->Operands[i].Rec->getName() ==
2127fa27ce4SDimitry Andric           ResultInst->Operands[TiedOpNum].Rec->getName())
2137fa27ce4SDimitry Andric         continue;
2147fa27ce4SDimitry Andric     }
2157fa27ce4SDimitry Andric 
2167fa27ce4SDimitry Andric     if (AliasOpNo >= Result->getNumArgs())
2177fa27ce4SDimitry Andric       PrintFatalError(R->getLoc(), "not enough arguments for instruction!");
2187fa27ce4SDimitry Andric 
2197fa27ce4SDimitry Andric     Record *InstOpRec = ResultInst->Operands[i].Rec;
2207fa27ce4SDimitry Andric     unsigned NumSubOps = ResultInst->Operands[i].MINumOperands;
2217fa27ce4SDimitry Andric     ResultOperand ResOp(static_cast<int64_t>(0));
2227fa27ce4SDimitry Andric     if (tryAliasOpMatch(Result, AliasOpNo, InstOpRec, (NumSubOps > 1),
2237fa27ce4SDimitry Andric                         R->getLoc(), T, ResOp)) {
2247fa27ce4SDimitry Andric       // If this is a simple operand, or a complex operand with a custom match
2257fa27ce4SDimitry Andric       // class, then we can match is verbatim.
2267fa27ce4SDimitry Andric       if (NumSubOps == 1 || (InstOpRec->getValue("ParserMatchClass") &&
2277fa27ce4SDimitry Andric                              InstOpRec->getValueAsDef("ParserMatchClass")
2287fa27ce4SDimitry Andric                                      ->getValueAsString("Name") != "Imm")) {
2297fa27ce4SDimitry Andric         ResultOperands.push_back(ResOp);
230ac9a064cSDimitry Andric         ResultInstOperandIndex.push_back(std::pair(i, -1));
2317fa27ce4SDimitry Andric         ++AliasOpNo;
2327fa27ce4SDimitry Andric 
2337fa27ce4SDimitry Andric         // Otherwise, we need to match each of the suboperands individually.
2347fa27ce4SDimitry Andric       } else {
2357fa27ce4SDimitry Andric         DagInit *MIOI = ResultInst->Operands[i].MIOperandInfo;
2367fa27ce4SDimitry Andric         for (unsigned SubOp = 0; SubOp != NumSubOps; ++SubOp) {
2377fa27ce4SDimitry Andric           Record *SubRec = cast<DefInit>(MIOI->getArg(SubOp))->getDef();
2387fa27ce4SDimitry Andric 
2397fa27ce4SDimitry Andric           // Take care to instantiate each of the suboperands with the correct
2407fa27ce4SDimitry Andric           // nomenclature: $foo.bar
2417fa27ce4SDimitry Andric           ResultOperands.emplace_back(
2427fa27ce4SDimitry Andric               Result->getArgName(AliasOpNo)->getAsUnquotedString() + "." +
2437fa27ce4SDimitry Andric                   MIOI->getArgName(SubOp)->getAsUnquotedString(),
2447fa27ce4SDimitry Andric               SubRec);
245ac9a064cSDimitry Andric           ResultInstOperandIndex.push_back(std::pair(i, SubOp));
2467fa27ce4SDimitry Andric         }
2477fa27ce4SDimitry Andric         ++AliasOpNo;
2487fa27ce4SDimitry Andric       }
2497fa27ce4SDimitry Andric       continue;
2507fa27ce4SDimitry Andric     }
2517fa27ce4SDimitry Andric 
2527fa27ce4SDimitry Andric     // If the argument did not match the instruction operand, and the operand
2537fa27ce4SDimitry Andric     // is composed of multiple suboperands, try matching the suboperands.
2547fa27ce4SDimitry Andric     if (NumSubOps > 1) {
2557fa27ce4SDimitry Andric       DagInit *MIOI = ResultInst->Operands[i].MIOperandInfo;
2567fa27ce4SDimitry Andric       for (unsigned SubOp = 0; SubOp != NumSubOps; ++SubOp) {
2577fa27ce4SDimitry Andric         if (AliasOpNo >= Result->getNumArgs())
2587fa27ce4SDimitry Andric           PrintFatalError(R->getLoc(), "not enough arguments for instruction!");
2597fa27ce4SDimitry Andric         Record *SubRec = cast<DefInit>(MIOI->getArg(SubOp))->getDef();
2607fa27ce4SDimitry Andric         if (tryAliasOpMatch(Result, AliasOpNo, SubRec, false, R->getLoc(), T,
2617fa27ce4SDimitry Andric                             ResOp)) {
2627fa27ce4SDimitry Andric           ResultOperands.push_back(ResOp);
263ac9a064cSDimitry Andric           ResultInstOperandIndex.push_back(std::pair(i, SubOp));
2647fa27ce4SDimitry Andric           ++AliasOpNo;
2657fa27ce4SDimitry Andric         } else {
2667fa27ce4SDimitry Andric           PrintFatalError(
2677fa27ce4SDimitry Andric               R->getLoc(),
2687fa27ce4SDimitry Andric               "result argument #" + Twine(AliasOpNo) +
2697fa27ce4SDimitry Andric                   " does not match instruction operand class " +
2707fa27ce4SDimitry Andric                   (SubOp == 0 ? InstOpRec->getName() : SubRec->getName()));
2717fa27ce4SDimitry Andric         }
2727fa27ce4SDimitry Andric       }
2737fa27ce4SDimitry Andric       continue;
2747fa27ce4SDimitry Andric     }
2757fa27ce4SDimitry Andric     PrintFatalError(R->getLoc(),
2767fa27ce4SDimitry Andric                     "result argument #" + Twine(AliasOpNo) +
2777fa27ce4SDimitry Andric                         " does not match instruction operand class " +
2787fa27ce4SDimitry Andric                         InstOpRec->getName());
2797fa27ce4SDimitry Andric   }
2807fa27ce4SDimitry Andric 
2817fa27ce4SDimitry Andric   if (AliasOpNo != Result->getNumArgs())
2827fa27ce4SDimitry Andric     PrintFatalError(R->getLoc(), "too many operands for instruction!");
2837fa27ce4SDimitry Andric }
284