1 | //===- llvm/InlineAsm.h - Class to represent inline asm strings -*- C++ -*-===// |
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 class represents the inline asm strings, which are Value*'s that are |
10 | // used as the callee operand of call instructions. InlineAsm's are uniqued |
11 | // like constants, and created via InlineAsm::get(...). |
12 | // |
13 | //===----------------------------------------------------------------------===// |
14 | |
15 | #ifndef LLVM_IR_INLINEASM_H |
16 | #define LLVM_IR_INLINEASM_H |
17 | |
18 | #include "llvm/ADT/Bitfields.h" |
19 | #include "llvm/ADT/SmallVector.h" |
20 | #include "llvm/ADT/StringRef.h" |
21 | #include "llvm/IR/Value.h" |
22 | #include "llvm/Support/ErrorHandling.h" |
23 | #include <cassert> |
24 | #include <string> |
25 | #include <vector> |
26 | |
27 | namespace llvm { |
28 | |
29 | class Error; |
30 | class FunctionType; |
31 | class PointerType; |
32 | template <class ConstantClass> class ConstantUniqueMap; |
33 | |
34 | class InlineAsm final : public Value { |
35 | public: |
36 | enum AsmDialect { |
37 | AD_ATT, |
38 | AD_Intel |
39 | }; |
40 | |
41 | private: |
42 | friend struct InlineAsmKeyType; |
43 | friend class ConstantUniqueMap<InlineAsm>; |
44 | |
45 | std::string AsmString, Constraints; |
46 | FunctionType *FTy; |
47 | bool HasSideEffects; |
48 | bool IsAlignStack; |
49 | AsmDialect Dialect; |
50 | bool CanThrow; |
51 | |
52 | InlineAsm(FunctionType *Ty, const std::string &AsmString, |
53 | const std::string &Constraints, bool hasSideEffects, |
54 | bool isAlignStack, AsmDialect asmDialect, bool canThrow); |
55 | |
56 | /// When the ConstantUniqueMap merges two types and makes two InlineAsms |
57 | /// identical, it destroys one of them with this method. |
58 | void destroyConstant(); |
59 | |
60 | public: |
61 | InlineAsm(const InlineAsm &) = delete; |
62 | InlineAsm &operator=(const InlineAsm &) = delete; |
63 | |
64 | /// InlineAsm::get - Return the specified uniqued inline asm string. |
65 | /// |
66 | static InlineAsm *get(FunctionType *Ty, StringRef AsmString, |
67 | StringRef Constraints, bool hasSideEffects, |
68 | bool isAlignStack = false, |
69 | AsmDialect asmDialect = AD_ATT, bool canThrow = false); |
70 | |
71 | bool hasSideEffects() const { return HasSideEffects; } |
72 | bool isAlignStack() const { return IsAlignStack; } |
73 | AsmDialect getDialect() const { return Dialect; } |
74 | bool canThrow() const { return CanThrow; } |
75 | |
76 | /// getType - InlineAsm's are always pointers. |
77 | /// |
78 | PointerType *getType() const { |
79 | return reinterpret_cast<PointerType*>(Value::getType()); |
80 | } |
81 | |
82 | /// getFunctionType - InlineAsm's are always pointers to functions. |
83 | /// |
84 | FunctionType *getFunctionType() const; |
85 | |
86 | const std::string &getAsmString() const { return AsmString; } |
87 | const std::string &getConstraintString() const { return Constraints; } |
88 | void collectAsmStrs(SmallVectorImpl<StringRef> &AsmStrs) const; |
89 | |
90 | /// This static method can be used by the parser to check to see if the |
91 | /// specified constraint string is legal for the type. |
92 | static Error verify(FunctionType *Ty, StringRef Constraints); |
93 | |
94 | // Constraint String Parsing |
95 | enum ConstraintPrefix { |
96 | isInput, // 'x' |
97 | isOutput, // '=x' |
98 | isClobber, // '~x' |
99 | isLabel, // '!x' |
100 | }; |
101 | |
102 | using ConstraintCodeVector = std::vector<std::string>; |
103 | |
104 | struct SubConstraintInfo { |
105 | /// MatchingInput - If this is not -1, this is an output constraint where an |
106 | /// input constraint is required to match it (e.g. "0"). The value is the |
107 | /// constraint number that matches this one (for example, if this is |
108 | /// constraint #0 and constraint #4 has the value "0", this will be 4). |
109 | int MatchingInput = -1; |
110 | |
111 | /// Code - The constraint code, either the register name (in braces) or the |
112 | /// constraint letter/number. |
113 | ConstraintCodeVector Codes; |
114 | |
115 | /// Default constructor. |
116 | SubConstraintInfo() = default; |
117 | }; |
118 | |
119 | using SubConstraintInfoVector = std::vector<SubConstraintInfo>; |
120 | struct ConstraintInfo; |
121 | using ConstraintInfoVector = std::vector<ConstraintInfo>; |
122 | |
123 | struct ConstraintInfo { |
124 | /// Type - The basic type of the constraint: input/output/clobber/label |
125 | /// |
126 | ConstraintPrefix Type = isInput; |
127 | |
128 | /// isEarlyClobber - "&": output operand writes result before inputs are all |
129 | /// read. This is only ever set for an output operand. |
130 | bool isEarlyClobber = false; |
131 | |
132 | /// MatchingInput - If this is not -1, this is an output constraint where an |
133 | /// input constraint is required to match it (e.g. "0"). The value is the |
134 | /// constraint number that matches this one (for example, if this is |
135 | /// constraint #0 and constraint #4 has the value "0", this will be 4). |
136 | int MatchingInput = -1; |
137 | |
138 | /// hasMatchingInput - Return true if this is an output constraint that has |
139 | /// a matching input constraint. |
140 | bool hasMatchingInput() const { return MatchingInput != -1; } |
141 | |
142 | /// isCommutative - This is set to true for a constraint that is commutative |
143 | /// with the next operand. |
144 | bool isCommutative = false; |
145 | |
146 | /// isIndirect - True if this operand is an indirect operand. This means |
147 | /// that the address of the source or destination is present in the call |
148 | /// instruction, instead of it being returned or passed in explicitly. This |
149 | /// is represented with a '*' in the asm string. |
150 | bool isIndirect = false; |
151 | |
152 | /// Code - The constraint code, either the register name (in braces) or the |
153 | /// constraint letter/number. |
154 | ConstraintCodeVector Codes; |
155 | |
156 | /// isMultipleAlternative - '|': has multiple-alternative constraints. |
157 | bool isMultipleAlternative = false; |
158 | |
159 | /// multipleAlternatives - If there are multiple alternative constraints, |
160 | /// this array will contain them. Otherwise it will be empty. |
161 | SubConstraintInfoVector multipleAlternatives; |
162 | |
163 | /// The currently selected alternative constraint index. |
164 | unsigned currentAlternativeIndex = 0; |
165 | |
166 | /// Default constructor. |
167 | ConstraintInfo() = default; |
168 | |
169 | /// Parse - Analyze the specified string (e.g. "=*&{eax}") and fill in the |
170 | /// fields in this structure. If the constraint string is not understood, |
171 | /// return true, otherwise return false. |
172 | bool Parse(StringRef Str, ConstraintInfoVector &ConstraintsSoFar); |
173 | |
174 | /// selectAlternative - Point this constraint to the alternative constraint |
175 | /// indicated by the index. |
176 | void selectAlternative(unsigned index); |
177 | |
178 | /// Whether this constraint corresponds to an argument. |
179 | bool hasArg() const { |
180 | return Type == isInput || (Type == isOutput && isIndirect); |
181 | } |
182 | }; |
183 | |
184 | /// ParseConstraints - Split up the constraint string into the specific |
185 | /// constraints and their prefixes. If this returns an empty vector, and if |
186 | /// the constraint string itself isn't empty, there was an error parsing. |
187 | static ConstraintInfoVector ParseConstraints(StringRef ConstraintString); |
188 | |
189 | /// ParseConstraints - Parse the constraints of this inlineasm object, |
190 | /// returning them the same way that ParseConstraints(str) does. |
191 | ConstraintInfoVector ParseConstraints() const { |
192 | return ParseConstraints(ConstraintString: Constraints); |
193 | } |
194 | |
195 | // Methods for support type inquiry through isa, cast, and dyn_cast: |
196 | static bool classof(const Value *V) { |
197 | return V->getValueID() == Value::InlineAsmVal; |
198 | } |
199 | |
200 | enum : uint32_t { |
201 | // Fixed operands on an INLINEASM SDNode. |
202 | Op_InputChain = 0, |
203 | Op_AsmString = 1, |
204 | Op_MDNode = 2, |
205 | = 3, // HasSideEffects, IsAlignStack, AsmDialect. |
206 | Op_FirstOperand = 4, |
207 | |
208 | // Fixed operands on an INLINEASM MachineInstr. |
209 | MIOp_AsmString = 0, |
210 | = 1, // HasSideEffects, IsAlignStack, AsmDialect. |
211 | MIOp_FirstOperand = 2, |
212 | |
213 | // Interpretation of the MIOp_ExtraInfo bit field. |
214 | = 1, |
215 | = 2, |
216 | = 4, |
217 | = 8, |
218 | = 16, |
219 | = 32, |
220 | }; |
221 | |
222 | // Inline asm operands map to multiple SDNode / MachineInstr operands. |
223 | // The first operand is an immediate describing the asm operand, the low |
224 | // bits is the kind: |
225 | enum class Kind : uint8_t { |
226 | RegUse = 1, // Input register, "r". |
227 | RegDef = 2, // Output register, "=r". |
228 | RegDefEarlyClobber = 3, // Early-clobber output register, "=&r". |
229 | Clobber = 4, // Clobbered register, "~r". |
230 | Imm = 5, // Immediate. |
231 | Mem = 6, // Memory operand, "m", or an address, "p". |
232 | Func = 7, // Address operand of function call |
233 | }; |
234 | |
235 | // Memory constraint codes. |
236 | // Addresses are included here as they need to be treated the same by the |
237 | // backend, the only difference is that they are not used to actaully |
238 | // access memory by the instruction. |
239 | enum class ConstraintCode : uint32_t { |
240 | Unknown = 0, |
241 | es, |
242 | i, |
243 | k, |
244 | m, |
245 | o, |
246 | v, |
247 | A, |
248 | Q, |
249 | R, |
250 | S, |
251 | T, |
252 | Um, |
253 | Un, |
254 | Uq, |
255 | Us, |
256 | Ut, |
257 | Uv, |
258 | Uy, |
259 | X, |
260 | Z, |
261 | ZB, |
262 | ZC, |
263 | Zy, |
264 | |
265 | // Address constraints |
266 | p, |
267 | ZQ, |
268 | ZR, |
269 | ZS, |
270 | ZT, |
271 | |
272 | Max = ZT, |
273 | }; |
274 | |
275 | // This class is intentionally packed into a 32b value as it is used as a |
276 | // MVT::i32 ConstantSDNode SDValue for SelectionDAG and as immediate operands |
277 | // on INLINEASM and INLINEASM_BR MachineInstr's. |
278 | // |
279 | // The encoding of Flag is currently: |
280 | // Bits 2-0 - A Kind::* value indicating the kind of the operand. |
281 | // (KindField) |
282 | // Bits 15-3 - The number of SDNode operands associated with this inline |
283 | // assembly operand. Once lowered to MIR, this represents the |
284 | // number of MachineOperands necessary to refer to a |
285 | // MachineOperandType::MO_FrameIndex. (NumOperands) |
286 | // Bit 31 - Determines if this is a matched operand. (IsMatched) |
287 | // If bit 31 is set: |
288 | // Bits 30-16 - The operand number that this operand must match. |
289 | // (MatchedOperandNo) |
290 | // Else if bits 2-0 are Kind::Mem: |
291 | // Bits 30-16 - A ConstraintCode:: value indicating the original |
292 | // constraint code. (MemConstraintCode) |
293 | // Else: |
294 | // Bits 29-16 - The register class ID to use for the operand. (RegClass) |
295 | // Bit 30 - If the register is permitted to be spilled. |
296 | // (RegMayBeFolded) |
297 | // Defaults to false "r", may be set for constraints like |
298 | // "rm" (or "g"). |
299 | // |
300 | // As such, MatchedOperandNo, MemConstraintCode, and |
301 | // (RegClass+RegMayBeFolded) are views of the same slice of bits, but are |
302 | // mutually exclusive depending on the fields IsMatched then KindField. |
303 | class Flag { |
304 | uint32_t Storage; |
305 | using KindField = Bitfield::Element<Kind, 0, 3, Kind::Func>; |
306 | using NumOperands = Bitfield::Element<unsigned, 3, 13>; |
307 | using MatchedOperandNo = Bitfield::Element<unsigned, 16, 15>; |
308 | using MemConstraintCode = Bitfield::Element<ConstraintCode, 16, 15, ConstraintCode::Max>; |
309 | using RegClass = Bitfield::Element<unsigned, 16, 14>; |
310 | using RegMayBeFolded = Bitfield::Element<bool, 30, 1>; |
311 | using IsMatched = Bitfield::Element<bool, 31, 1>; |
312 | |
313 | |
314 | unsigned getMatchedOperandNo() const { return Bitfield::get<MatchedOperandNo>(Packed: Storage); } |
315 | unsigned getRegClass() const { return Bitfield::get<RegClass>(Packed: Storage); } |
316 | bool isMatched() const { return Bitfield::get<IsMatched>(Packed: Storage); } |
317 | |
318 | public: |
319 | Flag() : Storage(0) {} |
320 | explicit Flag(uint32_t F) : Storage(F) {} |
321 | Flag(enum Kind K, unsigned NumOps) : Storage(0) { |
322 | Bitfield::set<KindField>(Packed&: Storage, Value: K); |
323 | Bitfield::set<NumOperands>(Packed&: Storage, Value: NumOps); |
324 | } |
325 | operator uint32_t() { return Storage; } |
326 | Kind getKind() const { return Bitfield::get<KindField>(Packed: Storage); } |
327 | bool isRegUseKind() const { return getKind() == Kind::RegUse; } |
328 | bool isRegDefKind() const { return getKind() == Kind::RegDef; } |
329 | bool isRegDefEarlyClobberKind() const { |
330 | return getKind() == Kind::RegDefEarlyClobber; |
331 | } |
332 | bool isClobberKind() const { return getKind() == Kind::Clobber; } |
333 | bool isImmKind() const { return getKind() == Kind::Imm; } |
334 | bool isMemKind() const { return getKind() == Kind::Mem; } |
335 | bool isFuncKind() const { return getKind() == Kind::Func; } |
336 | StringRef getKindName() const { |
337 | switch (getKind()) { |
338 | case Kind::RegUse: |
339 | return "reguse" ; |
340 | case Kind::RegDef: |
341 | return "regdef" ; |
342 | case Kind::RegDefEarlyClobber: |
343 | return "regdef-ec" ; |
344 | case Kind::Clobber: |
345 | return "clobber" ; |
346 | case Kind::Imm: |
347 | return "imm" ; |
348 | case Kind::Mem: |
349 | case Kind::Func: |
350 | return "mem" ; |
351 | } |
352 | llvm_unreachable("impossible kind" ); |
353 | } |
354 | |
355 | /// getNumOperandRegisters - Extract the number of registers field from the |
356 | /// inline asm operand flag. |
357 | unsigned getNumOperandRegisters() const { |
358 | return Bitfield::get<NumOperands>(Packed: Storage); |
359 | } |
360 | |
361 | /// isUseOperandTiedToDef - Return true if the flag of the inline asm |
362 | /// operand indicates it is an use operand that's matched to a def operand. |
363 | bool isUseOperandTiedToDef(unsigned &Idx) const { |
364 | if (!isMatched()) |
365 | return false; |
366 | Idx = getMatchedOperandNo(); |
367 | return true; |
368 | } |
369 | |
370 | /// hasRegClassConstraint - Returns true if the flag contains a register |
371 | /// class constraint. Sets RC to the register class ID. |
372 | bool hasRegClassConstraint(unsigned &RC) const { |
373 | if (isMatched()) |
374 | return false; |
375 | // setRegClass() uses 0 to mean no register class, and otherwise stores |
376 | // RC + 1. |
377 | if (!getRegClass()) |
378 | return false; |
379 | RC = getRegClass() - 1; |
380 | return true; |
381 | } |
382 | |
383 | ConstraintCode getMemoryConstraintID() const { |
384 | assert((isMemKind() || isFuncKind()) && |
385 | "Not expected mem or function flag!" ); |
386 | return Bitfield::get<MemConstraintCode>(Packed: Storage); |
387 | } |
388 | |
389 | /// setMatchingOp - Augment an existing flag with information indicating |
390 | /// that this input operand is tied to a previous output operand. |
391 | void setMatchingOp(unsigned OperandNo) { |
392 | assert(getMatchedOperandNo() == 0 && "Matching operand already set" ); |
393 | Bitfield::set<MatchedOperandNo>(Packed&: Storage, Value: OperandNo); |
394 | Bitfield::set<IsMatched>(Packed&: Storage, Value: true); |
395 | } |
396 | |
397 | /// setRegClass - Augment an existing flag with the required register class |
398 | /// for the following register operands. A tied use operand cannot have a |
399 | /// register class, use the register class from the def operand instead. |
400 | void setRegClass(unsigned RC) { |
401 | assert(!isImmKind() && "Immediates cannot have a register class" ); |
402 | assert(!isMemKind() && "Memory operand cannot have a register class" ); |
403 | assert(getRegClass() == 0 && "Register class already set" ); |
404 | // Store RC + 1, reserve the value 0 to mean 'no register class'. |
405 | Bitfield::set<RegClass>(Packed&: Storage, Value: RC + 1); |
406 | } |
407 | |
408 | /// setMemConstraint - Augment an existing flag with the constraint code for |
409 | /// a memory constraint. |
410 | void setMemConstraint(ConstraintCode C) { |
411 | assert(getMemoryConstraintID() == ConstraintCode::Unknown && "Mem constraint already set" ); |
412 | Bitfield::set<MemConstraintCode>(Packed&: Storage, Value: C); |
413 | } |
414 | /// clearMemConstraint - Similar to setMemConstraint(0), but without the |
415 | /// assertion checking that the constraint has not been set previously. |
416 | void clearMemConstraint() { |
417 | assert((isMemKind() || isFuncKind()) && |
418 | "Flag is not a memory or function constraint!" ); |
419 | Bitfield::set<MemConstraintCode>(Packed&: Storage, Value: ConstraintCode::Unknown); |
420 | } |
421 | |
422 | /// Set a bit to denote that while this operand is some kind of register |
423 | /// (use, def, ...), a memory flag did appear in the original constraint |
424 | /// list. This is set by the instruction selection framework, and consumed |
425 | /// by the register allocator. While the register allocator is generally |
426 | /// responsible for spilling registers, we need to be able to distinguish |
427 | /// between registers that the register allocator has permission to fold |
428 | /// ("rm") vs ones it does not ("r"). This is because the inline asm may use |
429 | /// instructions which don't support memory addressing modes for that |
430 | /// operand. |
431 | void setRegMayBeFolded(bool B) { |
432 | assert((isRegDefKind() || isRegDefEarlyClobberKind() || isRegUseKind()) && |
433 | "Must be reg" ); |
434 | Bitfield::set<RegMayBeFolded>(Packed&: Storage, Value: B); |
435 | } |
436 | bool getRegMayBeFolded() const { |
437 | assert((isRegDefKind() || isRegDefEarlyClobberKind() || isRegUseKind()) && |
438 | "Must be reg" ); |
439 | return Bitfield::get<RegMayBeFolded>(Packed: Storage); |
440 | } |
441 | }; |
442 | |
443 | static std::vector<StringRef> (unsigned ) { |
444 | std::vector<StringRef> Result; |
445 | if (ExtraInfo & InlineAsm::Extra_HasSideEffects) |
446 | Result.push_back(x: "sideeffect" ); |
447 | if (ExtraInfo & InlineAsm::Extra_MayLoad) |
448 | Result.push_back(x: "mayload" ); |
449 | if (ExtraInfo & InlineAsm::Extra_MayStore) |
450 | Result.push_back(x: "maystore" ); |
451 | if (ExtraInfo & InlineAsm::Extra_IsConvergent) |
452 | Result.push_back(x: "isconvergent" ); |
453 | if (ExtraInfo & InlineAsm::Extra_IsAlignStack) |
454 | Result.push_back(x: "alignstack" ); |
455 | |
456 | AsmDialect Dialect = |
457 | InlineAsm::AsmDialect((ExtraInfo & InlineAsm::Extra_AsmDialect)); |
458 | |
459 | if (Dialect == InlineAsm::AD_ATT) |
460 | Result.push_back(x: "attdialect" ); |
461 | if (Dialect == InlineAsm::AD_Intel) |
462 | Result.push_back(x: "inteldialect" ); |
463 | |
464 | return Result; |
465 | } |
466 | |
467 | static StringRef getMemConstraintName(ConstraintCode C) { |
468 | switch (C) { |
469 | case ConstraintCode::es: |
470 | return "es" ; |
471 | case ConstraintCode::i: |
472 | return "i" ; |
473 | case ConstraintCode::k: |
474 | return "k" ; |
475 | case ConstraintCode::m: |
476 | return "m" ; |
477 | case ConstraintCode::o: |
478 | return "o" ; |
479 | case ConstraintCode::v: |
480 | return "v" ; |
481 | case ConstraintCode::A: |
482 | return "A" ; |
483 | case ConstraintCode::Q: |
484 | return "Q" ; |
485 | case ConstraintCode::R: |
486 | return "R" ; |
487 | case ConstraintCode::S: |
488 | return "S" ; |
489 | case ConstraintCode::T: |
490 | return "T" ; |
491 | case ConstraintCode::Um: |
492 | return "Um" ; |
493 | case ConstraintCode::Un: |
494 | return "Un" ; |
495 | case ConstraintCode::Uq: |
496 | return "Uq" ; |
497 | case ConstraintCode::Us: |
498 | return "Us" ; |
499 | case ConstraintCode::Ut: |
500 | return "Ut" ; |
501 | case ConstraintCode::Uv: |
502 | return "Uv" ; |
503 | case ConstraintCode::Uy: |
504 | return "Uy" ; |
505 | case ConstraintCode::X: |
506 | return "X" ; |
507 | case ConstraintCode::Z: |
508 | return "Z" ; |
509 | case ConstraintCode::ZB: |
510 | return "ZB" ; |
511 | case ConstraintCode::ZC: |
512 | return "ZC" ; |
513 | case ConstraintCode::Zy: |
514 | return "Zy" ; |
515 | case ConstraintCode::p: |
516 | return "p" ; |
517 | case ConstraintCode::ZQ: |
518 | return "ZQ" ; |
519 | case ConstraintCode::ZR: |
520 | return "ZR" ; |
521 | case ConstraintCode::ZS: |
522 | return "ZS" ; |
523 | case ConstraintCode::ZT: |
524 | return "ZT" ; |
525 | default: |
526 | llvm_unreachable("Unknown memory constraint" ); |
527 | } |
528 | } |
529 | }; |
530 | |
531 | } // end namespace llvm |
532 | |
533 | #endif // LLVM_IR_INLINEASM_H |
534 | |