From 9b0d4bfca0f23d39f5f2aef6b6740267a26ee17c Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Tue, 2 Nov 2010 22:55:03 +0000 Subject: [PATCH] rewrite EmitConvertToMCInst to iterate over the MCInst operands, filling them in one at a time. Previously this iterated over the asmoperands, which left the problem of "holes". The new approach simplifies things. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@118104 91177308-0d34-0410-b5e6-96231b3b80d8 --- utils/TableGen/AsmMatcherEmitter.cpp | 162 +++++++++++---------------- utils/TableGen/CodeGenInstruction.h | 13 ++- 2 files changed, 76 insertions(+), 99 deletions(-) diff --git a/utils/TableGen/AsmMatcherEmitter.cpp b/utils/TableGen/AsmMatcherEmitter.cpp index 32b7901e486..8dad17cfa21 100644 --- a/utils/TableGen/AsmMatcherEmitter.cpp +++ b/utils/TableGen/AsmMatcherEmitter.cpp @@ -1040,13 +1040,12 @@ void AsmMatcherInfo::BuildInfo() { // grovel for. Only worry about this for single entry operands, we have to // clean this up anyway. const CGIOperandList::OperandInfo *OI = &II->OperandList[Idx]; - if (OI->Constraints[0].isTied()) { - unsigned TiedOp = OI->Constraints[0].getTiedOperand(); - + int OITied = OI->getTiedRegister(); + if (OITied != -1) { // The tied operand index is an MIOperand index, find the operand that // contains it. for (unsigned i = 0, e = II->OperandList.size(); i != e; ++i) { - if (II->OperandList[i].MIOperandNo == TiedOp) { + if (II->OperandList[i].MIOperandNo == unsigned(OITied)) { OI = &II->OperandList[i]; break; } @@ -1064,16 +1063,6 @@ void AsmMatcherInfo::BuildInfo() { std::sort(Classes.begin(), Classes.end(), less_ptr()); } -static std::pair * -GetTiedOperandAtIndex(SmallVectorImpl > &List, - unsigned Index) { - for (unsigned i = 0, e = List.size(); i != e; ++i) - if (Index == List[i].first) - return &List[i]; - - return 0; -} - static void EmitConvertToMCInst(CodeGenTarget &Target, std::vector &Infos, raw_ostream &OS) { @@ -1103,111 +1092,88 @@ static void EmitConvertToMCInst(CodeGenTarget &Target, // TargetOperandClass - This is the target's operand class, like X86Operand. std::string TargetOperandClass = Target.getName() + "Operand"; + /// OperandMap - This is a mapping from the MCInst operands (specified by the + /// II.OperandList operands) to the AsmOperands that they filled in from. + SmallVector OperandMap; + for (std::vector::const_iterator it = Infos.begin(), ie = Infos.end(); it != ie; ++it) { MatchableInfo &II = **it; + OperandMap.clear(); + OperandMap.resize(II.OperandList.size(), -1); + // Order the (class) operands by the order to convert them into an MCInst. - SmallVector, 4> MIOperandList; for (unsigned i = 0, e = II.AsmOperands.size(); i != e; ++i) { MatchableInfo::Operand &Op = II.AsmOperands[i]; - if (Op.OperandInfo) - MIOperandList.push_back(std::make_pair(Op.OperandInfo->MIOperandNo, i)); - } - - // Find any tied operands. - SmallVector, 4> TiedOperands; - for (unsigned i = 0, e = II.OperandList.size(); i != e; ++i) { - const CGIOperandList::OperandInfo &OpInfo = II.OperandList[i]; - for (unsigned j = 0, e = OpInfo.Constraints.size(); j != e; ++j) { - const CGIOperandList::ConstraintInfo &CI = OpInfo.Constraints[j]; - if (!CI.isTied()) continue; - TiedOperands.push_back(std::make_pair(OpInfo.MIOperandNo, - CI.getTiedOperand())); - } - } - - array_pod_sort(MIOperandList.begin(), MIOperandList.end()); - - // Compute the total number of operands. - unsigned NumMIOperands = 0; - for (unsigned i = 0, e = II.OperandList.size(); i != e; ++i) { - const CGIOperandList::OperandInfo &OI = II.OperandList[i]; - NumMIOperands = std::max(NumMIOperands, OI.MIOperandNo+OI.MINumOperands); + if (!Op.OperandInfo) continue; + + unsigned LogicalOpNum = Op.OperandInfo - &II.OperandList[0]; + assert(LogicalOpNum < OperandMap.size() && "Invalid operand number"); + OperandMap[LogicalOpNum] = i; } // Build the conversion function signature. std::string Signature = "Convert"; - unsigned CurIndex = 0; - std::string CaseBody; raw_string_ostream CaseOS(CaseBody); // Compute the convert enum and the case body. - for (unsigned i = 0, e = MIOperandList.size(); i != e; ++i) { - MatchableInfo::Operand &Op = II.AsmOperands[MIOperandList[i].second]; - assert(CurIndex <= Op.OperandInfo->MIOperandNo && - "Duplicate match for instruction operand!"); - - // Add the implicit operands. - for (; CurIndex != Op.OperandInfo->MIOperandNo; ++CurIndex) { - // See if this is a tied operand. - std::pair *Tie = GetTiedOperandAtIndex(TiedOperands, - CurIndex); + for (unsigned i = 0, e = II.OperandList.size(); i != e; ++i) { + const CGIOperandList::OperandInfo &OpInfo = II.OperandList[i]; + + // Find out what operand from the asmparser that this MCInst operand comes + // from. + int SrcOperand = OperandMap[i]; + if (SrcOperand != -1) { + // Otherwise, this comes from something we parsed. + MatchableInfo::Operand &Op = II.AsmOperands[SrcOperand]; - if (!Tie) { - // If not, this is some implicit operand. Just assume it is a register - // for now. - CaseOS << " Inst.addOperand(MCOperand::CreateReg(0));\n"; - Signature += "__Imp"; - } else { - // Copy the tied operand. - assert(Tie->first>Tie->second && "Tied operand preceeds its target!"); - CaseOS << " Inst.addOperand(Inst.getOperand(" - << Tie->second << "));\n"; - Signature += "__Tie" + utostr(Tie->second); - } + // Registers are always converted the same, don't duplicate the + // conversion function based on them. + // + // FIXME: We could generalize this based on the render method, if it + // mattered. + Signature += "__"; + if (Op.Class->isRegisterClass()) + Signature += "Reg"; + else + Signature += Op.Class->ClassName; + Signature += utostr(Op.OperandInfo->MINumOperands); + Signature += "_" + itostr(SrcOperand); + + CaseOS << " ((" << TargetOperandClass << "*)Operands[" + << SrcOperand << "+1])->" << Op.Class->RenderMethod + << "(Inst, " << Op.OperandInfo->MINumOperands << ");\n"; + continue; } - // Registers are always converted the same, don't duplicate the conversion - // function based on them. - // - // FIXME: We could generalize this based on the render method, if it - // mattered. - Signature += "__"; - if (Op.Class->isRegisterClass()) - Signature += "Reg"; - else - Signature += Op.Class->ClassName; - Signature += utostr(Op.OperandInfo->MINumOperands); - Signature += "_" + utostr(MIOperandList[i].second); - - - CaseOS << " ((" << TargetOperandClass << "*)Operands[" - << MIOperandList[i].second << "+1])->" << Op.Class->RenderMethod - << "(Inst, " << Op.OperandInfo->MINumOperands << ");\n"; - CurIndex += Op.OperandInfo->MINumOperands; - } - - // And add trailing implicit operands. - for (; CurIndex != NumMIOperands; ++CurIndex) { - std::pair *Tie = GetTiedOperandAtIndex(TiedOperands, - CurIndex); - - if (!Tie) { - // If not, this is some implicit operand. Just assume it is a register - // for now. - CaseOS << " Inst.addOperand(MCOperand::CreateReg(0));\n"; - Signature += "__Imp"; - } else { + + // If this operand is tied to a previous one, just copy the MCInst operand + // from the earlier one. + int TiedOp = OpInfo.getTiedRegister(); + if (TiedOp != -1) { // Copy the tied operand. - assert(Tie->first>Tie->second && "Tied operand preceeds its target!"); - CaseOS << " Inst.addOperand(Inst.getOperand(" - << Tie->second << "));\n"; - Signature += "__Tie" + utostr(Tie->second); + // FIXME: What if the operand has multiple MINumOperands? This happens + // in ARM. + //assert(OpInfo.MINumOperands == 1); + + assert(i > unsigned(TiedOp) && "Tied operand preceeds its target!"); + CaseOS << " Inst.addOperand(Inst.getOperand(" << TiedOp << "));\n"; + Signature += "__Tie" + itostr(TiedOp); + continue; } - } + // Otherwise this is some sort of dummy operand that is mentioned in the + // ins/outs list but not mentioned in the asmstring, brutalize a dummy + // value into the operand. + // FIXME: This is a terrible hack: If an MCInst operand doesn't occur in + // the asmstring, there is no way to parse something meaningful. + // Just assume it is a zero register for now. + CaseOS << " Inst.addOperand(MCOperand::CreateReg(0));\n"; + Signature += "__Imp"; + } + II.ConversionFnKind = Signature; // Check if we have already generated this signature. diff --git a/utils/TableGen/CodeGenInstruction.h b/utils/TableGen/CodeGenInstruction.h index 78c88d797d3..24bdbe2794b 100644 --- a/utils/TableGen/CodeGenInstruction.h +++ b/utils/TableGen/CodeGenInstruction.h @@ -102,7 +102,18 @@ namespace llvm { const std::string &EMN, unsigned MION, unsigned MINO, DagInit *MIOI) : Rec(R), Name(N), PrinterMethodName(PMN), EncoderMethodName(EMN), - MIOperandNo(MION), MINumOperands(MINO), MIOperandInfo(MIOI) {} + MIOperandNo(MION), MINumOperands(MINO), MIOperandInfo(MIOI) {} + + + /// getTiedOperand - If this operand is tied to another one, return the + /// other operand number. Otherwise, return -1. + int getTiedRegister() const { + for (unsigned j = 0, e = Constraints.size(); j != e; ++j) { + const CGIOperandList::ConstraintInfo &CI = Constraints[j]; + if (CI.isTied()) return CI.getTiedOperand(); + } + return -1; + } }; CGIOperandList(Record *D); -- 2.34.1