Add an assert to MDNode::deleteTemporary check that the node being deleted
[oota-llvm.git] / lib / VMCore / InlineAsm.cpp
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(const 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(const 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   delete this;
51 }
52
53 const FunctionType *InlineAsm::getFunctionType() const {
54   return cast<FunctionType>(getType()->getElementType());
55 }
56
57 /// Parse - Analyze the specified string (e.g. "==&{eax}") and fill in the
58 /// fields in this structure.  If the constraint string is not understood,
59 /// return true, otherwise return false.
60 bool InlineAsm::ConstraintInfo::Parse(StringRef Str,
61                      std::vector<InlineAsm::ConstraintInfo> &ConstraintsSoFar) {
62   StringRef::iterator I = Str.begin(), E = Str.end();
63   
64   // Initialize
65   Type = isInput;
66   isEarlyClobber = false;
67   MatchingInput = -1;
68   isCommutative = false;
69   isIndirect = false;
70   
71   // Parse prefixes.
72   if (*I == '~') {
73     Type = isClobber;
74     ++I;
75   } else if (*I == '=') {
76     ++I;
77     Type = isOutput;
78   }
79   
80   if (*I == '*') {
81     isIndirect = true;
82     ++I;
83   }
84   
85   if (I == E) return true;  // Just a prefix, like "==" or "~".
86   
87   // Parse the modifiers.
88   bool DoneWithModifiers = false;
89   while (!DoneWithModifiers) {
90     switch (*I) {
91     default:
92       DoneWithModifiers = true;
93       break;
94     case '&':     // Early clobber.
95       if (Type != isOutput ||      // Cannot early clobber anything but output.
96           isEarlyClobber)          // Reject &&&&&&
97         return true;
98       isEarlyClobber = true;
99       break;
100     case '%':     // Commutative.
101       if (Type == isClobber ||     // Cannot commute clobbers.
102           isCommutative)           // Reject %%%%%
103         return true;
104       isCommutative = true;
105       break;
106     case '#':     // Comment.
107     case '*':     // Register preferencing.
108       return true;     // Not supported.
109     }
110     
111     if (!DoneWithModifiers) {
112       ++I;
113       if (I == E) return true;   // Just prefixes and modifiers!
114     }
115   }
116   
117   // Parse the various constraints.
118   while (I != E) {
119     if (*I == '{') {   // Physical register reference.
120       // Find the end of the register name.
121       StringRef::iterator ConstraintEnd = std::find(I+1, E, '}');
122       if (ConstraintEnd == E) return true;  // "{foo"
123       Codes.push_back(std::string(I, ConstraintEnd+1));
124       I = ConstraintEnd+1;
125     } else if (isdigit(*I)) {     // Matching Constraint
126       // Maximal munch numbers.
127       StringRef::iterator NumStart = I;
128       while (I != E && isdigit(*I))
129         ++I;
130       Codes.push_back(std::string(NumStart, I));
131       unsigned N = atoi(Codes.back().c_str());
132       // Check that this is a valid matching constraint!
133       if (N >= ConstraintsSoFar.size() || ConstraintsSoFar[N].Type != isOutput||
134           Type != isInput)
135         return true;  // Invalid constraint number.
136       
137       // If Operand N already has a matching input, reject this.  An output
138       // can't be constrained to the same value as multiple inputs.
139       if (ConstraintsSoFar[N].hasMatchingInput())
140         return true;
141       
142       // Note that operand #n has a matching input.
143       ConstraintsSoFar[N].MatchingInput = ConstraintsSoFar.size();
144     } else {
145       // Single letter constraint.
146       Codes.push_back(std::string(I, I+1));
147       ++I;
148     }
149   }
150
151   return false;
152 }
153
154 std::vector<InlineAsm::ConstraintInfo>
155 InlineAsm::ParseConstraints(StringRef Constraints) {
156   std::vector<ConstraintInfo> Result;
157   
158   // Scan the constraints string.
159   for (StringRef::iterator I = Constraints.begin(),
160          E = Constraints.end(); I != E; ) {
161     ConstraintInfo Info;
162
163     // Find the end of this constraint.
164     StringRef::iterator ConstraintEnd = std::find(I, E, ',');
165
166     if (ConstraintEnd == I ||  // Empty constraint like ",,"
167         Info.Parse(StringRef(I, ConstraintEnd-I), Result)) {
168       Result.clear();          // Erroneous constraint?
169       break;
170     }
171
172     Result.push_back(Info);
173     
174     // ConstraintEnd may be either the next comma or the end of the string.  In
175     // the former case, we skip the comma.
176     I = ConstraintEnd;
177     if (I != E) {
178       ++I;
179       if (I == E) { Result.clear(); break; }    // don't allow "xyz,"
180     }
181   }
182   
183   return Result;
184 }
185
186
187 /// Verify - Verify that the specified constraint string is reasonable for the
188 /// specified function type, and otherwise validate the constraint string.
189 bool InlineAsm::Verify(const FunctionType *Ty, StringRef ConstStr) {
190   if (Ty->isVarArg()) return false;
191   
192   std::vector<ConstraintInfo> Constraints = ParseConstraints(ConstStr);
193   
194   // Error parsing constraints.
195   if (Constraints.empty() && !ConstStr.empty()) return false;
196   
197   unsigned NumOutputs = 0, NumInputs = 0, NumClobbers = 0;
198   unsigned NumIndirect = 0;
199   
200   for (unsigned i = 0, e = Constraints.size(); i != e; ++i) {
201     switch (Constraints[i].Type) {
202     case InlineAsm::isOutput:
203       if ((NumInputs-NumIndirect) != 0 || NumClobbers != 0)
204         return false;  // outputs before inputs and clobbers.
205       if (!Constraints[i].isIndirect) {
206         ++NumOutputs;
207         break;
208       }
209       ++NumIndirect;
210       // FALLTHROUGH for Indirect Outputs.
211     case InlineAsm::isInput:
212       if (NumClobbers) return false;               // inputs before clobbers.
213       ++NumInputs;
214       break;
215     case InlineAsm::isClobber:
216       ++NumClobbers;
217       break;
218     }
219   }
220   
221   switch (NumOutputs) {
222   case 0:
223     if (!Ty->getReturnType()->isVoidTy()) return false;
224     break;
225   case 1:
226     if (Ty->getReturnType()->isStructTy()) return false;
227     break;
228   default:
229     const StructType *STy = dyn_cast<StructType>(Ty->getReturnType());
230     if (STy == 0 || STy->getNumElements() != NumOutputs)
231       return false;
232     break;
233   }      
234   
235   if (Ty->getNumParams() != NumInputs) return false;
236   return true;
237 }
238