InlineAsm.cpp revision 92ccf70ad448eb02f9f273d2c70ae4708b3bd0f2
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 "llvm/DerivedTypes.h"
16#include <algorithm>
17#include <cctype>
18using namespace llvm;
19
20// Implement the first virtual method in this class in this file so the
21// InlineAsm vtable is emitted here.
22InlineAsm::~InlineAsm() {
23}
24
25
26// NOTE: when memoizing the function type, we have to be careful to handle the
27// case when the type gets refined.
28
29InlineAsm *InlineAsm::get(const FunctionType *Ty, const StringRef &AsmString,
30                          const StringRef &Constraints, bool hasSideEffects) {
31  // FIXME: memoize!
32  return new InlineAsm(Ty, AsmString, Constraints, hasSideEffects);
33}
34
35InlineAsm::InlineAsm(const FunctionType *Ty, const StringRef &asmString,
36                     const StringRef &constraints, bool hasSideEffects)
37  : Value(PointerType::getUnqual(Ty),
38          Value::InlineAsmVal),
39    AsmString(asmString),
40    Constraints(constraints), HasSideEffects(hasSideEffects) {
41
42  // Do various checks on the constraint string and type.
43  assert(Verify(Ty, constraints) && "Function type not legal for constraints!");
44}
45
46const FunctionType *InlineAsm::getFunctionType() const {
47  return cast<FunctionType>(getType()->getElementType());
48}
49
50/// Parse - Analyze the specified string (e.g. "==&{eax}") and fill in the
51/// fields in this structure.  If the constraint string is not understood,
52/// return true, otherwise return false.
53bool InlineAsm::ConstraintInfo::Parse(const StringRef &Str,
54                     std::vector<InlineAsm::ConstraintInfo> &ConstraintsSoFar) {
55  StringRef::iterator I = Str.begin(), E = Str.end();
56
57  // Initialize
58  Type = isInput;
59  isEarlyClobber = false;
60  MatchingInput = -1;
61  isCommutative = false;
62  isIndirect = false;
63
64  // Parse prefixes.
65  if (*I == '~') {
66    Type = isClobber;
67    ++I;
68  } else if (*I == '=') {
69    ++I;
70    Type = isOutput;
71  }
72
73  if (*I == '*') {
74    isIndirect = true;
75    ++I;
76  }
77
78  if (I == E) return true;  // Just a prefix, like "==" or "~".
79
80  // Parse the modifiers.
81  bool DoneWithModifiers = false;
82  while (!DoneWithModifiers) {
83    switch (*I) {
84    default:
85      DoneWithModifiers = true;
86      break;
87    case '&':     // Early clobber.
88      if (Type != isOutput ||      // Cannot early clobber anything but output.
89          isEarlyClobber)          // Reject &&&&&&
90        return true;
91      isEarlyClobber = true;
92      break;
93    case '%':     // Commutative.
94      if (Type == isClobber ||     // Cannot commute clobbers.
95          isCommutative)           // Reject %%%%%
96        return true;
97      isCommutative = true;
98      break;
99    case '#':     // Comment.
100    case '*':     // Register preferencing.
101      return true;     // Not supported.
102    }
103
104    if (!DoneWithModifiers) {
105      ++I;
106      if (I == E) return true;   // Just prefixes and modifiers!
107    }
108  }
109
110  // Parse the various constraints.
111  while (I != E) {
112    if (*I == '{') {   // Physical register reference.
113      // Find the end of the register name.
114      StringRef::iterator ConstraintEnd = std::find(I+1, E, '}');
115      if (ConstraintEnd == E) return true;  // "{foo"
116      Codes.push_back(std::string(I, ConstraintEnd+1));
117      I = ConstraintEnd+1;
118    } else if (isdigit(*I)) {     // Matching Constraint
119      // Maximal munch numbers.
120      StringRef::iterator NumStart = I;
121      while (I != E && isdigit(*I))
122        ++I;
123      Codes.push_back(std::string(NumStart, I));
124      unsigned N = atoi(Codes.back().c_str());
125      // Check that this is a valid matching constraint!
126      if (N >= ConstraintsSoFar.size() || ConstraintsSoFar[N].Type != isOutput||
127          Type != isInput)
128        return true;  // Invalid constraint number.
129
130      // If Operand N already has a matching input, reject this.  An output
131      // can't be constrained to the same value as multiple inputs.
132      if (ConstraintsSoFar[N].hasMatchingInput())
133        return true;
134
135      // Note that operand #n has a matching input.
136      ConstraintsSoFar[N].MatchingInput = ConstraintsSoFar.size();
137    } else {
138      // Single letter constraint.
139      Codes.push_back(std::string(I, I+1));
140      ++I;
141    }
142  }
143
144  return false;
145}
146
147std::vector<InlineAsm::ConstraintInfo>
148InlineAsm::ParseConstraints(const StringRef &Constraints) {
149  std::vector<ConstraintInfo> Result;
150
151  // Scan the constraints string.
152  for (StringRef::iterator I = Constraints.begin(),
153         E = Constraints.end(); I != E; ) {
154    ConstraintInfo Info;
155
156    // Find the end of this constraint.
157    StringRef::iterator ConstraintEnd = std::find(I, E, ',');
158
159    if (ConstraintEnd == I ||  // Empty constraint like ",,"
160        Info.Parse(std::string(I, ConstraintEnd), Result)) {
161      Result.clear();          // Erroneous constraint?
162      break;
163    }
164
165    Result.push_back(Info);
166
167    // ConstraintEnd may be either the next comma or the end of the string.  In
168    // the former case, we skip the comma.
169    I = ConstraintEnd;
170    if (I != E) {
171      ++I;
172      if (I == E) { Result.clear(); break; }    // don't allow "xyz,"
173    }
174  }
175
176  return Result;
177}
178
179
180/// Verify - Verify that the specified constraint string is reasonable for the
181/// specified function type, and otherwise validate the constraint string.
182bool InlineAsm::Verify(const FunctionType *Ty, const StringRef &ConstStr) {
183  if (Ty->isVarArg()) return false;
184
185  std::vector<ConstraintInfo> Constraints = ParseConstraints(ConstStr);
186
187  // Error parsing constraints.
188  if (Constraints.empty() && !ConstStr.empty()) return false;
189
190  unsigned NumOutputs = 0, NumInputs = 0, NumClobbers = 0;
191  unsigned NumIndirect = 0;
192
193  for (unsigned i = 0, e = Constraints.size(); i != e; ++i) {
194    switch (Constraints[i].Type) {
195    case InlineAsm::isOutput:
196      if ((NumInputs-NumIndirect) != 0 || NumClobbers != 0)
197        return false;  // outputs before inputs and clobbers.
198      if (!Constraints[i].isIndirect) {
199        ++NumOutputs;
200        break;
201      }
202      ++NumIndirect;
203      // FALLTHROUGH for Indirect Outputs.
204    case InlineAsm::isInput:
205      if (NumClobbers) return false;               // inputs before clobbers.
206      ++NumInputs;
207      break;
208    case InlineAsm::isClobber:
209      ++NumClobbers;
210      break;
211    }
212  }
213
214  switch (NumOutputs) {
215  case 0:
216    if (Ty->getReturnType() != Type::VoidTy) return false;
217    break;
218  case 1:
219    if (isa<StructType>(Ty->getReturnType())) return false;
220    break;
221  default:
222    const StructType *STy = dyn_cast<StructType>(Ty->getReturnType());
223    if (STy == 0 || STy->getNumElements() != NumOutputs)
224      return false;
225    break;
226  }
227
228  if (Ty->getNumParams() != NumInputs) return false;
229  return true;
230}
231
232