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 assert(scInfo.MatchingInput >= 0); 167 } else { 168 if (ConstraintsSoFar[N].hasMatchingInput() && 169 (size_t)ConstraintsSoFar[N].MatchingInput != 170 ConstraintsSoFar.size()) 171 return true; 172 // Note that operand #n has a matching input. 173 ConstraintsSoFar[N].MatchingInput = ConstraintsSoFar.size(); 174 assert(ConstraintsSoFar[N].MatchingInput >= 0); 175 } 176 } else if (*I == '|') { 177 multipleAlternativeIndex++; 178 pCodes = &multipleAlternatives[multipleAlternativeIndex].Codes; 179 ++I; 180 } else if (*I == '^') { 181 // Multi-letter constraint 182 // FIXME: For now assuming these are 2-character constraints. 183 pCodes->push_back(StringRef(I+1, 2)); 184 I += 3; 185 } else { 186 // Single letter constraint. 187 pCodes->push_back(StringRef(I, 1)); 188 ++I; 189 } 190 } 191 192 return false; 193 } 194 195 /// selectAlternative - Point this constraint to the alternative constraint 196 /// indicated by the index. 197 void InlineAsm::ConstraintInfo::selectAlternative(unsigned index) { 198 if (index < multipleAlternatives.size()) { 199 currentAlternativeIndex = index; 200 InlineAsm::SubConstraintInfo &scInfo = 201 multipleAlternatives[currentAlternativeIndex]; 202 MatchingInput = scInfo.MatchingInput; 203 Codes = scInfo.Codes; 204 } 205 } 206 207 InlineAsm::ConstraintInfoVector 208 InlineAsm::ParseConstraints(StringRef Constraints) { 209 ConstraintInfoVector Result; 210 211 // Scan the constraints string. 212 for (StringRef::iterator I = Constraints.begin(), 213 E = Constraints.end(); I != E; ) { 214 ConstraintInfo Info; 215 216 // Find the end of this constraint. 217 StringRef::iterator ConstraintEnd = std::find(I, E, ','); 218 219 if (ConstraintEnd == I || // Empty constraint like ",," 220 Info.Parse(StringRef(I, ConstraintEnd-I), Result)) { 221 Result.clear(); // Erroneous constraint? 222 break; 223 } 224 225 Result.push_back(Info); 226 227 // ConstraintEnd may be either the next comma or the end of the string. In 228 // the former case, we skip the comma. 229 I = ConstraintEnd; 230 if (I != E) { 231 ++I; 232 if (I == E) { 233 Result.clear(); 234 break; 235 } // don't allow "xyz," 236 } 237 } 238 239 return Result; 240 } 241 242 /// Verify - Verify that the specified constraint string is reasonable for the 243 /// specified function type, and otherwise validate the constraint string. 244 bool InlineAsm::Verify(FunctionType *Ty, StringRef ConstStr) { 245 if (Ty->isVarArg()) return false; 246 247 ConstraintInfoVector Constraints = ParseConstraints(ConstStr); 248 249 // Error parsing constraints. 250 if (Constraints.empty() && !ConstStr.empty()) return false; 251 252 unsigned NumOutputs = 0, NumInputs = 0, NumClobbers = 0; 253 unsigned NumIndirect = 0; 254 255 for (unsigned i = 0, e = Constraints.size(); i != e; ++i) { 256 switch (Constraints[i].Type) { 257 case InlineAsm::isOutput: 258 if ((NumInputs-NumIndirect) != 0 || NumClobbers != 0) 259 return false; // outputs before inputs and clobbers. 260 if (!Constraints[i].isIndirect) { 261 ++NumOutputs; 262 break; 263 } 264 ++NumIndirect; 265 LLVM_FALLTHROUGH; // We fall through for Indirect Outputs. 266 case InlineAsm::isInput: 267 if (NumClobbers) return false; // inputs before clobbers. 268 ++NumInputs; 269 break; 270 case InlineAsm::isClobber: 271 ++NumClobbers; 272 break; 273 } 274 } 275 276 switch (NumOutputs) { 277 case 0: 278 if (!Ty->getReturnType()->isVoidTy()) return false; 279 break; 280 case 1: 281 if (Ty->getReturnType()->isStructTy()) return false; 282 break; 283 default: 284 StructType *STy = dyn_cast<StructType>(Ty->getReturnType()); 285 if (!STy || STy->getNumElements() != NumOutputs) 286 return false; 287 break; 288 } 289 290 if (Ty->getNumParams() != NumInputs) return false; 291 return true; 292 } 293