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