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