//===- InstrInfoEmitter.cpp - Generate a Instruction Set Desc. ------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
//
// This tablegen backend is responsible for emitting a description of the target
// instruction set for the code generator.
#include "Support/StringExtras.h"
#include <set>
+namespace llvm {
+
NodeType::ArgResultTypes NodeType::Translate(Record *R) {
const std::string &Name = R->getName();
+ if (Name == "DNVT_any") return Any;
if (Name == "DNVT_void") return Void;
if (Name == "DNVT_val" ) return Val;
if (Name == "DNVT_arg0") return Arg0;
+ if (Name == "DNVT_arg1") return Arg1;
if (Name == "DNVT_ptr" ) return Ptr;
+ if (Name == "DNVT_i8" ) return I8;
throw "Unknown DagNodeValType '" + Name + "'!";
}
return true;
}
- throw "Type inferfence contradiction found for pattern " + RecName;
+ throw "Type inference contradiction found for pattern " + RecName;
}
/// InstantiateNonterminals - If this pattern refers to any nonterminals which
///
void TreePatternNode::InstantiateNonterminals(InstrSelectorEmitter &ISE) {
if (!isLeaf()) {
- for (unsigned i = 0, e = Children.size(); i != e; ++i)
- Children[i]->InstantiateNonterminals(ISE);
+ for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
+ getChild(i)->InstantiateNonterminals(ISE);
return;
}
if (isLeaf()) {
New = new TreePatternNode(Value);
} else {
- std::vector<TreePatternNode*> CChildren(Children.size());
- for (unsigned i = 0, e = Children.size(); i != e; ++i)
- CChildren[i] = Children[i]->clone();
+ std::vector<std::pair<TreePatternNode*, std::string> > CChildren;
+ CChildren.reserve(Children.size());
+ for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
+ CChildren.push_back(std::make_pair(getChild(i)->clone(),getChildName(i)));
New = new TreePatternNode(Operator, CChildren);
}
New->setType(Type);
OS << "(" << N.getType() << ":";
OS << N.getOperator()->getName();
- const std::vector<TreePatternNode*> &Children = N.getChildren();
- if (!Children.empty()) {
- OS << " " << *Children[0];
- for (unsigned i = 1, e = Children.size(); i != e; ++i)
- OS << ", " << *Children[i];
+ if (N.getNumChildren() != 0) {
+ OS << " " << *N.getChild(0);
+ for (unsigned i = 1, e = N.getNumChildren(); i != e; ++i)
+ OS << ", " << *N.getChild(i);
}
return OS << ")";
}
//
Pattern::Pattern(PatternType pty, DagInit *RawPat, Record *TheRec,
InstrSelectorEmitter &ise)
- : PTy(pty), TheRecord(TheRec), ISE(ise) {
+ : PTy(pty), ResultNode(0), TheRecord(TheRec), ISE(ise) {
// First, parse the pattern...
Tree = ParseTreePattern(RawPat);
// Check to see if we have a top-level (set) of a register.
if (Tree->getOperator()->getName() == "set") {
- assert(Tree->getChildren().size() == 2 && "Set with != 2 arguments?");
+ assert(Tree->getNumChildren() == 2 && "Set with != 2 arguments?");
if (!Tree->getChild(0)->isLeaf())
error("Arg #0 of set should be a register or register class!");
- Result = Tree->getChild(0)->getValueRecord();
+ ResultNode = Tree->getChild(0);
+ ResultName = Tree->getChildName(0);
Tree = Tree->getChild(1);
}
}
+
+ calculateArgs(Tree, "");
}
void Pattern::error(const std::string &Msg) const {
throw M + TheRecord->getName() + ": " + Msg;
}
+/// calculateArgs - Compute the list of all of the arguments to this pattern,
+/// which are the non-void leaf nodes in this pattern.
+///
+void Pattern::calculateArgs(TreePatternNode *N, const std::string &Name) {
+ if (N->isLeaf() || N->getNumChildren() == 0) {
+ if (N->getType() != MVT::isVoid)
+ Args.push_back(std::make_pair(N, Name));
+ } else {
+ for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i)
+ calculateArgs(N->getChild(i), N->getChildName(i));
+ }
+}
+
/// getIntrinsicType - Check to see if the specified record has an intrinsic
/// type which should be applied to it. This infer the type of register
/// references from the register file information, for example.
return MVT::Other;
}
- throw "Error: Unknown value used: " + R->getName();
+ error("Unknown value used: " + R->getName());
+ return MVT::Other;
}
-TreePatternNode *Pattern::ParseTreePattern(DagInit *DI) {
- Record *Operator = DI->getNodeType();
- const std::vector<Init*> &Args = DI->getArgs();
+TreePatternNode *Pattern::ParseTreePattern(DagInit *Dag) {
+ Record *Operator = Dag->getNodeType();
if (Operator->isSubClassOf("ValueType")) {
// If the operator is a ValueType, then this must be "type cast" of a leaf
// node.
- if (Args.size() != 1)
+ if (Dag->getNumArgs() != 1)
error("Type cast only valid for a leaf node!");
- Init *Arg = Args[0];
+ Init *Arg = Dag->getArg(0);
TreePatternNode *New;
if (DefInit *DI = dynamic_cast<DefInit*>(Arg)) {
New = new TreePatternNode(DI);
// If it's a regclass or something else known, set the type.
New->setType(getIntrinsicType(DI->getDef()));
+ } else if (DagInit *DI = dynamic_cast<DagInit*>(Arg)) {
+ New = ParseTreePattern(DI);
} else {
Arg->dump();
error("Unknown leaf value for tree pattern!");
+ return 0;
}
// Apply the type cast...
if (!ISE.getNodeTypes().count(Operator))
error("Unrecognized node '" + Operator->getName() + "'!");
- std::vector<TreePatternNode*> Children;
+ std::vector<std::pair<TreePatternNode*, std::string> > Children;
- for (unsigned i = 0, e = Args.size(); i != e; ++i) {
- Init *Arg = Args[i];
+ for (unsigned i = 0, e = Dag->getNumArgs(); i != e; ++i) {
+ Init *Arg = Dag->getArg(i);
if (DagInit *DI = dynamic_cast<DagInit*>(Arg)) {
- Children.push_back(ParseTreePattern(DI));
- } else if (DefInit *DI = dynamic_cast<DefInit*>(Arg)) {
- Children.push_back(new TreePatternNode(DI));
- // If it's a regclass or something else known, set the type.
- Children.back()->setType(getIntrinsicType(DI->getDef()));
+ Children.push_back(std::make_pair(ParseTreePattern(DI),
+ Dag->getArgName(i)));
+ } else if (DefInit *DefI = dynamic_cast<DefInit*>(Arg)) {
+ Record *R = DefI->getDef();
+ // Direct reference to a leaf DagNode? Turn it into a DagNode if its own.
+ if (R->isSubClassOf("DagNode")) {
+ Dag->setArg(i, new DagInit(R,
+ std::vector<std::pair<Init*, std::string> >()));
+ --i; // Revisit this node...
+ } else {
+ Children.push_back(std::make_pair(new TreePatternNode(DefI),
+ Dag->getArgName(i)));
+ // If it's a regclass or something else known, set the type.
+ Children.back().first->setType(getIntrinsicType(R));
+ }
} else {
Arg->dump();
error("Unknown leaf value for tree pattern!");
// Check to see if we can infer anything about the argument types from the
// return types...
- const std::vector<TreePatternNode*> &Children = N->getChildren();
- if (Children.size() != NT.ArgTypes.size())
+ if (N->getNumChildren() != NT.ArgTypes.size())
error("Incorrect number of children for " + Operator->getName() + " node!");
- for (unsigned i = 0, e = Children.size(); i != e; ++i) {
- TreePatternNode *Child = Children[i];
+ for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i) {
+ TreePatternNode *Child = N->getChild(i);
AnyUnset |= InferTypes(Child, MadeChange);
switch (NT.ArgTypes[i]) {
+ case NodeType::Any: break;
+ case NodeType::I8:
+ MadeChange |= Child->updateNodeType(MVT::i1, TheRecord->getName());
+ break;
case NodeType::Arg0:
- MadeChange |= Child->updateNodeType(Children[0]->getType(),
+ MadeChange |= Child->updateNodeType(N->getChild(0)->getType(),
+ TheRecord->getName());
+ break;
+ case NodeType::Arg1:
+ MadeChange |= Child->updateNodeType(N->getChild(1)->getType(),
TheRecord->getName());
break;
case NodeType::Val:
MadeChange |= Child->updateNodeType(ISE.getTarget().getPointerType(),
TheRecord->getName());
break;
+ case NodeType::Void:
+ MadeChange |= Child->updateNodeType(MVT::isVoid, TheRecord->getName());
+ break;
default: assert(0 && "Invalid argument ArgType!");
}
}
// See if we can infer anything about the return type now...
switch (NT.ResultType) {
+ case NodeType::Any: break;
case NodeType::Void:
MadeChange |= N->updateNodeType(MVT::isVoid, TheRecord->getName());
break;
+ case NodeType::I8:
+ MadeChange |= N->updateNodeType(MVT::i1, TheRecord->getName());
+ break;
case NodeType::Arg0:
- MadeChange |= N->updateNodeType(Children[0]->getType(),
+ MadeChange |= N->updateNodeType(N->getChild(0)->getType(),
+ TheRecord->getName());
+ break;
+ case NodeType::Arg1:
+ MadeChange |= N->updateNodeType(N->getChild(1)->getType(),
TheRecord->getName());
break;
-
case NodeType::Ptr:
MadeChange |= N->updateNodeType(ISE.getTarget().getPointerType(),
TheRecord->getName());
} else {
assert(0 && "Don't know how to get a slot name for this!");
}
+ return "";
}
//===----------------------------------------------------------------------===//
if (a == 0 && ArgTypes.back() == NodeType::Arg0)
throw "In node " + Node->getName() + ", arg 0 cannot have type 'arg0'!";
- if (ArgTypes.back() == NodeType::Void)
- throw "In node " + Node->getName() + ", args cannot be void type!";
+ if (a == 1 && ArgTypes.back() == NodeType::Arg1)
+ throw "In node " + Node->getName() + ", arg 1 cannot have type 'arg1'!";
}
- if (RetTy == NodeType::Arg0 && Args->getSize() == 0)
+ if ((RetTy == NodeType::Arg0 && Args->getSize() == 0) ||
+ (RetTy == NodeType::Arg1 && Args->getSize() < 2))
throw "In node " + Node->getName() +
- ", invalid return type for nullary node!";
+ ", invalid return type for node with this many operands!";
// Add the node type mapping now...
NodeTypes[Node] = NodeType(RetTy, ArgTypes);
// Loop over all of the patterns, adding them to the ComputableValues map
for (std::map<Record*, Pattern*>::iterator I = Patterns.begin(),
E = Patterns.end(); I != E; ++I)
- if (I->second->isResolved())
- ComputableValues.addPattern(I->second);
+ if (I->second->isResolved()) {
+ // We don't want to add patterns like R32 = R32. This is a hack working
+ // around a special case of a general problem, but for now we explicitly
+ // forbid these patterns. They can never match anyway.
+ Pattern *P = I->second;
+ if (!P->getResult() || !P->getTree()->isLeaf() ||
+ P->getResult() != P->getTree()->getValueRecord())
+ ComputableValues.addPattern(P);
+ }
}
#if 0
OS << "\n" << Indent << "// Operand matching costs...\n";
std::set<std::string> ComputedValues; // Avoid duplicate computations...
for (unsigned i = 0, e = Patterns.size(); i != e; ++i) {
- const std::vector<TreePatternNode*> &Children =
- Patterns[i].second->getChildren();
- for (unsigned c = 0, e = Children.size(); c != e; ++c) {
- TreePatternNode *N = Children[c];
+ TreePatternNode *NParent = Patterns[i].second;
+ for (unsigned c = 0, e = NParent->getNumChildren(); c != e; ++c) {
+ TreePatternNode *N = NParent->getChild(c);
if (N->isLeaf()) {
Record *VR = N->getValueRecord();
const std::string &LeafName = VR->getName();
static void ReduceAllOperands(TreePatternNode *N, const std::string &Name,
std::vector<std::pair<TreePatternNode*, std::string> > &Operands,
std::ostream &OS) {
- if (!N->isLeaf()) {
+ if (N->isLeaf()) {
+ // If this is a leaf, register or nonterminal reference...
+ std::string SlotName = Pattern::getSlotName(N->getValueRecord());
+ OS << " ReducedValue_" << SlotName << " *" << Name << "Val = Reduce_"
+ << SlotName << "(" << Name << ", MBB);\n";
+ Operands.push_back(std::make_pair(N, Name+"Val"));
+ } else if (N->getNumChildren() == 0) {
+ // This is a reference to a leaf tree node, like an immediate or frame
+ // index.
+ if (N->getType() != MVT::isVoid) {
+ std::string SlotName =
+ getNodeName(N->getOperator()) + "_" + getName(N->getType());
+ OS << " ReducedValue_" << SlotName << " *" << Name << "Val = "
+ << Name << "->getValue<ReducedValue_" << SlotName << ">(ISD::"
+ << SlotName << "_Slot);\n";
+ Operands.push_back(std::make_pair(N, Name+"Val"));
+ }
+ } else {
+ // Otherwise this is an interior node...
for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i) {
std::string ChildName = Name + "_Op" + utostr(i);
OS << " SelectionDAGNode *" << ChildName << " = " << Name
<< "->getUse(" << i << ");\n";
ReduceAllOperands(N->getChild(i), ChildName, Operands, OS);
}
- } else {
- std::string SlotName = Pattern::getSlotName(N->getValueRecord());
- OS << " ReducedValue_" << SlotName << " *" << Name << "Val = Reduce_"
- << SlotName << "(" << Name << ", MBB);\n";
- Operands.push_back(std::make_pair(N, Name+"Val"));
}
}
+/// PrintExpanderOperand - Print out Arg as part of the instruction emission
+/// process for the expander pattern P. This argument may be referencing some
+/// values defined in P, or may just be physical register references or
+/// something like that. If PrintArg is true, we are printing out arguments to
+/// the BuildMI call. If it is false, we are printing the result register
+/// name.
+void InstrSelectorEmitter::PrintExpanderOperand(Init *Arg,
+ const std::string &NameVar,
+ TreePatternNode *ArgDeclNode,
+ Pattern *P, bool PrintArg,
+ std::ostream &OS) {
+ if (DefInit *DI = dynamic_cast<DefInit*>(Arg)) {
+ Record *Arg = DI->getDef();
+ if (!ArgDeclNode->isLeaf() && ArgDeclNode->getNumChildren() != 0)
+ P->error("Expected leaf node as argument!");
+ Record *ArgDecl = ArgDeclNode->isLeaf() ? ArgDeclNode->getValueRecord() :
+ ArgDeclNode->getOperator();
+ if (Arg->isSubClassOf("Register")) {
+ // This is a physical register reference... make sure that the instruction
+ // requested a register!
+ if (!ArgDecl->isSubClassOf("RegisterClass"))
+ P->error("Argument mismatch for instruction pattern!");
+
+ // FIXME: This should check to see if the register is in the specified
+ // register class!
+ if (PrintArg) OS << ".addReg(";
+ OS << getQualifiedName(Arg);
+ if (PrintArg) OS << ")";
+ return;
+ } else if (Arg->isSubClassOf("RegisterClass")) {
+ // If this is a symbolic register class reference, we must be using a
+ // named value.
+ if (NameVar.empty()) P->error("Did not specify WHICH register to pass!");
+ if (Arg != ArgDecl) P->error("Instruction pattern mismatch!");
+
+ if (PrintArg) OS << ".addReg(";
+ OS << NameVar;
+ if (PrintArg) OS << ")";
+ return;
+ } else if (Arg->getName() == "frameidx") {
+ if (!PrintArg) P->error("Cannot define a new frameidx value!");
+ OS << ".addFrameIndex(" << NameVar << ")";
+ return;
+ } else if (Arg->getName() == "basicblock") {
+ if (!PrintArg) P->error("Cannot define a new basicblock value!");
+ OS << ".addMBB(" << NameVar << ")";
+ return;
+ }
+ P->error("Unknown operand type '" + Arg->getName() + "' to expander!");
+ } else if (IntInit *II = dynamic_cast<IntInit*>(Arg)) {
+ if (!NameVar.empty())
+ P->error("Illegal to specify a name for a constant initializer arg!");
+
+ // Hack this check to allow R32 values with 0 as the initializer for memory
+ // references... FIXME!
+ if (ArgDeclNode->isLeaf() && II->getValue() == 0 &&
+ ArgDeclNode->getValueRecord()->getName() == "R32") {
+ OS << ".addReg(0)";
+ } else {
+ if (ArgDeclNode->isLeaf() || ArgDeclNode->getOperator()->getName()!="imm")
+ P->error("Illegal immediate int value '" + itostr(II->getValue()) +
+ "' operand!");
+ OS << ".addZImm(" << II->getValue() << ")";
+ }
+ return;
+ }
+ P->error("Unknown operand type to expander!");
+}
+
+static std::string getArgName(Pattern *P, const std::string &ArgName,
+ const std::vector<std::pair<TreePatternNode*, std::string> > &Operands) {
+ assert(P->getNumArgs() == Operands.size() &&"Argument computation mismatch!");
+ if (ArgName.empty()) return "";
+
+ for (unsigned i = 0, e = P->getNumArgs(); i != e; ++i)
+ if (P->getArgName(i) == ArgName)
+ return Operands[i].second + "->Val";
+
+ if (ArgName == P->getResultName())
+ return "NewReg";
+ P->error("Pattern does not define a value named $" + ArgName + "!");
+ return "";
+}
+
+
void InstrSelectorEmitter::run(std::ostream &OS) {
// Type-check all of the node types to ensure we "understand" them.
ReadNodeTypes();
// Clear InstantiatedNTs, we don't need it anymore...
InstantiatedNTs.clear();
- std::cerr << "Patterns aquired:\n";
+ DEBUG(std::cerr << "Patterns acquired:\n");
for (std::map<Record*, Pattern*>::iterator I = Patterns.begin(),
E = Patterns.end(); I != E; ++I)
if (I->second->isResolved())
- std::cerr << " " << *I->second << "\n";
+ DEBUG(std::cerr << " " << *I->second << "\n");
CalculateComputableValues();
+ OS << "#include \"llvm/CodeGen/MachineInstrBuilder.h\"\n";
+
EmitSourceFileHeader("Instruction Selector for the " + Target.getName() +
" target", OS);
<< " class " << Target.getName() << "ISel {\n"
<< " SelectionDAG &DAG;\n"
<< " public:\n"
- << " X86ISel(SelectionDAG &D) : DAG(D) {}\n"
+ << " " << Target.getName () << "ISel(SelectionDAG &D) : DAG(D) {}\n"
<< " void generateCode();\n"
<< " private:\n"
<< " unsigned makeAnotherReg(const TargetRegisterClass *RC) {\n"
OS << " };\n}\n\n";
// Emit the generateCode entry-point...
- OS << "void X86ISel::generateCode() {\n"
+ OS << "void " << Target.getName () << "ISel::generateCode() {\n"
<< " SelectionDAGNode *Root = DAG.getRoot();\n"
<< " assert(Root->getValueType() == MVT::isVoid && "
"\"Root of DAG produces value??\");\n\n"
<< " return N->getCostFor(" << SlotName << "_Slot);\n\n"
<< " unsigned Cost;\n"
<< " switch (N->getNodeType()) {\n"
- << " default: assert(0 && \"Unhandled node type for " << SlotName
- << "!\");\n";
+ << " default: Cost = ~0U >> 1; // Match failed\n"
+ << " N->setPatternCostFor(" << SlotName << "_Slot, NoMatchPattern, Cost, NumSlots);\n"
+ << " break;\n";
for (PatternOrganizer::NodesForSlot::iterator J = I->second.begin(),
E = I->second.end(); J != E; ++J)
std::vector<std::pair<TreePatternNode*, std::string> > Operands;
ReduceAllOperands(P->getTree(), "N", Operands, OS);
+ // Now that we have reduced all of our operands, and have the values
+ // that reduction produces, perform the reduction action for this
+ // pattern.
+ std::string Result;
+
+ // If the pattern produces a register result, generate a new register
+ // now.
+ if (Record *R = P->getResult()) {
+ assert(R->isSubClassOf("RegisterClass") &&
+ "Only handle register class results so far!");
+ OS << " unsigned NewReg = makeAnotherReg(" << Target.getName()
+ << "::" << R->getName() << "RegisterClass);\n";
+ Result = "NewReg";
+ DEBUG(OS << " std::cerr << \"%reg\" << NewReg << \" =\t\";\n");
+ } else {
+ DEBUG(OS << " std::cerr << \"\t\t\";\n");
+ Result = "0";
+ }
+
+ // Print out the pattern that matched...
+ DEBUG(OS << " std::cerr << \" " << P->getRecord()->getName() <<'"');
+ DEBUG(for (unsigned i = 0, e = Operands.size(); i != e; ++i)
+ if (Operands[i].first->isLeaf()) {
+ Record *RV = Operands[i].first->getValueRecord();
+ assert(RV->isSubClassOf("RegisterClass") &&
+ "Only handles registers here so far!");
+ OS << " << \" %reg\" << " << Operands[i].second
+ << "->Val";
+ } else {
+ OS << " << ' ' << " << Operands[i].second
+ << "->Val";
+ });
+ DEBUG(OS << " << \"\\n\";\n");
- OS << " std::cerr << \" " << P->getRecord()->getName()<< "\\n\";\n";
- OS << " Val = new ReducedValue_" << SlotName << "(0);\n"
+ // Generate the reduction code appropriate to the particular type of
+ // pattern that this is...
+ switch (P->getPatternType()) {
+ case Pattern::Instruction:
+ // Instruction patterns just emit a single MachineInstr, using BuildMI
+ OS << " BuildMI(MBB, " << Target.getName() << "::"
+ << P->getRecord()->getName() << ", " << Operands.size();
+ if (P->getResult()) OS << ", NewReg";
+ OS << ")";
+
+ for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
+ TreePatternNode *Op = Operands[i].first;
+ if (Op->isLeaf()) {
+ Record *RV = Op->getValueRecord();
+ assert(RV->isSubClassOf("RegisterClass") &&
+ "Only handles registers here so far!");
+ OS << ".addReg(" << Operands[i].second << "->Val)";
+ } else if (Op->getOperator()->getName() == "imm") {
+ OS << ".addZImm(" << Operands[i].second << "->Val)";
+ } else if (Op->getOperator()->getName() == "basicblock") {
+ OS << ".addMBB(" << Operands[i].second << "->Val)";
+ } else {
+ assert(0 && "Unknown value type!");
+ }
+ }
+ OS << ";\n";
+ break;
+ case Pattern::Expander: {
+ // Expander patterns emit one machine instr for each instruction in
+ // the list of instructions expanded to.
+ ListInit *Insts = P->getRecord()->getValueAsListInit("Result");
+ for (unsigned IN = 0, e = Insts->getSize(); IN != e; ++IN) {
+ DagInit *DIInst = dynamic_cast<DagInit*>(Insts->getElement(IN));
+ if (!DIInst) P->error("Result list must contain instructions!");
+ Record *InstRec = DIInst->getNodeType();
+ Pattern *InstPat = getPattern(InstRec);
+ if (!InstPat || InstPat->getPatternType() != Pattern::Instruction)
+ P->error("Instruction list must contain Instruction patterns!");
+
+ bool hasResult = InstPat->getResult() != 0;
+ if (InstPat->getNumArgs() != DIInst->getNumArgs()-hasResult) {
+ P->error("Incorrect number of arguments specified for inst '" +
+ InstPat->getRecord()->getName() + "' in result list!");
+ }
+
+ // Start emission of the instruction...
+ OS << " BuildMI(MBB, " << Target.getName() << "::"
+ << InstRec->getName() << ", "
+ << DIInst->getNumArgs()-hasResult;
+ // Emit register result if necessary..
+ if (hasResult) {
+ std::string ArgNameVal =
+ getArgName(P, DIInst->getArgName(0), Operands);
+ PrintExpanderOperand(DIInst->getArg(0), ArgNameVal,
+ InstPat->getResultNode(), P, false,
+ OS << ", ");
+ }
+ OS << ")";
+
+ for (unsigned i = hasResult, e = DIInst->getNumArgs(); i != e; ++i){
+ std::string ArgNameVal =
+ getArgName(P, DIInst->getArgName(i), Operands);
+
+ PrintExpanderOperand(DIInst->getArg(i), ArgNameVal,
+ InstPat->getArg(i-hasResult), P, true, OS);
+ }
+
+ OS << ";\n";
+ }
+ break;
+ }
+ default:
+ assert(0 && "Reduction of this type of pattern not implemented!");
+ }
+
+ OS << " Val = new ReducedValue_" << SlotName << "(" << Result<<");\n"
<< " break;\n"
<< " }\n";
}
<< " }\n\n N->addValue(Val); // Do not ever recalculate this\n"
<< " return Val;\n}\n\n";
}
+ EmitSourceFileTail(OS);
}
+} // End llvm namespace