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