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 ? 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 } else if (*I == '=') { 95 ++I; 96 Type = isOutput; 97 } 98 99 if (*I == '*') { 100 isIndirect = true; 101 ++I; 102 } 103 104 if (I == E) return true; // Just a prefix, like "==" or "~". 105 106 // Parse the modifiers. 107 bool DoneWithModifiers = false; 108 while (!DoneWithModifiers) { 109 switch (*I) { 110 default: 111 DoneWithModifiers = true; 112 break; 113 case '&': // Early clobber. 114 if (Type != isOutput || // Cannot early clobber anything but output. 115 isEarlyClobber) // Reject &&&&&& 116 return true; 117 isEarlyClobber = true; 118 break; 119 case '%': // Commutative. 120 if (Type == isClobber || // Cannot commute clobbers. 121 isCommutative) // Reject %%%%% 122 return true; 123 isCommutative = true; 124 break; 125 case '#': // Comment. 126 case '*': // Register preferencing. 127 return true; // Not supported. 128 } 129 130 if (!DoneWithModifiers) { 131 ++I; 132 if (I == E) return true; // Just prefixes and modifiers! 133 } 134 } 135 136 // Parse the various constraints. 137 while (I != E) { 138 if (*I == '{') { // Physical register reference. 139 // Find the end of the register name. 140 StringRef::iterator ConstraintEnd = std::find(I+1, E, '}'); 141 if (ConstraintEnd == E) return true; // "{foo" 142 pCodes->push_back(std::string(I, ConstraintEnd+1)); 143 I = ConstraintEnd+1; 144 } else if (isdigit(static_cast<unsigned char>(*I))) { // Matching Constraint 145 // Maximal munch numbers. 146 StringRef::iterator NumStart = I; 147 while (I != E && isdigit(static_cast<unsigned char>(*I))) 148 ++I; 149 pCodes->push_back(std::string(NumStart, I)); 150 unsigned N = atoi(pCodes->back().c_str()); 151 // Check that this is a valid matching constraint! 152 if (N >= ConstraintsSoFar.size() || ConstraintsSoFar[N].Type != isOutput|| 153 Type != isInput) 154 return true; // Invalid constraint number. 155 156 // If Operand N already has a matching input, reject this. An output 157 // can't be constrained to the same value as multiple inputs. 158 if (isMultipleAlternative) { 159 InlineAsm::SubConstraintInfo &scInfo = 160 ConstraintsSoFar[N].multipleAlternatives[multipleAlternativeIndex]; 161 if (scInfo.MatchingInput != -1) 162 return true; 163 // Note that operand #n has a matching input. 164 scInfo.MatchingInput = ConstraintsSoFar.size(); 165 } else { 166 if (ConstraintsSoFar[N].hasMatchingInput()) 167 return true; 168 // Note that operand #n has a matching input. 169 ConstraintsSoFar[N].MatchingInput = ConstraintsSoFar.size(); 170 } 171 } else if (*I == '|') { 172 multipleAlternativeIndex++; 173 pCodes = &multipleAlternatives[multipleAlternativeIndex].Codes; 174 ++I; 175 } else if (*I == '^') { 176 // Multi-letter constraint 177 // FIXME: For now assuming these are 2-character constraints. 178 pCodes->push_back(std::string(I+1, I+3)); 179 I += 3; 180 } else { 181 // Single letter constraint. 182 pCodes->push_back(std::string(I, I+1)); 183 ++I; 184 } 185 } 186 187 return false; 188} 189 190/// selectAlternative - Point this constraint to the alternative constraint 191/// indicated by the index. 192void InlineAsm::ConstraintInfo::selectAlternative(unsigned index) { 193 if (index < multipleAlternatives.size()) { 194 currentAlternativeIndex = index; 195 InlineAsm::SubConstraintInfo &scInfo = 196 multipleAlternatives[currentAlternativeIndex]; 197 MatchingInput = scInfo.MatchingInput; 198 Codes = scInfo.Codes; 199 } 200} 201 202InlineAsm::ConstraintInfoVector 203InlineAsm::ParseConstraints(StringRef Constraints) { 204 ConstraintInfoVector Result; 205 206 // Scan the constraints string. 207 for (StringRef::iterator I = Constraints.begin(), 208 E = Constraints.end(); I != E; ) { 209 ConstraintInfo Info; 210 211 // Find the end of this constraint. 212 StringRef::iterator ConstraintEnd = std::find(I, E, ','); 213 214 if (ConstraintEnd == I || // Empty constraint like ",," 215 Info.Parse(StringRef(I, ConstraintEnd-I), Result)) { 216 Result.clear(); // Erroneous constraint? 217 break; 218 } 219 220 Result.push_back(Info); 221 222 // ConstraintEnd may be either the next comma or the end of the string. In 223 // the former case, we skip the comma. 224 I = ConstraintEnd; 225 if (I != E) { 226 ++I; 227 if (I == E) { Result.clear(); break; } // don't allow "xyz," 228 } 229 } 230 231 return Result; 232} 233 234/// Verify - Verify that the specified constraint string is reasonable for the 235/// specified function type, and otherwise validate the constraint string. 236bool InlineAsm::Verify(FunctionType *Ty, StringRef ConstStr) { 237 if (Ty->isVarArg()) return false; 238 239 ConstraintInfoVector Constraints = ParseConstraints(ConstStr); 240 241 // Error parsing constraints. 242 if (Constraints.empty() && !ConstStr.empty()) return false; 243 244 unsigned NumOutputs = 0, NumInputs = 0, NumClobbers = 0; 245 unsigned NumIndirect = 0; 246 247 for (unsigned i = 0, e = Constraints.size(); i != e; ++i) { 248 switch (Constraints[i].Type) { 249 case InlineAsm::isOutput: 250 if ((NumInputs-NumIndirect) != 0 || NumClobbers != 0) 251 return false; // outputs before inputs and clobbers. 252 if (!Constraints[i].isIndirect) { 253 ++NumOutputs; 254 break; 255 } 256 ++NumIndirect; 257 // FALLTHROUGH for Indirect Outputs. 258 case InlineAsm::isInput: 259 if (NumClobbers) return false; // inputs before clobbers. 260 ++NumInputs; 261 break; 262 case InlineAsm::isClobber: 263 ++NumClobbers; 264 break; 265 } 266 } 267 268 switch (NumOutputs) { 269 case 0: 270 if (!Ty->getReturnType()->isVoidTy()) return false; 271 break; 272 case 1: 273 if (Ty->getReturnType()->isStructTy()) return false; 274 break; 275 default: 276 StructType *STy = dyn_cast<StructType>(Ty->getReturnType()); 277 if (!STy || STy->getNumElements() != NumOutputs) 278 return false; 279 break; 280 } 281 282 if (Ty->getNumParams() != NumInputs) return false; 283 return true; 284} 285 286