Introduce a new CodeGenInstruction::ConstraintInfo class

for representing constraint info semantically instead of
as a c expression that will be blatted out to the .inc
file.  Fix X86RecognizableInstr to use this instead of
parsing C code :).

llvm-svn: 95753
This commit is contained in:
Chris Lattner 2010-02-10 01:45:28 +00:00
parent 75c9a4eeae
commit a9dfb1bc07
4 changed files with 57 additions and 25 deletions

View File

@ -33,10 +33,10 @@ static void ParseConstraint(const std::string &CStr, CodeGenInstruction *I) {
I->ParseOperandName(Name, false);
// Build the string for the operand
std::string OpConstraint = "(1 << TOI::EARLY_CLOBBER)";
if (!I->OperandList[Op.first].Constraints[Op.second].empty())
if (!I->OperandList[Op.first].Constraints[Op.second].isNone())
throw "Operand '" + Name + "' cannot have multiple constraints!";
I->OperandList[Op.first].Constraints[Op.second] = OpConstraint;
I->OperandList[Op.first].Constraints[Op.second] =
CodeGenInstruction::ConstraintInfo::getEarlyClobber();
return;
}
@ -65,13 +65,11 @@ static void ParseConstraint(const std::string &CStr, CodeGenInstruction *I) {
unsigned FlatOpNo = I->getFlattenedOperandNumber(SrcOp);
// Build the string for the operand.
std::string OpConstraint =
"((" + utostr(FlatOpNo) + " << 16) | (1 << TOI::TIED_TO))";
if (!I->OperandList[DestOp.first].Constraints[DestOp.second].empty())
if (!I->OperandList[DestOp.first].Constraints[DestOp.second].isNone())
throw "Operand '" + DestOpName + "' cannot have multiple constraints!";
I->OperandList[DestOp.first].Constraints[DestOp.second] = OpConstraint;
I->OperandList[DestOp.first].Constraints[DestOp.second] =
CodeGenInstruction::ConstraintInfo::getTied(FlatOpNo);
}
static void ParseConstraints(const std::string &CStr, CodeGenInstruction *I) {
@ -210,18 +208,13 @@ CodeGenInstruction::CodeGenInstruction(Record *R, const std::string &AsmStr)
// For backward compatibility: isTwoAddress means operand 1 is tied to
// operand 0.
if (isTwoAddress) {
if (!OperandList[1].Constraints[0].empty())
if (!OperandList[1].Constraints[0].isNone())
throw R->getName() + ": cannot use isTwoAddress property: instruction "
"already has constraint set!";
OperandList[1].Constraints[0] = "((0 << 16) | (1 << TOI::TIED_TO))";
OperandList[1].Constraints[0] =
CodeGenInstruction::ConstraintInfo::getTied(0);
}
// Any operands with unset constraints get 0 as their constraint.
for (unsigned op = 0, e = OperandList.size(); op != e; ++op)
for (unsigned j = 0, e = OperandList[op].MINumOperands; j != e; ++j)
if (OperandList[op].Constraints[j].empty())
OperandList[op].Constraints[j] = "0";
// Parse the DisableEncoding field.
std::string DisableEncoding = R->getValueAsString("DisableEncoding");
while (1) {

View File

@ -32,6 +32,35 @@ namespace llvm {
/// instruction.
std::string AsmString;
class ConstraintInfo {
enum { None, EarlyClobber, Tied } Kind;
unsigned OtherTiedOperand;
public:
ConstraintInfo() : Kind(None) {}
static ConstraintInfo getEarlyClobber() {
ConstraintInfo I;
I.Kind = EarlyClobber;
return I;
}
static ConstraintInfo getTied(unsigned Op) {
ConstraintInfo I;
I.Kind = Tied;
I.OtherTiedOperand = Op;
return I;
}
bool isNone() const { return Kind == None; }
bool isEarlyClobber() const { return Kind == EarlyClobber; }
bool isTied() const { return Kind == Tied; }
unsigned getTiedOperand() const {
assert(isTied());
return OtherTiedOperand;
}
};
/// OperandInfo - The information we keep track of for each operand in the
/// operand list for a tablegen instruction.
struct OperandInfo {
@ -67,7 +96,7 @@ namespace llvm {
/// Constraint info for this operand. This operand can have pieces, so we
/// track constraint info for each.
std::vector<std::string> Constraints;
std::vector<ConstraintInfo> Constraints;
OperandInfo(Record *R, const std::string &N, const std::string &PMN,
unsigned MION, unsigned MINO, DagInit *MIOI)

View File

@ -118,7 +118,20 @@ InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) {
Res += "|(1<<TOI::OptionalDef)";
// Fill in constraint info.
Res += ", " + Inst.OperandList[i].Constraints[j];
Res += ", ";
const CodeGenInstruction::ConstraintInfo &Constraint =
Inst.OperandList[i].Constraints[j];
if (Constraint.isNone())
Res += "0";
else if (Constraint.isEarlyClobber())
Res += "(1 << TOI::EARLY_CLOBBER)";
else {
assert(Constraint.isTied());
Res += "((" + utostr(Constraint.getTiedOperand()) +
" << 16) | (1 << TOI::TIED_TO))";
}
Result.push_back(Res);
}
}

View File

@ -402,13 +402,10 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) {
for (operandIndex = 0; operandIndex < numOperands; ++operandIndex) {
if (OperandList[operandIndex].Constraints.size()) {
const std::string &constraint = OperandList[operandIndex].Constraints[0];
std::string::size_type tiedToPos;
if ((tiedToPos = constraint.find(" << 16) | (1 << TOI::TIED_TO))")) !=
constraint.npos) {
tiedToPos--;
operandMapping[operandIndex] = constraint[tiedToPos] - '0';
const CodeGenInstruction::ConstraintInfo &Constraint =
OperandList[operandIndex].Constraints[0];
if (Constraint.isTied()) {
operandMapping[operandIndex] = Constraint.getTiedOperand();
} else {
++numPhysicalOperands;
operandMapping[operandIndex] = operandIndex;