Chris Lattner | eef2fe7 | 2006-01-24 04:13:11 +0000 | [diff] [blame] | 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" |
Chris Lattner | 8547e3a | 2006-01-26 00:48:33 +0000 | [diff] [blame^] | 16 | #include <cctype> |
Chris Lattner | eef2fe7 | 2006-01-24 04:13:11 +0000 | [diff] [blame] | 17 | using namespace llvm; |
| 18 | |
Chris Lattner | a2d810d | 2006-01-25 22:26:05 +0000 | [diff] [blame] | 19 | // NOTE: when memoizing the function type, we have to be careful to handle the |
| 20 | // case when the type gets refined. |
| 21 | |
| 22 | InlineAsm *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 | |
Chris Lattner | eef2fe7 | 2006-01-24 04:13:11 +0000 | [diff] [blame] | 28 | InlineAsm::InlineAsm(const FunctionType *Ty, const std::string &asmString, |
Chris Lattner | 8bbcda2 | 2006-01-25 18:57:27 +0000 | [diff] [blame] | 29 | const std::string &constraints, bool hasSideEffects) |
| 30 | : Value(PointerType::get(Ty), Value::InlineAsmVal), AsmString(asmString), |
| 31 | Constraints(constraints), HasSideEffects(hasSideEffects) { |
Chris Lattner | eef2fe7 | 2006-01-24 04:13:11 +0000 | [diff] [blame] | 32 | |
Chris Lattner | a2d810d | 2006-01-25 22:26:05 +0000 | [diff] [blame] | 33 | // Do various checks on the constraint string and type. |
| 34 | assert(Verify(Ty, constraints) && "Function type not legal for constraints!"); |
Chris Lattner | eef2fe7 | 2006-01-24 04:13:11 +0000 | [diff] [blame] | 35 | } |
| 36 | |
| 37 | const FunctionType *InlineAsm::getFunctionType() const { |
| 38 | return cast<FunctionType>(getType()->getElementType()); |
| 39 | } |
Chris Lattner | a2d810d | 2006-01-25 22:26:05 +0000 | [diff] [blame] | 40 | |
Chris Lattner | 8547e3a | 2006-01-26 00:48:33 +0000 | [diff] [blame^] | 41 | /// Verify - Verify that the specified constraint string is reasonable for the |
| 42 | /// specified function type, and otherwise validate the constraint string. |
Chris Lattner | a2d810d | 2006-01-25 22:26:05 +0000 | [diff] [blame] | 43 | bool InlineAsm::Verify(const FunctionType *Ty, const std::string &Constraints) { |
Chris Lattner | 8547e3a | 2006-01-26 00:48:33 +0000 | [diff] [blame^] | 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; |
Chris Lattner | a2d810d | 2006-01-25 22:26:05 +0000 | [diff] [blame] | 109 | return true; |
| 110 | } |