forked from OSchip/llvm-project
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:
parent
75c9a4eeae
commit
a9dfb1bc07
|
@ -33,10 +33,10 @@ static void ParseConstraint(const std::string &CStr, CodeGenInstruction *I) {
|
||||||
I->ParseOperandName(Name, false);
|
I->ParseOperandName(Name, false);
|
||||||
|
|
||||||
// Build the string for the operand
|
// Build the string for the operand
|
||||||
std::string OpConstraint = "(1 << TOI::EARLY_CLOBBER)";
|
if (!I->OperandList[Op.first].Constraints[Op.second].isNone())
|
||||||
if (!I->OperandList[Op.first].Constraints[Op.second].empty())
|
|
||||||
throw "Operand '" + Name + "' cannot have multiple constraints!";
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,13 +65,11 @@ static void ParseConstraint(const std::string &CStr, CodeGenInstruction *I) {
|
||||||
|
|
||||||
|
|
||||||
unsigned FlatOpNo = I->getFlattenedOperandNumber(SrcOp);
|
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!";
|
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) {
|
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
|
// For backward compatibility: isTwoAddress means operand 1 is tied to
|
||||||
// operand 0.
|
// operand 0.
|
||||||
if (isTwoAddress) {
|
if (isTwoAddress) {
|
||||||
if (!OperandList[1].Constraints[0].empty())
|
if (!OperandList[1].Constraints[0].isNone())
|
||||||
throw R->getName() + ": cannot use isTwoAddress property: instruction "
|
throw R->getName() + ": cannot use isTwoAddress property: instruction "
|
||||||
"already has constraint set!";
|
"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.
|
// Parse the DisableEncoding field.
|
||||||
std::string DisableEncoding = R->getValueAsString("DisableEncoding");
|
std::string DisableEncoding = R->getValueAsString("DisableEncoding");
|
||||||
while (1) {
|
while (1) {
|
||||||
|
|
|
@ -32,6 +32,35 @@ namespace llvm {
|
||||||
/// instruction.
|
/// instruction.
|
||||||
std::string AsmString;
|
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
|
/// OperandInfo - The information we keep track of for each operand in the
|
||||||
/// operand list for a tablegen instruction.
|
/// operand list for a tablegen instruction.
|
||||||
struct OperandInfo {
|
struct OperandInfo {
|
||||||
|
@ -67,7 +96,7 @@ namespace llvm {
|
||||||
|
|
||||||
/// Constraint info for this operand. This operand can have pieces, so we
|
/// Constraint info for this operand. This operand can have pieces, so we
|
||||||
/// track constraint info for each.
|
/// 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,
|
OperandInfo(Record *R, const std::string &N, const std::string &PMN,
|
||||||
unsigned MION, unsigned MINO, DagInit *MIOI)
|
unsigned MION, unsigned MINO, DagInit *MIOI)
|
||||||
|
|
|
@ -118,7 +118,20 @@ InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) {
|
||||||
Res += "|(1<<TOI::OptionalDef)";
|
Res += "|(1<<TOI::OptionalDef)";
|
||||||
|
|
||||||
// Fill in constraint info.
|
// 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);
|
Result.push_back(Res);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -402,13 +402,10 @@ void RecognizableInstr::emitInstructionSpecifier(DisassemblerTables &tables) {
|
||||||
|
|
||||||
for (operandIndex = 0; operandIndex < numOperands; ++operandIndex) {
|
for (operandIndex = 0; operandIndex < numOperands; ++operandIndex) {
|
||||||
if (OperandList[operandIndex].Constraints.size()) {
|
if (OperandList[operandIndex].Constraints.size()) {
|
||||||
const std::string &constraint = OperandList[operandIndex].Constraints[0];
|
const CodeGenInstruction::ConstraintInfo &Constraint =
|
||||||
std::string::size_type tiedToPos;
|
OperandList[operandIndex].Constraints[0];
|
||||||
|
if (Constraint.isTied()) {
|
||||||
if ((tiedToPos = constraint.find(" << 16) | (1 << TOI::TIED_TO))")) !=
|
operandMapping[operandIndex] = Constraint.getTiedOperand();
|
||||||
constraint.npos) {
|
|
||||||
tiedToPos--;
|
|
||||||
operandMapping[operandIndex] = constraint[tiedToPos] - '0';
|
|
||||||
} else {
|
} else {
|
||||||
++numPhysicalOperands;
|
++numPhysicalOperands;
|
||||||
operandMapping[operandIndex] = operandIndex;
|
operandMapping[operandIndex] = operandIndex;
|
||||||
|
|
Loading…
Reference in New Issue