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(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 Op_ExtraInfo = 3, // HasSideEffects, IsAlignStack, AsmDialect. 206 Op_FirstOperand = 4, 207 208 // Fixed operands on an INLINEASM MachineInstr. 209 MIOp_AsmString = 0, 210 MIOp_ExtraInfo = 1, // HasSideEffects, IsAlignStack, AsmDialect. 211 MIOp_FirstOperand = 2, 212 213 // Interpretation of the MIOp_ExtraInfo bit field. 214 Extra_HasSideEffects = 1, 215 Extra_IsAlignStack = 2, 216 Extra_AsmDialect = 4, 217 Extra_MayLoad = 8, 218 Extra_MayStore = 16, 219 Extra_IsConvergent = 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>(Storage); } 315 unsigned getRegClass() const { return Bitfield::get<RegClass>(Storage); } 316 bool isMatched() const { return Bitfield::get<IsMatched>(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>(Storage, K); 323 Bitfield::set<NumOperands>(Storage, NumOps); 324 } 325 operator uint32_t() { return Storage; } 326 Kind getKind() const { return Bitfield::get<KindField>(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>(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>(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>(Storage, OperandNo); 394 Bitfield::set<IsMatched>(Storage, 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>(Storage, 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>(Storage, 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>(Storage, 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>(Storage, B); 435 } 436 bool getRegMayBeFolded() const { 437 assert((isRegDefKind() || isRegDefEarlyClobberKind() || isRegUseKind()) && 438 "Must be reg"); 439 return Bitfield::get<RegMayBeFolded>(Storage); 440 } 441 }; 442 443 static std::vector<StringRef> getExtraInfoNames(unsigned ExtraInfo) { 444 std::vector<StringRef> Result; 445 if (ExtraInfo & InlineAsm::Extra_HasSideEffects) 446 Result.push_back("sideeffect"); 447 if (ExtraInfo & InlineAsm::Extra_MayLoad) 448 Result.push_back("mayload"); 449 if (ExtraInfo & InlineAsm::Extra_MayStore) 450 Result.push_back("maystore"); 451 if (ExtraInfo & InlineAsm::Extra_IsConvergent) 452 Result.push_back("isconvergent"); 453 if (ExtraInfo & InlineAsm::Extra_IsAlignStack) 454 Result.push_back("alignstack"); 455 456 AsmDialect Dialect = 457 InlineAsm::AsmDialect((ExtraInfo & InlineAsm::Extra_AsmDialect)); 458 459 if (Dialect == InlineAsm::AD_ATT) 460 Result.push_back("attdialect"); 461 if (Dialect == InlineAsm::AD_Intel) 462 Result.push_back("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