LLVM API Documentation

InlineAsm.cpp
Go to the documentation of this file.
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