llvm.org GIT mirror llvm / 6cc654b
Split the impl of CodeGenInstruction out to its own .cpp file, add a getName() accessor. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@45645 91177308-0d34-0410-b5e6-96231b3b80d8 Chris Lattner 11 years ago
3 changed file(s) with 287 addition(s) and 265 deletion(s). Raw diff Collapse all Expand all
0 //===- CodeGenInstruction.cpp - CodeGen Instruction Class Wrapper ---------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements the CodeGenInstruction class.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "CodeGenInstruction.h"
14 #include "Record.h"
15 #include "llvm/ADT/StringExtras.h"
16 #include
17 using namespace llvm;
18
19 static void ParseConstraint(const std::string &CStr, CodeGenInstruction *I) {
20 // FIXME: Only supports TIED_TO for now.
21 std::string::size_type pos = CStr.find_first_of('=');
22 assert(pos != std::string::npos && "Unrecognized constraint");
23 std::string Name = CStr.substr(0, pos);
24
25 // TIED_TO: $src1 = $dst
26 std::string::size_type wpos = Name.find_first_of(" \t");
27 if (wpos == std::string::npos)
28 throw "Illegal format for tied-to constraint: '" + CStr + "'";
29 std::string DestOpName = Name.substr(0, wpos);
30 std::pair DestOp = I->ParseOperandName(DestOpName, false);
31
32 Name = CStr.substr(pos+1);
33 wpos = Name.find_first_not_of(" \t");
34 if (wpos == std::string::npos)
35 throw "Illegal format for tied-to constraint: '" + CStr + "'";
36
37 std::pair SrcOp =
38 I->ParseOperandName(Name.substr(wpos), false);
39 if (SrcOp > DestOp)
40 throw "Illegal tied-to operand constraint '" + CStr + "'";
41
42
43 unsigned FlatOpNo = I->getFlattenedOperandNumber(SrcOp);
44 // Build the string for the operand.
45 std::string OpConstraint =
46 "((" + utostr(FlatOpNo) + " << 16) | (1 << TOI::TIED_TO))";
47
48
49 if (!I->OperandList[DestOp.first].Constraints[DestOp.second].empty())
50 throw "Operand '" + DestOpName + "' cannot have multiple constraints!";
51 I->OperandList[DestOp.first].Constraints[DestOp.second] = OpConstraint;
52 }
53
54 static void ParseConstraints(const std::string &CStr, CodeGenInstruction *I) {
55 // Make sure the constraints list for each operand is large enough to hold
56 // constraint info, even if none is present.
57 for (unsigned i = 0, e = I->OperandList.size(); i != e; ++i)
58 I->OperandList[i].Constraints.resize(I->OperandList[i].MINumOperands);
59
60 if (CStr.empty()) return;
61
62 const std::string delims(",");
63 std::string::size_type bidx, eidx;
64
65 bidx = CStr.find_first_not_of(delims);
66 while (bidx != std::string::npos) {
67 eidx = CStr.find_first_of(delims, bidx);
68 if (eidx == std::string::npos)
69 eidx = CStr.length();
70
71 ParseConstraint(CStr.substr(bidx, eidx), I);
72 bidx = CStr.find_first_not_of(delims, eidx);
73 }
74 }
75
76 CodeGenInstruction::CodeGenInstruction(Record *R, const std::string &AsmStr)
77 : TheDef(R), AsmString(AsmStr) {
78 Name = R->getValueAsString("Name");
79 Namespace = R->getValueAsString("Namespace");
80
81 isReturn = R->getValueAsBit("isReturn");
82 isBranch = R->getValueAsBit("isBranch");
83 isIndirectBranch = R->getValueAsBit("isIndirectBranch");
84 isBarrier = R->getValueAsBit("isBarrier");
85 isCall = R->getValueAsBit("isCall");
86 isLoad = R->getValueAsBit("isLoad");
87 isStore = R->getValueAsBit("isStore");
88 isImplicitDef= R->getValueAsBit("isImplicitDef");
89 bool isTwoAddress = R->getValueAsBit("isTwoAddress");
90 isPredicable = R->getValueAsBit("isPredicable");
91 isConvertibleToThreeAddress = R->getValueAsBit("isConvertibleToThreeAddress");
92 isCommutable = R->getValueAsBit("isCommutable");
93 isTerminator = R->getValueAsBit("isTerminator");
94 isReMaterializable = R->getValueAsBit("isReMaterializable");
95 hasDelaySlot = R->getValueAsBit("hasDelaySlot");
96 usesCustomDAGSchedInserter = R->getValueAsBit("usesCustomDAGSchedInserter");
97 hasCtrlDep = R->getValueAsBit("hasCtrlDep");
98 isNotDuplicable = R->getValueAsBit("isNotDuplicable");
99 mayHaveSideEffects = R->getValueAsBit("mayHaveSideEffects");
100 neverHasSideEffects = R->getValueAsBit("neverHasSideEffects");
101 hasOptionalDef = false;
102 hasVariableNumberOfOperands = false;
103
104 if (mayHaveSideEffects && neverHasSideEffects)
105 throw R->getName() +
106 ": cannot have both 'mayHaveSideEffects' and 'neverHasSideEffects' set!";
107
108 DagInit *DI;
109 try {
110 DI = R->getValueAsDag("OutOperandList");
111 } catch (...) {
112 // Error getting operand list, just ignore it (sparcv9).
113 AsmString.clear();
114 OperandList.clear();
115 return;
116 }
117 NumDefs = DI->getNumArgs();
118
119 DagInit *IDI;
120 try {
121 IDI = R->getValueAsDag("InOperandList");
122 } catch (...) {
123 // Error getting operand list, just ignore it (sparcv9).
124 AsmString.clear();
125 OperandList.clear();
126 return;
127 }
128 DI = (DagInit*)(new BinOpInit(BinOpInit::CONCAT, DI, IDI))->Fold();
129
130 unsigned MIOperandNo = 0;
131 std::set OperandNames;
132 for (unsigned i = 0, e = DI->getNumArgs(); i != e; ++i) {
133 DefInit *Arg = dynamic_cast(DI->getArg(i));
134 if (!Arg)
135 throw "Illegal operand for the '" + R->getName() + "' instruction!";
136
137 Record *Rec = Arg->getDef();
138 std::string PrintMethod = "printOperand";
139 unsigned NumOps = 1;
140 DagInit *MIOpInfo = 0;
141 if (Rec->isSubClassOf("Operand")) {
142 PrintMethod = Rec->getValueAsString("PrintMethod");
143 MIOpInfo = Rec->getValueAsDag("MIOperandInfo");
144
145 // Verify that MIOpInfo has an 'ops' root value.
146 if (!dynamic_cast(MIOpInfo->getOperator()) ||
147 dynamic_cast(MIOpInfo->getOperator())
148 ->getDef()->getName() != "ops")
149 throw "Bad value for MIOperandInfo in operand '" + Rec->getName() +
150 "'\n";
151
152 // If we have MIOpInfo, then we have #operands equal to number of entries
153 // in MIOperandInfo.
154 if (unsigned NumArgs = MIOpInfo->getNumArgs())
155 NumOps = NumArgs;
156
157 if (Rec->isSubClassOf("PredicateOperand"))
158 isPredicable = true;
159 else if (Rec->isSubClassOf("OptionalDefOperand"))
160 hasOptionalDef = true;
161 } else if (Rec->getName() == "variable_ops") {
162 hasVariableNumberOfOperands = true;
163 continue;
164 } else if (!Rec->isSubClassOf("RegisterClass") &&
165 Rec->getName() != "ptr_rc")
166 throw "Unknown operand class '" + Rec->getName() +
167 "' in instruction '" + R->getName() + "' instruction!";
168
169 // Check that the operand has a name and that it's unique.
170 if (DI->getArgName(i).empty())
171 throw "In instruction '" + R->getName() + "', operand #" + utostr(i) +
172 " has no name!";
173 if (!OperandNames.insert(DI->getArgName(i)).second)
174 throw "In instruction '" + R->getName() + "', operand #" + utostr(i) +
175 " has the same name as a previous operand!";
176
177 OperandList.push_back(OperandInfo(Rec, DI->getArgName(i), PrintMethod,
178 MIOperandNo, NumOps, MIOpInfo));
179 MIOperandNo += NumOps;
180 }
181
182 // Parse Constraints.
183 ParseConstraints(R->getValueAsString("Constraints"), this);
184
185 // For backward compatibility: isTwoAddress means operand 1 is tied to
186 // operand 0.
187 if (isTwoAddress) {
188 if (!OperandList[1].Constraints[0].empty())
189 throw R->getName() + ": cannot use isTwoAddress property: instruction "
190 "already has constraint set!";
191 OperandList[1].Constraints[0] = "((0 << 16) | (1 << TOI::TIED_TO))";
192 }
193
194 // Any operands with unset constraints get 0 as their constraint.
195 for (unsigned op = 0, e = OperandList.size(); op != e; ++op)
196 for (unsigned j = 0, e = OperandList[op].MINumOperands; j != e; ++j)
197 if (OperandList[op].Constraints[j].empty())
198 OperandList[op].Constraints[j] = "0";
199
200 // Parse the DisableEncoding field.
201 std::string DisableEncoding = R->getValueAsString("DisableEncoding");
202 while (1) {
203 std::string OpName = getToken(DisableEncoding, " ,\t");
204 if (OpName.empty()) break;
205
206 // Figure out which operand this is.
207 std::pair Op = ParseOperandName(OpName, false);
208
209 // Mark the operand as not-to-be encoded.
210 if (Op.second >= OperandList[Op.first].DoNotEncode.size())
211 OperandList[Op.first].DoNotEncode.resize(Op.second+1);
212 OperandList[Op.first].DoNotEncode[Op.second] = true;
213 }
214 }
215
216 /// getName - Return the contents of the instruction Name field if set,
217 /// otherwise return the name of the def.
218 std::string CodeGenInstruction::getName() const {
219 if (!Name.empty()) return Name;
220 return TheDef->getName();
221 }
222
223
224 /// getOperandNamed - Return the index of the operand with the specified
225 /// non-empty name. If the instruction does not have an operand with the
226 /// specified name, throw an exception.
227 ///
228 unsigned CodeGenInstruction::getOperandNamed(const std::string &Name) const {
229 assert(!Name.empty() && "Cannot search for operand with no name!");
230 for (unsigned i = 0, e = OperandList.size(); i != e; ++i)
231 if (OperandList[i].Name == Name) return i;
232 throw "Instruction '" + TheDef->getName() +
233 "' does not have an operand named '$" + Name + "'!";
234 }
235
236 std::pair
237 CodeGenInstruction::ParseOperandName(const std::string &Op,
238 bool AllowWholeOp) {
239 if (Op.empty() || Op[0] != '$')
240 throw TheDef->getName() + ": Illegal operand name: '" + Op + "'";
241
242 std::string OpName = Op.substr(1);
243 std::string SubOpName;
244
245 // Check to see if this is $foo.bar.
246 std::string::size_type DotIdx = OpName.find_first_of(".");
247 if (DotIdx != std::string::npos) {
248 SubOpName = OpName.substr(DotIdx+1);
249 if (SubOpName.empty())
250 throw TheDef->getName() + ": illegal empty suboperand name in '" +Op +"'";
251 OpName = OpName.substr(0, DotIdx);
252 }
253
254 unsigned OpIdx = getOperandNamed(OpName);
255
256 if (SubOpName.empty()) { // If no suboperand name was specified:
257 // If one was needed, throw.
258 if (OperandList[OpIdx].MINumOperands > 1 && !AllowWholeOp &&
259 SubOpName.empty())
260 throw TheDef->getName() + ": Illegal to refer to"
261 " whole operand part of complex operand '" + Op + "'";
262
263 // Otherwise, return the operand.
264 return std::make_pair(OpIdx, 0U);
265 }
266
267 // Find the suboperand number involved.
268 DagInit *MIOpInfo = OperandList[OpIdx].MIOperandInfo;
269 if (MIOpInfo == 0)
270 throw TheDef->getName() + ": unknown suboperand name in '" + Op + "'";
271
272 // Find the operand with the right name.
273 for (unsigned i = 0, e = MIOpInfo->getNumArgs(); i != e; ++i)
274 if (MIOpInfo->getArgName(i) == SubOpName)
275 return std::make_pair(OpIdx, i);
276
277 // Otherwise, didn't find it!
278 throw TheDef->getName() + ": unknown suboperand name in '" + Op + "'";
279 }
3131 /// AsmString - The format string used to emit a .s file for the
3232 /// instruction.
3333 std::string AsmString;
34
34
35 /// getName - Return the contents of the instruction Name field if set,
36 /// otherwise return the name of the def.
37 std::string getName() const;
38
3539 /// OperandInfo - The information we keep track of for each operand in the
3640 /// operand list for a tablegen instruction.
3741 struct OperandInfo {
None //===- CodeGenTarget.cpp - CodeGen Target Class Wrapper ---------*- C++ -*-===//
0 //===- CodeGenTarget.cpp - CodeGen Target Class Wrapper -------------------===//
11 //
22 // The LLVM Compiler Infrastructure
33 //
66 //
77 //===----------------------------------------------------------------------===//
88 //
9 // This class wrap target description classes used by the various code
9 // This class wraps target description classes used by the various code
1010 // generation TableGen backends. This makes it easier to access the data and
1111 // provides a single place that needs to check it for validity. All of these
1212 // classes throw exceptions on error conditions.
1919 #include "llvm/ADT/StringExtras.h"
2020 #include "llvm/Support/CommandLine.h"
2121 #include "llvm/Support/Streams.h"
22 #include
2322 #include
2423 using namespace llvm;
2524
323322 return getInstructionSet()->getValueAsBit("isLittleEndianEncoding");
324323 }
325324
326
327
328 static void ParseConstraint(const std::string &CStr, CodeGenInstruction *I) {
329 // FIXME: Only supports TIED_TO for now.
330 std::string::size_type pos = CStr.find_first_of('=');
331 assert(pos != std::string::npos && "Unrecognized constraint");
332 std::string Name = CStr.substr(0, pos);
333
334 // TIED_TO: $src1 = $dst
335 std::string::size_type wpos = Name.find_first_of(" \t");
336 if (wpos == std::string::npos)
337 throw "Illegal format for tied-to constraint: '" + CStr + "'";
338 std::string DestOpName = Name.substr(0, wpos);
339 std::pair DestOp = I->ParseOperandName(DestOpName, false);
340
341 Name = CStr.substr(pos+1);
342 wpos = Name.find_first_not_of(" \t");
343 if (wpos == std::string::npos)
344 throw "Illegal format for tied-to constraint: '" + CStr + "'";
345
346 std::pair SrcOp =
347 I->ParseOperandName(Name.substr(wpos), false);
348 if (SrcOp > DestOp)
349 throw "Illegal tied-to operand constraint '" + CStr + "'";
350
351
352 unsigned FlatOpNo = I->getFlattenedOperandNumber(SrcOp);
353 // Build the string for the operand.
354 std::string OpConstraint =
355 "((" + utostr(FlatOpNo) + " << 16) | (1 << TOI::TIED_TO))";
356
357
358 if (!I->OperandList[DestOp.first].Constraints[DestOp.second].empty())
359 throw "Operand '" + DestOpName + "' cannot have multiple constraints!";
360 I->OperandList[DestOp.first].Constraints[DestOp.second] = OpConstraint;
361 }
362
363 static void ParseConstraints(const std::string &CStr, CodeGenInstruction *I) {
364 // Make sure the constraints list for each operand is large enough to hold
365 // constraint info, even if none is present.
366 for (unsigned i = 0, e = I->OperandList.size(); i != e; ++i)
367 I->OperandList[i].Constraints.resize(I->OperandList[i].MINumOperands);
368
369 if (CStr.empty()) return;
370
371 const std::string delims(",");
372 std::string::size_type bidx, eidx;
373
374 bidx = CStr.find_first_not_of(delims);
375 while (bidx != std::string::npos) {
376 eidx = CStr.find_first_of(delims, bidx);
377 if (eidx == std::string::npos)
378 eidx = CStr.length();
379
380 ParseConstraint(CStr.substr(bidx, eidx), I);
381 bidx = CStr.find_first_not_of(delims, eidx);
382 }
383 }
384
385 CodeGenInstruction::CodeGenInstruction(Record *R, const std::string &AsmStr)
386 : TheDef(R), AsmString(AsmStr) {
387 Name = R->getValueAsString("Name");
388 Namespace = R->getValueAsString("Namespace");
389
390 isReturn = R->getValueAsBit("isReturn");
391 isBranch = R->getValueAsBit("isBranch");
392 isIndirectBranch = R->getValueAsBit("isIndirectBranch");
393 isBarrier = R->getValueAsBit("isBarrier");
394 isCall = R->getValueAsBit("isCall");
395 isLoad = R->getValueAsBit("isLoad");
396 isStore = R->getValueAsBit("isStore");
397 isImplicitDef= R->getValueAsBit("isImplicitDef");
398 bool isTwoAddress = R->getValueAsBit("isTwoAddress");
399 isPredicable = R->getValueAsBit("isPredicable");
400 isConvertibleToThreeAddress = R->getValueAsBit("isConvertibleToThreeAddress");
401 isCommutable = R->getValueAsBit("isCommutable");
402 isTerminator = R->getValueAsBit("isTerminator");
403 isReMaterializable = R->getValueAsBit("isReMaterializable");
404 hasDelaySlot = R->getValueAsBit("hasDelaySlot");
405 usesCustomDAGSchedInserter = R->getValueAsBit("usesCustomDAGSchedInserter");
406 hasCtrlDep = R->getValueAsBit("hasCtrlDep");
407 isNotDuplicable = R->getValueAsBit("isNotDuplicable");
408 mayHaveSideEffects = R->getValueAsBit("mayHaveSideEffects");
409 neverHasSideEffects = R->getValueAsBit("neverHasSideEffects");
410 hasOptionalDef = false;
411 hasVariableNumberOfOperands = false;
412
413 if (mayHaveSideEffects && neverHasSideEffects)
414 throw R->getName() +
415 ": cannot have both 'mayHaveSideEffects' and 'neverHasSideEffects' set!";
416
417 DagInit *DI;
418 try {
419 DI = R->getValueAsDag("OutOperandList");
420 } catch (...) {
421 // Error getting operand list, just ignore it (sparcv9).
422 AsmString.clear();
423 OperandList.clear();
424 return;
425 }
426 NumDefs = DI->getNumArgs();
427
428 DagInit *IDI;
429 try {
430 IDI = R->getValueAsDag("InOperandList");
431 } catch (...) {
432 // Error getting operand list, just ignore it (sparcv9).
433 AsmString.clear();
434 OperandList.clear();
435 return;
436 }
437 DI = (DagInit*)(new BinOpInit(BinOpInit::CONCAT, DI, IDI))->Fold();
438
439 unsigned MIOperandNo = 0;
440 std::set OperandNames;
441 for (unsigned i = 0, e = DI->getNumArgs(); i != e; ++i) {
442 DefInit *Arg = dynamic_cast(DI->getArg(i));
443 if (!Arg)
444 throw "Illegal operand for the '" + R->getName() + "' instruction!";
445
446 Record *Rec = Arg->getDef();
447 std::string PrintMethod = "printOperand";
448 unsigned NumOps = 1;
449 DagInit *MIOpInfo = 0;
450 if (Rec->isSubClassOf("Operand")) {
451 PrintMethod = Rec->getValueAsString("PrintMethod");
452 MIOpInfo = Rec->getValueAsDag("MIOperandInfo");
453
454 // Verify that MIOpInfo has an 'ops' root value.
455 if (!dynamic_cast(MIOpInfo->getOperator()) ||
456 dynamic_cast(MIOpInfo->getOperator())
457 ->getDef()->getName() != "ops")
458 throw "Bad value for MIOperandInfo in operand '" + Rec->getName() +
459 "'\n";
460
461 // If we have MIOpInfo, then we have #operands equal to number of entries
462 // in MIOperandInfo.
463 if (unsigned NumArgs = MIOpInfo->getNumArgs())
464 NumOps = NumArgs;
465
466 if (Rec->isSubClassOf("PredicateOperand"))
467 isPredicable = true;
468 else if (Rec->isSubClassOf("OptionalDefOperand"))
469 hasOptionalDef = true;
470 } else if (Rec->getName() == "variable_ops") {
471 hasVariableNumberOfOperands = true;
472 continue;
473 } else if (!Rec->isSubClassOf("RegisterClass") &&
474 Rec->getName() != "ptr_rc")
475 throw "Unknown operand class '" + Rec->getName() +
476 "' in instruction '" + R->getName() + "' instruction!";
477
478 // Check that the operand has a name and that it's unique.
479 if (DI->getArgName(i).empty())
480 throw "In instruction '" + R->getName() + "', operand #" + utostr(i) +
481 " has no name!";
482 if (!OperandNames.insert(DI->getArgName(i)).second)
483 throw "In instruction '" + R->getName() + "', operand #" + utostr(i) +
484 " has the same name as a previous operand!";
485
486 OperandList.push_back(OperandInfo(Rec, DI->getArgName(i), PrintMethod,
487 MIOperandNo, NumOps, MIOpInfo));
488 MIOperandNo += NumOps;
489 }
490
491 // Parse Constraints.
492 ParseConstraints(R->getValueAsString("Constraints"), this);
493
494 // For backward compatibility: isTwoAddress means operand 1 is tied to
495 // operand 0.
496 if (isTwoAddress) {
497 if (!OperandList[1].Constraints[0].empty())
498 throw R->getName() + ": cannot use isTwoAddress property: instruction "
499 "already has constraint set!";
500 OperandList[1].Constraints[0] = "((0 << 16) | (1 << TOI::TIED_TO))";
501 }
502
503 // Any operands with unset constraints get 0 as their constraint.
504 for (unsigned op = 0, e = OperandList.size(); op != e; ++op)
505 for (unsigned j = 0, e = OperandList[op].MINumOperands; j != e; ++j)
506 if (OperandList[op].Constraints[j].empty())
507 OperandList[op].Constraints[j] = "0";
508
509 // Parse the DisableEncoding field.
510 std::string DisableEncoding = R->getValueAsString("DisableEncoding");
511 while (1) {
512 std::string OpName = getToken(DisableEncoding, " ,\t");
513 if (OpName.empty()) break;
514
515 // Figure out which operand this is.
516 std::pair Op = ParseOperandName(OpName, false);
517
518 // Mark the operand as not-to-be encoded.
519 if (Op.second >= OperandList[Op.first].DoNotEncode.size())
520 OperandList[Op.first].DoNotEncode.resize(Op.second+1);
521 OperandList[Op.first].DoNotEncode[Op.second] = true;
522 }
523 }
524
525
526
527 /// getOperandNamed - Return the index of the operand with the specified
528 /// non-empty name. If the instruction does not have an operand with the
529 /// specified name, throw an exception.
530 ///
531 unsigned CodeGenInstruction::getOperandNamed(const std::string &Name) const {
532 assert(!Name.empty() && "Cannot search for operand with no name!");
533 for (unsigned i = 0, e = OperandList.size(); i != e; ++i)
534 if (OperandList[i].Name == Name) return i;
535 throw "Instruction '" + TheDef->getName() +
536 "' does not have an operand named '$" + Name + "'!";
537 }
538
539 std::pair
540 CodeGenInstruction::ParseOperandName(const std::string &Op,
541 bool AllowWholeOp) {
542 if (Op.empty() || Op[0] != '$')
543 throw TheDef->getName() + ": Illegal operand name: '" + Op + "'";
544
545 std::string OpName = Op.substr(1);
546 std::string SubOpName;
547
548 // Check to see if this is $foo.bar.
549 std::string::size_type DotIdx = OpName.find_first_of(".");
550 if (DotIdx != std::string::npos) {
551 SubOpName = OpName.substr(DotIdx+1);
552 if (SubOpName.empty())
553 throw TheDef->getName() + ": illegal empty suboperand name in '" +Op +"'";
554 OpName = OpName.substr(0, DotIdx);
555 }
556
557 unsigned OpIdx = getOperandNamed(OpName);
558
559 if (SubOpName.empty()) { // If no suboperand name was specified:
560 // If one was needed, throw.
561 if (OperandList[OpIdx].MINumOperands > 1 && !AllowWholeOp &&
562 SubOpName.empty())
563 throw TheDef->getName() + ": Illegal to refer to"
564 " whole operand part of complex operand '" + Op + "'";
565
566 // Otherwise, return the operand.
567 return std::make_pair(OpIdx, 0U);
568 }
569
570 // Find the suboperand number involved.
571 DagInit *MIOpInfo = OperandList[OpIdx].MIOperandInfo;
572 if (MIOpInfo == 0)
573 throw TheDef->getName() + ": unknown suboperand name in '" + Op + "'";
574
575 // Find the operand with the right name.
576 for (unsigned i = 0, e = MIOpInfo->getNumArgs(); i != e; ++i)
577 if (MIOpInfo->getArgName(i) == SubOpName)
578 return std::make_pair(OpIdx, i);
579
580 // Otherwise, didn't find it!
581 throw TheDef->getName() + ": unknown suboperand name in '" + Op + "'";
582 }
583
584
585
586
587325 //===----------------------------------------------------------------------===//
588326 // ComplexPattern implementation
589327 //