Home | History | Annotate | Download | only in VMCore
      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/InlineAsm.h"
     15 #include "ConstantsContext.h"
     16 #include "LLVMContextImpl.h"
     17 #include "llvm/DerivedTypes.h"
     18 #include <algorithm>
     19 #include <cctype>
     20 using namespace llvm;
     21 
     22 // Implement the first virtual method in this class in this file so the
     23 // InlineAsm vtable is emitted here.
     24 InlineAsm::~InlineAsm() {
     25 }
     26 
     27 
     28 InlineAsm *InlineAsm::get(FunctionType *Ty, StringRef AsmString,
     29                           StringRef Constraints, bool hasSideEffects,
     30                           bool isAlignStack) {
     31   InlineAsmKeyType Key(AsmString, Constraints, hasSideEffects, isAlignStack);
     32   LLVMContextImpl *pImpl = Ty->getContext().pImpl;
     33   return pImpl->InlineAsms.getOrCreate(PointerType::getUnqual(Ty), Key);
     34 }
     35 
     36 InlineAsm::InlineAsm(PointerType *Ty, const std::string &asmString,
     37                      const std::string &constraints, bool hasSideEffects,
     38                      bool isAlignStack)
     39   : Value(Ty, Value::InlineAsmVal),
     40     AsmString(asmString),
     41     Constraints(constraints), HasSideEffects(hasSideEffects),
     42     IsAlignStack(isAlignStack) {
     43 
     44   // Do various checks on the constraint string and type.
     45   assert(Verify(getFunctionType(), constraints) &&
     46          "Function type not legal for constraints!");
     47 }
     48 
     49 void InlineAsm::destroyConstant() {
     50   getType()->getContext().pImpl->InlineAsms.remove(this);
     51   delete this;
     52 }
     53 
     54 FunctionType *InlineAsm::getFunctionType() const {
     55   return cast<FunctionType>(getType()->getElementType());
     56 }
     57 
     58 ///Default constructor.
     59 InlineAsm::ConstraintInfo::ConstraintInfo() :
     60   Type(isInput), isEarlyClobber(false),
     61   MatchingInput(-1), isCommutative(false),
     62   isIndirect(false), isMultipleAlternative(false),
     63   currentAlternativeIndex(0) {
     64 }
     65 
     66 /// Copy constructor.
     67 InlineAsm::ConstraintInfo::ConstraintInfo(const ConstraintInfo &other) :
     68   Type(other.Type), isEarlyClobber(other.isEarlyClobber),
     69   MatchingInput(other.MatchingInput), isCommutative(other.isCommutative),
     70   isIndirect(other.isIndirect), Codes(other.Codes),
     71   isMultipleAlternative(other.isMultipleAlternative),
     72   multipleAlternatives(other.multipleAlternatives),
     73   currentAlternativeIndex(other.currentAlternativeIndex) {
     74 }
     75 
     76 /// Parse - Analyze the specified string (e.g. "==&{eax}") and fill in the
     77 /// fields in this structure.  If the constraint string is not understood,
     78 /// return true, otherwise return false.
     79 bool InlineAsm::ConstraintInfo::Parse(StringRef Str,
     80                      InlineAsm::ConstraintInfoVector &ConstraintsSoFar) {
     81   StringRef::iterator I = Str.begin(), E = Str.end();
     82   unsigned multipleAlternativeCount = Str.count('|') + 1;
     83   unsigned multipleAlternativeIndex = 0;
     84   ConstraintCodeVector *pCodes = &Codes;
     85 
     86   // Initialize
     87   isMultipleAlternative = (multipleAlternativeCount > 1 ? true : false);
     88   if (isMultipleAlternative) {
     89     multipleAlternatives.resize(multipleAlternativeCount);
     90     pCodes = &multipleAlternatives[0].Codes;
     91   }
     92   Type = isInput;
     93   isEarlyClobber = false;
     94   MatchingInput = -1;
     95   isCommutative = false;
     96   isIndirect = false;
     97   currentAlternativeIndex = 0;
     98 
     99   // Parse prefixes.
    100   if (*I == '~') {
    101     Type = isClobber;
    102     ++I;
    103   } else if (*I == '=') {
    104     ++I;
    105     Type = isOutput;
    106   }
    107 
    108   if (*I == '*') {
    109     isIndirect = true;
    110     ++I;
    111   }
    112 
    113   if (I == E) return true;  // Just a prefix, like "==" or "~".
    114 
    115   // Parse the modifiers.
    116   bool DoneWithModifiers = false;
    117   while (!DoneWithModifiers) {
    118     switch (*I) {
    119     default:
    120       DoneWithModifiers = true;
    121       break;
    122     case '&':     // Early clobber.
    123       if (Type != isOutput ||      // Cannot early clobber anything but output.
    124           isEarlyClobber)          // Reject &&&&&&
    125         return true;
    126       isEarlyClobber = true;
    127       break;
    128     case '%':     // Commutative.
    129       if (Type == isClobber ||     // Cannot commute clobbers.
    130           isCommutative)           // Reject %%%%%
    131         return true;
    132       isCommutative = true;
    133       break;
    134     case '#':     // Comment.
    135     case '*':     // Register preferencing.
    136       return true;     // Not supported.
    137     }
    138 
    139     if (!DoneWithModifiers) {
    140       ++I;
    141       if (I == E) return true;   // Just prefixes and modifiers!
    142     }
    143   }
    144 
    145   // Parse the various constraints.
    146   while (I != E) {
    147     if (*I == '{') {   // Physical register reference.
    148       // Find the end of the register name.
    149       StringRef::iterator ConstraintEnd = std::find(I+1, E, '}');
    150       if (ConstraintEnd == E) return true;  // "{foo"
    151       pCodes->push_back(std::string(I, ConstraintEnd+1));
    152       I = ConstraintEnd+1;
    153     } else if (isdigit(*I)) {     // Matching Constraint
    154       // Maximal munch numbers.
    155       StringRef::iterator NumStart = I;
    156       while (I != E && isdigit(*I))
    157         ++I;
    158       pCodes->push_back(std::string(NumStart, I));
    159       unsigned N = atoi(pCodes->back().c_str());
    160       // Check that this is a valid matching constraint!
    161       if (N >= ConstraintsSoFar.size() || ConstraintsSoFar[N].Type != isOutput||
    162           Type != isInput)
    163         return true;  // Invalid constraint number.
    164 
    165       // If Operand N already has a matching input, reject this.  An output
    166       // can't be constrained to the same value as multiple inputs.
    167       if (isMultipleAlternative) {
    168         InlineAsm::SubConstraintInfo &scInfo =
    169           ConstraintsSoFar[N].multipleAlternatives[multipleAlternativeIndex];
    170         if (scInfo.MatchingInput != -1)
    171           return true;
    172         // Note that operand #n has a matching input.
    173         scInfo.MatchingInput = ConstraintsSoFar.size();
    174       } else {
    175         if (ConstraintsSoFar[N].hasMatchingInput())
    176           return true;
    177         // Note that operand #n has a matching input.
    178         ConstraintsSoFar[N].MatchingInput = ConstraintsSoFar.size();
    179         }
    180     } else if (*I == '|') {
    181       multipleAlternativeIndex++;
    182       pCodes = &multipleAlternatives[multipleAlternativeIndex].Codes;
    183       ++I;
    184     } else if (*I == '^') {
    185       // Multi-letter constraint
    186       // FIXME: For now assuming these are 2-character constraints.
    187       pCodes->push_back(std::string(I+1, I+3));
    188       I += 3;
    189     } else {
    190       // Single letter constraint.
    191       pCodes->push_back(std::string(I, I+1));
    192       ++I;
    193     }
    194   }
    195 
    196   return false;
    197 }
    198 
    199 /// selectAlternative - Point this constraint to the alternative constraint
    200 /// indicated by the index.
    201 void InlineAsm::ConstraintInfo::selectAlternative(unsigned index) {
    202   if (index < multipleAlternatives.size()) {
    203     currentAlternativeIndex = index;
    204     InlineAsm::SubConstraintInfo &scInfo =
    205       multipleAlternatives[currentAlternativeIndex];
    206     MatchingInput = scInfo.MatchingInput;
    207     Codes = scInfo.Codes;
    208   }
    209 }
    210 
    211 InlineAsm::ConstraintInfoVector
    212 InlineAsm::ParseConstraints(StringRef Constraints) {
    213   ConstraintInfoVector Result;
    214 
    215   // Scan the constraints string.
    216   for (StringRef::iterator I = Constraints.begin(),
    217          E = Constraints.end(); I != E; ) {
    218     ConstraintInfo Info;
    219 
    220     // Find the end of this constraint.
    221     StringRef::iterator ConstraintEnd = std::find(I, E, ',');
    222 
    223     if (ConstraintEnd == I ||  // Empty constraint like ",,"
    224         Info.Parse(StringRef(I, ConstraintEnd-I), Result)) {
    225       Result.clear();          // Erroneous constraint?
    226       break;
    227     }
    228 
    229     Result.push_back(Info);
    230 
    231     // ConstraintEnd may be either the next comma or the end of the string.  In
    232     // the former case, we skip the comma.
    233     I = ConstraintEnd;
    234     if (I != E) {
    235       ++I;
    236       if (I == E) { Result.clear(); break; }    // 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.
    245 bool 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 == 0 || STy->getNumElements() != NumOutputs)
    287       return false;
    288     break;
    289   }
    290 
    291   if (Ty->getNumParams() != NumInputs) return false;
    292   return true;
    293 }
    294 
    295