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/InlineAsm.h"
00015 #include "llvm/DerivedTypes.h"
00016 #include <algorithm>
00017 #include <cctype>
00018 using namespace llvm;
00019 
00020 // Implement the first virtual method in this class in this file so the
00021 // InlineAsm vtable is emitted here.
00022 InlineAsm::~InlineAsm() {
00023 }
00024 
00025 
00026 // NOTE: when memoizing the function type, we have to be careful to handle the
00027 // case when the type gets refined.
00028 
00029 InlineAsm *InlineAsm::get(const FunctionType *Ty, const std::string &AsmString,
00030                           const std::string &Constraints, bool hasSideEffects) {
00031   // FIXME: memoize!
00032   return new InlineAsm(Ty, AsmString, Constraints, hasSideEffects);  
00033 }
00034 
00035 InlineAsm::InlineAsm(const FunctionType *Ty, const std::string &asmString,
00036                      const std::string &constraints, bool hasSideEffects)
00037   : Value(PointerType::getUnqual(Ty), 
00038           Value::InlineAsmVal), 
00039     AsmString(asmString), 
00040     Constraints(constraints), HasSideEffects(hasSideEffects) {
00041 
00042   // Do various checks on the constraint string and type.
00043   assert(Verify(Ty, constraints) && "Function type not legal for constraints!");
00044 }
00045 
00046 const FunctionType *InlineAsm::getFunctionType() const {
00047   return cast<FunctionType>(getType()->getElementType());
00048 }
00049 
00050 /// Parse - Analyze the specified string (e.g. "==&{eax}") and fill in the
00051 /// fields in this structure.  If the constraint string is not understood,
00052 /// return true, otherwise return false.
00053 bool InlineAsm::ConstraintInfo::Parse(const std::string &Str,
00054                      std::vector<InlineAsm::ConstraintInfo> &ConstraintsSoFar) {
00055   std::string::const_iterator I = Str.begin(), E = Str.end();
00056   
00057   // Initialize
00058   Type = isInput;
00059   isEarlyClobber = false;
00060   MatchingInput = -1;
00061   isCommutative = false;
00062   isIndirect = false;
00063   
00064   // Parse prefixes.
00065   if (*I == '~') {
00066     Type = isClobber;
00067     ++I;
00068   } else if (*I == '=') {
00069     ++I;
00070     Type = isOutput;
00071   }
00072   
00073   if (*I == '*') {
00074     isIndirect = true;
00075     ++I;
00076   }
00077   
00078   if (I == E) return true;  // Just a prefix, like "==" or "~".
00079   
00080   // Parse the modifiers.
00081   bool DoneWithModifiers = false;
00082   while (!DoneWithModifiers) {
00083     switch (*I) {
00084     default:
00085       DoneWithModifiers = true;
00086       break;
00087     case '&':     // Early clobber.
00088       if (Type != isOutput ||      // Cannot early clobber anything but output.
00089           isEarlyClobber)          // Reject &&&&&&
00090         return true;
00091       isEarlyClobber = true;
00092       break;
00093     case '%':     // Commutative.
00094       if (Type == isClobber ||     // Cannot commute clobbers.
00095           isCommutative)           // Reject %%%%%
00096         return true;
00097       isCommutative = true;
00098       break;
00099     case '#':     // Comment.
00100     case '*':     // Register preferencing.
00101       return true;     // Not supported.
00102     }
00103     
00104     if (!DoneWithModifiers) {
00105       ++I;
00106       if (I == E) return true;   // Just prefixes and modifiers!
00107     }
00108   }
00109   
00110   // Parse the various constraints.
00111   while (I != E) {
00112     if (*I == '{') {   // Physical register reference.
00113       // Find the end of the register name.
00114       std::string::const_iterator ConstraintEnd = std::find(I+1, E, '}');
00115       if (ConstraintEnd == E) return true;  // "{foo"
00116       Codes.push_back(std::string(I, ConstraintEnd+1));
00117       I = ConstraintEnd+1;
00118     } else if (isdigit(*I)) {     // Matching Constraint
00119       // Maximal munch numbers.
00120       std::string::const_iterator NumStart = I;
00121       while (I != E && isdigit(*I))
00122         ++I;
00123       Codes.push_back(std::string(NumStart, I));
00124       unsigned N = atoi(Codes.back().c_str());
00125       // Check that this is a valid matching constraint!
00126       if (N >= ConstraintsSoFar.size() || ConstraintsSoFar[N].Type != isOutput||
00127           Type != isInput)
00128         return true;  // Invalid constraint number.
00129       
00130       // If Operand N already has a matching input, reject this.  An output
00131       // can't be constrained to the same value as multiple inputs.
00132       if (ConstraintsSoFar[N].hasMatchingInput())
00133         return true;
00134       
00135       // Note that operand #n has a matching input.
00136       ConstraintsSoFar[N].MatchingInput = ConstraintsSoFar.size();
00137     } else {
00138       // Single letter constraint.
00139       Codes.push_back(std::string(I, I+1));
00140       ++I;
00141     }
00142   }
00143 
00144   return false;
00145 }
00146 
00147 std::vector<InlineAsm::ConstraintInfo>
00148 InlineAsm::ParseConstraints(const std::string &Constraints) {
00149   std::vector<ConstraintInfo> Result;
00150   
00151   // Scan the constraints string.
00152   for (std::string::const_iterator I = Constraints.begin(), 
00153        E = Constraints.end(); I != E; ) {
00154     ConstraintInfo Info;
00155 
00156     // Find the end of this constraint.
00157     std::string::const_iterator ConstraintEnd = std::find(I, E, ',');
00158 
00159     if (ConstraintEnd == I ||  // Empty constraint like ",,"
00160         Info.Parse(std::string(I, ConstraintEnd), Result)) {
00161       Result.clear();          // Erroneous constraint?
00162       break;
00163     }
00164 
00165     Result.push_back(Info);
00166     
00167     // ConstraintEnd may be either the next comma or the end of the string.  In
00168     // the former case, we skip the comma.
00169     I = ConstraintEnd;
00170     if (I != E) {
00171       ++I;
00172       if (I == E) { Result.clear(); break; }    // don't allow "xyz,"
00173     }
00174   }
00175   
00176   return Result;
00177 }
00178 
00179 
00180 /// Verify - Verify that the specified constraint string is reasonable for the
00181 /// specified function type, and otherwise validate the constraint string.
00182 bool InlineAsm::Verify(const FunctionType *Ty, const std::string &ConstStr) {
00183   if (Ty->isVarArg()) return false;
00184   
00185   std::vector<ConstraintInfo> Constraints = ParseConstraints(ConstStr);
00186   
00187   // Error parsing constraints.
00188   if (Constraints.empty() && !ConstStr.empty()) return false;
00189   
00190   unsigned NumOutputs = 0, NumInputs = 0, NumClobbers = 0;
00191   unsigned NumIndirect = 0;
00192   
00193   for (unsigned i = 0, e = Constraints.size(); i != e; ++i) {
00194     switch (Constraints[i].Type) {
00195     case InlineAsm::isOutput:
00196       if ((NumInputs-NumIndirect) != 0 || NumClobbers != 0)
00197         return false;  // outputs before inputs and clobbers.
00198       if (!Constraints[i].isIndirect) {
00199         ++NumOutputs;
00200         break;
00201       }
00202       ++NumIndirect;
00203       // FALLTHROUGH for Indirect Outputs.
00204     case InlineAsm::isInput:
00205       if (NumClobbers) return false;               // inputs before clobbers.
00206       ++NumInputs;
00207       break;
00208     case InlineAsm::isClobber:
00209       ++NumClobbers;
00210       break;
00211     }
00212   }
00213   
00214   switch (NumOutputs) {
00215   case 0:
00216     if (Ty->getReturnType() != Type::VoidTy) return false;
00217     break;
00218   case 1:
00219     if (isa<StructType>(Ty->getReturnType())) return false;
00220     break;
00221   default:
00222     const StructType *STy = dyn_cast<StructType>(Ty->getReturnType());
00223     if (STy == 0 || STy->getNumElements() != NumOutputs)
00224       return false;
00225     break;
00226   }      
00227   
00228   if (Ty->getNumParams() != NumInputs) return false;
00229   return true;
00230 }
00231