CodeGenInstruction.cpp revision 205407
1193323Sed//===- CodeGenInstruction.cpp - CodeGen Instruction Class Wrapper ---------===// 2193323Sed// 3193323Sed// The LLVM Compiler Infrastructure 4193323Sed// 5193323Sed// This file is distributed under the University of Illinois Open Source 6193323Sed// License. See LICENSE.TXT for details. 7193323Sed// 8193323Sed//===----------------------------------------------------------------------===// 9193323Sed// 10193323Sed// This file implements the CodeGenInstruction class. 11193323Sed// 12193323Sed//===----------------------------------------------------------------------===// 13193323Sed 14193323Sed#include "CodeGenInstruction.h" 15193323Sed#include "Record.h" 16193323Sed#include "llvm/ADT/StringExtras.h" 17202375Srdivacky#include "llvm/ADT/STLExtras.h" 18193323Sed#include <set> 19193323Sedusing namespace llvm; 20193323Sed 21193323Sedstatic void ParseConstraint(const std::string &CStr, CodeGenInstruction *I) { 22201360Srdivacky // EARLY_CLOBBER: @early $reg 23201360Srdivacky std::string::size_type wpos = CStr.find_first_of(" \t"); 24201360Srdivacky std::string::size_type start = CStr.find_first_not_of(" \t"); 25201360Srdivacky std::string Tok = CStr.substr(start, wpos - start); 26201360Srdivacky if (Tok == "@earlyclobber") { 27201360Srdivacky std::string Name = CStr.substr(wpos+1); 28201360Srdivacky wpos = Name.find_first_not_of(" \t"); 29201360Srdivacky if (wpos == std::string::npos) 30201360Srdivacky throw "Illegal format for @earlyclobber constraint: '" + CStr + "'"; 31201360Srdivacky Name = Name.substr(wpos); 32201360Srdivacky std::pair<unsigned,unsigned> Op = 33201360Srdivacky I->ParseOperandName(Name, false); 34201360Srdivacky 35201360Srdivacky // Build the string for the operand 36203954Srdivacky if (!I->OperandList[Op.first].Constraints[Op.second].isNone()) 37201360Srdivacky throw "Operand '" + Name + "' cannot have multiple constraints!"; 38203954Srdivacky I->OperandList[Op.first].Constraints[Op.second] = 39203954Srdivacky CodeGenInstruction::ConstraintInfo::getEarlyClobber(); 40201360Srdivacky return; 41201360Srdivacky } 42201360Srdivacky 43201360Srdivacky // Only other constraint is "TIED_TO" for now. 44193323Sed std::string::size_type pos = CStr.find_first_of('='); 45193323Sed assert(pos != std::string::npos && "Unrecognized constraint"); 46201360Srdivacky start = CStr.find_first_not_of(" \t"); 47198090Srdivacky std::string Name = CStr.substr(start, pos - start); 48201360Srdivacky 49193323Sed // TIED_TO: $src1 = $dst 50201360Srdivacky wpos = Name.find_first_of(" \t"); 51193323Sed if (wpos == std::string::npos) 52193323Sed throw "Illegal format for tied-to constraint: '" + CStr + "'"; 53193323Sed std::string DestOpName = Name.substr(0, wpos); 54193323Sed std::pair<unsigned,unsigned> DestOp = I->ParseOperandName(DestOpName, false); 55201360Srdivacky 56193323Sed Name = CStr.substr(pos+1); 57193323Sed wpos = Name.find_first_not_of(" \t"); 58193323Sed if (wpos == std::string::npos) 59193323Sed throw "Illegal format for tied-to constraint: '" + CStr + "'"; 60201360Srdivacky 61193323Sed std::pair<unsigned,unsigned> SrcOp = 62193323Sed I->ParseOperandName(Name.substr(wpos), false); 63193323Sed if (SrcOp > DestOp) 64193323Sed throw "Illegal tied-to operand constraint '" + CStr + "'"; 65201360Srdivacky 66201360Srdivacky 67193323Sed unsigned FlatOpNo = I->getFlattenedOperandNumber(SrcOp); 68201360Srdivacky 69203954Srdivacky if (!I->OperandList[DestOp.first].Constraints[DestOp.second].isNone()) 70193323Sed throw "Operand '" + DestOpName + "' cannot have multiple constraints!"; 71203954Srdivacky I->OperandList[DestOp.first].Constraints[DestOp.second] = 72203954Srdivacky CodeGenInstruction::ConstraintInfo::getTied(FlatOpNo); 73193323Sed} 74193323Sed 75193323Sedstatic void ParseConstraints(const std::string &CStr, CodeGenInstruction *I) { 76193323Sed // Make sure the constraints list for each operand is large enough to hold 77193323Sed // constraint info, even if none is present. 78201360Srdivacky for (unsigned i = 0, e = I->OperandList.size(); i != e; ++i) 79193323Sed I->OperandList[i].Constraints.resize(I->OperandList[i].MINumOperands); 80201360Srdivacky 81193323Sed if (CStr.empty()) return; 82201360Srdivacky 83193323Sed const std::string delims(","); 84193323Sed std::string::size_type bidx, eidx; 85201360Srdivacky 86193323Sed bidx = CStr.find_first_not_of(delims); 87193323Sed while (bidx != std::string::npos) { 88193323Sed eidx = CStr.find_first_of(delims, bidx); 89193323Sed if (eidx == std::string::npos) 90193323Sed eidx = CStr.length(); 91201360Srdivacky 92198090Srdivacky ParseConstraint(CStr.substr(bidx, eidx - bidx), I); 93193323Sed bidx = CStr.find_first_not_of(delims, eidx); 94193323Sed } 95193323Sed} 96193323Sed 97193323SedCodeGenInstruction::CodeGenInstruction(Record *R, const std::string &AsmStr) 98193323Sed : TheDef(R), AsmString(AsmStr) { 99193323Sed Namespace = R->getValueAsString("Namespace"); 100193323Sed 101193323Sed isReturn = R->getValueAsBit("isReturn"); 102193323Sed isBranch = R->getValueAsBit("isBranch"); 103193323Sed isIndirectBranch = R->getValueAsBit("isIndirectBranch"); 104193323Sed isBarrier = R->getValueAsBit("isBarrier"); 105193323Sed isCall = R->getValueAsBit("isCall"); 106193323Sed canFoldAsLoad = R->getValueAsBit("canFoldAsLoad"); 107193323Sed mayLoad = R->getValueAsBit("mayLoad"); 108193323Sed mayStore = R->getValueAsBit("mayStore"); 109193323Sed bool isTwoAddress = R->getValueAsBit("isTwoAddress"); 110193323Sed isPredicable = R->getValueAsBit("isPredicable"); 111193323Sed isConvertibleToThreeAddress = R->getValueAsBit("isConvertibleToThreeAddress"); 112193323Sed isCommutable = R->getValueAsBit("isCommutable"); 113193323Sed isTerminator = R->getValueAsBit("isTerminator"); 114193323Sed isReMaterializable = R->getValueAsBit("isReMaterializable"); 115193323Sed hasDelaySlot = R->getValueAsBit("hasDelaySlot"); 116198892Srdivacky usesCustomInserter = R->getValueAsBit("usesCustomInserter"); 117193323Sed hasCtrlDep = R->getValueAsBit("hasCtrlDep"); 118193323Sed isNotDuplicable = R->getValueAsBit("isNotDuplicable"); 119193323Sed hasSideEffects = R->getValueAsBit("hasSideEffects"); 120193323Sed neverHasSideEffects = R->getValueAsBit("neverHasSideEffects"); 121193323Sed isAsCheapAsAMove = R->getValueAsBit("isAsCheapAsAMove"); 122198090Srdivacky hasExtraSrcRegAllocReq = R->getValueAsBit("hasExtraSrcRegAllocReq"); 123198090Srdivacky hasExtraDefRegAllocReq = R->getValueAsBit("hasExtraDefRegAllocReq"); 124193323Sed hasOptionalDef = false; 125193323Sed isVariadic = false; 126205407Srdivacky ImplicitDefs = R->getValueAsListOfDefs("Defs"); 127205407Srdivacky ImplicitUses = R->getValueAsListOfDefs("Uses"); 128193323Sed 129204642Srdivacky if (neverHasSideEffects + hasSideEffects > 1) 130193323Sed throw R->getName() + ": multiple conflicting side-effect flags set!"; 131193323Sed 132205407Srdivacky DagInit *OutDI = R->getValueAsDag("OutOperandList"); 133193323Sed 134205407Srdivacky if (DefInit *Init = dynamic_cast<DefInit*>(OutDI->getOperator())) { 135205407Srdivacky if (Init->getDef()->getName() != "outs") 136205407Srdivacky throw R->getName() + ": invalid def name for output list: use 'outs'"; 137205407Srdivacky } else 138205407Srdivacky throw R->getName() + ": invalid output list: use 'outs'"; 139205407Srdivacky 140205407Srdivacky NumDefs = OutDI->getNumArgs(); 141205407Srdivacky 142205407Srdivacky DagInit *InDI = R->getValueAsDag("InOperandList"); 143205407Srdivacky if (DefInit *Init = dynamic_cast<DefInit*>(InDI->getOperator())) { 144205407Srdivacky if (Init->getDef()->getName() != "ins") 145205407Srdivacky throw R->getName() + ": invalid def name for input list: use 'ins'"; 146205407Srdivacky } else 147205407Srdivacky throw R->getName() + ": invalid input list: use 'ins'"; 148205407Srdivacky 149193323Sed unsigned MIOperandNo = 0; 150193323Sed std::set<std::string> OperandNames; 151205407Srdivacky for (unsigned i = 0, e = InDI->getNumArgs()+OutDI->getNumArgs(); i != e; ++i){ 152205407Srdivacky Init *ArgInit; 153205407Srdivacky std::string ArgName; 154205407Srdivacky if (i < NumDefs) { 155205407Srdivacky ArgInit = OutDI->getArg(i); 156205407Srdivacky ArgName = OutDI->getArgName(i); 157205407Srdivacky } else { 158205407Srdivacky ArgInit = InDI->getArg(i-NumDefs); 159205407Srdivacky ArgName = InDI->getArgName(i-NumDefs); 160205407Srdivacky } 161205407Srdivacky 162205407Srdivacky DefInit *Arg = dynamic_cast<DefInit*>(ArgInit); 163193323Sed if (!Arg) 164193323Sed throw "Illegal operand for the '" + R->getName() + "' instruction!"; 165193323Sed 166193323Sed Record *Rec = Arg->getDef(); 167193323Sed std::string PrintMethod = "printOperand"; 168193323Sed unsigned NumOps = 1; 169193323Sed DagInit *MIOpInfo = 0; 170193323Sed if (Rec->isSubClassOf("Operand")) { 171193323Sed PrintMethod = Rec->getValueAsString("PrintMethod"); 172193323Sed MIOpInfo = Rec->getValueAsDag("MIOperandInfo"); 173201360Srdivacky 174193323Sed // Verify that MIOpInfo has an 'ops' root value. 175193323Sed if (!dynamic_cast<DefInit*>(MIOpInfo->getOperator()) || 176193323Sed dynamic_cast<DefInit*>(MIOpInfo->getOperator()) 177193323Sed ->getDef()->getName() != "ops") 178193323Sed throw "Bad value for MIOperandInfo in operand '" + Rec->getName() + 179193323Sed "'\n"; 180193323Sed 181193323Sed // If we have MIOpInfo, then we have #operands equal to number of entries 182193323Sed // in MIOperandInfo. 183193323Sed if (unsigned NumArgs = MIOpInfo->getNumArgs()) 184193323Sed NumOps = NumArgs; 185193323Sed 186193323Sed if (Rec->isSubClassOf("PredicateOperand")) 187193323Sed isPredicable = true; 188193323Sed else if (Rec->isSubClassOf("OptionalDefOperand")) 189193323Sed hasOptionalDef = true; 190193323Sed } else if (Rec->getName() == "variable_ops") { 191193323Sed isVariadic = true; 192193323Sed continue; 193201360Srdivacky } else if (!Rec->isSubClassOf("RegisterClass") && 194193323Sed Rec->getName() != "ptr_rc" && Rec->getName() != "unknown") 195193323Sed throw "Unknown operand class '" + Rec->getName() + 196193323Sed "' in '" + R->getName() + "' instruction!"; 197193323Sed 198193323Sed // Check that the operand has a name and that it's unique. 199205407Srdivacky if (ArgName.empty()) 200193323Sed throw "In instruction '" + R->getName() + "', operand #" + utostr(i) + 201193323Sed " has no name!"; 202205407Srdivacky if (!OperandNames.insert(ArgName).second) 203193323Sed throw "In instruction '" + R->getName() + "', operand #" + utostr(i) + 204193323Sed " has the same name as a previous operand!"; 205201360Srdivacky 206205407Srdivacky OperandList.push_back(OperandInfo(Rec, ArgName, PrintMethod, 207193323Sed MIOperandNo, NumOps, MIOpInfo)); 208193323Sed MIOperandNo += NumOps; 209193323Sed } 210193323Sed 211193323Sed // Parse Constraints. 212193323Sed ParseConstraints(R->getValueAsString("Constraints"), this); 213201360Srdivacky 214193323Sed // For backward compatibility: isTwoAddress means operand 1 is tied to 215193323Sed // operand 0. 216193323Sed if (isTwoAddress) { 217203954Srdivacky if (!OperandList[1].Constraints[0].isNone()) 218193323Sed throw R->getName() + ": cannot use isTwoAddress property: instruction " 219193323Sed "already has constraint set!"; 220203954Srdivacky OperandList[1].Constraints[0] = 221203954Srdivacky CodeGenInstruction::ConstraintInfo::getTied(0); 222193323Sed } 223201360Srdivacky 224193323Sed // Parse the DisableEncoding field. 225193323Sed std::string DisableEncoding = R->getValueAsString("DisableEncoding"); 226193323Sed while (1) { 227202375Srdivacky std::string OpName; 228202375Srdivacky tie(OpName, DisableEncoding) = getToken(DisableEncoding, " ,\t"); 229193323Sed if (OpName.empty()) break; 230193323Sed 231193323Sed // Figure out which operand this is. 232193323Sed std::pair<unsigned,unsigned> Op = ParseOperandName(OpName, false); 233193323Sed 234193323Sed // Mark the operand as not-to-be encoded. 235193323Sed if (Op.second >= OperandList[Op.first].DoNotEncode.size()) 236193323Sed OperandList[Op.first].DoNotEncode.resize(Op.second+1); 237193323Sed OperandList[Op.first].DoNotEncode[Op.second] = true; 238193323Sed } 239193323Sed} 240193323Sed 241193323Sed/// getOperandNamed - Return the index of the operand with the specified 242193323Sed/// non-empty name. If the instruction does not have an operand with the 243193323Sed/// specified name, throw an exception. 244193323Sed/// 245193323Sedunsigned CodeGenInstruction::getOperandNamed(const std::string &Name) const { 246193323Sed assert(!Name.empty() && "Cannot search for operand with no name!"); 247193323Sed for (unsigned i = 0, e = OperandList.size(); i != e; ++i) 248193323Sed if (OperandList[i].Name == Name) return i; 249193323Sed throw "Instruction '" + TheDef->getName() + 250193323Sed "' does not have an operand named '$" + Name + "'!"; 251193323Sed} 252193323Sed 253201360Srdivackystd::pair<unsigned,unsigned> 254193323SedCodeGenInstruction::ParseOperandName(const std::string &Op, 255193323Sed bool AllowWholeOp) { 256193323Sed if (Op.empty() || Op[0] != '$') 257193323Sed throw TheDef->getName() + ": Illegal operand name: '" + Op + "'"; 258201360Srdivacky 259193323Sed std::string OpName = Op.substr(1); 260193323Sed std::string SubOpName; 261201360Srdivacky 262193323Sed // Check to see if this is $foo.bar. 263193323Sed std::string::size_type DotIdx = OpName.find_first_of("."); 264193323Sed if (DotIdx != std::string::npos) { 265193323Sed SubOpName = OpName.substr(DotIdx+1); 266193323Sed if (SubOpName.empty()) 267193323Sed throw TheDef->getName() + ": illegal empty suboperand name in '" +Op +"'"; 268193323Sed OpName = OpName.substr(0, DotIdx); 269193323Sed } 270201360Srdivacky 271193323Sed unsigned OpIdx = getOperandNamed(OpName); 272193323Sed 273193323Sed if (SubOpName.empty()) { // If no suboperand name was specified: 274193323Sed // If one was needed, throw. 275193323Sed if (OperandList[OpIdx].MINumOperands > 1 && !AllowWholeOp && 276193323Sed SubOpName.empty()) 277193323Sed throw TheDef->getName() + ": Illegal to refer to" 278193323Sed " whole operand part of complex operand '" + Op + "'"; 279201360Srdivacky 280193323Sed // Otherwise, return the operand. 281193323Sed return std::make_pair(OpIdx, 0U); 282193323Sed } 283201360Srdivacky 284193323Sed // Find the suboperand number involved. 285193323Sed DagInit *MIOpInfo = OperandList[OpIdx].MIOperandInfo; 286193323Sed if (MIOpInfo == 0) 287193323Sed throw TheDef->getName() + ": unknown suboperand name in '" + Op + "'"; 288201360Srdivacky 289193323Sed // Find the operand with the right name. 290193323Sed for (unsigned i = 0, e = MIOpInfo->getNumArgs(); i != e; ++i) 291193323Sed if (MIOpInfo->getArgName(i) == SubOpName) 292193323Sed return std::make_pair(OpIdx, i); 293193323Sed 294193323Sed // Otherwise, didn't find it! 295193323Sed throw TheDef->getName() + ": unknown suboperand name in '" + Op + "'"; 296193323Sed} 297