2008-01-06 02:35:39 +01:00
|
|
|
//===- CodeGenInstruction.cpp - CodeGen Instruction Class Wrapper ---------===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file implements the CodeGenInstruction class.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "CodeGenInstruction.h"
|
2010-03-27 21:09:24 +01:00
|
|
|
#include "CodeGenTarget.h"
|
2008-01-06 02:35:39 +01:00
|
|
|
#include "Record.h"
|
|
|
|
#include "llvm/ADT/StringExtras.h"
|
2010-11-06 08:06:09 +01:00
|
|
|
#include "llvm/ADT/StringMap.h"
|
2010-01-11 19:03:24 +01:00
|
|
|
#include "llvm/ADT/STLExtras.h"
|
2008-01-06 02:35:39 +01:00
|
|
|
#include <set>
|
|
|
|
using namespace llvm;
|
|
|
|
|
2010-11-01 05:03:32 +01:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// CGIOperandList Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
2008-01-06 02:35:39 +01:00
|
|
|
|
2010-11-01 05:03:32 +01:00
|
|
|
CGIOperandList::CGIOperandList(Record *R) : TheDef(R) {
|
|
|
|
isPredicable = false;
|
2008-01-06 02:35:39 +01:00
|
|
|
hasOptionalDef = false;
|
2008-01-07 06:19:29 +01:00
|
|
|
isVariadic = false;
|
2010-11-01 05:03:32 +01:00
|
|
|
|
2010-03-18 22:07:39 +01:00
|
|
|
DagInit *OutDI = R->getValueAsDag("OutOperandList");
|
2010-11-01 05:03:32 +01:00
|
|
|
|
2010-03-18 22:07:39 +01:00
|
|
|
if (DefInit *Init = dynamic_cast<DefInit*>(OutDI->getOperator())) {
|
2010-03-18 21:56:35 +01:00
|
|
|
if (Init->getDef()->getName() != "outs")
|
2010-03-18 21:50:52 +01:00
|
|
|
throw R->getName() + ": invalid def name for output list: use 'outs'";
|
|
|
|
} else
|
|
|
|
throw R->getName() + ": invalid output list: use 'outs'";
|
2010-11-01 05:03:32 +01:00
|
|
|
|
2010-03-18 22:07:39 +01:00
|
|
|
NumDefs = OutDI->getNumArgs();
|
2010-11-01 05:03:32 +01:00
|
|
|
|
2010-03-18 22:07:39 +01:00
|
|
|
DagInit *InDI = R->getValueAsDag("InOperandList");
|
|
|
|
if (DefInit *Init = dynamic_cast<DefInit*>(InDI->getOperator())) {
|
2010-03-18 21:56:35 +01:00
|
|
|
if (Init->getDef()->getName() != "ins")
|
2010-03-18 21:50:52 +01:00
|
|
|
throw R->getName() + ": invalid def name for input list: use 'ins'";
|
|
|
|
} else
|
|
|
|
throw R->getName() + ": invalid input list: use 'ins'";
|
2010-11-01 05:03:32 +01:00
|
|
|
|
2008-01-06 02:35:39 +01:00
|
|
|
unsigned MIOperandNo = 0;
|
|
|
|
std::set<std::string> OperandNames;
|
2010-03-18 22:07:39 +01:00
|
|
|
for (unsigned i = 0, e = InDI->getNumArgs()+OutDI->getNumArgs(); i != e; ++i){
|
|
|
|
Init *ArgInit;
|
|
|
|
std::string ArgName;
|
|
|
|
if (i < NumDefs) {
|
|
|
|
ArgInit = OutDI->getArg(i);
|
|
|
|
ArgName = OutDI->getArgName(i);
|
|
|
|
} else {
|
|
|
|
ArgInit = InDI->getArg(i-NumDefs);
|
|
|
|
ArgName = InDI->getArgName(i-NumDefs);
|
|
|
|
}
|
|
|
|
|
|
|
|
DefInit *Arg = dynamic_cast<DefInit*>(ArgInit);
|
2008-01-06 02:35:39 +01:00
|
|
|
if (!Arg)
|
|
|
|
throw "Illegal operand for the '" + R->getName() + "' instruction!";
|
2010-11-01 05:03:32 +01:00
|
|
|
|
2008-01-06 02:35:39 +01:00
|
|
|
Record *Rec = Arg->getDef();
|
|
|
|
std::string PrintMethod = "printOperand";
|
2010-10-13 00:21:57 +02:00
|
|
|
std::string EncoderMethod;
|
2008-01-06 02:35:39 +01:00
|
|
|
unsigned NumOps = 1;
|
|
|
|
DagInit *MIOpInfo = 0;
|
|
|
|
if (Rec->isSubClassOf("Operand")) {
|
|
|
|
PrintMethod = Rec->getValueAsString("PrintMethod");
|
2010-10-13 00:21:57 +02:00
|
|
|
// If there is an explicit encoder method, use it.
|
|
|
|
if (Rec->getValue("EncoderMethod"))
|
|
|
|
EncoderMethod = Rec->getValueAsString("EncoderMethod");
|
2008-01-06 02:35:39 +01:00
|
|
|
MIOpInfo = Rec->getValueAsDag("MIOperandInfo");
|
2010-11-01 05:03:32 +01:00
|
|
|
|
2008-01-06 02:35:39 +01:00
|
|
|
// Verify that MIOpInfo has an 'ops' root value.
|
|
|
|
if (!dynamic_cast<DefInit*>(MIOpInfo->getOperator()) ||
|
|
|
|
dynamic_cast<DefInit*>(MIOpInfo->getOperator())
|
2010-11-01 05:03:32 +01:00
|
|
|
->getDef()->getName() != "ops")
|
2008-01-06 02:35:39 +01:00
|
|
|
throw "Bad value for MIOperandInfo in operand '" + Rec->getName() +
|
2010-11-01 05:03:32 +01:00
|
|
|
"'\n";
|
|
|
|
|
2008-01-06 02:35:39 +01:00
|
|
|
// If we have MIOpInfo, then we have #operands equal to number of entries
|
|
|
|
// in MIOperandInfo.
|
|
|
|
if (unsigned NumArgs = MIOpInfo->getNumArgs())
|
|
|
|
NumOps = NumArgs;
|
2010-11-01 05:03:32 +01:00
|
|
|
|
2008-01-06 02:35:39 +01:00
|
|
|
if (Rec->isSubClassOf("PredicateOperand"))
|
|
|
|
isPredicable = true;
|
|
|
|
else if (Rec->isSubClassOf("OptionalDefOperand"))
|
|
|
|
hasOptionalDef = true;
|
|
|
|
} else if (Rec->getName() == "variable_ops") {
|
2008-01-07 06:19:29 +01:00
|
|
|
isVariadic = true;
|
2008-01-06 02:35:39 +01:00
|
|
|
continue;
|
2009-12-15 20:28:13 +01:00
|
|
|
} else if (!Rec->isSubClassOf("RegisterClass") &&
|
2008-05-31 04:11:25 +02:00
|
|
|
Rec->getName() != "ptr_rc" && Rec->getName() != "unknown")
|
2008-01-06 02:35:39 +01:00
|
|
|
throw "Unknown operand class '" + Rec->getName() +
|
2010-11-01 05:03:32 +01:00
|
|
|
"' in '" + R->getName() + "' instruction!";
|
|
|
|
|
2008-01-06 02:35:39 +01:00
|
|
|
// Check that the operand has a name and that it's unique.
|
2010-03-18 22:07:39 +01:00
|
|
|
if (ArgName.empty())
|
2008-01-06 02:35:39 +01:00
|
|
|
throw "In instruction '" + R->getName() + "', operand #" + utostr(i) +
|
2010-11-01 05:03:32 +01:00
|
|
|
" has no name!";
|
2010-03-18 22:07:39 +01:00
|
|
|
if (!OperandNames.insert(ArgName).second)
|
2008-01-06 02:35:39 +01:00
|
|
|
throw "In instruction '" + R->getName() + "', operand #" + utostr(i) +
|
2010-11-01 05:03:32 +01:00
|
|
|
" has the same name as a previous operand!";
|
|
|
|
|
2010-10-13 00:21:57 +02:00
|
|
|
OperandList.push_back(OperandInfo(Rec, ArgName, PrintMethod, EncoderMethod,
|
2008-01-06 02:35:39 +01:00
|
|
|
MIOperandNo, NumOps, MIOpInfo));
|
|
|
|
MIOperandNo += NumOps;
|
|
|
|
}
|
2010-11-01 06:34:34 +01:00
|
|
|
|
|
|
|
|
|
|
|
// Make sure the constraints list for each operand is large enough to hold
|
|
|
|
// constraint info, even if none is present.
|
|
|
|
for (unsigned i = 0, e = OperandList.size(); i != e; ++i)
|
|
|
|
OperandList[i].Constraints.resize(OperandList[i].MINumOperands);
|
2008-01-06 02:35:39 +01:00
|
|
|
}
|
|
|
|
|
2010-11-01 05:03:32 +01:00
|
|
|
|
2008-01-06 02:35:39 +01:00
|
|
|
/// getOperandNamed - Return the index of the operand with the specified
|
|
|
|
/// non-empty name. If the instruction does not have an operand with the
|
|
|
|
/// specified name, throw an exception.
|
|
|
|
///
|
2010-11-01 05:03:32 +01:00
|
|
|
unsigned CGIOperandList::getOperandNamed(StringRef Name) const {
|
2010-10-11 20:25:51 +02:00
|
|
|
unsigned OpIdx;
|
|
|
|
if (hasOperandNamed(Name, OpIdx)) return OpIdx;
|
2010-11-01 05:03:32 +01:00
|
|
|
throw "'" + TheDef->getName() + "' does not have an operand named '$" +
|
|
|
|
Name.str() + "'!";
|
2008-01-06 02:35:39 +01:00
|
|
|
}
|
|
|
|
|
2010-10-11 20:25:51 +02:00
|
|
|
/// hasOperandNamed - Query whether the instruction has an operand of the
|
|
|
|
/// given name. If so, return true and set OpIdx to the index of the
|
|
|
|
/// operand. Otherwise, return false.
|
2010-11-01 05:03:32 +01:00
|
|
|
bool CGIOperandList::hasOperandNamed(StringRef Name, unsigned &OpIdx) const {
|
2010-10-11 20:25:51 +02:00
|
|
|
assert(!Name.empty() && "Cannot search for operand with no name!");
|
|
|
|
for (unsigned i = 0, e = OperandList.size(); i != e; ++i)
|
|
|
|
if (OperandList[i].Name == Name) {
|
|
|
|
OpIdx = i;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2009-12-15 20:28:13 +01:00
|
|
|
std::pair<unsigned,unsigned>
|
2010-11-01 05:03:32 +01:00
|
|
|
CGIOperandList::ParseOperandName(const std::string &Op, bool AllowWholeOp) {
|
2008-01-06 02:35:39 +01:00
|
|
|
if (Op.empty() || Op[0] != '$')
|
|
|
|
throw TheDef->getName() + ": Illegal operand name: '" + Op + "'";
|
2010-11-01 05:03:32 +01:00
|
|
|
|
2008-01-06 02:35:39 +01:00
|
|
|
std::string OpName = Op.substr(1);
|
|
|
|
std::string SubOpName;
|
2010-11-01 05:03:32 +01:00
|
|
|
|
2008-01-06 02:35:39 +01:00
|
|
|
// Check to see if this is $foo.bar.
|
|
|
|
std::string::size_type DotIdx = OpName.find_first_of(".");
|
|
|
|
if (DotIdx != std::string::npos) {
|
|
|
|
SubOpName = OpName.substr(DotIdx+1);
|
|
|
|
if (SubOpName.empty())
|
|
|
|
throw TheDef->getName() + ": illegal empty suboperand name in '" +Op +"'";
|
|
|
|
OpName = OpName.substr(0, DotIdx);
|
|
|
|
}
|
2010-11-01 05:03:32 +01:00
|
|
|
|
2008-01-06 02:35:39 +01:00
|
|
|
unsigned OpIdx = getOperandNamed(OpName);
|
2010-11-01 05:03:32 +01:00
|
|
|
|
2008-01-06 02:35:39 +01:00
|
|
|
if (SubOpName.empty()) { // If no suboperand name was specified:
|
|
|
|
// If one was needed, throw.
|
|
|
|
if (OperandList[OpIdx].MINumOperands > 1 && !AllowWholeOp &&
|
|
|
|
SubOpName.empty())
|
|
|
|
throw TheDef->getName() + ": Illegal to refer to"
|
2010-11-01 05:03:32 +01:00
|
|
|
" whole operand part of complex operand '" + Op + "'";
|
|
|
|
|
2008-01-06 02:35:39 +01:00
|
|
|
// Otherwise, return the operand.
|
|
|
|
return std::make_pair(OpIdx, 0U);
|
|
|
|
}
|
2010-11-01 05:03:32 +01:00
|
|
|
|
2008-01-06 02:35:39 +01:00
|
|
|
// Find the suboperand number involved.
|
|
|
|
DagInit *MIOpInfo = OperandList[OpIdx].MIOperandInfo;
|
|
|
|
if (MIOpInfo == 0)
|
|
|
|
throw TheDef->getName() + ": unknown suboperand name in '" + Op + "'";
|
2010-11-01 05:03:32 +01:00
|
|
|
|
2008-01-06 02:35:39 +01:00
|
|
|
// Find the operand with the right name.
|
|
|
|
for (unsigned i = 0, e = MIOpInfo->getNumArgs(); i != e; ++i)
|
|
|
|
if (MIOpInfo->getArgName(i) == SubOpName)
|
|
|
|
return std::make_pair(OpIdx, i);
|
2010-11-01 05:03:32 +01:00
|
|
|
|
2008-01-06 02:35:39 +01:00
|
|
|
// Otherwise, didn't find it!
|
|
|
|
throw TheDef->getName() + ": unknown suboperand name in '" + Op + "'";
|
|
|
|
}
|
2010-03-27 21:09:24 +01:00
|
|
|
|
2010-11-01 05:03:32 +01:00
|
|
|
static void ParseConstraint(const std::string &CStr, CGIOperandList &Ops) {
|
|
|
|
// 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 = Ops.ParseOperandName(Name, false);
|
|
|
|
|
|
|
|
// Build the string for the operand
|
|
|
|
if (!Ops[Op.first].Constraints[Op.second].isNone())
|
|
|
|
throw "Operand '" + Name + "' cannot have multiple constraints!";
|
|
|
|
Ops[Op.first].Constraints[Op.second] =
|
|
|
|
CGIOperandList::ConstraintInfo::getEarlyClobber();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Only other constraint is "TIED_TO" for now.
|
|
|
|
std::string::size_type pos = CStr.find_first_of('=');
|
|
|
|
assert(pos != std::string::npos && "Unrecognized constraint");
|
|
|
|
start = CStr.find_first_not_of(" \t");
|
|
|
|
std::string Name = CStr.substr(start, pos - start);
|
|
|
|
|
|
|
|
// TIED_TO: $src1 = $dst
|
|
|
|
wpos = Name.find_first_of(" \t");
|
|
|
|
if (wpos == std::string::npos)
|
|
|
|
throw "Illegal format for tied-to constraint: '" + CStr + "'";
|
|
|
|
std::string DestOpName = Name.substr(0, wpos);
|
|
|
|
std::pair<unsigned,unsigned> DestOp = Ops.ParseOperandName(DestOpName, false);
|
|
|
|
|
|
|
|
Name = CStr.substr(pos+1);
|
|
|
|
wpos = Name.find_first_not_of(" \t");
|
|
|
|
if (wpos == std::string::npos)
|
|
|
|
throw "Illegal format for tied-to constraint: '" + CStr + "'";
|
|
|
|
|
|
|
|
std::pair<unsigned,unsigned> SrcOp =
|
|
|
|
Ops.ParseOperandName(Name.substr(wpos), false);
|
|
|
|
if (SrcOp > DestOp)
|
|
|
|
throw "Illegal tied-to operand constraint '" + CStr + "'";
|
|
|
|
|
|
|
|
|
|
|
|
unsigned FlatOpNo = Ops.getFlattenedOperandNumber(SrcOp);
|
|
|
|
|
|
|
|
if (!Ops[DestOp.first].Constraints[DestOp.second].isNone())
|
|
|
|
throw "Operand '" + DestOpName + "' cannot have multiple constraints!";
|
|
|
|
Ops[DestOp.first].Constraints[DestOp.second] =
|
|
|
|
CGIOperandList::ConstraintInfo::getTied(FlatOpNo);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void ParseConstraints(const std::string &CStr, CGIOperandList &Ops) {
|
|
|
|
if (CStr.empty()) return;
|
|
|
|
|
|
|
|
const std::string delims(",");
|
|
|
|
std::string::size_type bidx, eidx;
|
|
|
|
|
|
|
|
bidx = CStr.find_first_not_of(delims);
|
|
|
|
while (bidx != std::string::npos) {
|
|
|
|
eidx = CStr.find_first_of(delims, bidx);
|
|
|
|
if (eidx == std::string::npos)
|
|
|
|
eidx = CStr.length();
|
|
|
|
|
|
|
|
ParseConstraint(CStr.substr(bidx, eidx - bidx), Ops);
|
|
|
|
bidx = CStr.find_first_not_of(delims, eidx);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CGIOperandList::ProcessDisableEncoding(std::string DisableEncoding) {
|
|
|
|
while (1) {
|
|
|
|
std::string OpName;
|
|
|
|
tie(OpName, DisableEncoding) = getToken(DisableEncoding, " ,\t");
|
|
|
|
if (OpName.empty()) break;
|
|
|
|
|
|
|
|
// Figure out which operand this is.
|
|
|
|
std::pair<unsigned,unsigned> Op = ParseOperandName(OpName, false);
|
|
|
|
|
|
|
|
// Mark the operand as not-to-be encoded.
|
|
|
|
if (Op.second >= OperandList[Op.first].DoNotEncode.size())
|
|
|
|
OperandList[Op.first].DoNotEncode.resize(Op.second+1);
|
|
|
|
OperandList[Op.first].DoNotEncode[Op.second] = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// CodeGenInstruction Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
CodeGenInstruction::CodeGenInstruction(Record *R) : TheDef(R), Operands(R) {
|
|
|
|
Namespace = R->getValueAsString("Namespace");
|
|
|
|
AsmString = R->getValueAsString("AsmString");
|
|
|
|
|
|
|
|
isReturn = R->getValueAsBit("isReturn");
|
|
|
|
isBranch = R->getValueAsBit("isBranch");
|
|
|
|
isIndirectBranch = R->getValueAsBit("isIndirectBranch");
|
|
|
|
isCompare = R->getValueAsBit("isCompare");
|
|
|
|
isBarrier = R->getValueAsBit("isBarrier");
|
|
|
|
isCall = R->getValueAsBit("isCall");
|
|
|
|
canFoldAsLoad = R->getValueAsBit("canFoldAsLoad");
|
|
|
|
mayLoad = R->getValueAsBit("mayLoad");
|
|
|
|
mayStore = R->getValueAsBit("mayStore");
|
|
|
|
isPredicable = Operands.isPredicable || R->getValueAsBit("isPredicable");
|
|
|
|
isConvertibleToThreeAddress = R->getValueAsBit("isConvertibleToThreeAddress");
|
|
|
|
isCommutable = R->getValueAsBit("isCommutable");
|
|
|
|
isTerminator = R->getValueAsBit("isTerminator");
|
|
|
|
isReMaterializable = R->getValueAsBit("isReMaterializable");
|
|
|
|
hasDelaySlot = R->getValueAsBit("hasDelaySlot");
|
|
|
|
usesCustomInserter = R->getValueAsBit("usesCustomInserter");
|
|
|
|
hasCtrlDep = R->getValueAsBit("hasCtrlDep");
|
|
|
|
isNotDuplicable = R->getValueAsBit("isNotDuplicable");
|
|
|
|
hasSideEffects = R->getValueAsBit("hasSideEffects");
|
|
|
|
neverHasSideEffects = R->getValueAsBit("neverHasSideEffects");
|
|
|
|
isAsCheapAsAMove = R->getValueAsBit("isAsCheapAsAMove");
|
|
|
|
hasExtraSrcRegAllocReq = R->getValueAsBit("hasExtraSrcRegAllocReq");
|
|
|
|
hasExtraDefRegAllocReq = R->getValueAsBit("hasExtraDefRegAllocReq");
|
|
|
|
ImplicitDefs = R->getValueAsListOfDefs("Defs");
|
|
|
|
ImplicitUses = R->getValueAsListOfDefs("Uses");
|
|
|
|
|
|
|
|
if (neverHasSideEffects + hasSideEffects > 1)
|
|
|
|
throw R->getName() + ": multiple conflicting side-effect flags set!";
|
|
|
|
|
|
|
|
// Parse Constraints.
|
|
|
|
ParseConstraints(R->getValueAsString("Constraints"), Operands);
|
|
|
|
|
|
|
|
// Parse the DisableEncoding field.
|
|
|
|
Operands.ProcessDisableEncoding(R->getValueAsString("DisableEncoding"));
|
|
|
|
}
|
2010-03-27 21:09:24 +01:00
|
|
|
|
|
|
|
/// HasOneImplicitDefWithKnownVT - If the instruction has at least one
|
|
|
|
/// implicit def and it has a known VT, return the VT, otherwise return
|
|
|
|
/// MVT::Other.
|
|
|
|
MVT::SimpleValueType CodeGenInstruction::
|
|
|
|
HasOneImplicitDefWithKnownVT(const CodeGenTarget &TargetInfo) const {
|
|
|
|
if (ImplicitDefs.empty()) return MVT::Other;
|
|
|
|
|
|
|
|
// Check to see if the first implicit def has a resolvable type.
|
|
|
|
Record *FirstImplicitDef = ImplicitDefs[0];
|
|
|
|
assert(FirstImplicitDef->isSubClassOf("Register"));
|
|
|
|
const std::vector<MVT::SimpleValueType> &RegVTs =
|
|
|
|
TargetInfo.getRegisterVTs(FirstImplicitDef);
|
|
|
|
if (RegVTs.size() == 1)
|
|
|
|
return RegVTs[0];
|
|
|
|
return MVT::Other;
|
|
|
|
}
|
|
|
|
|
2010-11-01 02:07:14 +01:00
|
|
|
|
|
|
|
/// FlattenAsmStringVariants - Flatten the specified AsmString to only
|
|
|
|
/// include text from the specified variant, returning the new string.
|
|
|
|
std::string CodeGenInstruction::
|
|
|
|
FlattenAsmStringVariants(StringRef Cur, unsigned Variant) {
|
|
|
|
std::string Res = "";
|
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
// Find the start of the next variant string.
|
|
|
|
size_t VariantsStart = 0;
|
|
|
|
for (size_t e = Cur.size(); VariantsStart != e; ++VariantsStart)
|
|
|
|
if (Cur[VariantsStart] == '{' &&
|
|
|
|
(VariantsStart == 0 || (Cur[VariantsStart-1] != '$' &&
|
|
|
|
Cur[VariantsStart-1] != '\\')))
|
|
|
|
break;
|
|
|
|
|
|
|
|
// Add the prefix to the result.
|
|
|
|
Res += Cur.slice(0, VariantsStart);
|
|
|
|
if (VariantsStart == Cur.size())
|
|
|
|
break;
|
|
|
|
|
|
|
|
++VariantsStart; // Skip the '{'.
|
|
|
|
|
|
|
|
// Scan to the end of the variants string.
|
|
|
|
size_t VariantsEnd = VariantsStart;
|
|
|
|
unsigned NestedBraces = 1;
|
|
|
|
for (size_t e = Cur.size(); VariantsEnd != e; ++VariantsEnd) {
|
|
|
|
if (Cur[VariantsEnd] == '}' && Cur[VariantsEnd-1] != '\\') {
|
|
|
|
if (--NestedBraces == 0)
|
|
|
|
break;
|
|
|
|
} else if (Cur[VariantsEnd] == '{')
|
|
|
|
++NestedBraces;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Select the Nth variant (or empty).
|
|
|
|
StringRef Selection = Cur.slice(VariantsStart, VariantsEnd);
|
|
|
|
for (unsigned i = 0; i != Variant; ++i)
|
|
|
|
Selection = Selection.split('|').second;
|
|
|
|
Res += Selection.split('|').first;
|
|
|
|
|
|
|
|
assert(VariantsEnd != Cur.size() &&
|
|
|
|
"Unterminated variants in assembly string!");
|
|
|
|
Cur = Cur.substr(VariantsEnd + 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
return Res;
|
|
|
|
}
|
|
|
|
|
2010-11-01 05:05:41 +01:00
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
/// CodeGenInstAlias Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
Reimplement BuildResultOperands to be in terms of the result instruction's
operand list instead of the operand list redundantly declared on the alias
or instruction.
With this change, we finally remove the ins/outs list on the alias. Before:
def : InstAlias<(outs GR16:$dst), (ins GR8 :$src),
"movsx $src, $dst",
(MOVSX16rr8W GR16:$dst, GR8:$src)>;
After:
def : InstAlias<"movsx $src, $dst",
(MOVSX16rr8W GR16:$dst, GR8:$src)>;
This also makes the alias mechanism more general and powerful, which will
be exploited in subsequent patches.
llvm-svn: 118329
2010-11-06 08:14:44 +01:00
|
|
|
CodeGenInstAlias::CodeGenInstAlias(Record *R, CodeGenTarget &T) : TheDef(R) {
|
2010-11-01 05:05:41 +01:00
|
|
|
AsmString = R->getValueAsString("AsmString");
|
2010-11-01 06:34:34 +01:00
|
|
|
Result = R->getValueAsDag("ResultInst");
|
2010-11-06 07:39:47 +01:00
|
|
|
|
|
|
|
// Verify that the root of the result is an instruction.
|
|
|
|
DefInit *DI = dynamic_cast<DefInit*>(Result->getOperator());
|
|
|
|
if (DI == 0 || !DI->getDef()->isSubClassOf("Instruction"))
|
|
|
|
throw TGError(R->getLoc(), "result of inst alias should be an instruction");
|
|
|
|
|
|
|
|
ResultInst = &T.getInstruction(DI->getDef());
|
2010-11-06 07:54:38 +01:00
|
|
|
|
2010-11-06 08:06:09 +01:00
|
|
|
// NameClass - If argument names are repeated, we need to verify they have
|
|
|
|
// the same class.
|
|
|
|
StringMap<Record*> NameClass;
|
2010-11-06 07:54:38 +01:00
|
|
|
|
|
|
|
// Decode and validate the arguments of the result.
|
2010-11-06 08:31:43 +01:00
|
|
|
unsigned AliasOpNo = 0;
|
|
|
|
for (unsigned i = 0, e = ResultInst->Operands.size(); i != e; ++i) {
|
|
|
|
// Tied registers don't have an entry in the result dag.
|
|
|
|
if (ResultInst->Operands[i].getTiedRegister() != -1)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (AliasOpNo >= Result->getNumArgs())
|
|
|
|
throw TGError(R->getLoc(), "result has " + utostr(Result->getNumArgs()) +
|
|
|
|
" arguments, but " + ResultInst->TheDef->getName() +
|
|
|
|
" instruction expects " +
|
|
|
|
utostr(ResultInst->Operands.size()) + " operands!");
|
|
|
|
|
|
|
|
|
|
|
|
Init *Arg = Result->getArg(AliasOpNo);
|
2010-11-06 07:54:38 +01:00
|
|
|
|
|
|
|
// If the operand is a record, it must have a name, and the record type must
|
|
|
|
// match up with the instruction's argument type.
|
|
|
|
if (DefInit *ADI = dynamic_cast<DefInit*>(Arg)) {
|
2010-11-06 08:31:43 +01:00
|
|
|
if (Result->getArgName(AliasOpNo).empty())
|
|
|
|
throw TGError(R->getLoc(), "result argument #" + utostr(AliasOpNo) +
|
2010-11-06 07:54:38 +01:00
|
|
|
" must have a name!");
|
|
|
|
|
|
|
|
if (ADI->getDef() != ResultInst->Operands[i].Rec)
|
2010-11-06 08:31:43 +01:00
|
|
|
throw TGError(R->getLoc(), "result argument #" + utostr(AliasOpNo) +
|
2010-11-06 07:54:38 +01:00
|
|
|
" declared with class " + ADI->getDef()->getName() +
|
|
|
|
", instruction operand is class " +
|
|
|
|
ResultInst->Operands[i].Rec->getName());
|
|
|
|
|
2010-11-06 08:06:09 +01:00
|
|
|
// 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
|
|
|
|
// same type.
|
2010-11-06 08:31:43 +01:00
|
|
|
Record *&Entry = NameClass[Result->getArgName(AliasOpNo)];
|
2010-11-06 08:06:09 +01:00
|
|
|
if (Entry && Entry != ADI->getDef())
|
2010-11-06 08:31:43 +01:00
|
|
|
throw TGError(R->getLoc(), "result value $" +
|
|
|
|
Result->getArgName(AliasOpNo) +
|
2010-11-06 08:06:09 +01:00
|
|
|
" is both " + Entry->getName() + " and " +
|
|
|
|
ADI->getDef()->getName() + "!");
|
|
|
|
|
2010-11-06 07:54:38 +01:00
|
|
|
// Now that it is validated, add it.
|
2010-11-06 08:31:43 +01:00
|
|
|
ResultOperands.push_back(ResultOperand(Result->getArgName(AliasOpNo),
|
2010-11-06 07:54:38 +01:00
|
|
|
ADI->getDef()));
|
2010-11-06 08:31:43 +01:00
|
|
|
++AliasOpNo;
|
2010-11-06 07:54:38 +01:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
throw TGError(R->getLoc(), "result of inst alias has unknown operand type");
|
|
|
|
}
|
2010-11-06 08:31:43 +01:00
|
|
|
|
|
|
|
if (AliasOpNo != Result->getNumArgs())
|
|
|
|
throw TGError(R->getLoc(), "result has " + utostr(Result->getNumArgs()) +
|
|
|
|
" arguments, but " + ResultInst->TheDef->getName() +
|
|
|
|
" instruction expects " + utostr(ResultInst->Operands.size())+
|
|
|
|
" operands!");
|
2010-11-01 05:05:41 +01:00
|
|
|
}
|