mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-19 18:24:00 +00:00
Add @earlyclobber TableGen constraint
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@91554 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@ -25,9 +25,10 @@ class TargetRegisterInfo;
|
|||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
namespace TOI {
|
namespace TOI {
|
||||||
// Operand constraints: only "tied_to" for now.
|
// Operand constraints
|
||||||
enum OperandConstraint {
|
enum OperandConstraint {
|
||||||
TIED_TO = 0 // Must be allocated the same register as.
|
TIED_TO = 0, // Must be allocated the same register as.
|
||||||
|
EARLY_CLOBBER // Operand is an early clobber register operand
|
||||||
};
|
};
|
||||||
|
|
||||||
/// OperandFlags - These are flags set on operands, but should be considered
|
/// OperandFlags - These are flags set on operands, but should be considered
|
||||||
|
@ -555,8 +555,13 @@ void MachineInstr::addOperand(const MachineOperand &Op) {
|
|||||||
Operands.back().ParentMI = this;
|
Operands.back().ParentMI = this;
|
||||||
|
|
||||||
// If the operand is a register, update the operand's use list.
|
// If the operand is a register, update the operand's use list.
|
||||||
if (Op.isReg())
|
if (Op.isReg()) {
|
||||||
Operands.back().AddRegOperandToRegInfo(RegInfo);
|
Operands.back().AddRegOperandToRegInfo(RegInfo);
|
||||||
|
// If the register operand is flagged as early, mark the operand as such
|
||||||
|
unsigned OpNo = Operands.size() - 1;
|
||||||
|
if (TID->getOperandConstraint(OpNo, TOI::EARLY_CLOBBER) != -1)
|
||||||
|
Operands[OpNo].setIsEarlyClobber(true);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -573,8 +578,12 @@ void MachineInstr::addOperand(const MachineOperand &Op) {
|
|||||||
|
|
||||||
// Do explicitly set the reginfo for this operand though, to ensure the
|
// Do explicitly set the reginfo for this operand though, to ensure the
|
||||||
// next/prev fields are properly nulled out.
|
// next/prev fields are properly nulled out.
|
||||||
if (Operands[OpNo].isReg())
|
if (Operands[OpNo].isReg()) {
|
||||||
Operands[OpNo].AddRegOperandToRegInfo(0);
|
Operands[OpNo].AddRegOperandToRegInfo(0);
|
||||||
|
// If the register operand is flagged as early, mark the operand as such
|
||||||
|
if (TID->getOperandConstraint(OpNo, TOI::EARLY_CLOBBER) != -1)
|
||||||
|
Operands[OpNo].setIsEarlyClobber(true);
|
||||||
|
}
|
||||||
|
|
||||||
} else if (Operands.size()+1 <= Operands.capacity()) {
|
} else if (Operands.size()+1 <= Operands.capacity()) {
|
||||||
// Otherwise, we have to remove register operands from their register use
|
// Otherwise, we have to remove register operands from their register use
|
||||||
@ -594,8 +603,12 @@ void MachineInstr::addOperand(const MachineOperand &Op) {
|
|||||||
Operands.insert(Operands.begin()+OpNo, Op);
|
Operands.insert(Operands.begin()+OpNo, Op);
|
||||||
Operands[OpNo].ParentMI = this;
|
Operands[OpNo].ParentMI = this;
|
||||||
|
|
||||||
if (Operands[OpNo].isReg())
|
if (Operands[OpNo].isReg()) {
|
||||||
Operands[OpNo].AddRegOperandToRegInfo(RegInfo);
|
Operands[OpNo].AddRegOperandToRegInfo(RegInfo);
|
||||||
|
// If the register operand is flagged as early, mark the operand as such
|
||||||
|
if (TID->getOperandConstraint(OpNo, TOI::EARLY_CLOBBER) != -1)
|
||||||
|
Operands[OpNo].setIsEarlyClobber(true);
|
||||||
|
}
|
||||||
|
|
||||||
// Re-add all the implicit ops.
|
// Re-add all the implicit ops.
|
||||||
for (unsigned i = OpNo+1, e = Operands.size(); i != e; ++i) {
|
for (unsigned i = OpNo+1, e = Operands.size(); i != e; ++i) {
|
||||||
@ -613,6 +626,11 @@ void MachineInstr::addOperand(const MachineOperand &Op) {
|
|||||||
|
|
||||||
// Re-add all the operands.
|
// Re-add all the operands.
|
||||||
AddRegOperandsToUseLists(*RegInfo);
|
AddRegOperandsToUseLists(*RegInfo);
|
||||||
|
|
||||||
|
// If the register operand is flagged as early, mark the operand as such
|
||||||
|
if (Operands[OpNo].isReg()
|
||||||
|
&& TID->getOperandConstraint(OpNo, TOI::EARLY_CLOBBER) != -1)
|
||||||
|
Operands[OpNo].setIsEarlyClobber(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,14 +18,35 @@
|
|||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
static void ParseConstraint(const std::string &CStr, CodeGenInstruction *I) {
|
static void ParseConstraint(const std::string &CStr, CodeGenInstruction *I) {
|
||||||
// FIXME: Only supports TIED_TO for now.
|
// 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)
|
||||||
|
throw "Illegal format for @earlyclobber constraint: '" + CStr + "'";
|
||||||
|
Name = Name.substr(wpos);
|
||||||
|
std::pair<unsigned,unsigned> Op =
|
||||||
|
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())
|
||||||
|
throw "Operand '" + Name + "' cannot have multiple constraints!";
|
||||||
|
I->OperandList[Op.first].Constraints[Op.second] = OpConstraint;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only other constraint is "TIED_TO" for now.
|
||||||
std::string::size_type pos = CStr.find_first_of('=');
|
std::string::size_type pos = CStr.find_first_of('=');
|
||||||
assert(pos != std::string::npos && "Unrecognized constraint");
|
assert(pos != std::string::npos && "Unrecognized constraint");
|
||||||
std::string::size_type start = CStr.find_first_not_of(" \t");
|
start = CStr.find_first_not_of(" \t");
|
||||||
std::string Name = CStr.substr(start, pos - start);
|
std::string Name = CStr.substr(start, pos - start);
|
||||||
|
|
||||||
// TIED_TO: $src1 = $dst
|
// TIED_TO: $src1 = $dst
|
||||||
std::string::size_type wpos = Name.find_first_of(" \t");
|
wpos = Name.find_first_of(" \t");
|
||||||
if (wpos == std::string::npos)
|
if (wpos == std::string::npos)
|
||||||
throw "Illegal format for tied-to constraint: '" + CStr + "'";
|
throw "Illegal format for tied-to constraint: '" + CStr + "'";
|
||||||
std::string DestOpName = Name.substr(0, wpos);
|
std::string DestOpName = Name.substr(0, wpos);
|
||||||
@ -47,7 +68,6 @@ static void ParseConstraint(const std::string &CStr, CodeGenInstruction *I) {
|
|||||||
std::string OpConstraint =
|
std::string OpConstraint =
|
||||||
"((" + utostr(FlatOpNo) + " << 16) | (1 << TOI::TIED_TO))";
|
"((" + utostr(FlatOpNo) + " << 16) | (1 << TOI::TIED_TO))";
|
||||||
|
|
||||||
|
|
||||||
if (!I->OperandList[DestOp.first].Constraints[DestOp.second].empty())
|
if (!I->OperandList[DestOp.first].Constraints[DestOp.second].empty())
|
||||||
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] = OpConstraint;
|
||||||
|
Reference in New Issue
Block a user