implement more checking to reject things like:

(someinst GR16:$foo, GR32:$foo)

Reimplement BuildAliasOperandReference to be correctly
based on the names of operands in the result pattern,
instead of on the instruction operand definitions.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@118328 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2010-11-06 07:06:09 +00:00
parent d0f225cafc
commit 3f2c8e474b
2 changed files with 25 additions and 34 deletions

View File

@ -1160,47 +1160,24 @@ BuildInstructionOperandReference(MatchableInfo *II,
Op.SrcOpName = OperandName;
}
/// BuildAliasOperandReference - When parsing an operand reference out of the
/// matching string (e.g. "movsx $src, $dst"), determine what the class of the
/// operand reference is by looking it up in the result pattern definition.
void AsmMatcherInfo::BuildAliasOperandReference(MatchableInfo *II,
StringRef OperandName,
MatchableInfo::AsmOperand &Op) {
const CodeGenInstAlias &CGA = *II->DefRec.get<const CodeGenInstAlias*>();
// FIXME: This is a total hack, it should not be a copy of
// BuildInstructionOperandReference
const CGIOperandList &Operands = CGA.Operands;
// Map this token to an operand. FIXME: Move elsewhere.
unsigned Idx;
if (!Operands.hasOperandNamed(OperandName, Idx))
throw TGError(II->TheDef->getLoc(), "error: unable to find operand: '" +
OperandName.str() + "'");
// Set up the operand class.
Op.Class = getOperandClass(Operands[Idx]);
// If the named operand is tied, canonicalize it to the untied operand.
// For example, something like:
// (outs GPR:$dst), (ins GPR:$src)
// with an asmstring of
// "inc $src"
// we want to canonicalize to:
// "inc $dst"
// so that we know how to provide the $dst operand when filling in the result.
int OITied = Operands[Idx].getTiedRegister();
if (OITied != -1) {
// The tied operand index is an MIOperand index, find the operand that
// contains it.
for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
if (Operands[i].MIOperandNo == unsigned(OITied)) {
OperandName = Operands[i].Name;
break;
}
for (unsigned i = 0, e = CGA.ResultOperands.size(); i != e; ++i)
if (CGA.ResultOperands[i].Name == OperandName) {
Op.Class = getOperandClass(CGA.ResultInst->Operands[i]);
Op.SrcOpName = OperandName;
return;
}
}
Op.SrcOpName = OperandName;
throw TGError(II->TheDef->getLoc(), "error: unable to find operand: '" +
OperandName.str() + "'");
}
void MatchableInfo::BuildResultOperands() {

View File

@ -15,6 +15,7 @@
#include "CodeGenTarget.h"
#include "Record.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/STLExtras.h"
#include <set>
using namespace llvm;
@ -407,6 +408,10 @@ CodeGenInstAlias::CodeGenInstAlias(Record *R, CodeGenTarget &T)
" arguments, but " + ResultInst->TheDef->getName() +
" instruction expects " + utostr(ResultInst->Operands.size())+
" operands!");
// NameClass - If argument names are repeated, we need to verify they have
// the same class.
StringMap<Record*> NameClass;
// Decode and validate the arguments of the result.
for (unsigned i = 0, e = Result->getNumArgs(); i != e; ++i) {
@ -425,6 +430,15 @@ CodeGenInstAlias::CodeGenInstAlias(Record *R, CodeGenTarget &T)
", instruction operand is class " +
ResultInst->Operands[i].Rec->getName());
// 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.
Record *&Entry = NameClass[Result->getArgName(i)];
if (Entry && Entry != ADI->getDef())
throw TGError(R->getLoc(), "result value $" + Result->getArgName(i) +
" is both " + Entry->getName() + " and " +
ADI->getDef()->getName() + "!");
// Now that it is validated, add it.
ResultOperands.push_back(ResultOperand(Result->getArgName(i),
ADI->getDef()));