1 | //===- CodeGenInstruction.cpp - CodeGen Instruction Class Wrapper ---------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // This file implements the CodeGenInstruction class. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #include "CodeGenInstruction.h" |
14 | #include "CodeGenTarget.h" |
15 | #include "llvm/ADT/StringExtras.h" |
16 | #include "llvm/TableGen/Error.h" |
17 | #include "llvm/TableGen/Record.h" |
18 | #include <set> |
19 | using namespace llvm; |
20 | |
21 | //===----------------------------------------------------------------------===// |
22 | // CGIOperandList Implementation |
23 | //===----------------------------------------------------------------------===// |
24 | |
25 | CGIOperandList::CGIOperandList(Record *R) : TheDef(R) { |
26 | isPredicable = false; |
27 | hasOptionalDef = false; |
28 | isVariadic = false; |
29 | |
30 | DagInit *OutDI = R->getValueAsDag(FieldName: "OutOperandList" ); |
31 | |
32 | if (DefInit *Init = dyn_cast<DefInit>(Val: OutDI->getOperator())) { |
33 | if (Init->getDef()->getName() != "outs" ) |
34 | PrintFatalError(ErrorLoc: R->getLoc(), |
35 | Msg: R->getName() + |
36 | ": invalid def name for output list: use 'outs'" ); |
37 | } else |
38 | PrintFatalError(ErrorLoc: R->getLoc(), |
39 | Msg: R->getName() + ": invalid output list: use 'outs'" ); |
40 | |
41 | NumDefs = OutDI->getNumArgs(); |
42 | |
43 | DagInit *InDI = R->getValueAsDag(FieldName: "InOperandList" ); |
44 | if (DefInit *Init = dyn_cast<DefInit>(Val: InDI->getOperator())) { |
45 | if (Init->getDef()->getName() != "ins" ) |
46 | PrintFatalError(ErrorLoc: R->getLoc(), |
47 | Msg: R->getName() + |
48 | ": invalid def name for input list: use 'ins'" ); |
49 | } else |
50 | PrintFatalError(ErrorLoc: R->getLoc(), |
51 | Msg: R->getName() + ": invalid input list: use 'ins'" ); |
52 | |
53 | unsigned MIOperandNo = 0; |
54 | std::set<std::string> OperandNames; |
55 | unsigned e = InDI->getNumArgs() + OutDI->getNumArgs(); |
56 | OperandList.reserve(n: e); |
57 | bool VariadicOuts = false; |
58 | for (unsigned i = 0; i != e; ++i) { |
59 | Init *ArgInit; |
60 | StringRef ArgName; |
61 | if (i < NumDefs) { |
62 | ArgInit = OutDI->getArg(Num: i); |
63 | ArgName = OutDI->getArgNameStr(Num: i); |
64 | } else { |
65 | ArgInit = InDI->getArg(Num: i - NumDefs); |
66 | ArgName = InDI->getArgNameStr(Num: i - NumDefs); |
67 | } |
68 | |
69 | DagInit *SubArgDag = dyn_cast<DagInit>(Val: ArgInit); |
70 | if (SubArgDag) |
71 | ArgInit = SubArgDag->getOperator(); |
72 | |
73 | DefInit *Arg = dyn_cast<DefInit>(Val: ArgInit); |
74 | if (!Arg) |
75 | PrintFatalError(ErrorLoc: R->getLoc(), Msg: "Illegal operand for the '" + R->getName() + |
76 | "' instruction!" ); |
77 | |
78 | Record *Rec = Arg->getDef(); |
79 | std::string PrintMethod = "printOperand" ; |
80 | std::string EncoderMethod; |
81 | std::string OperandType = "OPERAND_UNKNOWN" ; |
82 | std::string OperandNamespace = "MCOI" ; |
83 | unsigned NumOps = 1; |
84 | DagInit *MIOpInfo = nullptr; |
85 | if (Rec->isSubClassOf(Name: "RegisterOperand" )) { |
86 | PrintMethod = std::string(Rec->getValueAsString(FieldName: "PrintMethod" )); |
87 | OperandType = std::string(Rec->getValueAsString(FieldName: "OperandType" )); |
88 | OperandNamespace = std::string(Rec->getValueAsString(FieldName: "OperandNamespace" )); |
89 | EncoderMethod = std::string(Rec->getValueAsString(FieldName: "EncoderMethod" )); |
90 | } else if (Rec->isSubClassOf(Name: "Operand" )) { |
91 | PrintMethod = std::string(Rec->getValueAsString(FieldName: "PrintMethod" )); |
92 | OperandType = std::string(Rec->getValueAsString(FieldName: "OperandType" )); |
93 | OperandNamespace = std::string(Rec->getValueAsString(FieldName: "OperandNamespace" )); |
94 | // If there is an explicit encoder method, use it. |
95 | EncoderMethod = std::string(Rec->getValueAsString(FieldName: "EncoderMethod" )); |
96 | MIOpInfo = Rec->getValueAsDag(FieldName: "MIOperandInfo" ); |
97 | |
98 | // Verify that MIOpInfo has an 'ops' root value. |
99 | if (!isa<DefInit>(Val: MIOpInfo->getOperator()) || |
100 | cast<DefInit>(Val: MIOpInfo->getOperator())->getDef()->getName() != "ops" ) |
101 | PrintFatalError(ErrorLoc: R->getLoc(), |
102 | Msg: "Bad value for MIOperandInfo in operand '" + |
103 | Rec->getName() + "'\n" ); |
104 | |
105 | // If we have MIOpInfo, then we have #operands equal to number of entries |
106 | // in MIOperandInfo. |
107 | if (unsigned NumArgs = MIOpInfo->getNumArgs()) |
108 | NumOps = NumArgs; |
109 | |
110 | if (Rec->isSubClassOf(Name: "PredicateOp" )) |
111 | isPredicable = true; |
112 | else if (Rec->isSubClassOf(Name: "OptionalDefOperand" )) |
113 | hasOptionalDef = true; |
114 | } else if (Rec->getName() == "variable_ops" ) { |
115 | if (i < NumDefs) |
116 | VariadicOuts = true; |
117 | isVariadic = true; |
118 | continue; |
119 | } else if (Rec->isSubClassOf(Name: "RegisterClass" )) { |
120 | OperandType = "OPERAND_REGISTER" ; |
121 | } else if (!Rec->isSubClassOf(Name: "PointerLikeRegClass" ) && |
122 | !Rec->isSubClassOf(Name: "unknown_class" )) { |
123 | PrintFatalError(ErrorLoc: R->getLoc(), Msg: "Unknown operand class '" + Rec->getName() + |
124 | "' in '" + R->getName() + |
125 | "' instruction!" ); |
126 | } |
127 | |
128 | // Check that the operand has a name and that it's unique. |
129 | if (ArgName.empty()) |
130 | PrintFatalError(ErrorLoc: R->getLoc(), Msg: "In instruction '" + R->getName() + |
131 | "', operand #" + Twine(i) + |
132 | " has no name!" ); |
133 | if (!OperandNames.insert(x: std::string(ArgName)).second) |
134 | PrintFatalError(ErrorLoc: R->getLoc(), |
135 | Msg: "In instruction '" + R->getName() + "', operand #" + |
136 | Twine(i) + |
137 | " has the same name as a previous operand!" ); |
138 | |
139 | OperandInfo &OpInfo = OperandList.emplace_back( |
140 | args&: Rec, args: std::string(ArgName), args: std::string(PrintMethod), |
141 | args: OperandNamespace + "::" + OperandType, args&: MIOperandNo, args&: NumOps, args&: MIOpInfo); |
142 | |
143 | if (SubArgDag) { |
144 | if (SubArgDag->getNumArgs() != NumOps) { |
145 | PrintFatalError(ErrorLoc: R->getLoc(), Msg: "In instruction '" + R->getName() + |
146 | "', operand #" + Twine(i) + " has " + |
147 | Twine(SubArgDag->getNumArgs()) + |
148 | " sub-arg names, expected " + |
149 | Twine(NumOps) + "." ); |
150 | } |
151 | |
152 | for (unsigned j = 0; j < NumOps; ++j) { |
153 | if (!isa<UnsetInit>(Val: SubArgDag->getArg(Num: j))) |
154 | PrintFatalError(ErrorLoc: R->getLoc(), |
155 | Msg: "In instruction '" + R->getName() + "', operand #" + |
156 | Twine(i) + " sub-arg #" + Twine(j) + |
157 | " has unexpected operand (expected only $name)." ); |
158 | |
159 | StringRef SubArgName = SubArgDag->getArgNameStr(Num: j); |
160 | if (SubArgName.empty()) |
161 | PrintFatalError(ErrorLoc: R->getLoc(), Msg: "In instruction '" + R->getName() + |
162 | "', operand #" + Twine(i) + |
163 | " has no name!" ); |
164 | if (!OperandNames.insert(x: std::string(SubArgName)).second) |
165 | PrintFatalError(ErrorLoc: R->getLoc(), |
166 | Msg: "In instruction '" + R->getName() + "', operand #" + |
167 | Twine(i) + " sub-arg #" + Twine(j) + |
168 | " has the same name as a previous operand!" ); |
169 | |
170 | if (auto MaybeEncoderMethod = |
171 | cast<DefInit>(Val: MIOpInfo->getArg(Num: j)) |
172 | ->getDef() |
173 | ->getValueAsOptionalString(FieldName: "EncoderMethod" )) { |
174 | OpInfo.EncoderMethodNames[j] = *MaybeEncoderMethod; |
175 | } |
176 | |
177 | OpInfo.SubOpNames[j] = SubArgName; |
178 | SubOpAliases[SubArgName] = std::pair(i, j); |
179 | } |
180 | } else if (!EncoderMethod.empty()) { |
181 | // If we have no explicit sub-op dag, but have an top-level encoder |
182 | // method, the single encoder will multiple sub-ops, itself. |
183 | OpInfo.EncoderMethodNames[0] = EncoderMethod; |
184 | for (unsigned j = 1; j < NumOps; ++j) |
185 | OpInfo.DoNotEncode[j] = true; |
186 | } |
187 | |
188 | MIOperandNo += NumOps; |
189 | } |
190 | |
191 | if (VariadicOuts) |
192 | --NumDefs; |
193 | } |
194 | |
195 | /// getOperandNamed - Return the index of the operand with the specified |
196 | /// non-empty name. If the instruction does not have an operand with the |
197 | /// specified name, abort. |
198 | /// |
199 | unsigned CGIOperandList::getOperandNamed(StringRef Name) const { |
200 | unsigned OpIdx; |
201 | if (hasOperandNamed(Name, OpIdx)) |
202 | return OpIdx; |
203 | PrintFatalError(ErrorLoc: TheDef->getLoc(), Msg: "'" + TheDef->getName() + |
204 | "' does not have an operand named '$" + |
205 | Name + "'!" ); |
206 | } |
207 | |
208 | /// hasOperandNamed - Query whether the instruction has an operand of the |
209 | /// given name. If so, return true and set OpIdx to the index of the |
210 | /// operand. Otherwise, return false. |
211 | bool CGIOperandList::hasOperandNamed(StringRef Name, unsigned &OpIdx) const { |
212 | assert(!Name.empty() && "Cannot search for operand with no name!" ); |
213 | for (unsigned i = 0, e = OperandList.size(); i != e; ++i) |
214 | if (OperandList[i].Name == Name) { |
215 | OpIdx = i; |
216 | return true; |
217 | } |
218 | return false; |
219 | } |
220 | |
221 | bool CGIOperandList::hasSubOperandAlias( |
222 | StringRef Name, std::pair<unsigned, unsigned> &SubOp) const { |
223 | assert(!Name.empty() && "Cannot search for operand with no name!" ); |
224 | auto SubOpIter = SubOpAliases.find(Key: Name); |
225 | if (SubOpIter != SubOpAliases.end()) { |
226 | SubOp = SubOpIter->second; |
227 | return true; |
228 | } |
229 | return false; |
230 | } |
231 | |
232 | std::pair<unsigned, unsigned> |
233 | CGIOperandList::ParseOperandName(StringRef Op, bool AllowWholeOp) { |
234 | if (!Op.starts_with(Prefix: "$" )) |
235 | PrintFatalError(ErrorLoc: TheDef->getLoc(), |
236 | Msg: TheDef->getName() + ": Illegal operand name: '" + Op + "'" ); |
237 | |
238 | StringRef OpName = Op.substr(Start: 1); |
239 | StringRef SubOpName; |
240 | |
241 | // Check to see if this is $foo.bar. |
242 | StringRef::size_type DotIdx = OpName.find_first_of(C: '.'); |
243 | if (DotIdx != StringRef::npos) { |
244 | SubOpName = OpName.substr(Start: DotIdx + 1); |
245 | if (SubOpName.empty()) |
246 | PrintFatalError(ErrorLoc: TheDef->getLoc(), |
247 | Msg: TheDef->getName() + |
248 | ": illegal empty suboperand name in '" + Op + "'" ); |
249 | OpName = OpName.substr(Start: 0, N: DotIdx); |
250 | } |
251 | |
252 | unsigned OpIdx; |
253 | |
254 | if (std::pair<unsigned, unsigned> SubOp; hasSubOperandAlias(Name: OpName, SubOp)) { |
255 | // Found a name for a piece of an operand, just return it directly. |
256 | if (!SubOpName.empty()) { |
257 | PrintFatalError( |
258 | ErrorLoc: TheDef->getLoc(), |
259 | Msg: TheDef->getName() + |
260 | ": Cannot use dotted suboperand name within suboperand '" + |
261 | OpName + "'" ); |
262 | } |
263 | return SubOp; |
264 | } |
265 | |
266 | OpIdx = getOperandNamed(Name: OpName); |
267 | |
268 | if (SubOpName.empty()) { // If no suboperand name was specified: |
269 | // If one was needed, throw. |
270 | if (OperandList[OpIdx].MINumOperands > 1 && !AllowWholeOp && |
271 | SubOpName.empty()) |
272 | PrintFatalError(ErrorLoc: TheDef->getLoc(), |
273 | Msg: TheDef->getName() + |
274 | ": Illegal to refer to" |
275 | " whole operand part of complex operand '" + |
276 | Op + "'" ); |
277 | |
278 | // Otherwise, return the operand. |
279 | return std::pair(OpIdx, 0U); |
280 | } |
281 | |
282 | // Find the suboperand number involved. |
283 | DagInit *MIOpInfo = OperandList[OpIdx].MIOperandInfo; |
284 | if (!MIOpInfo) |
285 | PrintFatalError(ErrorLoc: TheDef->getLoc(), Msg: TheDef->getName() + |
286 | ": unknown suboperand name in '" + |
287 | Op + "'" ); |
288 | |
289 | // Find the operand with the right name. |
290 | for (unsigned i = 0, e = MIOpInfo->getNumArgs(); i != e; ++i) |
291 | if (MIOpInfo->getArgNameStr(Num: i) == SubOpName) |
292 | return std::pair(OpIdx, i); |
293 | |
294 | // Otherwise, didn't find it! |
295 | PrintFatalError(ErrorLoc: TheDef->getLoc(), Msg: TheDef->getName() + |
296 | ": unknown suboperand name in '" + Op + |
297 | "'" ); |
298 | return std::pair(0U, 0U); |
299 | } |
300 | |
301 | static void ParseConstraint(StringRef CStr, CGIOperandList &Ops, Record *Rec) { |
302 | // EARLY_CLOBBER: @early $reg |
303 | StringRef::size_type wpos = CStr.find_first_of(Chars: " \t" ); |
304 | StringRef::size_type start = CStr.find_first_not_of(Chars: " \t" ); |
305 | StringRef Tok = CStr.substr(Start: start, N: wpos - start); |
306 | if (Tok == "@earlyclobber" ) { |
307 | StringRef Name = CStr.substr(Start: wpos + 1); |
308 | wpos = Name.find_first_not_of(Chars: " \t" ); |
309 | if (wpos == StringRef::npos) |
310 | PrintFatalError(ErrorLoc: Rec->getLoc(), |
311 | Msg: "Illegal format for @earlyclobber constraint in '" + |
312 | Rec->getName() + "': '" + CStr + "'" ); |
313 | Name = Name.substr(Start: wpos); |
314 | std::pair<unsigned, unsigned> Op = Ops.ParseOperandName(Op: Name, AllowWholeOp: false); |
315 | |
316 | // Build the string for the operand |
317 | if (!Ops[Op.first].Constraints[Op.second].isNone()) |
318 | PrintFatalError(ErrorLoc: Rec->getLoc(), Msg: "Operand '" + Name + "' of '" + |
319 | Rec->getName() + |
320 | "' cannot have multiple constraints!" ); |
321 | Ops[Op.first].Constraints[Op.second] = |
322 | CGIOperandList::ConstraintInfo::getEarlyClobber(); |
323 | return; |
324 | } |
325 | |
326 | // Only other constraint is "TIED_TO" for now. |
327 | StringRef::size_type pos = CStr.find_first_of(C: '='); |
328 | if (pos == StringRef::npos || pos == 0 || |
329 | CStr.find_first_of(Chars: " \t" , From: pos) != (pos + 1) || |
330 | CStr.find_last_of(Chars: " \t" , From: pos) != (pos - 1)) |
331 | PrintFatalError(ErrorLoc: Rec->getLoc(), Msg: "Unrecognized constraint '" + CStr + |
332 | "' in '" + Rec->getName() + "'" ); |
333 | start = CStr.find_first_not_of(Chars: " \t" ); |
334 | |
335 | // TIED_TO: $src1 = $dst |
336 | wpos = CStr.find_first_of(Chars: " \t" , From: start); |
337 | if (wpos == StringRef::npos || wpos > pos) |
338 | PrintFatalError(ErrorLoc: Rec->getLoc(), |
339 | Msg: "Illegal format for tied-to constraint in '" + |
340 | Rec->getName() + "': '" + CStr + "'" ); |
341 | StringRef LHSOpName = CStr.substr(Start: start, N: wpos - start); |
342 | std::pair<unsigned, unsigned> LHSOp = Ops.ParseOperandName(Op: LHSOpName, AllowWholeOp: false); |
343 | |
344 | wpos = CStr.find_first_not_of(Chars: " \t" , From: pos + 1); |
345 | if (wpos == StringRef::npos) |
346 | PrintFatalError(ErrorLoc: Rec->getLoc(), |
347 | Msg: "Illegal format for tied-to constraint: '" + CStr + "'" ); |
348 | |
349 | StringRef RHSOpName = CStr.substr(Start: wpos); |
350 | std::pair<unsigned, unsigned> RHSOp = Ops.ParseOperandName(Op: RHSOpName, AllowWholeOp: false); |
351 | |
352 | // Sort the operands into order, which should put the output one |
353 | // first. But keep the original order, for use in diagnostics. |
354 | bool FirstIsDest = (LHSOp < RHSOp); |
355 | std::pair<unsigned, unsigned> DestOp = (FirstIsDest ? LHSOp : RHSOp); |
356 | StringRef DestOpName = (FirstIsDest ? LHSOpName : RHSOpName); |
357 | std::pair<unsigned, unsigned> SrcOp = (FirstIsDest ? RHSOp : LHSOp); |
358 | StringRef SrcOpName = (FirstIsDest ? RHSOpName : LHSOpName); |
359 | |
360 | // Ensure one operand is a def and the other is a use. |
361 | if (DestOp.first >= Ops.NumDefs) |
362 | PrintFatalError(ErrorLoc: Rec->getLoc(), Msg: "Input operands '" + LHSOpName + "' and '" + |
363 | RHSOpName + "' of '" + Rec->getName() + |
364 | "' cannot be tied!" ); |
365 | if (SrcOp.first < Ops.NumDefs) |
366 | PrintFatalError(ErrorLoc: Rec->getLoc(), Msg: "Output operands '" + LHSOpName + "' and '" + |
367 | RHSOpName + "' of '" + Rec->getName() + |
368 | "' cannot be tied!" ); |
369 | |
370 | // The constraint has to go on the operand with higher index, i.e. |
371 | // the source one. Check there isn't another constraint there |
372 | // already. |
373 | if (!Ops[SrcOp.first].Constraints[SrcOp.second].isNone()) |
374 | PrintFatalError(ErrorLoc: Rec->getLoc(), Msg: "Operand '" + SrcOpName + "' of '" + |
375 | Rec->getName() + |
376 | "' cannot have multiple constraints!" ); |
377 | |
378 | unsigned DestFlatOpNo = Ops.getFlattenedOperandNumber(Op: DestOp); |
379 | auto NewConstraint = CGIOperandList::ConstraintInfo::getTied(Op: DestFlatOpNo); |
380 | |
381 | // Check that the earlier operand is not the target of another tie |
382 | // before making it the target of this one. |
383 | for (const CGIOperandList::OperandInfo &Op : Ops) { |
384 | for (unsigned i = 0; i < Op.MINumOperands; i++) |
385 | if (Op.Constraints[i] == NewConstraint) |
386 | PrintFatalError(ErrorLoc: Rec->getLoc(), |
387 | Msg: "Operand '" + DestOpName + "' of '" + Rec->getName() + |
388 | "' cannot have multiple operands tied to it!" ); |
389 | } |
390 | |
391 | Ops[SrcOp.first].Constraints[SrcOp.second] = NewConstraint; |
392 | } |
393 | |
394 | static void ParseConstraints(StringRef CStr, CGIOperandList &Ops, Record *Rec) { |
395 | if (CStr.empty()) |
396 | return; |
397 | |
398 | StringRef delims("," ); |
399 | StringRef::size_type bidx, eidx; |
400 | |
401 | bidx = CStr.find_first_not_of(Chars: delims); |
402 | while (bidx != StringRef::npos) { |
403 | eidx = CStr.find_first_of(Chars: delims, From: bidx); |
404 | if (eidx == StringRef::npos) |
405 | eidx = CStr.size(); |
406 | |
407 | ParseConstraint(CStr: CStr.substr(Start: bidx, N: eidx - bidx), Ops, Rec); |
408 | bidx = CStr.find_first_not_of(Chars: delims, From: eidx); |
409 | } |
410 | } |
411 | |
412 | void CGIOperandList::ProcessDisableEncoding(StringRef DisableEncoding) { |
413 | while (true) { |
414 | StringRef OpName; |
415 | std::tie(args&: OpName, args&: DisableEncoding) = getToken(Source: DisableEncoding, Delimiters: " ,\t" ); |
416 | if (OpName.empty()) |
417 | break; |
418 | |
419 | // Figure out which operand this is. |
420 | std::pair<unsigned, unsigned> Op = ParseOperandName(Op: OpName, AllowWholeOp: false); |
421 | |
422 | // Mark the operand as not-to-be encoded. |
423 | OperandList[Op.first].DoNotEncode[Op.second] = true; |
424 | } |
425 | } |
426 | |
427 | //===----------------------------------------------------------------------===// |
428 | // CodeGenInstruction Implementation |
429 | //===----------------------------------------------------------------------===// |
430 | |
431 | CodeGenInstruction::CodeGenInstruction(Record *R) |
432 | : TheDef(R), Operands(R), InferredFrom(nullptr) { |
433 | Namespace = R->getValueAsString(FieldName: "Namespace" ); |
434 | AsmString = std::string(R->getValueAsString(FieldName: "AsmString" )); |
435 | |
436 | isPreISelOpcode = R->getValueAsBit(FieldName: "isPreISelOpcode" ); |
437 | isReturn = R->getValueAsBit(FieldName: "isReturn" ); |
438 | isEHScopeReturn = R->getValueAsBit(FieldName: "isEHScopeReturn" ); |
439 | isBranch = R->getValueAsBit(FieldName: "isBranch" ); |
440 | isIndirectBranch = R->getValueAsBit(FieldName: "isIndirectBranch" ); |
441 | isCompare = R->getValueAsBit(FieldName: "isCompare" ); |
442 | isMoveImm = R->getValueAsBit(FieldName: "isMoveImm" ); |
443 | isMoveReg = R->getValueAsBit(FieldName: "isMoveReg" ); |
444 | isBitcast = R->getValueAsBit(FieldName: "isBitcast" ); |
445 | isSelect = R->getValueAsBit(FieldName: "isSelect" ); |
446 | isBarrier = R->getValueAsBit(FieldName: "isBarrier" ); |
447 | isCall = R->getValueAsBit(FieldName: "isCall" ); |
448 | isAdd = R->getValueAsBit(FieldName: "isAdd" ); |
449 | isTrap = R->getValueAsBit(FieldName: "isTrap" ); |
450 | canFoldAsLoad = R->getValueAsBit(FieldName: "canFoldAsLoad" ); |
451 | isPredicable = !R->getValueAsBit(FieldName: "isUnpredicable" ) && |
452 | (Operands.isPredicable || R->getValueAsBit(FieldName: "isPredicable" )); |
453 | isConvertibleToThreeAddress = R->getValueAsBit(FieldName: "isConvertibleToThreeAddress" ); |
454 | isCommutable = R->getValueAsBit(FieldName: "isCommutable" ); |
455 | isTerminator = R->getValueAsBit(FieldName: "isTerminator" ); |
456 | isReMaterializable = R->getValueAsBit(FieldName: "isReMaterializable" ); |
457 | hasDelaySlot = R->getValueAsBit(FieldName: "hasDelaySlot" ); |
458 | usesCustomInserter = R->getValueAsBit(FieldName: "usesCustomInserter" ); |
459 | hasPostISelHook = R->getValueAsBit(FieldName: "hasPostISelHook" ); |
460 | hasCtrlDep = R->getValueAsBit(FieldName: "hasCtrlDep" ); |
461 | isNotDuplicable = R->getValueAsBit(FieldName: "isNotDuplicable" ); |
462 | isRegSequence = R->getValueAsBit(FieldName: "isRegSequence" ); |
463 | isExtractSubreg = R->getValueAsBit(FieldName: "isExtractSubreg" ); |
464 | isInsertSubreg = R->getValueAsBit(FieldName: "isInsertSubreg" ); |
465 | isConvergent = R->getValueAsBit(FieldName: "isConvergent" ); |
466 | hasNoSchedulingInfo = R->getValueAsBit(FieldName: "hasNoSchedulingInfo" ); |
467 | FastISelShouldIgnore = R->getValueAsBit(FieldName: "FastISelShouldIgnore" ); |
468 | variadicOpsAreDefs = R->getValueAsBit(FieldName: "variadicOpsAreDefs" ); |
469 | isAuthenticated = R->getValueAsBit(FieldName: "isAuthenticated" ); |
470 | |
471 | bool Unset; |
472 | mayLoad = R->getValueAsBitOrUnset(FieldName: "mayLoad" , Unset); |
473 | mayLoad_Unset = Unset; |
474 | mayStore = R->getValueAsBitOrUnset(FieldName: "mayStore" , Unset); |
475 | mayStore_Unset = Unset; |
476 | mayRaiseFPException = R->getValueAsBit(FieldName: "mayRaiseFPException" ); |
477 | hasSideEffects = R->getValueAsBitOrUnset(FieldName: "hasSideEffects" , Unset); |
478 | hasSideEffects_Unset = Unset; |
479 | |
480 | isAsCheapAsAMove = R->getValueAsBit(FieldName: "isAsCheapAsAMove" ); |
481 | hasExtraSrcRegAllocReq = R->getValueAsBit(FieldName: "hasExtraSrcRegAllocReq" ); |
482 | hasExtraDefRegAllocReq = R->getValueAsBit(FieldName: "hasExtraDefRegAllocReq" ); |
483 | isCodeGenOnly = R->getValueAsBit(FieldName: "isCodeGenOnly" ); |
484 | isPseudo = R->getValueAsBit(FieldName: "isPseudo" ); |
485 | isMeta = R->getValueAsBit(FieldName: "isMeta" ); |
486 | ImplicitDefs = R->getValueAsListOfDefs(FieldName: "Defs" ); |
487 | ImplicitUses = R->getValueAsListOfDefs(FieldName: "Uses" ); |
488 | |
489 | // This flag is only inferred from the pattern. |
490 | hasChain = false; |
491 | hasChain_Inferred = false; |
492 | |
493 | // Parse Constraints. |
494 | ParseConstraints(CStr: R->getValueAsString(FieldName: "Constraints" ), Ops&: Operands, Rec: R); |
495 | |
496 | // Parse the DisableEncoding field. |
497 | Operands.ProcessDisableEncoding(DisableEncoding: R->getValueAsString(FieldName: "DisableEncoding" )); |
498 | |
499 | // First check for a ComplexDeprecationPredicate. |
500 | if (R->getValue(Name: "ComplexDeprecationPredicate" )) { |
501 | HasComplexDeprecationPredicate = true; |
502 | DeprecatedReason = |
503 | std::string(R->getValueAsString(FieldName: "ComplexDeprecationPredicate" )); |
504 | } else if (RecordVal *Dep = R->getValue(Name: "DeprecatedFeatureMask" )) { |
505 | // Check if we have a Subtarget feature mask. |
506 | HasComplexDeprecationPredicate = false; |
507 | DeprecatedReason = Dep->getValue()->getAsString(); |
508 | } else { |
509 | // This instruction isn't deprecated. |
510 | HasComplexDeprecationPredicate = false; |
511 | DeprecatedReason = "" ; |
512 | } |
513 | } |
514 | |
515 | /// HasOneImplicitDefWithKnownVT - If the instruction has at least one |
516 | /// implicit def and it has a known VT, return the VT, otherwise return |
517 | /// MVT::Other. |
518 | MVT::SimpleValueType CodeGenInstruction::HasOneImplicitDefWithKnownVT( |
519 | const CodeGenTarget &TargetInfo) const { |
520 | if (ImplicitDefs.empty()) |
521 | return MVT::Other; |
522 | |
523 | // Check to see if the first implicit def has a resolvable type. |
524 | Record *FirstImplicitDef = ImplicitDefs[0]; |
525 | assert(FirstImplicitDef->isSubClassOf("Register" )); |
526 | const std::vector<ValueTypeByHwMode> &RegVTs = |
527 | TargetInfo.getRegisterVTs(R: FirstImplicitDef); |
528 | if (RegVTs.size() == 1 && RegVTs[0].isSimple()) |
529 | return RegVTs[0].getSimple().SimpleTy; |
530 | return MVT::Other; |
531 | } |
532 | |
533 | /// FlattenAsmStringVariants - Flatten the specified AsmString to only |
534 | /// include text from the specified variant, returning the new string. |
535 | std::string CodeGenInstruction::FlattenAsmStringVariants(StringRef Cur, |
536 | unsigned Variant) { |
537 | std::string Res; |
538 | |
539 | for (;;) { |
540 | // Find the start of the next variant string. |
541 | size_t VariantsStart = 0; |
542 | for (size_t e = Cur.size(); VariantsStart != e; ++VariantsStart) |
543 | if (Cur[VariantsStart] == '{' && |
544 | (VariantsStart == 0 || |
545 | (Cur[VariantsStart - 1] != '$' && Cur[VariantsStart - 1] != '\\'))) |
546 | break; |
547 | |
548 | // Add the prefix to the result. |
549 | Res += Cur.slice(Start: 0, End: VariantsStart); |
550 | if (VariantsStart == Cur.size()) |
551 | break; |
552 | |
553 | ++VariantsStart; // Skip the '{'. |
554 | |
555 | // Scan to the end of the variants string. |
556 | size_t VariantsEnd = VariantsStart; |
557 | unsigned NestedBraces = 1; |
558 | for (size_t e = Cur.size(); VariantsEnd != e; ++VariantsEnd) { |
559 | if (Cur[VariantsEnd] == '}' && Cur[VariantsEnd - 1] != '\\') { |
560 | if (--NestedBraces == 0) |
561 | break; |
562 | } else if (Cur[VariantsEnd] == '{') |
563 | ++NestedBraces; |
564 | } |
565 | |
566 | // Select the Nth variant (or empty). |
567 | StringRef Selection = Cur.slice(Start: VariantsStart, End: VariantsEnd); |
568 | for (unsigned i = 0; i != Variant; ++i) |
569 | Selection = Selection.split(Separator: '|').second; |
570 | Res += Selection.split(Separator: '|').first; |
571 | |
572 | assert(VariantsEnd != Cur.size() && |
573 | "Unterminated variants in assembly string!" ); |
574 | Cur = Cur.substr(Start: VariantsEnd + 1); |
575 | } |
576 | |
577 | return Res; |
578 | } |
579 | |
580 | bool CodeGenInstruction::isOperandImpl(StringRef OpListName, unsigned i, |
581 | StringRef PropertyName) const { |
582 | DagInit *ConstraintList = TheDef->getValueAsDag(FieldName: OpListName); |
583 | if (!ConstraintList || i >= ConstraintList->getNumArgs()) |
584 | return false; |
585 | |
586 | DefInit *Constraint = dyn_cast<DefInit>(Val: ConstraintList->getArg(Num: i)); |
587 | if (!Constraint) |
588 | return false; |
589 | |
590 | return Constraint->getDef()->isSubClassOf(Name: "TypedOperand" ) && |
591 | Constraint->getDef()->getValueAsBit(FieldName: PropertyName); |
592 | } |
593 | |