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/SmallVector.h" 19 #include "llvm/ADT/StringRef.h" 20 #include "llvm/IR/Value.h" 21 #include "llvm/Support/ErrorHandling.h" 22 #include <cassert> 23 #include <string> 24 #include <vector> 25 26 namespace llvm { 27 28 class Error; 29 class FunctionType; 30 class PointerType; 31 template <class ConstantClass> class ConstantUniqueMap; 32 33 class InlineAsm final : public Value { 34 public: 35 enum AsmDialect { 36 AD_ATT, 37 AD_Intel 38 }; 39 40 private: 41 friend struct InlineAsmKeyType; 42 friend class ConstantUniqueMap<InlineAsm>; 43 44 std::string AsmString, Constraints; 45 FunctionType *FTy; 46 bool HasSideEffects; 47 bool IsAlignStack; 48 AsmDialect Dialect; 49 bool CanThrow; 50 51 InlineAsm(FunctionType *Ty, const std::string &AsmString, 52 const std::string &Constraints, bool hasSideEffects, 53 bool isAlignStack, AsmDialect asmDialect, bool canThrow); 54 55 /// When the ConstantUniqueMap merges two types and makes two InlineAsms 56 /// identical, it destroys one of them with this method. 57 void destroyConstant(); 58 59 public: 60 InlineAsm(const InlineAsm &) = delete; 61 InlineAsm &operator=(const InlineAsm &) = delete; 62 63 /// InlineAsm::get - Return the specified uniqued inline asm string. 64 /// 65 static InlineAsm *get(FunctionType *Ty, StringRef AsmString, 66 StringRef Constraints, bool hasSideEffects, 67 bool isAlignStack = false, 68 AsmDialect asmDialect = AD_ATT, bool canThrow = false); 69 hasSideEffects()70 bool hasSideEffects() const { return HasSideEffects; } isAlignStack()71 bool isAlignStack() const { return IsAlignStack; } getDialect()72 AsmDialect getDialect() const { return Dialect; } canThrow()73 bool canThrow() const { return CanThrow; } 74 75 /// getType - InlineAsm's are always pointers. 76 /// getType()77 PointerType *getType() const { 78 return reinterpret_cast<PointerType*>(Value::getType()); 79 } 80 81 /// getFunctionType - InlineAsm's are always pointers to functions. 82 /// 83 FunctionType *getFunctionType() const; 84 getAsmString()85 const std::string &getAsmString() const { return AsmString; } getConstraintString()86 const std::string &getConstraintString() const { return Constraints; } 87 void collectAsmStrs(SmallVectorImpl<StringRef> &AsmStrs) const; 88 89 /// This static method can be used by the parser to check to see if the 90 /// specified constraint string is legal for the type. 91 static Error verify(FunctionType *Ty, StringRef Constraints); 92 93 // Constraint String Parsing 94 enum ConstraintPrefix { 95 isInput, // 'x' 96 isOutput, // '=x' 97 isClobber, // '~x' 98 isLabel, // '!x' 99 }; 100 101 using ConstraintCodeVector = std::vector<std::string>; 102 103 struct SubConstraintInfo { 104 /// MatchingInput - If this is not -1, this is an output constraint where an 105 /// input constraint is required to match it (e.g. "0"). The value is the 106 /// constraint number that matches this one (for example, if this is 107 /// constraint #0 and constraint #4 has the value "0", this will be 4). 108 int MatchingInput = -1; 109 110 /// Code - The constraint code, either the register name (in braces) or the 111 /// constraint letter/number. 112 ConstraintCodeVector Codes; 113 114 /// Default constructor. 115 SubConstraintInfo() = default; 116 }; 117 118 using SubConstraintInfoVector = std::vector<SubConstraintInfo>; 119 struct ConstraintInfo; 120 using ConstraintInfoVector = std::vector<ConstraintInfo>; 121 122 struct ConstraintInfo { 123 /// Type - The basic type of the constraint: input/output/clobber/label 124 /// 125 ConstraintPrefix Type = isInput; 126 127 /// isEarlyClobber - "&": output operand writes result before inputs are all 128 /// read. This is only ever set for an output operand. 129 bool isEarlyClobber = false; 130 131 /// MatchingInput - If this is not -1, this is an output constraint where an 132 /// input constraint is required to match it (e.g. "0"). The value is the 133 /// constraint number that matches this one (for example, if this is 134 /// constraint #0 and constraint #4 has the value "0", this will be 4). 135 int MatchingInput = -1; 136 137 /// hasMatchingInput - Return true if this is an output constraint that has 138 /// a matching input constraint. hasMatchingInputConstraintInfo139 bool hasMatchingInput() const { return MatchingInput != -1; } 140 141 /// isCommutative - This is set to true for a constraint that is commutative 142 /// with the next operand. 143 bool isCommutative = false; 144 145 /// isIndirect - True if this operand is an indirect operand. This means 146 /// that the address of the source or destination is present in the call 147 /// instruction, instead of it being returned or passed in explicitly. This 148 /// is represented with a '*' in the asm string. 149 bool isIndirect = false; 150 151 /// Code - The constraint code, either the register name (in braces) or the 152 /// constraint letter/number. 153 ConstraintCodeVector Codes; 154 155 /// isMultipleAlternative - '|': has multiple-alternative constraints. 156 bool isMultipleAlternative = false; 157 158 /// multipleAlternatives - If there are multiple alternative constraints, 159 /// this array will contain them. Otherwise it will be empty. 160 SubConstraintInfoVector multipleAlternatives; 161 162 /// The currently selected alternative constraint index. 163 unsigned currentAlternativeIndex = 0; 164 165 /// Default constructor. 166 ConstraintInfo() = default; 167 168 /// Parse - Analyze the specified string (e.g. "=*&{eax}") and fill in the 169 /// fields in this structure. If the constraint string is not understood, 170 /// return true, otherwise return false. 171 bool Parse(StringRef Str, ConstraintInfoVector &ConstraintsSoFar); 172 173 /// selectAlternative - Point this constraint to the alternative constraint 174 /// indicated by the index. 175 void selectAlternative(unsigned index); 176 177 /// Whether this constraint corresponds to an argument. hasArgConstraintInfo178 bool hasArg() const { 179 return Type == isInput || (Type == isOutput && isIndirect); 180 } 181 }; 182 183 /// ParseConstraints - Split up the constraint string into the specific 184 /// constraints and their prefixes. If this returns an empty vector, and if 185 /// the constraint string itself isn't empty, there was an error parsing. 186 static ConstraintInfoVector ParseConstraints(StringRef ConstraintString); 187 188 /// ParseConstraints - Parse the constraints of this inlineasm object, 189 /// returning them the same way that ParseConstraints(str) does. ParseConstraints()190 ConstraintInfoVector ParseConstraints() const { 191 return ParseConstraints(Constraints); 192 } 193 194 // Methods for support type inquiry through isa, cast, and dyn_cast: classof(const Value * V)195 static bool classof(const Value *V) { 196 return V->getValueID() == Value::InlineAsmVal; 197 } 198 199 // These are helper methods for dealing with flags in the INLINEASM SDNode 200 // in the backend. 201 // 202 // The encoding of the flag word is currently: 203 // Bits 2-0 - A Kind_* value indicating the kind of the operand. 204 // Bits 15-3 - The number of SDNode operands associated with this inline 205 // assembly operand. 206 // If bit 31 is set: 207 // Bit 30-16 - The operand number that this operand must match. 208 // When bits 2-0 are Kind_Mem, the Constraint_* value must be 209 // obtained from the flags for this operand number. 210 // Else if bits 2-0 are Kind_Mem: 211 // Bit 30-16 - A Constraint_* value indicating the original constraint 212 // code. 213 // Else: 214 // Bit 30-16 - The register class ID to use for the operand. 215 216 enum : uint32_t { 217 // Fixed operands on an INLINEASM SDNode. 218 Op_InputChain = 0, 219 Op_AsmString = 1, 220 Op_MDNode = 2, 221 Op_ExtraInfo = 3, // HasSideEffects, IsAlignStack, AsmDialect. 222 Op_FirstOperand = 4, 223 224 // Fixed operands on an INLINEASM MachineInstr. 225 MIOp_AsmString = 0, 226 MIOp_ExtraInfo = 1, // HasSideEffects, IsAlignStack, AsmDialect. 227 MIOp_FirstOperand = 2, 228 229 // Interpretation of the MIOp_ExtraInfo bit field. 230 Extra_HasSideEffects = 1, 231 Extra_IsAlignStack = 2, 232 Extra_AsmDialect = 4, 233 Extra_MayLoad = 8, 234 Extra_MayStore = 16, 235 Extra_IsConvergent = 32, 236 237 // Inline asm operands map to multiple SDNode / MachineInstr operands. 238 // The first operand is an immediate describing the asm operand, the low 239 // bits is the kind: 240 Kind_RegUse = 1, // Input register, "r". 241 Kind_RegDef = 2, // Output register, "=r". 242 Kind_RegDefEarlyClobber = 3, // Early-clobber output register, "=&r". 243 Kind_Clobber = 4, // Clobbered register, "~r". 244 Kind_Imm = 5, // Immediate. 245 Kind_Mem = 6, // Memory operand, "m", or an address, "p". 246 Kind_Func = 7, // Address operand of function call 247 248 // Memory constraint codes. 249 // These could be tablegenerated but there's little need to do that since 250 // there's plenty of space in the encoding to support the union of all 251 // constraint codes for all targets. 252 // Addresses are included here as they need to be treated the same by the 253 // backend, the only difference is that they are not used to actaully 254 // access memory by the instruction. 255 Constraint_Unknown = 0, 256 Constraint_es, 257 Constraint_i, 258 Constraint_k, 259 Constraint_m, 260 Constraint_o, 261 Constraint_v, 262 Constraint_A, 263 Constraint_Q, 264 Constraint_R, 265 Constraint_S, 266 Constraint_T, 267 Constraint_Um, 268 Constraint_Un, 269 Constraint_Uq, 270 Constraint_Us, 271 Constraint_Ut, 272 Constraint_Uv, 273 Constraint_Uy, 274 Constraint_X, 275 Constraint_Z, 276 Constraint_ZB, 277 Constraint_ZC, 278 Constraint_Zy, 279 280 // Address constraints 281 Constraint_p, 282 Constraint_ZQ, 283 Constraint_ZR, 284 Constraint_ZS, 285 Constraint_ZT, 286 287 Constraints_Max = Constraint_ZT, 288 Constraints_ShiftAmount = 16, 289 290 Flag_MatchingOperand = 0x80000000 291 }; 292 getFlagWord(unsigned Kind,unsigned NumOps)293 static unsigned getFlagWord(unsigned Kind, unsigned NumOps) { 294 assert(((NumOps << 3) & ~0xffff) == 0 && "Too many inline asm operands!"); 295 assert(Kind >= Kind_RegUse && Kind <= Kind_Func && "Invalid Kind"); 296 return Kind | (NumOps << 3); 297 } 298 isRegDefKind(unsigned Flag)299 static bool isRegDefKind(unsigned Flag){ return getKind(Flag) == Kind_RegDef;} isImmKind(unsigned Flag)300 static bool isImmKind(unsigned Flag) { return getKind(Flag) == Kind_Imm; } isMemKind(unsigned Flag)301 static bool isMemKind(unsigned Flag) { return getKind(Flag) == Kind_Mem; } isFuncKind(unsigned Flag)302 static bool isFuncKind(unsigned Flag) { return getKind(Flag) == Kind_Func; } isRegDefEarlyClobberKind(unsigned Flag)303 static bool isRegDefEarlyClobberKind(unsigned Flag) { 304 return getKind(Flag) == Kind_RegDefEarlyClobber; 305 } isClobberKind(unsigned Flag)306 static bool isClobberKind(unsigned Flag) { 307 return getKind(Flag) == Kind_Clobber; 308 } 309 310 /// getFlagWordForMatchingOp - Augment an existing flag word returned by 311 /// getFlagWord with information indicating that this input operand is tied 312 /// to a previous output operand. getFlagWordForMatchingOp(unsigned InputFlag,unsigned MatchedOperandNo)313 static unsigned getFlagWordForMatchingOp(unsigned InputFlag, 314 unsigned MatchedOperandNo) { 315 assert(MatchedOperandNo <= 0x7fff && "Too big matched operand"); 316 assert((InputFlag & ~0xffff) == 0 && "High bits already contain data"); 317 return InputFlag | Flag_MatchingOperand | (MatchedOperandNo << 16); 318 } 319 320 /// getFlagWordForRegClass - Augment an existing flag word returned by 321 /// getFlagWord with the required register class for the following register 322 /// operands. 323 /// A tied use operand cannot have a register class, use the register class 324 /// from the def operand instead. getFlagWordForRegClass(unsigned InputFlag,unsigned RC)325 static unsigned getFlagWordForRegClass(unsigned InputFlag, unsigned RC) { 326 // Store RC + 1, reserve the value 0 to mean 'no register class'. 327 ++RC; 328 assert(!isImmKind(InputFlag) && "Immediates cannot have a register class"); 329 assert(!isMemKind(InputFlag) && "Memory operand cannot have a register class"); 330 assert(RC <= 0x7fff && "Too large register class ID"); 331 assert((InputFlag & ~0xffff) == 0 && "High bits already contain data"); 332 return InputFlag | (RC << 16); 333 } 334 335 /// Augment an existing flag word returned by getFlagWord with the constraint 336 /// code for a memory constraint. getFlagWordForMem(unsigned InputFlag,unsigned Constraint)337 static unsigned getFlagWordForMem(unsigned InputFlag, unsigned Constraint) { 338 assert((isMemKind(InputFlag) || isFuncKind(InputFlag)) && 339 "InputFlag is not a memory (include function) constraint!"); 340 assert(Constraint <= 0x7fff && "Too large a memory constraint ID"); 341 assert(Constraint <= Constraints_Max && "Unknown constraint ID"); 342 assert((InputFlag & ~0xffff) == 0 && "High bits already contain data"); 343 return InputFlag | (Constraint << Constraints_ShiftAmount); 344 } 345 convertMemFlagWordToMatchingFlagWord(unsigned InputFlag)346 static unsigned convertMemFlagWordToMatchingFlagWord(unsigned InputFlag) { 347 assert(isMemKind(InputFlag)); 348 return InputFlag & ~(0x7fff << Constraints_ShiftAmount); 349 } 350 getKind(unsigned Flags)351 static unsigned getKind(unsigned Flags) { 352 return Flags & 7; 353 } 354 getMemoryConstraintID(unsigned Flag)355 static unsigned getMemoryConstraintID(unsigned Flag) { 356 assert((isMemKind(Flag) || isFuncKind(Flag)) && 357 "Not expected mem or function flang!"); 358 return (Flag >> Constraints_ShiftAmount) & 0x7fff; 359 } 360 361 /// getNumOperandRegisters - Extract the number of registers field from the 362 /// inline asm operand flag. getNumOperandRegisters(unsigned Flag)363 static unsigned getNumOperandRegisters(unsigned Flag) { 364 return (Flag & 0xffff) >> 3; 365 } 366 367 /// isUseOperandTiedToDef - Return true if the flag of the inline asm 368 /// operand indicates it is an use operand that's matched to a def operand. isUseOperandTiedToDef(unsigned Flag,unsigned & Idx)369 static bool isUseOperandTiedToDef(unsigned Flag, unsigned &Idx) { 370 if ((Flag & Flag_MatchingOperand) == 0) 371 return false; 372 Idx = (Flag & ~Flag_MatchingOperand) >> 16; 373 return true; 374 } 375 376 /// hasRegClassConstraint - Returns true if the flag contains a register 377 /// class constraint. Sets RC to the register class ID. hasRegClassConstraint(unsigned Flag,unsigned & RC)378 static bool hasRegClassConstraint(unsigned Flag, unsigned &RC) { 379 if (Flag & Flag_MatchingOperand) 380 return false; 381 unsigned High = Flag >> 16; 382 // getFlagWordForRegClass() uses 0 to mean no register class, and otherwise 383 // stores RC + 1. 384 if (!High) 385 return false; 386 RC = High - 1; 387 return true; 388 } 389 getExtraInfoNames(unsigned ExtraInfo)390 static std::vector<StringRef> getExtraInfoNames(unsigned ExtraInfo) { 391 std::vector<StringRef> Result; 392 if (ExtraInfo & InlineAsm::Extra_HasSideEffects) 393 Result.push_back("sideeffect"); 394 if (ExtraInfo & InlineAsm::Extra_MayLoad) 395 Result.push_back("mayload"); 396 if (ExtraInfo & InlineAsm::Extra_MayStore) 397 Result.push_back("maystore"); 398 if (ExtraInfo & InlineAsm::Extra_IsConvergent) 399 Result.push_back("isconvergent"); 400 if (ExtraInfo & InlineAsm::Extra_IsAlignStack) 401 Result.push_back("alignstack"); 402 403 AsmDialect Dialect = 404 InlineAsm::AsmDialect((ExtraInfo & InlineAsm::Extra_AsmDialect)); 405 406 if (Dialect == InlineAsm::AD_ATT) 407 Result.push_back("attdialect"); 408 if (Dialect == InlineAsm::AD_Intel) 409 Result.push_back("inteldialect"); 410 411 return Result; 412 } 413 getKindName(unsigned Kind)414 static StringRef getKindName(unsigned Kind) { 415 switch (Kind) { 416 case InlineAsm::Kind_RegUse: 417 return "reguse"; 418 case InlineAsm::Kind_RegDef: 419 return "regdef"; 420 case InlineAsm::Kind_RegDefEarlyClobber: 421 return "regdef-ec"; 422 case InlineAsm::Kind_Clobber: 423 return "clobber"; 424 case InlineAsm::Kind_Imm: 425 return "imm"; 426 case InlineAsm::Kind_Mem: 427 case InlineAsm::Kind_Func: 428 return "mem"; 429 default: 430 llvm_unreachable("Unknown operand kind"); 431 } 432 } 433 getMemConstraintName(unsigned Constraint)434 static StringRef getMemConstraintName(unsigned Constraint) { 435 switch (Constraint) { 436 case InlineAsm::Constraint_es: 437 return "es"; 438 case InlineAsm::Constraint_i: 439 return "i"; 440 case InlineAsm::Constraint_k: 441 return "k"; 442 case InlineAsm::Constraint_m: 443 return "m"; 444 case InlineAsm::Constraint_o: 445 return "o"; 446 case InlineAsm::Constraint_v: 447 return "v"; 448 case InlineAsm::Constraint_Q: 449 return "Q"; 450 case InlineAsm::Constraint_R: 451 return "R"; 452 case InlineAsm::Constraint_S: 453 return "S"; 454 case InlineAsm::Constraint_T: 455 return "T"; 456 case InlineAsm::Constraint_Um: 457 return "Um"; 458 case InlineAsm::Constraint_Un: 459 return "Un"; 460 case InlineAsm::Constraint_Uq: 461 return "Uq"; 462 case InlineAsm::Constraint_Us: 463 return "Us"; 464 case InlineAsm::Constraint_Ut: 465 return "Ut"; 466 case InlineAsm::Constraint_Uv: 467 return "Uv"; 468 case InlineAsm::Constraint_Uy: 469 return "Uy"; 470 case InlineAsm::Constraint_X: 471 return "X"; 472 case InlineAsm::Constraint_Z: 473 return "Z"; 474 case InlineAsm::Constraint_ZB: 475 return "ZB"; 476 case InlineAsm::Constraint_ZC: 477 return "ZC"; 478 case InlineAsm::Constraint_Zy: 479 return "Zy"; 480 case InlineAsm::Constraint_p: 481 return "p"; 482 case InlineAsm::Constraint_ZQ: 483 return "ZQ"; 484 case InlineAsm::Constraint_ZR: 485 return "ZR"; 486 case InlineAsm::Constraint_ZS: 487 return "ZS"; 488 case InlineAsm::Constraint_ZT: 489 return "ZT"; 490 default: 491 llvm_unreachable("Unknown memory constraint"); 492 } 493 } 494 }; 495 496 } // end namespace llvm 497 498 #endif // LLVM_IR_INLINEASM_H 499