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