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 InlineAsm *InlineAsm::get(FunctionType *FTy, StringRef AsmString,
     28                           StringRef Constraints, bool hasSideEffects,
     29                           bool isAlignStack, AsmDialect asmDialect) {
     30   InlineAsmKeyType Key(AsmString, Constraints, FTy, hasSideEffects,
     31                        isAlignStack, asmDialect);
     32   LLVMContextImpl *pImpl = FTy->getContext().pImpl;
     33   return pImpl->InlineAsms.getOrCreate(PointerType::getUnqual(FTy), Key);
     34 }
     35 
     36 InlineAsm::InlineAsm(FunctionType *FTy, const std::string &asmString,
     37                      const std::string &constraints, bool hasSideEffects,
     38                      bool isAlignStack, AsmDialect asmDialect)
     39     : Value(PointerType::getUnqual(FTy), Value::InlineAsmVal),
     40       AsmString(asmString), Constraints(constraints), FTy(FTy),
     41       HasSideEffects(hasSideEffects), IsAlignStack(isAlignStack),
     42       Dialect(asmDialect) {
     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 FTy;
     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 /// Parse - Analyze the specified string (e.g. "==&{eax}") and fill in the
     67 /// fields in this structure.  If the constraint string is not understood,
     68 /// return true, otherwise return false.
     69 bool InlineAsm::ConstraintInfo::Parse(StringRef Str,
     70                      InlineAsm::ConstraintInfoVector &ConstraintsSoFar) {
     71   StringRef::iterator I = Str.begin(), E = Str.end();
     72   unsigned multipleAlternativeCount = Str.count('|') + 1;
     73   unsigned multipleAlternativeIndex = 0;
     74   ConstraintCodeVector *pCodes = &Codes;
     75 
     76   // Initialize
     77   isMultipleAlternative = multipleAlternativeCount > 1;
     78   if (isMultipleAlternative) {
     79     multipleAlternatives.resize(multipleAlternativeCount);
     80     pCodes = &multipleAlternatives[0].Codes;
     81   }
     82   Type = isInput;
     83   isEarlyClobber = false;
     84   MatchingInput = -1;
     85   isCommutative = false;
     86   isIndirect = false;
     87   currentAlternativeIndex = 0;
     88 
     89   // Parse prefixes.
     90   if (*I == '~') {
     91     Type = isClobber;
     92     ++I;
     93 
     94     // '{' must immediately follow '~'.
     95     if (I != E && *I != '{')
     96       return true;
     97   } else if (*I == '=') {
     98     ++I;
     99     Type = isOutput;
    100   }
    101 
    102   if (*I == '*') {
    103     isIndirect = true;
    104     ++I;
    105   }
    106 
    107   if (I == E) return true;  // Just a prefix, like "==" or "~".
    108 
    109   // Parse the modifiers.
    110   bool DoneWithModifiers = false;
    111   while (!DoneWithModifiers) {
    112     switch (*I) {
    113     default:
    114       DoneWithModifiers = true;
    115       break;
    116     case '&':     // Early clobber.
    117       if (Type != isOutput ||      // Cannot early clobber anything but output.
    118           isEarlyClobber)          // Reject &&&&&&
    119         return true;
    120       isEarlyClobber = true;
    121       break;
    122     case '%':     // Commutative.
    123       if (Type == isClobber ||     // Cannot commute clobbers.
    124           isCommutative)           // Reject %%%%%
    125         return true;
    126       isCommutative = true;
    127       break;
    128     case '#':     // Comment.
    129     case '*':     // Register preferencing.
    130       return true;     // Not supported.
    131     }
    132 
    133     if (!DoneWithModifiers) {
    134       ++I;
    135       if (I == E) return true;   // Just prefixes and modifiers!
    136     }
    137   }
    138 
    139   // Parse the various constraints.
    140   while (I != E) {
    141     if (*I == '{') {   // Physical register reference.
    142       // Find the end of the register name.
    143       StringRef::iterator ConstraintEnd = std::find(I+1, E, '}');
    144       if (ConstraintEnd == E) return true;  // "{foo"
    145       pCodes->push_back(StringRef(I, ConstraintEnd+1 - I));
    146       I = ConstraintEnd+1;
    147     } else if (isdigit(static_cast<unsigned char>(*I))) { // Matching Constraint
    148       // Maximal munch numbers.
    149       StringRef::iterator NumStart = I;
    150       while (I != E && isdigit(static_cast<unsigned char>(*I)))
    151         ++I;
    152       pCodes->push_back(StringRef(NumStart, I - NumStart));
    153       unsigned N = atoi(pCodes->back().c_str());
    154       // Check that this is a valid matching constraint!
    155       if (N >= ConstraintsSoFar.size() || ConstraintsSoFar[N].Type != isOutput||
    156           Type != isInput)
    157         return true;  // Invalid constraint number.
    158 
    159       // If Operand N already has a matching input, reject this.  An output
    160       // can't be constrained to the same value as multiple inputs.
    161       if (isMultipleAlternative) {
    162         if (multipleAlternativeIndex >=
    163             ConstraintsSoFar[N].multipleAlternatives.size())
    164           return true;
    165         InlineAsm::SubConstraintInfo &scInfo =
    166           ConstraintsSoFar[N].multipleAlternatives[multipleAlternativeIndex];
    167         if (scInfo.MatchingInput != -1)
    168           return true;
    169         // Note that operand #n has a matching input.
    170         scInfo.MatchingInput = ConstraintsSoFar.size();
    171       } else {
    172         if (ConstraintsSoFar[N].hasMatchingInput() &&
    173             (size_t)ConstraintsSoFar[N].MatchingInput !=
    174                 ConstraintsSoFar.size())
    175           return true;
    176         // Note that operand #n has a matching input.
    177         ConstraintsSoFar[N].MatchingInput = ConstraintsSoFar.size();
    178         }
    179     } else if (*I == '|') {
    180       multipleAlternativeIndex++;
    181       pCodes = &multipleAlternatives[multipleAlternativeIndex].Codes;
    182       ++I;
    183     } else if (*I == '^') {
    184       // Multi-letter constraint
    185       // FIXME: For now assuming these are 2-character constraints.
    186       pCodes->push_back(StringRef(I+1, 2));
    187       I += 3;
    188     } else {
    189       // Single letter constraint.
    190       pCodes->push_back(StringRef(I, 1));
    191       ++I;
    192     }
    193   }
    194 
    195   return false;
    196 }
    197 
    198 /// selectAlternative - Point this constraint to the alternative constraint
    199 /// indicated by the index.
    200 void InlineAsm::ConstraintInfo::selectAlternative(unsigned index) {
    201   if (index < multipleAlternatives.size()) {
    202     currentAlternativeIndex = index;
    203     InlineAsm::SubConstraintInfo &scInfo =
    204       multipleAlternatives[currentAlternativeIndex];
    205     MatchingInput = scInfo.MatchingInput;
    206     Codes = scInfo.Codes;
    207   }
    208 }
    209 
    210 InlineAsm::ConstraintInfoVector
    211 InlineAsm::ParseConstraints(StringRef Constraints) {
    212   ConstraintInfoVector Result;
    213 
    214   // Scan the constraints string.
    215   for (StringRef::iterator I = Constraints.begin(),
    216          E = Constraints.end(); I != E; ) {
    217     ConstraintInfo Info;
    218 
    219     // Find the end of this constraint.
    220     StringRef::iterator ConstraintEnd = std::find(I, E, ',');
    221 
    222     if (ConstraintEnd == I ||  // Empty constraint like ",,"
    223         Info.Parse(StringRef(I, ConstraintEnd-I), Result)) {
    224       Result.clear();          // Erroneous constraint?
    225       break;
    226     }
    227 
    228     Result.push_back(Info);
    229 
    230     // ConstraintEnd may be either the next comma or the end of the string.  In
    231     // the former case, we skip the comma.
    232     I = ConstraintEnd;
    233     if (I != E) {
    234       ++I;
    235       if (I == E) {
    236         Result.clear();
    237         break;
    238       } // don't allow "xyz,"
    239     }
    240   }
    241 
    242   return Result;
    243 }
    244 
    245 /// Verify - Verify that the specified constraint string is reasonable for the
    246 /// specified function type, and otherwise validate the constraint string.
    247 bool InlineAsm::Verify(FunctionType *Ty, StringRef ConstStr) {
    248   if (Ty->isVarArg()) return false;
    249 
    250   ConstraintInfoVector Constraints = ParseConstraints(ConstStr);
    251 
    252   // Error parsing constraints.
    253   if (Constraints.empty() && !ConstStr.empty()) return false;
    254 
    255   unsigned NumOutputs = 0, NumInputs = 0, NumClobbers = 0;
    256   unsigned NumIndirect = 0;
    257 
    258   for (unsigned i = 0, e = Constraints.size(); i != e; ++i) {
    259     switch (Constraints[i].Type) {
    260     case InlineAsm::isOutput:
    261       if ((NumInputs-NumIndirect) != 0 || NumClobbers != 0)
    262         return false;  // outputs before inputs and clobbers.
    263       if (!Constraints[i].isIndirect) {
    264         ++NumOutputs;
    265         break;
    266       }
    267       ++NumIndirect;
    268       // FALLTHROUGH for Indirect Outputs.
    269     case InlineAsm::isInput:
    270       if (NumClobbers) return false;               // inputs before clobbers.
    271       ++NumInputs;
    272       break;
    273     case InlineAsm::isClobber:
    274       ++NumClobbers;
    275       break;
    276     }
    277   }
    278 
    279   switch (NumOutputs) {
    280   case 0:
    281     if (!Ty->getReturnType()->isVoidTy()) return false;
    282     break;
    283   case 1:
    284     if (Ty->getReturnType()->isStructTy()) return false;
    285     break;
    286   default:
    287     StructType *STy = dyn_cast<StructType>(Ty->getReturnType());
    288     if (!STy || STy->getNumElements() != NumOutputs)
    289       return false;
    290     break;
    291   }
    292 
    293   if (Ty->getNumParams() != NumInputs) return false;
    294   return true;
    295 }
    296