InlineAsm.cpp revision 3b91778659ec7d515ae1354022f0213e5de64d80
1//===-- InlineAsm.cpp - Implement the InlineAsm class ---------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file was developed by Chris Lattner and is distributed under the
6// University of Illinois Open Source 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 <cctype>
17using namespace llvm;
18
19// NOTE: when memoizing the function type, we have to be careful to handle the
20// case when the type gets refined.
21
22InlineAsm *InlineAsm::get(const FunctionType *Ty, const std::string &AsmString,
23                          const std::string &Constraints, bool hasSideEffects) {
24  // FIXME: memoize!
25  return new InlineAsm(Ty, AsmString, Constraints, hasSideEffects);
26}
27
28InlineAsm::InlineAsm(const FunctionType *Ty, const std::string &asmString,
29                     const std::string &constraints, bool hasSideEffects)
30  : Value(PointerType::get(Ty), Value::InlineAsmVal), AsmString(asmString),
31    Constraints(constraints), HasSideEffects(hasSideEffects) {
32
33  // Do various checks on the constraint string and type.
34  assert(Verify(Ty, constraints) && "Function type not legal for constraints!");
35}
36
37const FunctionType *InlineAsm::getFunctionType() const {
38  return cast<FunctionType>(getType()->getElementType());
39}
40
41/// Verify - Verify that the specified constraint string is reasonable for the
42/// specified function type, and otherwise validate the constraint string.
43bool InlineAsm::Verify(const FunctionType *Ty, const std::string &Constraints) {
44  if (Ty->isVarArg()) return false;
45
46  unsigned NumOutputs = 0, NumInputs = 0, NumClobbers = 0;
47
48  // Scan the constraints string.
49  for (std::string::const_iterator I = Constraints.begin(),
50         E = Constraints.end(); I != E; ) {
51    if (*I == ',') return false;  // Empty constraint like ",,"
52
53    // Parse the prefix.
54    enum {
55      isInput,            // 'x'
56      isOutput,           // '=x'
57      isIndirectOutput,   // '==x'
58      isClobber,          // '~x'
59    } ConstraintType = isInput;
60
61    if (*I == '~') {
62      ConstraintType = isClobber;
63      ++I;
64    } else if (*I == '=') {
65      ++I;
66      if (I != E && *I == '=') {
67        ConstraintType = isIndirectOutput;
68        ++I;
69      } else {
70        ConstraintType = isOutput;
71      }
72    }
73
74    if (I == E) return false;   // Just a prefix, like "==" or "~".
75
76    switch (ConstraintType) {
77    case isOutput:
78      if (NumInputs || NumClobbers) return false;  // outputs come first.
79      ++NumOutputs;
80      break;
81    case isInput:
82    case isIndirectOutput:
83      if (NumClobbers) return false;               // inputs before clobbers.
84      ++NumInputs;
85      break;
86    case isClobber:
87      ++NumClobbers;
88      break;
89    }
90
91    // Parse the id.  We accept [a-zA-Z0-9] currently.
92    while (I != E && isalnum(*I)) ++I;
93
94    // If we reached the end of the ID, we must have the end of the string or a
95    // comma, which we skip now.
96    if (I != E) {
97      if (*I != ',') return false;
98      ++I;
99      if (I == E) return false;    // don't allow "xyz,"
100    }
101  }
102
103  if (NumOutputs > 1) return false;  // Only one result allowed.
104
105  if ((Ty->getReturnType() != Type::VoidTy) != NumOutputs)
106    return false;   // NumOutputs = 1 iff has a result type.
107
108  if (Ty->getNumParams() != NumInputs) return false;
109  return true;
110}
111