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 /// Copy constructor. 68 InlineAsm::ConstraintInfo::ConstraintInfo(const ConstraintInfo &other) : 69 Type(other.Type), isEarlyClobber(other.isEarlyClobber), 70 MatchingInput(other.MatchingInput), isCommutative(other.isCommutative), 71 isIndirect(other.isIndirect), Codes(other.Codes), 72 isMultipleAlternative(other.isMultipleAlternative), 73 multipleAlternatives(other.multipleAlternatives), 74 currentAlternativeIndex(other.currentAlternativeIndex) { 75 } 76 77 /// Parse - Analyze the specified string (e.g. "==&{eax}") and fill in the 78 /// fields in this structure. If the constraint string is not understood, 79 /// return true, otherwise return false. 80 bool InlineAsm::ConstraintInfo::Parse(StringRef Str, 81 InlineAsm::ConstraintInfoVector &ConstraintsSoFar) { 82 StringRef::iterator I = Str.begin(), E = Str.end(); 83 unsigned multipleAlternativeCount = Str.count('|') + 1; 84 unsigned multipleAlternativeIndex = 0; 85 ConstraintCodeVector *pCodes = &Codes; 86 87 // Initialize 88 isMultipleAlternative = (multipleAlternativeCount > 1 ? true : false); 89 if (isMultipleAlternative) { 90 multipleAlternatives.resize(multipleAlternativeCount); 91 pCodes = &multipleAlternatives[0].Codes; 92 } 93 Type = isInput; 94 isEarlyClobber = false; 95 MatchingInput = -1; 96 isCommutative = false; 97 isIndirect = false; 98 currentAlternativeIndex = 0; 99 100 // Parse prefixes. 101 if (*I == '~') { 102 Type = isClobber; 103 ++I; 104 } else if (*I == '=') { 105 ++I; 106 Type = isOutput; 107 } 108 109 if (*I == '*') { 110 isIndirect = true; 111 ++I; 112 } 113 114 if (I == E) return true; // Just a prefix, like "==" or "~". 115 116 // Parse the modifiers. 117 bool DoneWithModifiers = false; 118 while (!DoneWithModifiers) { 119 switch (*I) { 120 default: 121 DoneWithModifiers = true; 122 break; 123 case '&': // Early clobber. 124 if (Type != isOutput || // Cannot early clobber anything but output. 125 isEarlyClobber) // Reject &&&&&& 126 return true; 127 isEarlyClobber = true; 128 break; 129 case '%': // Commutative. 130 if (Type == isClobber || // Cannot commute clobbers. 131 isCommutative) // Reject %%%%% 132 return true; 133 isCommutative = true; 134 break; 135 case '#': // Comment. 136 case '*': // Register preferencing. 137 return true; // Not supported. 138 } 139 140 if (!DoneWithModifiers) { 141 ++I; 142 if (I == E) return true; // Just prefixes and modifiers! 143 } 144 } 145 146 // Parse the various constraints. 147 while (I != E) { 148 if (*I == '{') { // Physical register reference. 149 // Find the end of the register name. 150 StringRef::iterator ConstraintEnd = std::find(I+1, E, '}'); 151 if (ConstraintEnd == E) return true; // "{foo" 152 pCodes->push_back(std::string(I, ConstraintEnd+1)); 153 I = ConstraintEnd+1; 154 } else if (isdigit(static_cast<unsigned char>(*I))) { // Matching Constraint 155 // Maximal munch numbers. 156 StringRef::iterator NumStart = I; 157 while (I != E && isdigit(static_cast<unsigned char>(*I))) 158 ++I; 159 pCodes->push_back(std::string(NumStart, I)); 160 unsigned N = atoi(pCodes->back().c_str()); 161 // Check that this is a valid matching constraint! 162 if (N >= ConstraintsSoFar.size() || ConstraintsSoFar[N].Type != isOutput|| 163 Type != isInput) 164 return true; // Invalid constraint number. 165 166 // If Operand N already has a matching input, reject this. An output 167 // can't be constrained to the same value as multiple inputs. 168 if (isMultipleAlternative) { 169 InlineAsm::SubConstraintInfo &scInfo = 170 ConstraintsSoFar[N].multipleAlternatives[multipleAlternativeIndex]; 171 if (scInfo.MatchingInput != -1) 172 return true; 173 // Note that operand #n has a matching input. 174 scInfo.MatchingInput = ConstraintsSoFar.size(); 175 } else { 176 if (ConstraintsSoFar[N].hasMatchingInput()) 177 return true; 178 // Note that operand #n has a matching input. 179 ConstraintsSoFar[N].MatchingInput = ConstraintsSoFar.size(); 180 } 181 } else if (*I == '|') { 182 multipleAlternativeIndex++; 183 pCodes = &multipleAlternatives[multipleAlternativeIndex].Codes; 184 ++I; 185 } else if (*I == '^') { 186 // Multi-letter constraint 187 // FIXME: For now assuming these are 2-character constraints. 188 pCodes->push_back(std::string(I+1, I+3)); 189 I += 3; 190 } else { 191 // Single letter constraint. 192 pCodes->push_back(std::string(I, I+1)); 193 ++I; 194 } 195 } 196 197 return false; 198 } 199 200 /// selectAlternative - Point this constraint to the alternative constraint 201 /// indicated by the index. 202 void InlineAsm::ConstraintInfo::selectAlternative(unsigned index) { 203 if (index < multipleAlternatives.size()) { 204 currentAlternativeIndex = index; 205 InlineAsm::SubConstraintInfo &scInfo = 206 multipleAlternatives[currentAlternativeIndex]; 207 MatchingInput = scInfo.MatchingInput; 208 Codes = scInfo.Codes; 209 } 210 } 211 212 InlineAsm::ConstraintInfoVector 213 InlineAsm::ParseConstraints(StringRef Constraints) { 214 ConstraintInfoVector Result; 215 216 // Scan the constraints string. 217 for (StringRef::iterator I = Constraints.begin(), 218 E = Constraints.end(); I != E; ) { 219 ConstraintInfo Info; 220 221 // Find the end of this constraint. 222 StringRef::iterator ConstraintEnd = std::find(I, E, ','); 223 224 if (ConstraintEnd == I || // Empty constraint like ",," 225 Info.Parse(StringRef(I, ConstraintEnd-I), Result)) { 226 Result.clear(); // Erroneous constraint? 227 break; 228 } 229 230 Result.push_back(Info); 231 232 // ConstraintEnd may be either the next comma or the end of the string. In 233 // the former case, we skip the comma. 234 I = ConstraintEnd; 235 if (I != E) { 236 ++I; 237 if (I == E) { Result.clear(); break; } // 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 // FALLTHROUGH 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 == 0 || STy->getNumElements() != NumOutputs) 288 return false; 289 break; 290 } 291 292 if (Ty->getNumParams() != NumInputs) return false; 293 return true; 294 } 295 296