LLVM API Documentation
00001 //===-- InlineAsm.cpp - Implement the InlineAsm class ---------------------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file implements the InlineAsm class. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #include "llvm/IR/InlineAsm.h" 00015 #include "ConstantsContext.h" 00016 #include "LLVMContextImpl.h" 00017 #include "llvm/IR/DerivedTypes.h" 00018 #include <algorithm> 00019 #include <cctype> 00020 using namespace llvm; 00021 00022 // Implement the first virtual method in this class in this file so the 00023 // InlineAsm vtable is emitted here. 00024 InlineAsm::~InlineAsm() { 00025 } 00026 00027 00028 InlineAsm *InlineAsm::get(FunctionType *Ty, StringRef AsmString, 00029 StringRef Constraints, bool hasSideEffects, 00030 bool isAlignStack, AsmDialect asmDialect) { 00031 InlineAsmKeyType Key(AsmString, Constraints, hasSideEffects, isAlignStack, 00032 asmDialect); 00033 LLVMContextImpl *pImpl = Ty->getContext().pImpl; 00034 return pImpl->InlineAsms.getOrCreate(PointerType::getUnqual(Ty), Key); 00035 } 00036 00037 InlineAsm::InlineAsm(PointerType *Ty, const std::string &asmString, 00038 const std::string &constraints, bool hasSideEffects, 00039 bool isAlignStack, AsmDialect asmDialect) 00040 : Value(Ty, Value::InlineAsmVal), 00041 AsmString(asmString), Constraints(constraints), 00042 HasSideEffects(hasSideEffects), IsAlignStack(isAlignStack), 00043 Dialect(asmDialect) { 00044 00045 // Do various checks on the constraint string and type. 00046 assert(Verify(getFunctionType(), constraints) && 00047 "Function type not legal for constraints!"); 00048 } 00049 00050 void InlineAsm::destroyConstant() { 00051 getType()->getContext().pImpl->InlineAsms.remove(this); 00052 delete this; 00053 } 00054 00055 FunctionType *InlineAsm::getFunctionType() const { 00056 return cast<FunctionType>(getType()->getElementType()); 00057 } 00058 00059 ///Default constructor. 00060 InlineAsm::ConstraintInfo::ConstraintInfo() : 00061 Type(isInput), isEarlyClobber(false), 00062 MatchingInput(-1), isCommutative(false), 00063 isIndirect(false), isMultipleAlternative(false), 00064 currentAlternativeIndex(0) { 00065 } 00066 00067 /// Parse - Analyze the specified string (e.g. "==&{eax}") and fill in the 00068 /// fields in this structure. If the constraint string is not understood, 00069 /// return true, otherwise return false. 00070 bool InlineAsm::ConstraintInfo::Parse(StringRef Str, 00071 InlineAsm::ConstraintInfoVector &ConstraintsSoFar) { 00072 StringRef::iterator I = Str.begin(), E = Str.end(); 00073 unsigned multipleAlternativeCount = Str.count('|') + 1; 00074 unsigned multipleAlternativeIndex = 0; 00075 ConstraintCodeVector *pCodes = &Codes; 00076 00077 // Initialize 00078 isMultipleAlternative = (multipleAlternativeCount > 1 ? true : false); 00079 if (isMultipleAlternative) { 00080 multipleAlternatives.resize(multipleAlternativeCount); 00081 pCodes = &multipleAlternatives[0].Codes; 00082 } 00083 Type = isInput; 00084 isEarlyClobber = false; 00085 MatchingInput = -1; 00086 isCommutative = false; 00087 isIndirect = false; 00088 currentAlternativeIndex = 0; 00089 00090 // Parse prefixes. 00091 if (*I == '~') { 00092 Type = isClobber; 00093 ++I; 00094 00095 // '{' must immediately follow '~'. 00096 if (I != E && *I != '{') 00097 return true; 00098 } else if (*I == '=') { 00099 ++I; 00100 Type = isOutput; 00101 } 00102 00103 if (*I == '*') { 00104 isIndirect = true; 00105 ++I; 00106 } 00107 00108 if (I == E) return true; // Just a prefix, like "==" or "~". 00109 00110 // Parse the modifiers. 00111 bool DoneWithModifiers = false; 00112 while (!DoneWithModifiers) { 00113 switch (*I) { 00114 default: 00115 DoneWithModifiers = true; 00116 break; 00117 case '&': // Early clobber. 00118 if (Type != isOutput || // Cannot early clobber anything but output. 00119 isEarlyClobber) // Reject &&&&&& 00120 return true; 00121 isEarlyClobber = true; 00122 break; 00123 case '%': // Commutative. 00124 if (Type == isClobber || // Cannot commute clobbers. 00125 isCommutative) // Reject %%%%% 00126 return true; 00127 isCommutative = true; 00128 break; 00129 case '#': // Comment. 00130 case '*': // Register preferencing. 00131 return true; // Not supported. 00132 } 00133 00134 if (!DoneWithModifiers) { 00135 ++I; 00136 if (I == E) return true; // Just prefixes and modifiers! 00137 } 00138 } 00139 00140 // Parse the various constraints. 00141 while (I != E) { 00142 if (*I == '{') { // Physical register reference. 00143 // Find the end of the register name. 00144 StringRef::iterator ConstraintEnd = std::find(I+1, E, '}'); 00145 if (ConstraintEnd == E) return true; // "{foo" 00146 pCodes->push_back(std::string(I, ConstraintEnd+1)); 00147 I = ConstraintEnd+1; 00148 } else if (isdigit(static_cast<unsigned char>(*I))) { // Matching Constraint 00149 // Maximal munch numbers. 00150 StringRef::iterator NumStart = I; 00151 while (I != E && isdigit(static_cast<unsigned char>(*I))) 00152 ++I; 00153 pCodes->push_back(std::string(NumStart, I)); 00154 unsigned N = atoi(pCodes->back().c_str()); 00155 // Check that this is a valid matching constraint! 00156 if (N >= ConstraintsSoFar.size() || ConstraintsSoFar[N].Type != isOutput|| 00157 Type != isInput) 00158 return true; // Invalid constraint number. 00159 00160 // If Operand N already has a matching input, reject this. An output 00161 // can't be constrained to the same value as multiple inputs. 00162 if (isMultipleAlternative) { 00163 InlineAsm::SubConstraintInfo &scInfo = 00164 ConstraintsSoFar[N].multipleAlternatives[multipleAlternativeIndex]; 00165 if (scInfo.MatchingInput != -1) 00166 return true; 00167 // Note that operand #n has a matching input. 00168 scInfo.MatchingInput = ConstraintsSoFar.size(); 00169 } else { 00170 if (ConstraintsSoFar[N].hasMatchingInput()) 00171 return true; 00172 // Note that operand #n has a matching input. 00173 ConstraintsSoFar[N].MatchingInput = ConstraintsSoFar.size(); 00174 } 00175 } else if (*I == '|') { 00176 multipleAlternativeIndex++; 00177 pCodes = &multipleAlternatives[multipleAlternativeIndex].Codes; 00178 ++I; 00179 } else if (*I == '^') { 00180 // Multi-letter constraint 00181 // FIXME: For now assuming these are 2-character constraints. 00182 pCodes->push_back(std::string(I+1, I+3)); 00183 I += 3; 00184 } else { 00185 // Single letter constraint. 00186 pCodes->push_back(std::string(I, I+1)); 00187 ++I; 00188 } 00189 } 00190 00191 return false; 00192 } 00193 00194 /// selectAlternative - Point this constraint to the alternative constraint 00195 /// indicated by the index. 00196 void InlineAsm::ConstraintInfo::selectAlternative(unsigned index) { 00197 if (index < multipleAlternatives.size()) { 00198 currentAlternativeIndex = index; 00199 InlineAsm::SubConstraintInfo &scInfo = 00200 multipleAlternatives[currentAlternativeIndex]; 00201 MatchingInput = scInfo.MatchingInput; 00202 Codes = scInfo.Codes; 00203 } 00204 } 00205 00206 InlineAsm::ConstraintInfoVector 00207 InlineAsm::ParseConstraints(StringRef Constraints) { 00208 ConstraintInfoVector Result; 00209 00210 // Scan the constraints string. 00211 for (StringRef::iterator I = Constraints.begin(), 00212 E = Constraints.end(); I != E; ) { 00213 ConstraintInfo Info; 00214 00215 // Find the end of this constraint. 00216 StringRef::iterator ConstraintEnd = std::find(I, E, ','); 00217 00218 if (ConstraintEnd == I || // Empty constraint like ",," 00219 Info.Parse(StringRef(I, ConstraintEnd-I), Result)) { 00220 Result.clear(); // Erroneous constraint? 00221 break; 00222 } 00223 00224 Result.push_back(Info); 00225 00226 // ConstraintEnd may be either the next comma or the end of the string. In 00227 // the former case, we skip the comma. 00228 I = ConstraintEnd; 00229 if (I != E) { 00230 ++I; 00231 if (I == E) { Result.clear(); break; } // don't allow "xyz," 00232 } 00233 } 00234 00235 return Result; 00236 } 00237 00238 /// Verify - Verify that the specified constraint string is reasonable for the 00239 /// specified function type, and otherwise validate the constraint string. 00240 bool InlineAsm::Verify(FunctionType *Ty, StringRef ConstStr) { 00241 if (Ty->isVarArg()) return false; 00242 00243 ConstraintInfoVector Constraints = ParseConstraints(ConstStr); 00244 00245 // Error parsing constraints. 00246 if (Constraints.empty() && !ConstStr.empty()) return false; 00247 00248 unsigned NumOutputs = 0, NumInputs = 0, NumClobbers = 0; 00249 unsigned NumIndirect = 0; 00250 00251 for (unsigned i = 0, e = Constraints.size(); i != e; ++i) { 00252 switch (Constraints[i].Type) { 00253 case InlineAsm::isOutput: 00254 if ((NumInputs-NumIndirect) != 0 || NumClobbers != 0) 00255 return false; // outputs before inputs and clobbers. 00256 if (!Constraints[i].isIndirect) { 00257 ++NumOutputs; 00258 break; 00259 } 00260 ++NumIndirect; 00261 // FALLTHROUGH for Indirect Outputs. 00262 case InlineAsm::isInput: 00263 if (NumClobbers) return false; // inputs before clobbers. 00264 ++NumInputs; 00265 break; 00266 case InlineAsm::isClobber: 00267 ++NumClobbers; 00268 break; 00269 } 00270 } 00271 00272 switch (NumOutputs) { 00273 case 0: 00274 if (!Ty->getReturnType()->isVoidTy()) return false; 00275 break; 00276 case 1: 00277 if (Ty->getReturnType()->isStructTy()) return false; 00278 break; 00279 default: 00280 StructType *STy = dyn_cast<StructType>(Ty->getReturnType()); 00281 if (!STy || STy->getNumElements() != NumOutputs) 00282 return false; 00283 break; 00284 } 00285 00286 if (Ty->getNumParams() != NumInputs) return false; 00287 return true; 00288 } 00289