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