Home | History | Annotate | Download | only in IR
      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>
     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, 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 
     37 InlineAsm::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 
     50 void InlineAsm::destroyConstant() {
     51   getType()->getContext().pImpl->InlineAsms.remove(this);
     52   delete this;
     53 }
     54 
     55 FunctionType *InlineAsm::getFunctionType() const {
     56   return cast<FunctionType>(getType()->getElementType());
     57 }
     58 
     59 ///Default constructor.
     60 InlineAsm::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.
     70 bool 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;
     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 
     95     // '{' must immediately follow '~'.
     96     if (I != E && *I != '{')
     97       return true;
     98   } else if (*I == '=') {
     99     ++I;
    100     Type = isOutput;
    101   }
    102 
    103   if (*I == '*') {
    104     isIndirect = true;
    105     ++I;
    106   }
    107 
    108   if (I == E) return true;  // Just a prefix, like "==" or "~".
    109 
    110   // Parse the modifiers.
    111   bool DoneWithModifiers = false;
    112   while (!DoneWithModifiers) {
    113     switch (*I) {
    114     default:
    115       DoneWithModifiers = true;
    116       break;
    117     case '&':     // Early clobber.
    118       if (Type != isOutput ||      // Cannot early clobber anything but output.
    119           isEarlyClobber)          // Reject &&&&&&
    120         return true;
    121       isEarlyClobber = true;
    122       break;
    123     case '%':     // Commutative.
    124       if (Type == isClobber ||     // Cannot commute clobbers.
    125           isCommutative)           // Reject %%%%%
    126         return true;
    127       isCommutative = true;
    128       break;
    129     case '#':     // Comment.
    130     case '*':     // Register preferencing.
    131       return true;     // Not supported.
    132     }
    133 
    134     if (!DoneWithModifiers) {
    135       ++I;
    136       if (I == E) return true;   // Just prefixes and modifiers!
    137     }
    138   }
    139 
    140   // Parse the various constraints.
    141   while (I != E) {
    142     if (*I == '{') {   // Physical register reference.
    143       // Find the end of the register name.
    144       StringRef::iterator ConstraintEnd = std::find(I+1, E, '}');
    145       if (ConstraintEnd == E) return true;  // "{foo"
    146       pCodes->push_back(std::string(I, ConstraintEnd+1));
    147       I = ConstraintEnd+1;
    148     } else if (isdigit(static_cast<unsigned char>(*I))) { // Matching Constraint
    149       // Maximal munch numbers.
    150       StringRef::iterator NumStart = I;
    151       while (I != E && isdigit(static_cast<unsigned char>(*I)))
    152         ++I;
    153       pCodes->push_back(std::string(NumStart, I));
    154       unsigned N = atoi(pCodes->back().c_str());
    155       // Check that this is a valid matching constraint!
    156       if (N >= ConstraintsSoFar.size() || ConstraintsSoFar[N].Type != isOutput||
    157           Type != isInput)
    158         return true;  // Invalid constraint number.
    159 
    160       // If Operand N already has a matching input, reject this.  An output
    161       // can't be constrained to the same value as multiple inputs.
    162       if (isMultipleAlternative) {
    163         InlineAsm::SubConstraintInfo &scInfo =
    164           ConstraintsSoFar[N].multipleAlternatives[multipleAlternativeIndex];
    165         if (scInfo.MatchingInput != -1)
    166           return true;
    167         // Note that operand #n has a matching input.
    168         scInfo.MatchingInput = ConstraintsSoFar.size();
    169       } else {
    170         if (ConstraintsSoFar[N].hasMatchingInput() &&
    171             (size_t)ConstraintsSoFar[N].MatchingInput !=
    172                 ConstraintsSoFar.size())
    173           return true;
    174         // Note that operand #n has a matching input.
    175         ConstraintsSoFar[N].MatchingInput = ConstraintsSoFar.size();
    176         }
    177     } else if (*I == '|') {
    178       multipleAlternativeIndex++;
    179       pCodes = &multipleAlternatives[multipleAlternativeIndex].Codes;
    180       ++I;
    181     } else if (*I == '^') {
    182       // Multi-letter constraint
    183       // FIXME: For now assuming these are 2-character constraints.
    184       pCodes->push_back(std::string(I+1, I+3));
    185       I += 3;
    186     } else {
    187       // Single letter constraint.
    188       pCodes->push_back(std::string(I, I+1));
    189       ++I;
    190     }
    191   }
    192 
    193   return false;
    194 }
    195 
    196 /// selectAlternative - Point this constraint to the alternative constraint
    197 /// indicated by the index.
    198 void InlineAsm::ConstraintInfo::selectAlternative(unsigned index) {
    199   if (index < multipleAlternatives.size()) {
    200     currentAlternativeIndex = index;
    201     InlineAsm::SubConstraintInfo &scInfo =
    202       multipleAlternatives[currentAlternativeIndex];
    203     MatchingInput = scInfo.MatchingInput;
    204     Codes = scInfo.Codes;
    205   }
    206 }
    207 
    208 InlineAsm::ConstraintInfoVector
    209 InlineAsm::ParseConstraints(StringRef Constraints) {
    210   ConstraintInfoVector Result;
    211 
    212   // Scan the constraints string.
    213   for (StringRef::iterator I = Constraints.begin(),
    214          E = Constraints.end(); I != E; ) {
    215     ConstraintInfo Info;
    216 
    217     // Find the end of this constraint.
    218     StringRef::iterator ConstraintEnd = std::find(I, E, ',');
    219 
    220     if (ConstraintEnd == I ||  // Empty constraint like ",,"
    221         Info.Parse(StringRef(I, ConstraintEnd-I), Result)) {
    222       Result.clear();          // Erroneous constraint?
    223       break;
    224     }
    225 
    226     Result.push_back(Info);
    227 
    228     // ConstraintEnd may be either the next comma or the end of the string.  In
    229     // the former case, we skip the comma.
    230     I = ConstraintEnd;
    231     if (I != E) {
    232       ++I;
    233       if (I == E) {
    234         Result.clear();
    235         break;
    236       } // 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 || STy->getNumElements() != NumOutputs)
    287       return false;
    288     break;
    289   }
    290 
    291   if (Ty->getNumParams() != NumInputs) return false;
    292   return true;
    293 }
    294 
    295