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