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