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