summaryrefslogtreecommitdiff
path: root/utils/TableGen
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2010-11-06 19:57:21 +0000
committerChris Lattner <sabre@nondot.org>2010-11-06 19:57:21 +0000
commit90fd797dc739319347861d4f3984bc8952ae9a29 (patch)
tree606f6e49e3dc37ec32c49d07519667df46bba585 /utils/TableGen
parent8d5acb7007decaf0c30bf4a3d4c55e5cc2cce0a7 (diff)
downloadllvm-90fd797dc739319347861d4f3984bc8952ae9a29.tar.gz
llvm-90fd797dc739319347861d4f3984bc8952ae9a29.tar.bz2
llvm-90fd797dc739319347861d4f3984bc8952ae9a29.tar.xz
add (and document) the ability for alias results to have
fixed physical registers. Start moving fp comparison aliases to the .td file (which default to using %st1 if nothing is specified). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@118352 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'utils/TableGen')
-rw-r--r--utils/TableGen/AsmMatcherEmitter.cpp42
-rw-r--r--utils/TableGen/CodeGenInstruction.cpp32
-rw-r--r--utils/TableGen/CodeGenInstruction.h6
-rw-r--r--utils/TableGen/CodeGenRegisters.h6
4 files changed, 75 insertions, 11 deletions
diff --git a/utils/TableGen/AsmMatcherEmitter.cpp b/utils/TableGen/AsmMatcherEmitter.cpp
index 46866140eb..151c1b2f4b 100644
--- a/utils/TableGen/AsmMatcherEmitter.cpp
+++ b/utils/TableGen/AsmMatcherEmitter.cpp
@@ -274,7 +274,10 @@ struct MatchableInfo {
/// ImmOperand - This represents an immediate value that is dumped into
/// the operand.
- ImmOperand
+ ImmOperand,
+
+ /// RegOperand - This represents a fixed register that is dumped in.
+ RegOperand
} Kind;
union {
@@ -288,6 +291,9 @@ struct MatchableInfo {
/// ImmVal - This is the immediate value added to the instruction.
int64_t ImmVal;
+
+ /// Register - This is the register record.
+ Record *Register;
};
/// OpInfo - This is the information about the instruction operand that is
@@ -320,6 +326,16 @@ struct MatchableInfo {
X.OpInfo = Op;
return X;
}
+
+ static ResOperand getRegOp(Record *Reg,
+ const CGIOperandList::OperandInfo *Op) {
+ ResOperand X;
+ X.Kind = RegOperand;
+ X.Register = Reg;
+ X.OpInfo = Op;
+ return X;
+ }
+
};
/// TheDef - This is the definition of the instruction or InstAlias that this
@@ -1243,7 +1259,8 @@ void MatchableInfo::BuildAliasResultOperands() {
// Find out what operand from the asmparser that this MCInst operand comes
// from.
- if (CGA.ResultOperands[AliasOpNo].isRecord()) {
+ switch (CGA.ResultOperands[AliasOpNo].Kind) {
+ case CodeGenInstAlias::ResultOperand::K_Record: {
StringRef Name = CGA.ResultOperands[AliasOpNo++].getName();
int SrcOperand = FindAsmOperandNamed(Name);
if (SrcOperand != -1) {
@@ -1255,10 +1272,18 @@ void MatchableInfo::BuildAliasResultOperands() {
TheDef->getName() + "' has operand '" + OpInfo.Name +
"' that doesn't appear in asm string!");
}
-
- int64_t ImmVal = CGA.ResultOperands[AliasOpNo++].getImm();
- ResOperands.push_back(ResOperand::getImmOp(ImmVal, &OpInfo));
- continue;
+ case CodeGenInstAlias::ResultOperand::K_Imm: {
+ int64_t ImmVal = CGA.ResultOperands[AliasOpNo++].getImm();
+ ResOperands.push_back(ResOperand::getImmOp(ImmVal, &OpInfo));
+ continue;
+ }
+
+ case CodeGenInstAlias::ResultOperand::K_Reg: {
+ Record *Reg = CGA.ResultOperands[AliasOpNo++].getRegister();
+ ResOperands.push_back(ResOperand::getRegOp(Reg, &OpInfo));
+ continue;
+ }
+ }
}
}
@@ -1341,6 +1366,11 @@ static void EmitConvertToMCInst(CodeGenTarget &Target,
Signature += "__imm" + itostr(Val);
break;
}
+ case MatchableInfo::ResOperand::RegOperand: {
+ std::string N = getQualifiedName(OpInfo.Register);
+ CaseOS << " Inst.addOperand(MCOperand::CreateReg(" << N << "));\n";
+ Signature += "__reg" + OpInfo.Register->getName();
+ }
}
}
diff --git a/utils/TableGen/CodeGenInstruction.cpp b/utils/TableGen/CodeGenInstruction.cpp
index 924608cbf0..84a8b9137e 100644
--- a/utils/TableGen/CodeGenInstruction.cpp
+++ b/utils/TableGen/CodeGenInstruction.cpp
@@ -419,6 +419,30 @@ CodeGenInstAlias::CodeGenInstAlias(Record *R, CodeGenTarget &T) : TheDef(R) {
Init *Arg = Result->getArg(AliasOpNo);
+ Record *ResultOpRec = ResultInst->Operands[i].Rec;
+
+ // Handle explicit registers.
+ if (DefInit *ADI = dynamic_cast<DefInit*>(Arg)) {
+ if (ADI->getDef()->isSubClassOf("Register")) {
+ if (!Result->getArgName(AliasOpNo).empty())
+ throw TGError(R->getLoc(), "result fixed register argument must "
+ "not have a name!");
+
+ if (!ResultOpRec->isSubClassOf("RegisterClass"))
+ throw TGError(R->getLoc(), "result fixed register argument is not "
+ "passed to a RegisterClass operand!");
+
+ if (!T.getRegisterClass(ResultOpRec).containsRegister(ADI->getDef()))
+ throw TGError(R->getLoc(), "fixed register " +ADI->getDef()->getName()
+ + " is not a member of the " + ResultOpRec->getName() +
+ " register class!");
+
+ // Now that it is validated, add it.
+ ResultOperands.push_back(ResultOperand(ADI->getDef()));
+ ++AliasOpNo;
+ continue;
+ }
+ }
// If the operand is a record, it must have a name, and the record type must
// match up with the instruction's argument type.
@@ -427,11 +451,11 @@ CodeGenInstAlias::CodeGenInstAlias(Record *R, CodeGenTarget &T) : TheDef(R) {
throw TGError(R->getLoc(), "result argument #" + utostr(AliasOpNo) +
" must have a name!");
- if (ADI->getDef() != ResultInst->Operands[i].Rec)
+ if (ADI->getDef() != ResultOpRec)
throw TGError(R->getLoc(), "result argument #" + utostr(AliasOpNo) +
" declared with class " + ADI->getDef()->getName() +
", instruction operand is class " +
- ResultInst->Operands[i].Rec->getName());
+ ResultOpRec->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
@@ -456,9 +480,9 @@ CodeGenInstAlias::CodeGenInstAlias(Record *R, CodeGenTarget &T) : TheDef(R) {
throw TGError(R->getLoc(), "result argument #" + utostr(AliasOpNo) +
" must not have a name!");
if (ResultInst->Operands[i].MINumOperands != 1 ||
- !ResultInst->Operands[i].Rec->isSubClassOf("Operand"))
+ !ResultOpRec->isSubClassOf("Operand"))
throw TGError(R->getLoc(), "invalid argument class " +
- ResultInst->Operands[i].Rec->getName() +
+ ResultOpRec->getName() +
" for integer result operand!");
ResultOperands.push_back(ResultOperand(II->getValue()));
++AliasOpNo;
diff --git a/utils/TableGen/CodeGenInstruction.h b/utils/TableGen/CodeGenInstruction.h
index ac593dfb17..9cd23e6fa8 100644
--- a/utils/TableGen/CodeGenInstruction.h
+++ b/utils/TableGen/CodeGenInstruction.h
@@ -275,18 +275,22 @@ namespace llvm {
public:
enum {
K_Record,
- K_Imm
+ K_Imm,
+ K_Reg
} Kind;
ResultOperand(StringRef N, Record *r) : Name(N), R(r), Kind(K_Record) {}
ResultOperand(int64_t I) : Imm(I), Kind(K_Imm) {}
+ ResultOperand(Record *r) : R(r), Kind(K_Reg) {}
bool isRecord() const { return Kind == K_Record; }
bool isImm() const { return Kind == K_Imm; }
+ bool isReg() const { return Kind == K_Reg; }
StringRef getName() const { assert(isRecord()); return Name; }
Record *getRecord() const { assert(isRecord()); return R; }
int64_t getImm() const { assert(isImm()); return Imm; }
+ Record *getRegister() const { assert(isReg()); return R; }
};
/// ResultOperands - The decoded operands for the result instruction.
diff --git a/utils/TableGen/CodeGenRegisters.h b/utils/TableGen/CodeGenRegisters.h
index ccd3d222bb..bbd0cefa58 100644
--- a/utils/TableGen/CodeGenRegisters.h
+++ b/utils/TableGen/CodeGenRegisters.h
@@ -57,6 +57,12 @@ namespace llvm {
abort();
}
+ bool containsRegister(Record *R) const {
+ for (unsigned i = 0, e = Elements.size(); i != e; ++i)
+ if (Elements[i] == R) return true;
+ return false;
+ }
+
// Returns true if RC is a strict subclass.
// RC is a sub-class of this class if it is a valid replacement for any
// instruction operand where a register of this classis required. It must