2008-01-06 09:35:39 +08:00
|
|
|
//===- CodeGenInstruction.cpp - CodeGen Instruction Class Wrapper ---------===//
|
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// 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
|
2008-01-06 09:35:39 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file implements the CodeGenInstruction class.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "CodeGenInstruction.h"
|
2010-03-28 04:09:24 +08:00
|
|
|
#include "CodeGenTarget.h"
|
2012-12-04 18:37:14 +08:00
|
|
|
#include "llvm/ADT/STLExtras.h"
|
2008-01-06 09:35:39 +08:00
|
|
|
#include "llvm/ADT/StringExtras.h"
|
2010-11-06 15:06:09 +08:00
|
|
|
#include "llvm/ADT/StringMap.h"
|
2012-12-04 18:37:14 +08:00
|
|
|
#include "llvm/TableGen/Error.h"
|
|
|
|
#include "llvm/TableGen/Record.h"
|
2008-01-06 09:35:39 +08:00
|
|
|
#include <set>
|
|
|
|
using namespace llvm;
|
|
|
|
|
2010-11-01 12:03:32 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// CGIOperandList Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
2008-01-06 09:35:39 +08:00
|
|
|
|
2010-11-01 12:03:32 +08:00
|
|
|
CGIOperandList::CGIOperandList(Record *R) : TheDef(R) {
|
|
|
|
isPredicable = false;
|
2008-01-06 09:35:39 +08:00
|
|
|
hasOptionalDef = false;
|
2008-01-07 13:19:29 +08:00
|
|
|
isVariadic = false;
|
2011-01-26 10:03:37 +08:00
|
|
|
|
2011-07-30 06:43:06 +08:00
|
|
|
DagInit *OutDI = R->getValueAsDag("OutOperandList");
|
2011-01-26 10:03:37 +08:00
|
|
|
|
2012-10-11 04:24:43 +08:00
|
|
|
if (DefInit *Init = dyn_cast<DefInit>(OutDI->getOperator())) {
|
2010-03-19 04:56:35 +08:00
|
|
|
if (Init->getDef()->getName() != "outs")
|
2012-10-26 04:33:17 +08:00
|
|
|
PrintFatalError(R->getName() + ": invalid def name for output list: use 'outs'");
|
2010-03-19 04:50:52 +08:00
|
|
|
} else
|
2012-10-26 04:33:17 +08:00
|
|
|
PrintFatalError(R->getName() + ": invalid output list: use 'outs'");
|
2011-01-26 10:03:37 +08:00
|
|
|
|
2010-03-19 05:07:39 +08:00
|
|
|
NumDefs = OutDI->getNumArgs();
|
2010-11-01 12:03:32 +08:00
|
|
|
|
2011-07-30 06:43:06 +08:00
|
|
|
DagInit *InDI = R->getValueAsDag("InOperandList");
|
2012-10-11 04:24:43 +08:00
|
|
|
if (DefInit *Init = dyn_cast<DefInit>(InDI->getOperator())) {
|
2010-03-19 04:56:35 +08:00
|
|
|
if (Init->getDef()->getName() != "ins")
|
2012-10-26 04:33:17 +08:00
|
|
|
PrintFatalError(R->getName() + ": invalid def name for input list: use 'ins'");
|
2010-03-19 04:50:52 +08:00
|
|
|
} else
|
2012-10-26 04:33:17 +08:00
|
|
|
PrintFatalError(R->getName() + ": invalid input list: use 'ins'");
|
2011-01-26 10:03:37 +08:00
|
|
|
|
2008-01-06 09:35:39 +08:00
|
|
|
unsigned MIOperandNo = 0;
|
|
|
|
std::set<std::string> OperandNames;
|
2016-02-04 03:34:28 +08:00
|
|
|
unsigned e = InDI->getNumArgs() + OutDI->getNumArgs();
|
|
|
|
OperandList.reserve(e);
|
|
|
|
for (unsigned i = 0; i != e; ++i){
|
2011-07-30 06:43:06 +08:00
|
|
|
Init *ArgInit;
|
2016-12-05 14:00:46 +08:00
|
|
|
StringRef ArgName;
|
2010-03-19 05:07:39 +08:00
|
|
|
if (i < NumDefs) {
|
|
|
|
ArgInit = OutDI->getArg(i);
|
2016-12-05 14:00:46 +08:00
|
|
|
ArgName = OutDI->getArgNameStr(i);
|
2010-03-19 05:07:39 +08:00
|
|
|
} else {
|
|
|
|
ArgInit = InDI->getArg(i-NumDefs);
|
2016-12-05 14:00:46 +08:00
|
|
|
ArgName = InDI->getArgNameStr(i-NumDefs);
|
2010-03-19 05:07:39 +08:00
|
|
|
}
|
2011-01-26 10:03:37 +08:00
|
|
|
|
2012-10-11 04:24:43 +08:00
|
|
|
DefInit *Arg = dyn_cast<DefInit>(ArgInit);
|
2008-01-06 09:35:39 +08:00
|
|
|
if (!Arg)
|
2012-10-26 04:33:17 +08:00
|
|
|
PrintFatalError("Illegal operand for the '" + R->getName() + "' instruction!");
|
2011-01-26 10:03:37 +08:00
|
|
|
|
2008-01-06 09:35:39 +08:00
|
|
|
Record *Rec = Arg->getDef();
|
|
|
|
std::string PrintMethod = "printOperand";
|
2010-10-13 06:21:57 +08:00
|
|
|
std::string EncoderMethod;
|
2011-07-15 05:47:18 +08:00
|
|
|
std::string OperandType = "OPERAND_UNKNOWN";
|
2015-01-13 03:33:09 +08:00
|
|
|
std::string OperandNamespace = "MCOI";
|
2008-01-06 09:35:39 +08:00
|
|
|
unsigned NumOps = 1;
|
2014-04-15 15:20:03 +08:00
|
|
|
DagInit *MIOpInfo = nullptr;
|
2011-06-28 05:06:21 +08:00
|
|
|
if (Rec->isSubClassOf("RegisterOperand")) {
|
|
|
|
PrintMethod = Rec->getValueAsString("PrintMethod");
|
2015-01-13 03:33:09 +08:00
|
|
|
OperandType = Rec->getValueAsString("OperandType");
|
|
|
|
OperandNamespace = Rec->getValueAsString("OperandNamespace");
|
2017-05-15 18:13:07 +08:00
|
|
|
EncoderMethod = Rec->getValueAsString("EncoderMethod");
|
2011-06-28 05:06:21 +08:00
|
|
|
} else if (Rec->isSubClassOf("Operand")) {
|
2008-01-06 09:35:39 +08:00
|
|
|
PrintMethod = Rec->getValueAsString("PrintMethod");
|
2011-07-15 05:47:18 +08:00
|
|
|
OperandType = Rec->getValueAsString("OperandType");
|
2015-12-23 07:37:37 +08:00
|
|
|
OperandNamespace = Rec->getValueAsString("OperandNamespace");
|
2010-10-13 06:21:57 +08:00
|
|
|
// If there is an explicit encoder method, use it.
|
2010-11-15 13:19:05 +08:00
|
|
|
EncoderMethod = Rec->getValueAsString("EncoderMethod");
|
2008-01-06 09:35:39 +08:00
|
|
|
MIOpInfo = Rec->getValueAsDag("MIOperandInfo");
|
2011-01-26 10:03:37 +08:00
|
|
|
|
2008-01-06 09:35:39 +08:00
|
|
|
// Verify that MIOpInfo has an 'ops' root value.
|
2012-10-11 04:24:47 +08:00
|
|
|
if (!isa<DefInit>(MIOpInfo->getOperator()) ||
|
|
|
|
cast<DefInit>(MIOpInfo->getOperator())->getDef()->getName() != "ops")
|
2012-10-26 04:33:17 +08:00
|
|
|
PrintFatalError("Bad value for MIOperandInfo in operand '" + Rec->getName() +
|
|
|
|
"'\n");
|
2011-01-26 10:03:37 +08:00
|
|
|
|
2008-01-06 09:35:39 +08:00
|
|
|
// If we have MIOpInfo, then we have #operands equal to number of entries
|
|
|
|
// in MIOperandInfo.
|
|
|
|
if (unsigned NumArgs = MIOpInfo->getNumArgs())
|
|
|
|
NumOps = NumArgs;
|
2011-01-26 10:03:37 +08:00
|
|
|
|
2013-08-22 17:57:11 +08:00
|
|
|
if (Rec->isSubClassOf("PredicateOp"))
|
2008-01-06 09:35:39 +08:00
|
|
|
isPredicable = true;
|
|
|
|
else if (Rec->isSubClassOf("OptionalDefOperand"))
|
|
|
|
hasOptionalDef = true;
|
|
|
|
} else if (Rec->getName() == "variable_ops") {
|
2008-01-07 13:19:29 +08:00
|
|
|
isVariadic = true;
|
2008-01-06 09:35:39 +08:00
|
|
|
continue;
|
2011-07-15 05:47:18 +08:00
|
|
|
} else if (Rec->isSubClassOf("RegisterClass")) {
|
|
|
|
OperandType = "OPERAND_REGISTER";
|
|
|
|
} else if (!Rec->isSubClassOf("PointerLikeRegClass") &&
|
2012-09-12 07:47:08 +08:00
|
|
|
!Rec->isSubClassOf("unknown_class"))
|
2012-10-26 04:33:17 +08:00
|
|
|
PrintFatalError("Unknown operand class '" + Rec->getName() +
|
|
|
|
"' in '" + R->getName() + "' instruction!");
|
2011-01-26 10:03:37 +08:00
|
|
|
|
2008-01-06 09:35:39 +08:00
|
|
|
// Check that the operand has a name and that it's unique.
|
2010-03-19 05:07:39 +08:00
|
|
|
if (ArgName.empty())
|
2014-03-30 01:17:15 +08:00
|
|
|
PrintFatalError("In instruction '" + R->getName() + "', operand #" +
|
|
|
|
Twine(i) + " has no name!");
|
2010-03-19 05:07:39 +08:00
|
|
|
if (!OperandNames.insert(ArgName).second)
|
2014-03-30 01:17:15 +08:00
|
|
|
PrintFatalError("In instruction '" + R->getName() + "', operand #" +
|
|
|
|
Twine(i) + " has the same name as a previous operand!");
|
2011-01-26 10:03:37 +08:00
|
|
|
|
2015-05-30 03:43:39 +08:00
|
|
|
OperandList.emplace_back(Rec, ArgName, PrintMethod, EncoderMethod,
|
|
|
|
OperandNamespace + "::" + OperandType, MIOperandNo,
|
|
|
|
NumOps, MIOpInfo);
|
2008-01-06 09:35:39 +08:00
|
|
|
MIOperandNo += NumOps;
|
|
|
|
}
|
2011-01-26 10:03:37 +08:00
|
|
|
|
|
|
|
|
2010-11-01 13:34:34 +08:00
|
|
|
// Make sure the constraints list for each operand is large enough to hold
|
|
|
|
// constraint info, even if none is present.
|
2017-10-06 17:32:45 +08:00
|
|
|
for (OperandInfo &OpInfo : OperandList)
|
|
|
|
OpInfo.Constraints.resize(OpInfo.MINumOperands);
|
2008-01-06 09:35:39 +08:00
|
|
|
}
|
|
|
|
|
2010-11-01 12:03:32 +08:00
|
|
|
|
2008-01-06 09:35:39 +08:00
|
|
|
/// getOperandNamed - Return the index of the operand with the specified
|
|
|
|
/// non-empty name. If the instruction does not have an operand with the
|
2012-10-26 04:33:17 +08:00
|
|
|
/// specified name, abort.
|
2008-01-06 09:35:39 +08:00
|
|
|
///
|
2010-11-01 12:03:32 +08:00
|
|
|
unsigned CGIOperandList::getOperandNamed(StringRef Name) const {
|
2010-10-12 02:25:51 +08:00
|
|
|
unsigned OpIdx;
|
|
|
|
if (hasOperandNamed(Name, OpIdx)) return OpIdx;
|
2014-03-30 01:17:15 +08:00
|
|
|
PrintFatalError("'" + TheDef->getName() +
|
|
|
|
"' does not have an operand named '$" + Name + "'!");
|
2008-01-06 09:35:39 +08:00
|
|
|
}
|
|
|
|
|
2010-10-12 02:25:51 +08:00
|
|
|
/// hasOperandNamed - Query whether the instruction has an operand of the
|
|
|
|
/// given name. If so, return true and set OpIdx to the index of the
|
|
|
|
/// operand. Otherwise, return false.
|
2010-11-01 12:03:32 +08:00
|
|
|
bool CGIOperandList::hasOperandNamed(StringRef Name, unsigned &OpIdx) const {
|
2010-10-12 02:25:51 +08:00
|
|
|
assert(!Name.empty() && "Cannot search for operand with no name!");
|
|
|
|
for (unsigned i = 0, e = OperandList.size(); i != e; ++i)
|
|
|
|
if (OperandList[i].Name == Name) {
|
|
|
|
OpIdx = i;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2009-12-16 03:28:13 +08:00
|
|
|
std::pair<unsigned,unsigned>
|
2010-11-01 12:03:32 +08:00
|
|
|
CGIOperandList::ParseOperandName(const std::string &Op, bool AllowWholeOp) {
|
2008-01-06 09:35:39 +08:00
|
|
|
if (Op.empty() || Op[0] != '$')
|
2012-10-26 04:33:17 +08:00
|
|
|
PrintFatalError(TheDef->getName() + ": Illegal operand name: '" + Op + "'");
|
2011-01-26 10:03:37 +08:00
|
|
|
|
2008-01-06 09:35:39 +08:00
|
|
|
std::string OpName = Op.substr(1);
|
|
|
|
std::string SubOpName;
|
2011-01-26 10:03:37 +08:00
|
|
|
|
2008-01-06 09:35:39 +08:00
|
|
|
// Check to see if this is $foo.bar.
|
2016-11-30 18:01:11 +08:00
|
|
|
std::string::size_type DotIdx = OpName.find_first_of('.');
|
2008-01-06 09:35:39 +08:00
|
|
|
if (DotIdx != std::string::npos) {
|
|
|
|
SubOpName = OpName.substr(DotIdx+1);
|
|
|
|
if (SubOpName.empty())
|
2012-10-26 04:33:17 +08:00
|
|
|
PrintFatalError(TheDef->getName() + ": illegal empty suboperand name in '" +Op +"'");
|
2008-01-06 09:35:39 +08:00
|
|
|
OpName = OpName.substr(0, DotIdx);
|
|
|
|
}
|
2011-01-26 10:03:37 +08:00
|
|
|
|
2008-01-06 09:35:39 +08:00
|
|
|
unsigned OpIdx = getOperandNamed(OpName);
|
2011-01-26 10:03:37 +08:00
|
|
|
|
2008-01-06 09:35:39 +08:00
|
|
|
if (SubOpName.empty()) { // If no suboperand name was specified:
|
|
|
|
// If one was needed, throw.
|
|
|
|
if (OperandList[OpIdx].MINumOperands > 1 && !AllowWholeOp &&
|
|
|
|
SubOpName.empty())
|
2012-10-26 04:33:17 +08:00
|
|
|
PrintFatalError(TheDef->getName() + ": Illegal to refer to"
|
|
|
|
" whole operand part of complex operand '" + Op + "'");
|
2011-01-26 10:03:37 +08:00
|
|
|
|
2008-01-06 09:35:39 +08:00
|
|
|
// Otherwise, return the operand.
|
|
|
|
return std::make_pair(OpIdx, 0U);
|
|
|
|
}
|
2011-01-26 10:03:37 +08:00
|
|
|
|
2008-01-06 09:35:39 +08:00
|
|
|
// Find the suboperand number involved.
|
2011-07-30 06:43:06 +08:00
|
|
|
DagInit *MIOpInfo = OperandList[OpIdx].MIOperandInfo;
|
2014-04-15 15:20:03 +08:00
|
|
|
if (!MIOpInfo)
|
2012-10-26 04:33:17 +08:00
|
|
|
PrintFatalError(TheDef->getName() + ": unknown suboperand name in '" + Op + "'");
|
2011-01-26 10:03:37 +08:00
|
|
|
|
2008-01-06 09:35:39 +08:00
|
|
|
// Find the operand with the right name.
|
|
|
|
for (unsigned i = 0, e = MIOpInfo->getNumArgs(); i != e; ++i)
|
2016-12-05 14:00:46 +08:00
|
|
|
if (MIOpInfo->getArgNameStr(i) == SubOpName)
|
2008-01-06 09:35:39 +08:00
|
|
|
return std::make_pair(OpIdx, i);
|
2011-01-26 10:03:37 +08:00
|
|
|
|
2008-01-06 09:35:39 +08:00
|
|
|
// Otherwise, didn't find it!
|
2012-10-26 04:33:17 +08:00
|
|
|
PrintFatalError(TheDef->getName() + ": unknown suboperand name in '" + Op + "'");
|
2013-08-16 09:43:31 +08:00
|
|
|
return std::make_pair(0U, 0U);
|
2008-01-06 09:35:39 +08:00
|
|
|
}
|
2010-03-28 04:09:24 +08:00
|
|
|
|
[TableGen] Better error checking for TIED_TO constraints.
There are quite strong constraints on how you can use the TIED_TO
constraint between MC operands, many of which are currently not
checked until compiler run time.
MachineVerifier enforces that operands can only be tied together in
pairs (no three-way ties), and MachineInstr::tieOperands enforces that
one of the tied operands must be an output operand (def) and the other
must be an input operand (use).
Now we check these at TableGen time, so that if you violate any of
them in a new instruction definition, you find out immediately,
instead of having to wait until you compile something that makes code
generation hit one of those assertions.
Also in this commit, all the error reports in ParseConstraint now
include the name and source location of the def where the problem
happened, so that if you do trigger any of these errors, it's easier
to find the part of your TableGen input where you made the mistake.
The trunk sources already build successfully with this additional
error check, so I think no in-tree target has any of these problems.
Reviewers: fhahn, lhames, nhaehnle, MatzeB
Reviewed By: MatzeB
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D53815
llvm-svn: 347743
2018-11-28 19:43:49 +08:00
|
|
|
static void ParseConstraint(const std::string &CStr, CGIOperandList &Ops,
|
|
|
|
Record *Rec) {
|
2010-11-01 12:03:32 +08:00
|
|
|
// EARLY_CLOBBER: @early $reg
|
|
|
|
std::string::size_type wpos = CStr.find_first_of(" \t");
|
|
|
|
std::string::size_type start = CStr.find_first_not_of(" \t");
|
|
|
|
std::string Tok = CStr.substr(start, wpos - start);
|
|
|
|
if (Tok == "@earlyclobber") {
|
|
|
|
std::string Name = CStr.substr(wpos+1);
|
|
|
|
wpos = Name.find_first_not_of(" \t");
|
|
|
|
if (wpos == std::string::npos)
|
[TableGen] Better error checking for TIED_TO constraints.
There are quite strong constraints on how you can use the TIED_TO
constraint between MC operands, many of which are currently not
checked until compiler run time.
MachineVerifier enforces that operands can only be tied together in
pairs (no three-way ties), and MachineInstr::tieOperands enforces that
one of the tied operands must be an output operand (def) and the other
must be an input operand (use).
Now we check these at TableGen time, so that if you violate any of
them in a new instruction definition, you find out immediately,
instead of having to wait until you compile something that makes code
generation hit one of those assertions.
Also in this commit, all the error reports in ParseConstraint now
include the name and source location of the def where the problem
happened, so that if you do trigger any of these errors, it's easier
to find the part of your TableGen input where you made the mistake.
The trunk sources already build successfully with this additional
error check, so I think no in-tree target has any of these problems.
Reviewers: fhahn, lhames, nhaehnle, MatzeB
Reviewed By: MatzeB
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D53815
llvm-svn: 347743
2018-11-28 19:43:49 +08:00
|
|
|
PrintFatalError(
|
|
|
|
Rec->getLoc(), "Illegal format for @earlyclobber constraint in '" +
|
|
|
|
Rec->getName() + "': '" + CStr + "'");
|
2010-11-01 12:03:32 +08:00
|
|
|
Name = Name.substr(wpos);
|
|
|
|
std::pair<unsigned,unsigned> Op = Ops.ParseOperandName(Name, false);
|
2011-01-26 10:03:37 +08:00
|
|
|
|
2010-11-01 12:03:32 +08:00
|
|
|
// Build the string for the operand
|
|
|
|
if (!Ops[Op.first].Constraints[Op.second].isNone())
|
[TableGen] Better error checking for TIED_TO constraints.
There are quite strong constraints on how you can use the TIED_TO
constraint between MC operands, many of which are currently not
checked until compiler run time.
MachineVerifier enforces that operands can only be tied together in
pairs (no three-way ties), and MachineInstr::tieOperands enforces that
one of the tied operands must be an output operand (def) and the other
must be an input operand (use).
Now we check these at TableGen time, so that if you violate any of
them in a new instruction definition, you find out immediately,
instead of having to wait until you compile something that makes code
generation hit one of those assertions.
Also in this commit, all the error reports in ParseConstraint now
include the name and source location of the def where the problem
happened, so that if you do trigger any of these errors, it's easier
to find the part of your TableGen input where you made the mistake.
The trunk sources already build successfully with this additional
error check, so I think no in-tree target has any of these problems.
Reviewers: fhahn, lhames, nhaehnle, MatzeB
Reviewed By: MatzeB
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D53815
llvm-svn: 347743
2018-11-28 19:43:49 +08:00
|
|
|
PrintFatalError(
|
|
|
|
Rec->getLoc(), "Operand '" + Name + "' of '" + Rec->getName() +
|
|
|
|
"' cannot have multiple constraints!");
|
2010-11-01 12:03:32 +08:00
|
|
|
Ops[Op.first].Constraints[Op.second] =
|
|
|
|
CGIOperandList::ConstraintInfo::getEarlyClobber();
|
|
|
|
return;
|
|
|
|
}
|
2011-01-26 10:03:37 +08:00
|
|
|
|
2010-11-01 12:03:32 +08:00
|
|
|
// Only other constraint is "TIED_TO" for now.
|
|
|
|
std::string::size_type pos = CStr.find_first_of('=');
|
[TableGen] Better error checking for TIED_TO constraints.
There are quite strong constraints on how you can use the TIED_TO
constraint between MC operands, many of which are currently not
checked until compiler run time.
MachineVerifier enforces that operands can only be tied together in
pairs (no three-way ties), and MachineInstr::tieOperands enforces that
one of the tied operands must be an output operand (def) and the other
must be an input operand (use).
Now we check these at TableGen time, so that if you violate any of
them in a new instruction definition, you find out immediately,
instead of having to wait until you compile something that makes code
generation hit one of those assertions.
Also in this commit, all the error reports in ParseConstraint now
include the name and source location of the def where the problem
happened, so that if you do trigger any of these errors, it's easier
to find the part of your TableGen input where you made the mistake.
The trunk sources already build successfully with this additional
error check, so I think no in-tree target has any of these problems.
Reviewers: fhahn, lhames, nhaehnle, MatzeB
Reviewed By: MatzeB
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D53815
llvm-svn: 347743
2018-11-28 19:43:49 +08:00
|
|
|
if (pos == std::string::npos)
|
|
|
|
PrintFatalError(
|
|
|
|
Rec->getLoc(), "Unrecognized constraint '" + CStr +
|
|
|
|
"' in '" + Rec->getName() + "'");
|
2010-11-01 12:03:32 +08:00
|
|
|
start = CStr.find_first_not_of(" \t");
|
2011-01-26 10:03:37 +08:00
|
|
|
|
2010-11-01 12:03:32 +08:00
|
|
|
// TIED_TO: $src1 = $dst
|
[TableGen] Better error checking for TIED_TO constraints.
There are quite strong constraints on how you can use the TIED_TO
constraint between MC operands, many of which are currently not
checked until compiler run time.
MachineVerifier enforces that operands can only be tied together in
pairs (no three-way ties), and MachineInstr::tieOperands enforces that
one of the tied operands must be an output operand (def) and the other
must be an input operand (use).
Now we check these at TableGen time, so that if you violate any of
them in a new instruction definition, you find out immediately,
instead of having to wait until you compile something that makes code
generation hit one of those assertions.
Also in this commit, all the error reports in ParseConstraint now
include the name and source location of the def where the problem
happened, so that if you do trigger any of these errors, it's easier
to find the part of your TableGen input where you made the mistake.
The trunk sources already build successfully with this additional
error check, so I think no in-tree target has any of these problems.
Reviewers: fhahn, lhames, nhaehnle, MatzeB
Reviewed By: MatzeB
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D53815
llvm-svn: 347743
2018-11-28 19:43:49 +08:00
|
|
|
wpos = CStr.find_first_of(" \t", start);
|
|
|
|
if (wpos == std::string::npos || wpos > pos)
|
|
|
|
PrintFatalError(
|
|
|
|
Rec->getLoc(), "Illegal format for tied-to constraint in '" +
|
|
|
|
Rec->getName() + "': '" + CStr + "'");
|
|
|
|
std::string LHSOpName = StringRef(CStr).substr(start, wpos - start);
|
|
|
|
std::pair<unsigned,unsigned> LHSOp = Ops.ParseOperandName(LHSOpName, false);
|
|
|
|
|
|
|
|
wpos = CStr.find_first_not_of(" \t", pos + 1);
|
2010-11-01 12:03:32 +08:00
|
|
|
if (wpos == std::string::npos)
|
[TableGen] Better error checking for TIED_TO constraints.
There are quite strong constraints on how you can use the TIED_TO
constraint between MC operands, many of which are currently not
checked until compiler run time.
MachineVerifier enforces that operands can only be tied together in
pairs (no three-way ties), and MachineInstr::tieOperands enforces that
one of the tied operands must be an output operand (def) and the other
must be an input operand (use).
Now we check these at TableGen time, so that if you violate any of
them in a new instruction definition, you find out immediately,
instead of having to wait until you compile something that makes code
generation hit one of those assertions.
Also in this commit, all the error reports in ParseConstraint now
include the name and source location of the def where the problem
happened, so that if you do trigger any of these errors, it's easier
to find the part of your TableGen input where you made the mistake.
The trunk sources already build successfully with this additional
error check, so I think no in-tree target has any of these problems.
Reviewers: fhahn, lhames, nhaehnle, MatzeB
Reviewed By: MatzeB
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D53815
llvm-svn: 347743
2018-11-28 19:43:49 +08:00
|
|
|
PrintFatalError(
|
|
|
|
Rec->getLoc(), "Illegal format for tied-to constraint: '" + CStr + "'");
|
|
|
|
|
|
|
|
std::string RHSOpName = StringRef(CStr).substr(wpos);
|
|
|
|
std::pair<unsigned,unsigned> RHSOp = Ops.ParseOperandName(RHSOpName, false);
|
|
|
|
|
|
|
|
// Sort the operands into order, which should put the output one
|
|
|
|
// first. But keep the original order, for use in diagnostics.
|
|
|
|
bool FirstIsDest = (LHSOp < RHSOp);
|
|
|
|
std::pair<unsigned,unsigned> DestOp = (FirstIsDest ? LHSOp : RHSOp);
|
|
|
|
StringRef DestOpName = (FirstIsDest ? LHSOpName : RHSOpName);
|
|
|
|
std::pair<unsigned,unsigned> SrcOp = (FirstIsDest ? RHSOp : LHSOp);
|
|
|
|
StringRef SrcOpName = (FirstIsDest ? RHSOpName : LHSOpName);
|
|
|
|
|
|
|
|
// Ensure one operand is a def and the other is a use.
|
|
|
|
if (DestOp.first >= Ops.NumDefs)
|
|
|
|
PrintFatalError(
|
|
|
|
Rec->getLoc(), "Input operands '" + LHSOpName + "' and '" + RHSOpName +
|
|
|
|
"' of '" + Rec->getName() + "' cannot be tied!");
|
|
|
|
if (SrcOp.first < Ops.NumDefs)
|
|
|
|
PrintFatalError(
|
|
|
|
Rec->getLoc(), "Output operands '" + LHSOpName + "' and '" + RHSOpName +
|
|
|
|
"' of '" + Rec->getName() + "' cannot be tied!");
|
|
|
|
|
|
|
|
// The constraint has to go on the operand with higher index, i.e.
|
|
|
|
// the source one. Check there isn't another constraint there
|
|
|
|
// already.
|
|
|
|
if (!Ops[SrcOp.first].Constraints[SrcOp.second].isNone())
|
|
|
|
PrintFatalError(
|
|
|
|
Rec->getLoc(), "Operand '" + SrcOpName + "' of '" + Rec->getName() +
|
|
|
|
"' cannot have multiple constraints!");
|
2011-01-26 10:03:37 +08:00
|
|
|
|
[TableGen] Better error checking for TIED_TO constraints.
There are quite strong constraints on how you can use the TIED_TO
constraint between MC operands, many of which are currently not
checked until compiler run time.
MachineVerifier enforces that operands can only be tied together in
pairs (no three-way ties), and MachineInstr::tieOperands enforces that
one of the tied operands must be an output operand (def) and the other
must be an input operand (use).
Now we check these at TableGen time, so that if you violate any of
them in a new instruction definition, you find out immediately,
instead of having to wait until you compile something that makes code
generation hit one of those assertions.
Also in this commit, all the error reports in ParseConstraint now
include the name and source location of the def where the problem
happened, so that if you do trigger any of these errors, it's easier
to find the part of your TableGen input where you made the mistake.
The trunk sources already build successfully with this additional
error check, so I think no in-tree target has any of these problems.
Reviewers: fhahn, lhames, nhaehnle, MatzeB
Reviewed By: MatzeB
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D53815
llvm-svn: 347743
2018-11-28 19:43:49 +08:00
|
|
|
unsigned DestFlatOpNo = Ops.getFlattenedOperandNumber(DestOp);
|
|
|
|
auto NewConstraint = CGIOperandList::ConstraintInfo::getTied(DestFlatOpNo);
|
|
|
|
|
|
|
|
// Check that the earlier operand is not the target of another tie
|
|
|
|
// before making it the target of this one.
|
|
|
|
for (const CGIOperandList::OperandInfo &Op : Ops) {
|
|
|
|
for (unsigned i = 0; i < Op.MINumOperands; i++)
|
|
|
|
if (Op.Constraints[i] == NewConstraint)
|
|
|
|
PrintFatalError(
|
|
|
|
Rec->getLoc(), "Operand '" + DestOpName + "' of '" + Rec->getName() +
|
|
|
|
"' cannot have multiple operands tied to it!");
|
2012-10-21 06:44:13 +08:00
|
|
|
}
|
2011-01-26 10:03:37 +08:00
|
|
|
|
[TableGen] Better error checking for TIED_TO constraints.
There are quite strong constraints on how you can use the TIED_TO
constraint between MC operands, many of which are currently not
checked until compiler run time.
MachineVerifier enforces that operands can only be tied together in
pairs (no three-way ties), and MachineInstr::tieOperands enforces that
one of the tied operands must be an output operand (def) and the other
must be an input operand (use).
Now we check these at TableGen time, so that if you violate any of
them in a new instruction definition, you find out immediately,
instead of having to wait until you compile something that makes code
generation hit one of those assertions.
Also in this commit, all the error reports in ParseConstraint now
include the name and source location of the def where the problem
happened, so that if you do trigger any of these errors, it's easier
to find the part of your TableGen input where you made the mistake.
The trunk sources already build successfully with this additional
error check, so I think no in-tree target has any of these problems.
Reviewers: fhahn, lhames, nhaehnle, MatzeB
Reviewed By: MatzeB
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D53815
llvm-svn: 347743
2018-11-28 19:43:49 +08:00
|
|
|
Ops[SrcOp.first].Constraints[SrcOp.second] = NewConstraint;
|
2010-11-01 12:03:32 +08:00
|
|
|
}
|
|
|
|
|
[TableGen] Better error checking for TIED_TO constraints.
There are quite strong constraints on how you can use the TIED_TO
constraint between MC operands, many of which are currently not
checked until compiler run time.
MachineVerifier enforces that operands can only be tied together in
pairs (no three-way ties), and MachineInstr::tieOperands enforces that
one of the tied operands must be an output operand (def) and the other
must be an input operand (use).
Now we check these at TableGen time, so that if you violate any of
them in a new instruction definition, you find out immediately,
instead of having to wait until you compile something that makes code
generation hit one of those assertions.
Also in this commit, all the error reports in ParseConstraint now
include the name and source location of the def where the problem
happened, so that if you do trigger any of these errors, it's easier
to find the part of your TableGen input where you made the mistake.
The trunk sources already build successfully with this additional
error check, so I think no in-tree target has any of these problems.
Reviewers: fhahn, lhames, nhaehnle, MatzeB
Reviewed By: MatzeB
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D53815
llvm-svn: 347743
2018-11-28 19:43:49 +08:00
|
|
|
static void ParseConstraints(const std::string &CStr, CGIOperandList &Ops,
|
|
|
|
Record *Rec) {
|
2010-11-01 12:03:32 +08:00
|
|
|
if (CStr.empty()) return;
|
2011-01-26 10:03:37 +08:00
|
|
|
|
2010-11-01 12:03:32 +08:00
|
|
|
const std::string delims(",");
|
|
|
|
std::string::size_type bidx, eidx;
|
2011-01-26 10:03:37 +08:00
|
|
|
|
2010-11-01 12:03:32 +08:00
|
|
|
bidx = CStr.find_first_not_of(delims);
|
|
|
|
while (bidx != std::string::npos) {
|
|
|
|
eidx = CStr.find_first_of(delims, bidx);
|
|
|
|
if (eidx == std::string::npos)
|
|
|
|
eidx = CStr.length();
|
2011-01-26 10:03:37 +08:00
|
|
|
|
[TableGen] Better error checking for TIED_TO constraints.
There are quite strong constraints on how you can use the TIED_TO
constraint between MC operands, many of which are currently not
checked until compiler run time.
MachineVerifier enforces that operands can only be tied together in
pairs (no three-way ties), and MachineInstr::tieOperands enforces that
one of the tied operands must be an output operand (def) and the other
must be an input operand (use).
Now we check these at TableGen time, so that if you violate any of
them in a new instruction definition, you find out immediately,
instead of having to wait until you compile something that makes code
generation hit one of those assertions.
Also in this commit, all the error reports in ParseConstraint now
include the name and source location of the def where the problem
happened, so that if you do trigger any of these errors, it's easier
to find the part of your TableGen input where you made the mistake.
The trunk sources already build successfully with this additional
error check, so I think no in-tree target has any of these problems.
Reviewers: fhahn, lhames, nhaehnle, MatzeB
Reviewed By: MatzeB
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D53815
llvm-svn: 347743
2018-11-28 19:43:49 +08:00
|
|
|
ParseConstraint(CStr.substr(bidx, eidx - bidx), Ops, Rec);
|
2010-11-01 12:03:32 +08:00
|
|
|
bidx = CStr.find_first_not_of(delims, eidx);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CGIOperandList::ProcessDisableEncoding(std::string DisableEncoding) {
|
|
|
|
while (1) {
|
2011-07-21 14:21:31 +08:00
|
|
|
std::pair<StringRef, StringRef> P = getToken(DisableEncoding, " ,\t");
|
|
|
|
std::string OpName = P.first;
|
|
|
|
DisableEncoding = P.second;
|
2010-11-01 12:03:32 +08:00
|
|
|
if (OpName.empty()) break;
|
2011-01-26 10:03:37 +08:00
|
|
|
|
2010-11-01 12:03:32 +08:00
|
|
|
// Figure out which operand this is.
|
|
|
|
std::pair<unsigned,unsigned> Op = ParseOperandName(OpName, false);
|
2011-01-26 10:03:37 +08:00
|
|
|
|
2010-11-01 12:03:32 +08:00
|
|
|
// Mark the operand as not-to-be encoded.
|
|
|
|
if (Op.second >= OperandList[Op.first].DoNotEncode.size())
|
|
|
|
OperandList[Op.first].DoNotEncode.resize(Op.second+1);
|
|
|
|
OperandList[Op.first].DoNotEncode[Op.second] = true;
|
|
|
|
}
|
2011-01-26 10:03:37 +08:00
|
|
|
|
2010-11-01 12:03:32 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// CodeGenInstruction Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2012-08-24 08:31:16 +08:00
|
|
|
CodeGenInstruction::CodeGenInstruction(Record *R)
|
2014-04-15 15:20:03 +08:00
|
|
|
: TheDef(R), Operands(R), InferredFrom(nullptr) {
|
2010-11-01 12:03:32 +08:00
|
|
|
Namespace = R->getValueAsString("Namespace");
|
|
|
|
AsmString = R->getValueAsString("AsmString");
|
|
|
|
|
|
|
|
isReturn = R->getValueAsBit("isReturn");
|
2018-08-22 03:44:11 +08:00
|
|
|
isEHScopeReturn = R->getValueAsBit("isEHScopeReturn");
|
2010-11-01 12:03:32 +08:00
|
|
|
isBranch = R->getValueAsBit("isBranch");
|
|
|
|
isIndirectBranch = R->getValueAsBit("isIndirectBranch");
|
|
|
|
isCompare = R->getValueAsBit("isCompare");
|
2010-11-18 04:13:28 +08:00
|
|
|
isMoveImm = R->getValueAsBit("isMoveImm");
|
2018-05-23 23:28:28 +08:00
|
|
|
isMoveReg = R->getValueAsBit("isMoveReg");
|
2011-03-15 13:09:26 +08:00
|
|
|
isBitcast = R->getValueAsBit("isBitcast");
|
2012-08-17 07:11:47 +08:00
|
|
|
isSelect = R->getValueAsBit("isSelect");
|
2010-11-01 12:03:32 +08:00
|
|
|
isBarrier = R->getValueAsBit("isBarrier");
|
|
|
|
isCall = R->getValueAsBit("isCall");
|
2016-09-14 16:20:03 +08:00
|
|
|
isAdd = R->getValueAsBit("isAdd");
|
2018-07-13 23:19:33 +08:00
|
|
|
isTrap = R->getValueAsBit("isTrap");
|
2010-11-01 12:03:32 +08:00
|
|
|
canFoldAsLoad = R->getValueAsBit("canFoldAsLoad");
|
|
|
|
isPredicable = Operands.isPredicable || R->getValueAsBit("isPredicable");
|
|
|
|
isConvertibleToThreeAddress = R->getValueAsBit("isConvertibleToThreeAddress");
|
|
|
|
isCommutable = R->getValueAsBit("isCommutable");
|
|
|
|
isTerminator = R->getValueAsBit("isTerminator");
|
|
|
|
isReMaterializable = R->getValueAsBit("isReMaterializable");
|
|
|
|
hasDelaySlot = R->getValueAsBit("hasDelaySlot");
|
|
|
|
usesCustomInserter = R->getValueAsBit("usesCustomInserter");
|
2011-09-21 02:22:31 +08:00
|
|
|
hasPostISelHook = R->getValueAsBit("hasPostISelHook");
|
2010-11-01 12:03:32 +08:00
|
|
|
hasCtrlDep = R->getValueAsBit("hasCtrlDep");
|
|
|
|
isNotDuplicable = R->getValueAsBit("isNotDuplicable");
|
2014-08-12 06:17:14 +08:00
|
|
|
isRegSequence = R->getValueAsBit("isRegSequence");
|
2014-08-21 05:51:26 +08:00
|
|
|
isExtractSubreg = R->getValueAsBit("isExtractSubreg");
|
2014-08-21 07:49:36 +08:00
|
|
|
isInsertSubreg = R->getValueAsBit("isInsertSubreg");
|
2015-05-29 02:33:39 +08:00
|
|
|
isConvergent = R->getValueAsBit("isConvergent");
|
2016-03-02 04:03:11 +08:00
|
|
|
hasNoSchedulingInfo = R->getValueAsBit("hasNoSchedulingInfo");
|
2018-05-22 22:36:58 +08:00
|
|
|
FastISelShouldIgnore = R->getValueAsBit("FastISelShouldIgnore");
|
2018-12-03 18:32:42 +08:00
|
|
|
variadicOpsAreDefs = R->getValueAsBit("variadicOpsAreDefs");
|
2012-08-24 03:34:46 +08:00
|
|
|
|
2014-02-05 17:10:40 +08:00
|
|
|
bool Unset;
|
|
|
|
mayLoad = R->getValueAsBitOrUnset("mayLoad", Unset);
|
|
|
|
mayLoad_Unset = Unset;
|
|
|
|
mayStore = R->getValueAsBitOrUnset("mayStore", Unset);
|
|
|
|
mayStore_Unset = Unset;
|
|
|
|
hasSideEffects = R->getValueAsBitOrUnset("hasSideEffects", Unset);
|
|
|
|
hasSideEffects_Unset = Unset;
|
2012-08-24 03:34:46 +08:00
|
|
|
|
2010-11-01 12:03:32 +08:00
|
|
|
isAsCheapAsAMove = R->getValueAsBit("isAsCheapAsAMove");
|
|
|
|
hasExtraSrcRegAllocReq = R->getValueAsBit("hasExtraSrcRegAllocReq");
|
|
|
|
hasExtraDefRegAllocReq = R->getValueAsBit("hasExtraDefRegAllocReq");
|
2011-07-07 08:48:02 +08:00
|
|
|
isCodeGenOnly = R->getValueAsBit("isCodeGenOnly");
|
2011-07-07 05:33:38 +08:00
|
|
|
isPseudo = R->getValueAsBit("isPseudo");
|
2010-11-01 12:03:32 +08:00
|
|
|
ImplicitDefs = R->getValueAsListOfDefs("Defs");
|
|
|
|
ImplicitUses = R->getValueAsListOfDefs("Uses");
|
|
|
|
|
[TableGen] Support multi-alternative pattern fragments
A TableGen instruction record usually contains a DAG pattern that will
describe the SelectionDAG operation that can be implemented by this
instruction. However, there will be cases where several different DAG
patterns can all be implemented by the same instruction. The way to
represent this today is to write additional patterns in the Pattern
(or usually Pat) class that map those extra DAG patterns to the
instruction. This usually also works fine.
However, I've noticed cases where the current setup seems to require
quite a bit of extra (and duplicated) text in the target .td files.
For example, in the SystemZ back-end, there are quite a number of
instructions that can implement an "add-with-overflow" operation.
The same instructions also need to be used to implement just plain
addition (simply ignoring the extra overflow output). The current
solution requires creating extra Pat pattern for every instruction,
duplicating the information about which particular add operands
map best to which particular instruction.
This patch enhances TableGen to support a new PatFrags class, which
can be used to encapsulate multiple alternative patterns that may
all match to the same instruction. It operates the same way as the
existing PatFrag class, except that it accepts a list of DAG patterns
to match instead of just a single one. As an example, we can now define
a PatFrags to match either an "add-with-overflow" or a regular add
operation:
def z_sadd : PatFrags<(ops node:$src1, node:$src2),
[(z_saddo node:$src1, node:$src2),
(add node:$src1, node:$src2)]>;
and then use this in the add instruction pattern:
defm AR : BinaryRRAndK<"ar", 0x1A, 0xB9F8, z_sadd, GR32, GR32>;
These SystemZ target changes are implemented here as well.
Note that PatFrag is now defined as a subclass of PatFrags, which
means that some users of internals of PatFrag need to be updated.
(E.g. instead of using PatFrag.Fragment you now need to use
!head(PatFrag.Fragments).)
The implementation is based on the following main ideas:
- InlinePatternFragments may now replace each original pattern
with several result patterns, not just one.
- parseInstructionPattern delays calling InlinePatternFragments
and InferAllTypes. Instead, it extracts a single DAG match
pattern from the main instruction pattern.
- Processing of the DAG match pattern part of the main instruction
pattern now shares most code with processing match patterns from
the Pattern class.
- Direct use of main instruction patterns in InferFromPattern and
EmitResultInstructionAsOperand is removed; everything now operates
solely on DAG match patterns.
Reviewed by: hfinkel
Differential Revision: https://reviews.llvm.org/D48545
llvm-svn: 336999
2018-07-13 21:18:00 +08:00
|
|
|
// This flag is only inferred from the pattern.
|
|
|
|
hasChain = false;
|
|
|
|
hasChain_Inferred = false;
|
|
|
|
|
2010-11-01 12:03:32 +08:00
|
|
|
// Parse Constraints.
|
[TableGen] Better error checking for TIED_TO constraints.
There are quite strong constraints on how you can use the TIED_TO
constraint between MC operands, many of which are currently not
checked until compiler run time.
MachineVerifier enforces that operands can only be tied together in
pairs (no three-way ties), and MachineInstr::tieOperands enforces that
one of the tied operands must be an output operand (def) and the other
must be an input operand (use).
Now we check these at TableGen time, so that if you violate any of
them in a new instruction definition, you find out immediately,
instead of having to wait until you compile something that makes code
generation hit one of those assertions.
Also in this commit, all the error reports in ParseConstraint now
include the name and source location of the def where the problem
happened, so that if you do trigger any of these errors, it's easier
to find the part of your TableGen input where you made the mistake.
The trunk sources already build successfully with this additional
error check, so I think no in-tree target has any of these problems.
Reviewers: fhahn, lhames, nhaehnle, MatzeB
Reviewed By: MatzeB
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D53815
llvm-svn: 347743
2018-11-28 19:43:49 +08:00
|
|
|
ParseConstraints(R->getValueAsString("Constraints"), Operands, R);
|
2010-11-01 12:03:32 +08:00
|
|
|
|
|
|
|
// Parse the DisableEncoding field.
|
|
|
|
Operands.ProcessDisableEncoding(R->getValueAsString("DisableEncoding"));
|
2013-09-12 18:28:05 +08:00
|
|
|
|
|
|
|
// First check for a ComplexDeprecationPredicate.
|
|
|
|
if (R->getValue("ComplexDeprecationPredicate")) {
|
|
|
|
HasComplexDeprecationPredicate = true;
|
|
|
|
DeprecatedReason = R->getValueAsString("ComplexDeprecationPredicate");
|
|
|
|
} else if (RecordVal *Dep = R->getValue("DeprecatedFeatureMask")) {
|
|
|
|
// Check if we have a Subtarget feature mask.
|
|
|
|
HasComplexDeprecationPredicate = false;
|
|
|
|
DeprecatedReason = Dep->getValue()->getAsString();
|
|
|
|
} else {
|
|
|
|
// This instruction isn't deprecated.
|
|
|
|
HasComplexDeprecationPredicate = false;
|
|
|
|
DeprecatedReason = "";
|
|
|
|
}
|
2010-11-01 12:03:32 +08:00
|
|
|
}
|
2010-03-28 04:09:24 +08:00
|
|
|
|
|
|
|
/// HasOneImplicitDefWithKnownVT - If the instruction has at least one
|
|
|
|
/// implicit def and it has a known VT, return the VT, otherwise return
|
|
|
|
/// MVT::Other.
|
|
|
|
MVT::SimpleValueType CodeGenInstruction::
|
|
|
|
HasOneImplicitDefWithKnownVT(const CodeGenTarget &TargetInfo) const {
|
|
|
|
if (ImplicitDefs.empty()) return MVT::Other;
|
2011-01-26 10:03:37 +08:00
|
|
|
|
2010-03-28 04:09:24 +08:00
|
|
|
// Check to see if the first implicit def has a resolvable type.
|
|
|
|
Record *FirstImplicitDef = ImplicitDefs[0];
|
|
|
|
assert(FirstImplicitDef->isSubClassOf("Register"));
|
2017-09-15 00:56:21 +08:00
|
|
|
const std::vector<ValueTypeByHwMode> &RegVTs =
|
2010-03-28 04:09:24 +08:00
|
|
|
TargetInfo.getRegisterVTs(FirstImplicitDef);
|
2017-09-15 00:56:21 +08:00
|
|
|
if (RegVTs.size() == 1 && RegVTs[0].isSimple())
|
|
|
|
return RegVTs[0].getSimple().SimpleTy;
|
2010-03-28 04:09:24 +08:00
|
|
|
return MVT::Other;
|
|
|
|
}
|
|
|
|
|
2010-11-01 09:07:14 +08:00
|
|
|
|
|
|
|
/// FlattenAsmStringVariants - Flatten the specified AsmString to only
|
|
|
|
/// include text from the specified variant, returning the new string.
|
|
|
|
std::string CodeGenInstruction::
|
|
|
|
FlattenAsmStringVariants(StringRef Cur, unsigned Variant) {
|
|
|
|
std::string Res = "";
|
2011-01-26 10:03:37 +08:00
|
|
|
|
2010-11-01 09:07:14 +08:00
|
|
|
for (;;) {
|
|
|
|
// Find the start of the next variant string.
|
|
|
|
size_t VariantsStart = 0;
|
|
|
|
for (size_t e = Cur.size(); VariantsStart != e; ++VariantsStart)
|
|
|
|
if (Cur[VariantsStart] == '{' &&
|
|
|
|
(VariantsStart == 0 || (Cur[VariantsStart-1] != '$' &&
|
|
|
|
Cur[VariantsStart-1] != '\\')))
|
|
|
|
break;
|
2011-01-26 10:03:37 +08:00
|
|
|
|
2010-11-01 09:07:14 +08:00
|
|
|
// Add the prefix to the result.
|
|
|
|
Res += Cur.slice(0, VariantsStart);
|
|
|
|
if (VariantsStart == Cur.size())
|
|
|
|
break;
|
2011-01-26 10:03:37 +08:00
|
|
|
|
2010-11-01 09:07:14 +08:00
|
|
|
++VariantsStart; // Skip the '{'.
|
2011-01-26 10:03:37 +08:00
|
|
|
|
2010-11-01 09:07:14 +08:00
|
|
|
// Scan to the end of the variants string.
|
|
|
|
size_t VariantsEnd = VariantsStart;
|
|
|
|
unsigned NestedBraces = 1;
|
|
|
|
for (size_t e = Cur.size(); VariantsEnd != e; ++VariantsEnd) {
|
|
|
|
if (Cur[VariantsEnd] == '}' && Cur[VariantsEnd-1] != '\\') {
|
|
|
|
if (--NestedBraces == 0)
|
|
|
|
break;
|
|
|
|
} else if (Cur[VariantsEnd] == '{')
|
|
|
|
++NestedBraces;
|
|
|
|
}
|
2011-01-26 10:03:37 +08:00
|
|
|
|
2010-11-01 09:07:14 +08:00
|
|
|
// Select the Nth variant (or empty).
|
|
|
|
StringRef Selection = Cur.slice(VariantsStart, VariantsEnd);
|
|
|
|
for (unsigned i = 0; i != Variant; ++i)
|
|
|
|
Selection = Selection.split('|').second;
|
|
|
|
Res += Selection.split('|').first;
|
2011-01-26 10:03:37 +08:00
|
|
|
|
2010-11-01 09:07:14 +08:00
|
|
|
assert(VariantsEnd != Cur.size() &&
|
|
|
|
"Unterminated variants in assembly string!");
|
|
|
|
Cur = Cur.substr(VariantsEnd + 1);
|
|
|
|
}
|
2011-01-26 10:03:37 +08:00
|
|
|
|
2010-11-01 09:07:14 +08:00
|
|
|
return Res;
|
|
|
|
}
|
|
|
|
|
2017-11-18 08:16:44 +08:00
|
|
|
bool CodeGenInstruction::isOperandAPointer(unsigned i) const {
|
|
|
|
if (DagInit *ConstraintList = TheDef->getValueAsDag("InOperandList")) {
|
|
|
|
if (i < ConstraintList->getNumArgs()) {
|
|
|
|
if (DefInit *Constraint = dyn_cast<DefInit>(ConstraintList->getArg(i))) {
|
|
|
|
return Constraint->getDef()->isSubClassOf("TypedOperand") &&
|
|
|
|
Constraint->getDef()->getValueAsBit("IsPointer");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2010-11-01 12:05:41 +08:00
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
/// CodeGenInstAlias Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2011-01-27 03:44:55 +08:00
|
|
|
/// tryAliasOpMatch - This is a helper function for the CodeGenInstAlias
|
|
|
|
/// constructor. It checks if an argument in an InstAlias pattern matches
|
|
|
|
/// the corresponding operand of the instruction. It returns true on a
|
|
|
|
/// successful match, with ResOp set to the result operand to be used.
|
2011-07-30 06:43:06 +08:00
|
|
|
bool CodeGenInstAlias::tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo,
|
2011-01-27 03:44:55 +08:00
|
|
|
Record *InstOpRec, bool hasSubOps,
|
Print out the location of expanded multiclass defs in TableGen errors.
When reporting an error for a defm, we would previously only report the
location of the outer defm, which is not always where the error is.
Now we also print the location of the expanded multiclass defs:
lib/Target/X86/X86InstrSSE.td:2902:12: error: foo
defm ADD : basic_sse12_fp_binop_s<0x58, "add", fadd, SSE_ALU_ITINS_S>,
^
lib/Target/X86/X86InstrSSE.td:2801:11: note: instantiated from multiclass
defm PD : sse12_fp_packed<opc, !strconcat(OpcodeStr, "pd"), OpNode, VR128,
^
lib/Target/X86/X86InstrSSE.td:194:5: note: instantiated from multiclass
def rm : PI<opc, MRMSrcMem, (outs RC:$dst), (ins RC:$src1, x86memop:$src2),
^
llvm-svn: 162409
2012-08-23 07:33:58 +08:00
|
|
|
ArrayRef<SMLoc> Loc, CodeGenTarget &T,
|
2011-01-27 03:44:55 +08:00
|
|
|
ResultOperand &ResOp) {
|
2011-07-30 06:43:06 +08:00
|
|
|
Init *Arg = Result->getArg(AliasOpNo);
|
2012-10-11 04:24:43 +08:00
|
|
|
DefInit *ADI = dyn_cast<DefInit>(Arg);
|
2014-04-15 15:20:03 +08:00
|
|
|
Record *ResultRecord = ADI ? ADI->getDef() : nullptr;
|
2011-01-27 03:44:55 +08:00
|
|
|
|
|
|
|
if (ADI && ADI->getDef() == InstOpRec) {
|
|
|
|
// If the operand is a record, it must have a name, and the record type
|
|
|
|
// must match up with the instruction's argument type.
|
2016-12-05 14:00:46 +08:00
|
|
|
if (!Result->getArgName(AliasOpNo))
|
2014-03-30 01:17:15 +08:00
|
|
|
PrintFatalError(Loc, "result argument #" + Twine(AliasOpNo) +
|
|
|
|
" must have a name!");
|
2016-12-05 14:00:46 +08:00
|
|
|
ResOp = ResultOperand(Result->getArgNameStr(AliasOpNo), ResultRecord);
|
2011-01-27 03:44:55 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2011-10-29 00:43:40 +08:00
|
|
|
// For register operands, the source register class can be a subclass
|
|
|
|
// of the instruction register class, not just an exact match.
|
2014-03-29 17:03:22 +08:00
|
|
|
if (InstOpRec->isSubClassOf("RegisterOperand"))
|
|
|
|
InstOpRec = InstOpRec->getValueAsDef("RegClass");
|
|
|
|
|
|
|
|
if (ADI && ADI->getDef()->isSubClassOf("RegisterOperand"))
|
|
|
|
ADI = ADI->getDef()->getValueAsDef("RegClass")->getDefInit();
|
|
|
|
|
2011-10-29 00:43:40 +08:00
|
|
|
if (ADI && ADI->getDef()->isSubClassOf("RegisterClass")) {
|
|
|
|
if (!InstOpRec->isSubClassOf("RegisterClass"))
|
|
|
|
return false;
|
2011-10-29 06:32:53 +08:00
|
|
|
if (!T.getRegisterClass(InstOpRec)
|
|
|
|
.hasSubClass(&T.getRegisterClass(ADI->getDef())))
|
|
|
|
return false;
|
2016-12-05 14:00:46 +08:00
|
|
|
ResOp = ResultOperand(Result->getArgNameStr(AliasOpNo), ResultRecord);
|
2011-10-29 06:32:53 +08:00
|
|
|
return true;
|
2011-10-29 00:43:40 +08:00
|
|
|
}
|
|
|
|
|
2011-01-27 03:44:55 +08:00
|
|
|
// Handle explicit registers.
|
|
|
|
if (ADI && ADI->getDef()->isSubClassOf("Register")) {
|
2011-08-20 04:33:06 +08:00
|
|
|
if (InstOpRec->isSubClassOf("OptionalDefOperand")) {
|
|
|
|
DagInit *DI = InstOpRec->getValueAsDag("MIOperandInfo");
|
|
|
|
// The operand info should only have a single (register) entry. We
|
|
|
|
// want the register class of it.
|
2012-10-11 04:24:47 +08:00
|
|
|
InstOpRec = cast<DefInit>(DI->getArg(0))->getDef();
|
2011-08-20 04:33:06 +08:00
|
|
|
}
|
|
|
|
|
2011-01-27 03:44:55 +08:00
|
|
|
if (!InstOpRec->isSubClassOf("RegisterClass"))
|
|
|
|
return false;
|
|
|
|
|
2011-06-15 12:50:36 +08:00
|
|
|
if (!T.getRegisterClass(InstOpRec)
|
|
|
|
.contains(T.getRegBank().getReg(ADI->getDef())))
|
2012-10-26 04:33:17 +08:00
|
|
|
PrintFatalError(Loc, "fixed register " + ADI->getDef()->getName() +
|
|
|
|
" is not a member of the " + InstOpRec->getName() +
|
|
|
|
" register class!");
|
2011-01-27 03:44:55 +08:00
|
|
|
|
2016-12-05 14:00:46 +08:00
|
|
|
if (Result->getArgName(AliasOpNo))
|
2012-10-26 04:33:17 +08:00
|
|
|
PrintFatalError(Loc, "result fixed register argument must "
|
|
|
|
"not have a name!");
|
2011-01-27 03:44:55 +08:00
|
|
|
|
2014-03-29 17:03:22 +08:00
|
|
|
ResOp = ResultOperand(ResultRecord);
|
2011-01-27 03:44:55 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Handle "zero_reg" for optional def operands.
|
|
|
|
if (ADI && ADI->getDef()->getName() == "zero_reg") {
|
|
|
|
|
|
|
|
// Check if this is an optional def.
|
2011-11-15 09:46:57 +08:00
|
|
|
// Tied operands where the source is a sub-operand of a complex operand
|
|
|
|
// need to represent both operands in the alias destination instruction.
|
|
|
|
// Allow zero_reg for the tied portion. This can and should go away once
|
|
|
|
// the MC representation of things doesn't use tied operands at all.
|
|
|
|
//if (!InstOpRec->isSubClassOf("OptionalDefOperand"))
|
|
|
|
// throw TGError(Loc, "reg0 used for result that is not an "
|
|
|
|
// "OptionalDefOperand!");
|
2011-01-27 03:44:55 +08:00
|
|
|
|
2014-04-15 15:20:03 +08:00
|
|
|
ResOp = ResultOperand(static_cast<Record*>(nullptr));
|
2011-01-27 03:44:55 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2011-10-29 06:32:53 +08:00
|
|
|
// Literal integers.
|
2012-10-11 04:24:43 +08:00
|
|
|
if (IntInit *II = dyn_cast<IntInit>(Arg)) {
|
2011-01-27 03:44:55 +08:00
|
|
|
if (hasSubOps || !InstOpRec->isSubClassOf("Operand"))
|
|
|
|
return false;
|
|
|
|
// Integer arguments can't have names.
|
2016-12-05 14:00:46 +08:00
|
|
|
if (Result->getArgName(AliasOpNo))
|
2014-03-30 01:17:15 +08:00
|
|
|
PrintFatalError(Loc, "result argument #" + Twine(AliasOpNo) +
|
2012-10-26 04:33:17 +08:00
|
|
|
" must not have a name!");
|
2011-01-27 03:44:55 +08:00
|
|
|
ResOp = ResultOperand(II->getValue());
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2014-08-07 13:47:04 +08:00
|
|
|
// Bits<n> (also used for 0bxx literals)
|
|
|
|
if (BitsInit *BI = dyn_cast<BitsInit>(Arg)) {
|
|
|
|
if (hasSubOps || !InstOpRec->isSubClassOf("Operand"))
|
|
|
|
return false;
|
|
|
|
if (!BI->isComplete())
|
|
|
|
return false;
|
|
|
|
// Convert the bits init to an integer and use that for the result.
|
|
|
|
IntInit *II =
|
|
|
|
dyn_cast_or_null<IntInit>(BI->convertInitializerTo(IntRecTy::get()));
|
|
|
|
if (!II)
|
|
|
|
return false;
|
|
|
|
ResOp = ResultOperand(II->getValue());
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2011-10-29 06:32:53 +08:00
|
|
|
// If both are Operands with the same MVT, allow the conversion. It's
|
|
|
|
// up to the user to make sure the values are appropriate, just like
|
|
|
|
// for isel Pat's.
|
2014-12-13 05:48:03 +08:00
|
|
|
if (InstOpRec->isSubClassOf("Operand") && ADI &&
|
2011-10-29 06:32:53 +08:00
|
|
|
ADI->getDef()->isSubClassOf("Operand")) {
|
|
|
|
// FIXME: What other attributes should we check here? Identical
|
|
|
|
// MIOperandInfo perhaps?
|
|
|
|
if (InstOpRec->getValueInit("Type") != ADI->getDef()->getValueInit("Type"))
|
|
|
|
return false;
|
2016-12-05 14:00:46 +08:00
|
|
|
ResOp = ResultOperand(Result->getArgNameStr(AliasOpNo), ADI->getDef());
|
2011-10-29 06:32:53 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2011-01-27 03:44:55 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2014-05-15 21:36:01 +08:00
|
|
|
unsigned CodeGenInstAlias::ResultOperand::getMINumOperands() const {
|
|
|
|
if (!isRecord())
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
Record *Rec = getRecord();
|
|
|
|
if (!Rec->isSubClassOf("Operand"))
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
DagInit *MIOpInfo = Rec->getValueAsDag("MIOperandInfo");
|
|
|
|
if (MIOpInfo->getNumArgs() == 0) {
|
|
|
|
// Unspecified, so it defaults to 1
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return MIOpInfo->getNumArgs();
|
|
|
|
}
|
|
|
|
|
2018-06-18 09:28:01 +08:00
|
|
|
CodeGenInstAlias::CodeGenInstAlias(Record *R, CodeGenTarget &T)
|
2014-05-15 19:16:32 +08:00
|
|
|
: TheDef(R) {
|
2010-11-01 13:34:34 +08:00
|
|
|
Result = R->getValueAsDag("ResultInst");
|
2014-05-15 19:16:32 +08:00
|
|
|
AsmString = R->getValueAsString("AsmString");
|
|
|
|
|
2010-11-06 14:39:47 +08:00
|
|
|
|
|
|
|
// Verify that the root of the result is an instruction.
|
2012-10-11 04:24:43 +08:00
|
|
|
DefInit *DI = dyn_cast<DefInit>(Result->getOperator());
|
2014-04-15 15:20:03 +08:00
|
|
|
if (!DI || !DI->getDef()->isSubClassOf("Instruction"))
|
2012-10-26 04:33:17 +08:00
|
|
|
PrintFatalError(R->getLoc(),
|
|
|
|
"result of inst alias should be an instruction");
|
2010-11-06 14:39:47 +08:00
|
|
|
|
|
|
|
ResultInst = &T.getInstruction(DI->getDef());
|
2011-01-26 10:03:37 +08:00
|
|
|
|
2010-11-06 15:06:09 +08:00
|
|
|
// NameClass - If argument names are repeated, we need to verify they have
|
|
|
|
// the same class.
|
|
|
|
StringMap<Record*> NameClass;
|
2011-01-21 02:38:10 +08:00
|
|
|
for (unsigned i = 0, e = Result->getNumArgs(); i != e; ++i) {
|
2012-10-11 04:24:43 +08:00
|
|
|
DefInit *ADI = dyn_cast<DefInit>(Result->getArg(i));
|
2016-12-05 14:00:46 +08:00
|
|
|
if (!ADI || !Result->getArgName(i))
|
2011-01-21 02:38:10 +08:00
|
|
|
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.
|
2016-12-05 14:00:46 +08:00
|
|
|
Record *&Entry = NameClass[Result->getArgNameStr(i)];
|
2011-01-21 02:38:10 +08:00
|
|
|
if (Entry && Entry != ADI->getDef())
|
2016-12-05 14:00:46 +08:00
|
|
|
PrintFatalError(R->getLoc(), "result value $" + Result->getArgNameStr(i) +
|
2012-10-26 04:33:17 +08:00
|
|
|
" is both " + Entry->getName() + " and " +
|
|
|
|
ADI->getDef()->getName() + "!");
|
2011-01-21 02:38:10 +08:00
|
|
|
Entry = ADI->getDef();
|
|
|
|
}
|
2011-01-26 10:03:37 +08:00
|
|
|
|
2010-11-06 14:54:38 +08:00
|
|
|
// Decode and validate the arguments of the result.
|
2010-11-06 15:31:43 +08:00
|
|
|
unsigned AliasOpNo = 0;
|
|
|
|
for (unsigned i = 0, e = ResultInst->Operands.size(); i != e; ++i) {
|
2011-01-27 03:44:55 +08:00
|
|
|
|
2011-11-15 09:46:57 +08:00
|
|
|
// 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 (ResultInst->Operands[i].MINumOperands == 1 &&
|
[TableGen][AsmMatcherEmitter] Allow tied operands of different classes in aliases.
Allow a tied operand of a different operand class in InstAliases,
so that the operand can be printed (and added to the MC instruction)
as the appropriate register. For example, 'GPR64as32', which would
be printed/parsed as a 32bit register and should match a tied 64bit
register operand, where the former is a sub-register of the latter.
This patch also generalizes the constraint checking to an overrideable
method in MCTargetAsmParser, so that target asmparsers can specify
whether a given operand satisfies the tied register constraint.
Reviewers: olista01, rengolin, fhahn, SjoerdMeijer, samparker, dsanders, craig.topper
Reviewed By: fhahn
Differential Revision: https://reviews.llvm.org/D47714
llvm-svn: 334942
2018-06-18 21:39:29 +08:00
|
|
|
ResultInst->Operands[i].getTiedRegister() != -1) {
|
|
|
|
// Tied operands of different RegisterClass should be explicit within an
|
|
|
|
// instruction's syntax and so cannot be skipped.
|
|
|
|
int TiedOpNum = ResultInst->Operands[i].getTiedRegister();
|
|
|
|
if (ResultInst->Operands[i].Rec->getName() ==
|
|
|
|
ResultInst->Operands[TiedOpNum].Rec->getName())
|
|
|
|
continue;
|
|
|
|
}
|
2010-11-06 15:31:43 +08:00
|
|
|
|
|
|
|
if (AliasOpNo >= Result->getNumArgs())
|
2012-10-26 04:33:17 +08:00
|
|
|
PrintFatalError(R->getLoc(), "not enough arguments for instruction!");
|
2011-01-27 03:44:55 +08:00
|
|
|
|
|
|
|
Record *InstOpRec = ResultInst->Operands[i].Rec;
|
|
|
|
unsigned NumSubOps = ResultInst->Operands[i].MINumOperands;
|
|
|
|
ResultOperand ResOp(static_cast<int64_t>(0));
|
|
|
|
if (tryAliasOpMatch(Result, AliasOpNo, InstOpRec, (NumSubOps > 1),
|
|
|
|
R->getLoc(), T, ResOp)) {
|
2012-06-08 08:25:03 +08:00
|
|
|
// If this is a simple operand, or a complex operand with a custom match
|
|
|
|
// class, then we can match is verbatim.
|
|
|
|
if (NumSubOps == 1 ||
|
|
|
|
(InstOpRec->getValue("ParserMatchClass") &&
|
|
|
|
InstOpRec->getValueAsDef("ParserMatchClass")
|
|
|
|
->getValueAsString("Name") != "Imm")) {
|
|
|
|
ResultOperands.push_back(ResOp);
|
|
|
|
ResultInstOperandIndex.push_back(std::make_pair(i, -1));
|
|
|
|
++AliasOpNo;
|
|
|
|
|
|
|
|
// Otherwise, we need to match each of the suboperands individually.
|
|
|
|
} else {
|
|
|
|
DagInit *MIOI = ResultInst->Operands[i].MIOperandInfo;
|
|
|
|
for (unsigned SubOp = 0; SubOp != NumSubOps; ++SubOp) {
|
2012-10-11 04:24:47 +08:00
|
|
|
Record *SubRec = cast<DefInit>(MIOI->getArg(SubOp))->getDef();
|
2012-06-08 08:25:03 +08:00
|
|
|
|
|
|
|
// Take care to instantiate each of the suboperands with the correct
|
|
|
|
// nomenclature: $foo.bar
|
2016-12-05 14:00:46 +08:00
|
|
|
ResultOperands.emplace_back(
|
|
|
|
Result->getArgName(AliasOpNo)->getAsUnquotedString() + "." +
|
|
|
|
MIOI->getArgName(SubOp)->getAsUnquotedString(), SubRec);
|
2012-06-08 08:25:03 +08:00
|
|
|
ResultInstOperandIndex.push_back(std::make_pair(i, SubOp));
|
|
|
|
}
|
|
|
|
++AliasOpNo;
|
|
|
|
}
|
2010-11-06 14:54:38 +08:00
|
|
|
continue;
|
|
|
|
}
|
2011-01-26 10:03:37 +08:00
|
|
|
|
2011-01-27 03:44:55 +08:00
|
|
|
// If the argument did not match the instruction operand, and the operand
|
|
|
|
// is composed of multiple suboperands, try matching the suboperands.
|
|
|
|
if (NumSubOps > 1) {
|
2011-07-30 06:43:06 +08:00
|
|
|
DagInit *MIOI = ResultInst->Operands[i].MIOperandInfo;
|
2011-01-27 03:44:55 +08:00
|
|
|
for (unsigned SubOp = 0; SubOp != NumSubOps; ++SubOp) {
|
|
|
|
if (AliasOpNo >= Result->getNumArgs())
|
2012-10-26 04:33:17 +08:00
|
|
|
PrintFatalError(R->getLoc(), "not enough arguments for instruction!");
|
2012-10-11 04:24:47 +08:00
|
|
|
Record *SubRec = cast<DefInit>(MIOI->getArg(SubOp))->getDef();
|
2011-01-27 03:44:55 +08:00
|
|
|
if (tryAliasOpMatch(Result, AliasOpNo, SubRec, false,
|
|
|
|
R->getLoc(), T, ResOp)) {
|
|
|
|
ResultOperands.push_back(ResOp);
|
|
|
|
ResultInstOperandIndex.push_back(std::make_pair(i, SubOp));
|
|
|
|
++AliasOpNo;
|
|
|
|
} else {
|
2014-03-30 01:17:15 +08:00
|
|
|
PrintFatalError(R->getLoc(), "result argument #" + Twine(AliasOpNo) +
|
2011-01-27 03:44:55 +08:00
|
|
|
" does not match instruction operand class " +
|
|
|
|
(SubOp == 0 ? InstOpRec->getName() :SubRec->getName()));
|
|
|
|
}
|
|
|
|
}
|
2010-11-07 03:25:43 +08:00
|
|
|
continue;
|
|
|
|
}
|
2014-03-30 01:17:15 +08:00
|
|
|
PrintFatalError(R->getLoc(), "result argument #" + Twine(AliasOpNo) +
|
2012-10-26 04:33:17 +08:00
|
|
|
" does not match instruction operand class " +
|
|
|
|
InstOpRec->getName());
|
2010-11-06 14:54:38 +08:00
|
|
|
}
|
2011-01-26 10:03:37 +08:00
|
|
|
|
2010-11-06 15:31:43 +08:00
|
|
|
if (AliasOpNo != Result->getNumArgs())
|
2012-10-26 04:33:17 +08:00
|
|
|
PrintFatalError(R->getLoc(), "too many operands for instruction!");
|
2010-11-01 12:05:41 +08:00
|
|
|
}
|