I was hitting this error and the error location was pointing to the register class definition instead of the incorrect InstAlias. Pass in the InstAlias location to make it easier to debug. Happens with `def : InstAlias<"foo", (Inst X0)>`, where `Inst` takes a RegClassByHwMode operand that is not necessarily satisfied by register X0. Similar problem with the CompressPat backend. Reviewed By: arsenm Pull Request: https://github.com/llvm/llvm-project/pull/170790
240 lines
9.9 KiB
C++
240 lines
9.9 KiB
C++
//===- 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<ResultOperand>
|
|
matchSimpleOperand(const Init *Arg, const StringInit *ArgName, const Record *Op,
|
|
const CodeGenTarget &T, ArrayRef<SMLoc> Loc) {
|
|
if (const Record *OpRC = T.getAsRegClassLike(Op)) {
|
|
if (const auto *ArgDef = dyn_cast<DefInit>(Arg)) {
|
|
const Record *ArgRec = ArgDef->getDef();
|
|
|
|
// Match 'RegClass:$name' or 'RegOp:$name'.
|
|
if (const Record *ArgRC = T.getInitValueAsRegClassLike(Arg)) {
|
|
if (ArgRC->isSubClassOf("RegisterClass")) {
|
|
if (!OpRC->isSubClassOf("RegisterClass") ||
|
|
!T.getRegisterClass(OpRC, Loc).hasSubClass(
|
|
&T.getRegisterClass(ArgRC, Loc)))
|
|
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, Loc).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<IntInit>(
|
|
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<DefInit>(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' but got " +
|
|
Op->getName() + " instead");
|
|
}
|
|
|
|
static Expected<ResultOperand> matchComplexOperand(const Init *Arg,
|
|
const StringInit *ArgName,
|
|
const Record *Op) {
|
|
assert(Op->isSubClassOf("Operand"));
|
|
const auto *ArgDef = dyn_cast<DefInit>(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<DefInit>(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<const Record *> NameClass;
|
|
for (unsigned i = 0, e = Result->getNumArgs(); i != e; ++i) {
|
|
const DefInit *ADI = dyn_cast<DefInit>(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<DagInit>(Result->getArg(ArgIdx))) {
|
|
// The argument is a DAG. The operator must be the name of the operand.
|
|
if (auto *Operator = dyn_cast<DefInit>(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<DefInit>(OpInfo.MIOperandInfo->getArg(SubOpIdx))->getDef();
|
|
Expected<ResultOperand> ResOpOrErr = matchSimpleOperand(
|
|
ArgDag->getArg(SubOpIdx), ArgDag->getArgName(SubOpIdx), SubOp, T,
|
|
R->getLoc());
|
|
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<ResultOperand> 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<ResultOperand> ResOpOrErr =
|
|
matchSimpleOperand(Result->getArg(ArgIdx), Result->getArgName(ArgIdx),
|
|
Op, T, R->getLoc());
|
|
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!");
|
|
}
|