InlineAsm.cpp revision 2c3e0051c31c3f5b2328b447eadf1cf9c4427442
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> 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, 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 37InlineAsm::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 50void InlineAsm::destroyConstant() { 51 getType()->getContext().pImpl->InlineAsms.remove(this); 52 delete this; 53} 54 55FunctionType *InlineAsm::getFunctionType() const { 56 return cast<FunctionType>(getType()->getElementType()); 57} 58 59///Default constructor. 60InlineAsm::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. 70bool 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; 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 (size_t)ConstraintsSoFar[N].MatchingInput != 172 ConstraintsSoFar.size()) 173 return true; 174 // Note that operand #n has a matching input. 175 ConstraintsSoFar[N].MatchingInput = ConstraintsSoFar.size(); 176 } 177 } else if (*I == '|') { 178 multipleAlternativeIndex++; 179 pCodes = &multipleAlternatives[multipleAlternativeIndex].Codes; 180 ++I; 181 } else if (*I == '^') { 182 // Multi-letter constraint 183 // FIXME: For now assuming these are 2-character constraints. 184 pCodes->push_back(std::string(I+1, I+3)); 185 I += 3; 186 } else { 187 // Single letter constraint. 188 pCodes->push_back(std::string(I, I+1)); 189 ++I; 190 } 191 } 192 193 return false; 194} 195 196/// selectAlternative - Point this constraint to the alternative constraint 197/// indicated by the index. 198void InlineAsm::ConstraintInfo::selectAlternative(unsigned index) { 199 if (index < multipleAlternatives.size()) { 200 currentAlternativeIndex = index; 201 InlineAsm::SubConstraintInfo &scInfo = 202 multipleAlternatives[currentAlternativeIndex]; 203 MatchingInput = scInfo.MatchingInput; 204 Codes = scInfo.Codes; 205 } 206} 207 208InlineAsm::ConstraintInfoVector 209InlineAsm::ParseConstraints(StringRef Constraints) { 210 ConstraintInfoVector Result; 211 212 // Scan the constraints string. 213 for (StringRef::iterator I = Constraints.begin(), 214 E = Constraints.end(); I != E; ) { 215 ConstraintInfo Info; 216 217 // Find the end of this constraint. 218 StringRef::iterator ConstraintEnd = std::find(I, E, ','); 219 220 if (ConstraintEnd == I || // Empty constraint like ",," 221 Info.Parse(StringRef(I, ConstraintEnd-I), Result)) { 222 Result.clear(); // Erroneous constraint? 223 break; 224 } 225 226 Result.push_back(Info); 227 228 // ConstraintEnd may be either the next comma or the end of the string. In 229 // the former case, we skip the comma. 230 I = ConstraintEnd; 231 if (I != E) { 232 ++I; 233 if (I == E) { 234 Result.clear(); 235 break; 236 } // 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 || STy->getNumElements() != NumOutputs) 287 return false; 288 break; 289 } 290 291 if (Ty->getNumParams() != NumInputs) return false; 292 return true; 293} 294 295