1 //===- InlineAsm.cpp - Implement the InlineAsm class ----------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file implements the InlineAsm class. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "ConstantsContext.h" 15 #include "LLVMContextImpl.h" 16 #include "llvm/ADT/StringRef.h" 17 #include "llvm/IR/DerivedTypes.h" 18 #include "llvm/IR/InlineAsm.h" 19 #include "llvm/IR/LLVMContext.h" 20 #include "llvm/IR/Value.h" 21 #include "llvm/Support/Casting.h" 22 #include "llvm/Support/Compiler.h" 23 #include <algorithm> 24 #include <cassert> 25 #include <cctype> 26 #include <cstddef> 27 #include <cstdlib> 28 29 using namespace llvm; 30 31 InlineAsm::InlineAsm(FunctionType *FTy, const std::string &asmString, 32 const std::string &constraints, bool hasSideEffects, 33 bool isAlignStack, AsmDialect asmDialect) 34 : Value(PointerType::getUnqual(FTy), Value::InlineAsmVal), 35 AsmString(asmString), Constraints(constraints), FTy(FTy), 36 HasSideEffects(hasSideEffects), IsAlignStack(isAlignStack), 37 Dialect(asmDialect) { 38 // Do various checks on the constraint string and type. 39 assert(Verify(getFunctionType(), constraints) && 40 "Function type not legal for constraints!"); 41 } 42 43 // Implement the first virtual method in this class in this file so the 44 // InlineAsm vtable is emitted here. 45 InlineAsm::~InlineAsm() = default; 46 47 InlineAsm *InlineAsm::get(FunctionType *FTy, StringRef AsmString, 48 StringRef Constraints, bool hasSideEffects, 49 bool isAlignStack, AsmDialect asmDialect) { 50 InlineAsmKeyType Key(AsmString, Constraints, FTy, hasSideEffects, 51 isAlignStack, asmDialect); 52 LLVMContextImpl *pImpl = FTy->getContext().pImpl; 53 return pImpl->InlineAsms.getOrCreate(PointerType::getUnqual(FTy), Key); 54 } 55 56 void InlineAsm::destroyConstant() { 57 getType()->getContext().pImpl->InlineAsms.remove(this); 58 delete this; 59 } 60 61 FunctionType *InlineAsm::getFunctionType() const { 62 return FTy; 63 } 64 65 /// Parse - Analyze the specified string (e.g. "==&{eax}") and fill in the 66 /// fields in this structure. If the constraint string is not understood, 67 /// return true, otherwise return false. 68 bool InlineAsm::ConstraintInfo::Parse(StringRef Str, 69 InlineAsm::ConstraintInfoVector &ConstraintsSoFar) { 70 StringRef::iterator I = Str.begin(), E = Str.end(); 71 unsigned multipleAlternativeCount = Str.count('|') + 1; 72 unsigned multipleAlternativeIndex = 0; 73 ConstraintCodeVector *pCodes = &Codes; 74 75 // Initialize 76 isMultipleAlternative = multipleAlternativeCount > 1; 77 if (isMultipleAlternative) { 78 multipleAlternatives.resize(multipleAlternativeCount); 79 pCodes = &multipleAlternatives[0].Codes; 80 } 81 Type = isInput; 82 isEarlyClobber = false; 83 MatchingInput = -1; 84 isCommutative = false; 85 isIndirect = false; 86 currentAlternativeIndex = 0; 87 88 // Parse prefixes. 89 if (*I == '~') { 90 Type = isClobber; 91 ++I; 92 93 // '{' must immediately follow '~'. 94 if (I != E && *I != '{') 95 return true; 96 } else if (*I == '=') { 97 ++I; 98 Type = isOutput; 99 } 100 101 if (*I == '*') { 102 isIndirect = true; 103 ++I; 104 } 105 106 if (I == E) return true; // Just a prefix, like "==" or "~". 107 108 // Parse the modifiers. 109 bool DoneWithModifiers = false; 110 while (!DoneWithModifiers) { 111 switch (*I) { 112 default: 113 DoneWithModifiers = true; 114 break; 115 case '&': // Early clobber. 116 if (Type != isOutput || // Cannot early clobber anything but output. 117 isEarlyClobber) // Reject &&&&&& 118 return true; 119 isEarlyClobber = true; 120 break; 121 case '%': // Commutative. 122 if (Type == isClobber || // Cannot commute clobbers. 123 isCommutative) // Reject %%%%% 124 return true; 125 isCommutative = true; 126 break; 127 case '#': // Comment. 128 case '*': // Register preferencing. 129 return true; // Not supported. 130 } 131 132 if (!DoneWithModifiers) { 133 ++I; 134 if (I == E) return true; // Just prefixes and modifiers! 135 } 136 } 137 138 // Parse the various constraints. 139 while (I != E) { 140 if (*I == '{') { // Physical register reference. 141 // Find the end of the register name. 142 StringRef::iterator ConstraintEnd = std::find(I+1, E, '}'); 143 if (ConstraintEnd == E) return true; // "{foo" 144 pCodes->push_back(StringRef(I, ConstraintEnd+1 - I)); 145 I = ConstraintEnd+1; 146 } else if (isdigit(static_cast<unsigned char>(*I))) { // Matching Constraint 147 // Maximal munch numbers. 148 StringRef::iterator NumStart = I; 149 while (I != E && isdigit(static_cast<unsigned char>(*I))) 150 ++I; 151 pCodes->push_back(StringRef(NumStart, I - NumStart)); 152 unsigned N = atoi(pCodes->back().c_str()); 153 // Check that this is a valid matching constraint! 154 if (N >= ConstraintsSoFar.size() || ConstraintsSoFar[N].Type != isOutput|| 155 Type != isInput) 156 return true; // Invalid constraint number. 157 158 // If Operand N already has a matching input, reject this. An output 159 // can't be constrained to the same value as multiple inputs. 160 if (isMultipleAlternative) { 161 if (multipleAlternativeIndex >= 162 ConstraintsSoFar[N].multipleAlternatives.size()) 163 return true; 164 InlineAsm::SubConstraintInfo &scInfo = 165 ConstraintsSoFar[N].multipleAlternatives[multipleAlternativeIndex]; 166 if (scInfo.MatchingInput != -1) 167 return true; 168 // Note that operand #n has a matching input. 169 scInfo.MatchingInput = ConstraintsSoFar.size(); 170 } else { 171 if (ConstraintsSoFar[N].hasMatchingInput() && 172 (size_t)ConstraintsSoFar[N].MatchingInput != 173 ConstraintsSoFar.size()) 174 return true; 175 // Note that operand #n has a matching input. 176 ConstraintsSoFar[N].MatchingInput = ConstraintsSoFar.size(); 177 } 178 } else if (*I == '|') { 179 multipleAlternativeIndex++; 180 pCodes = &multipleAlternatives[multipleAlternativeIndex].Codes; 181 ++I; 182 } else if (*I == '^') { 183 // Multi-letter constraint 184 // FIXME: For now assuming these are 2-character constraints. 185 pCodes->push_back(StringRef(I+1, 2)); 186 I += 3; 187 } else { 188 // Single letter constraint. 189 pCodes->push_back(StringRef(I, 1)); 190 ++I; 191 } 192 } 193 194 return false; 195 } 196 197 /// selectAlternative - Point this constraint to the alternative constraint 198 /// indicated by the index. 199 void InlineAsm::ConstraintInfo::selectAlternative(unsigned index) { 200 if (index < multipleAlternatives.size()) { 201 currentAlternativeIndex = index; 202 InlineAsm::SubConstraintInfo &scInfo = 203 multipleAlternatives[currentAlternativeIndex]; 204 MatchingInput = scInfo.MatchingInput; 205 Codes = scInfo.Codes; 206 } 207 } 208 209 InlineAsm::ConstraintInfoVector 210 InlineAsm::ParseConstraints(StringRef Constraints) { 211 ConstraintInfoVector Result; 212 213 // Scan the constraints string. 214 for (StringRef::iterator I = Constraints.begin(), 215 E = Constraints.end(); I != E; ) { 216 ConstraintInfo Info; 217 218 // Find the end of this constraint. 219 StringRef::iterator ConstraintEnd = std::find(I, E, ','); 220 221 if (ConstraintEnd == I || // Empty constraint like ",," 222 Info.Parse(StringRef(I, ConstraintEnd-I), Result)) { 223 Result.clear(); // Erroneous constraint? 224 break; 225 } 226 227 Result.push_back(Info); 228 229 // ConstraintEnd may be either the next comma or the end of the string. In 230 // the former case, we skip the comma. 231 I = ConstraintEnd; 232 if (I != E) { 233 ++I; 234 if (I == E) { 235 Result.clear(); 236 break; 237 } // don't allow "xyz," 238 } 239 } 240 241 return Result; 242 } 243 244 /// Verify - Verify that the specified constraint string is reasonable for the 245 /// specified function type, and otherwise validate the constraint string. 246 bool InlineAsm::Verify(FunctionType *Ty, StringRef ConstStr) { 247 if (Ty->isVarArg()) return false; 248 249 ConstraintInfoVector Constraints = ParseConstraints(ConstStr); 250 251 // Error parsing constraints. 252 if (Constraints.empty() && !ConstStr.empty()) return false; 253 254 unsigned NumOutputs = 0, NumInputs = 0, NumClobbers = 0; 255 unsigned NumIndirect = 0; 256 257 for (unsigned i = 0, e = Constraints.size(); i != e; ++i) { 258 switch (Constraints[i].Type) { 259 case InlineAsm::isOutput: 260 if ((NumInputs-NumIndirect) != 0 || NumClobbers != 0) 261 return false; // outputs before inputs and clobbers. 262 if (!Constraints[i].isIndirect) { 263 ++NumOutputs; 264 break; 265 } 266 ++NumIndirect; 267 LLVM_FALLTHROUGH; // We fall through for Indirect Outputs. 268 case InlineAsm::isInput: 269 if (NumClobbers) return false; // inputs before clobbers. 270 ++NumInputs; 271 break; 272 case InlineAsm::isClobber: 273 ++NumClobbers; 274 break; 275 } 276 } 277 278 switch (NumOutputs) { 279 case 0: 280 if (!Ty->getReturnType()->isVoidTy()) return false; 281 break; 282 case 1: 283 if (Ty->getReturnType()->isStructTy()) return false; 284 break; 285 default: 286 StructType *STy = dyn_cast<StructType>(Ty->getReturnType()); 287 if (!STy || STy->getNumElements() != NumOutputs) 288 return false; 289 break; 290 } 291 292 if (Ty->getNumParams() != NumInputs) return false; 293 return true; 294 } 295