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