//===- CodeGenInstAlias.cpp - CodeGen InstAlias Class Wrapper -------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file implements the CodeGenInstAlias class. // //===----------------------------------------------------------------------===// #include "CodeGenInstAlias.h" #include "CodeGenInstruction.h" #include "CodeGenRegisters.h" #include "CodeGenTarget.h" #include "llvm/ADT/StringMap.h" #include "llvm/Support/Error.h" #include "llvm/TableGen/Error.h" #include "llvm/TableGen/Record.h" using namespace llvm; unsigned CodeGenInstAlias::ResultOperand::getMINumOperands() const { if (!isRecord()) return 1; const Record *Rec = getRecord(); if (!Rec->isSubClassOf("Operand")) return 1; const DagInit *MIOpInfo = Rec->getValueAsDag("MIOperandInfo"); if (MIOpInfo->getNumArgs() == 0) { // Unspecified, so it defaults to 1 return 1; } return MIOpInfo->getNumArgs(); } using ResultOperand = CodeGenInstAlias::ResultOperand; static Expected matchSimpleOperand(const Init *Arg, const StringInit *ArgName, const Record *Op, const CodeGenTarget &T) { if (Op->isSubClassOf("RegisterClass") || Op->isSubClassOf("RegisterOperand")) { const Record *OpRC = Op->isSubClassOf("RegisterClass") ? Op : Op->getValueAsDef("RegClass"); if (const auto *ArgDef = dyn_cast(Arg)) { const Record *ArgRec = ArgDef->getDef(); // Match 'RegClass:$name' or 'RegOp:$name'. if (const Record *ArgRC = T.getInitValueAsRegClassLike(Arg)) { if (ArgRC->isSubClassOf("RegisterClass")) { if (!T.getRegisterClass(OpRC).hasSubClass(&T.getRegisterClass(ArgRC))) return createStringError( "argument register class" + ArgRC->getName() + " is not a subclass of operand register class " + OpRC->getName()); if (!ArgName) return createStringError( "register class argument must have a name"); } // TODO: Verify RegClassByHwMode usage return ResultOperand::createRecord(ArgName->getAsUnquotedString(), ArgRec); } // Match 'Reg'. if (ArgRec->isSubClassOf("Register")) { if (!T.getRegisterClass(OpRC).contains(T.getRegBank().getReg(ArgRec))) return createStringError( "register argument " + ArgRec->getName() + " is not a member of operand register class " + OpRC->getName()); if (ArgName) return createStringError("register argument must not have a name"); return ResultOperand::createRegister(ArgRec); } // Match 'zero_reg'. if (ArgRec->getName() == "zero_reg") { if (ArgName) return createStringError("register argument must not have a name"); return ResultOperand::createRegister(nullptr); } } return createStringError("argument must be a subclass of RegisterClass, " "RegisterOperand, or zero_reg"); } if (Op->isSubClassOf("Operand")) { // Match integer or bits. if (const auto *ArgInt = dyn_cast_or_null( Arg->convertInitializerTo(IntRecTy::get(Arg->getRecordKeeper())))) { if (ArgName) return createStringError("integer argument must not have a name"); return ResultOperand::createImmediate(ArgInt->getValue()); } // Match a subclass of Operand. if (const auto *ArgDef = dyn_cast(Arg); ArgDef && ArgDef->getDef()->isSubClassOf("Operand")) { if (!ArgName) return createStringError("argument must have a name"); return ResultOperand::createRecord(ArgName->getAsUnquotedString(), ArgDef->getDef()); } return createStringError("argument must be a subclass of Operand"); } llvm_unreachable("Unknown operand kind"); } static Expected matchComplexOperand(const Init *Arg, const StringInit *ArgName, const Record *Op) { assert(Op->isSubClassOf("Operand")); const auto *ArgDef = dyn_cast(Arg); if (!ArgDef || !ArgDef->getDef()->isSubClassOf("Operand")) return createStringError("argument must be a subclass of Operand"); if (!ArgName) return createStringError("argument must have a name"); return ResultOperand::createRecord(ArgName->getAsUnquotedString(), ArgDef->getDef()); } CodeGenInstAlias::CodeGenInstAlias(const Record *R, const CodeGenTarget &T) : TheDef(R) { Result = R->getValueAsDag("ResultInst"); AsmString = R->getValueAsString("AsmString"); // Verify that the root of the result is an instruction. const DefInit *DI = dyn_cast(Result->getOperator()); if (!DI || !DI->getDef()->isSubClassOf("Instruction")) PrintFatalError(R->getLoc(), "result of inst alias should be an instruction"); ResultInst = &T.getInstruction(DI->getDef()); // NameClass - If argument names are repeated, we need to verify they have // the same class. StringMap NameClass; for (unsigned i = 0, e = Result->getNumArgs(); i != e; ++i) { const DefInit *ADI = dyn_cast(Result->getArg(i)); if (!ADI || !Result->getArgName(i)) continue; // Verify we don't have something like: (someinst GR16:$foo, GR32:$foo) // $foo can exist multiple times in the result list, but it must have the // same type. const Record *&Entry = NameClass[Result->getArgNameStr(i)]; if (Entry && Entry != ADI->getDef()) PrintFatalError(R->getLoc(), "result value $" + Result->getArgNameStr(i) + " is both " + Entry->getName() + " and " + ADI->getDef()->getName() + "!"); Entry = ADI->getDef(); } // Decode and validate the arguments of the result. unsigned ArgIdx = 0; for (auto [OpIdx, OpInfo] : enumerate(ResultInst->Operands)) { // Tied registers don't have an entry in the result dag unless they're part // of a complex operand, in which case we include them anyways, as we // don't have any other way to specify the whole operand. if (OpInfo.MINumOperands == 1 && OpInfo.getTiedRegister() != -1) { // Tied operands of different RegisterClass should be explicit within an // instruction's syntax and so cannot be skipped. int TiedOpNum = OpInfo.getTiedRegister(); if (OpInfo.Rec->getName() == ResultInst->Operands[TiedOpNum].Rec->getName()) continue; } if (ArgIdx >= Result->getNumArgs()) PrintFatalError(R->getLoc(), "not enough arguments for instruction!"); const Record *Op = OpInfo.Rec; if (Op->isSubClassOf("Operand") && !OpInfo.MIOperandInfo->arg_empty()) { // Complex operand (a subclass of Operand with non-empty MIOperandInfo). // The argument can be a DAG or a subclass of Operand. if (auto *ArgDag = dyn_cast(Result->getArg(ArgIdx))) { // The argument is a DAG. The operator must be the name of the operand. if (auto *Operator = dyn_cast(ArgDag->getOperator()); !Operator || Operator->getDef()->getName() != Op->getName()) PrintFatalError(R, "argument #" + Twine(ArgIdx) + " operator must be " + Op->getName()); // The number of sub-arguments and the number of sub-operands // must match exactly. unsigned NumSubOps = OpInfo.MIOperandInfo->getNumArgs(); unsigned NumSubArgs = ArgDag->getNumArgs(); if (NumSubArgs != NumSubOps) PrintFatalError(R, "argument #" + Twine(ArgIdx) + " must have exactly " + Twine(NumSubOps) + " sub-arguments"); // Match sub-operands individually. for (unsigned SubOpIdx = 0; SubOpIdx != NumSubOps; ++SubOpIdx) { const Record *SubOp = cast(OpInfo.MIOperandInfo->getArg(SubOpIdx))->getDef(); Expected ResOpOrErr = matchSimpleOperand( ArgDag->getArg(SubOpIdx), ArgDag->getArgName(SubOpIdx), SubOp, T); if (!ResOpOrErr) PrintFatalError(R, "in argument #" + Twine(ArgIdx) + "." + Twine(SubOpIdx) + ": " + toString(ResOpOrErr.takeError())); ResultOperands.push_back(*ResOpOrErr); ResultInstOperandIndex.emplace_back(OpIdx, SubOpIdx); } } else { // Match complex operand as a whole. Expected ResOpOrErr = matchComplexOperand( Result->getArg(ArgIdx), Result->getArgName(ArgIdx), Op); if (!ResOpOrErr) PrintFatalError(R, "in argument #" + Twine(ArgIdx) + ": " + toString(ResOpOrErr.takeError())); ResultOperands.push_back(*ResOpOrErr); ResultInstOperandIndex.emplace_back(OpIdx, -1); } } else { // Simple operand (RegisterClass, RegisterOperand or Operand with empty // MIOperandInfo). Expected ResOpOrErr = matchSimpleOperand( Result->getArg(ArgIdx), Result->getArgName(ArgIdx), Op, T); if (!ResOpOrErr) PrintFatalError(R, "in argument #" + Twine(ArgIdx) + ": " + toString(ResOpOrErr.takeError())); ResultOperands.push_back(*ResOpOrErr); ResultInstOperandIndex.emplace_back(OpIdx, -1); } ArgIdx++; } if (ArgIdx != Result->getNumArgs()) PrintFatalError(R->getLoc(), "too many operands for instruction!"); }