LLVM API Documentation
00001 //===-- InlineAsm.cpp - Implement the InlineAsm class ---------------------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file implements the InlineAsm class. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #include "llvm/InlineAsm.h" 00015 #include "llvm/DerivedTypes.h" 00016 #include <algorithm> 00017 #include <cctype> 00018 using namespace llvm; 00019 00020 // Implement the first virtual method in this class in this file so the 00021 // InlineAsm vtable is emitted here. 00022 InlineAsm::~InlineAsm() { 00023 } 00024 00025 00026 // NOTE: when memoizing the function type, we have to be careful to handle the 00027 // case when the type gets refined. 00028 00029 InlineAsm *InlineAsm::get(const FunctionType *Ty, const std::string &AsmString, 00030 const std::string &Constraints, bool hasSideEffects) { 00031 // FIXME: memoize! 00032 return new InlineAsm(Ty, AsmString, Constraints, hasSideEffects); 00033 } 00034 00035 InlineAsm::InlineAsm(const FunctionType *Ty, const std::string &asmString, 00036 const std::string &constraints, bool hasSideEffects) 00037 : Value(PointerType::getUnqual(Ty), 00038 Value::InlineAsmVal), 00039 AsmString(asmString), 00040 Constraints(constraints), HasSideEffects(hasSideEffects) { 00041 00042 // Do various checks on the constraint string and type. 00043 assert(Verify(Ty, constraints) && "Function type not legal for constraints!"); 00044 } 00045 00046 const FunctionType *InlineAsm::getFunctionType() const { 00047 return cast<FunctionType>(getType()->getElementType()); 00048 } 00049 00050 /// Parse - Analyze the specified string (e.g. "==&{eax}") and fill in the 00051 /// fields in this structure. If the constraint string is not understood, 00052 /// return true, otherwise return false. 00053 bool InlineAsm::ConstraintInfo::Parse(const std::string &Str, 00054 std::vector<InlineAsm::ConstraintInfo> &ConstraintsSoFar) { 00055 std::string::const_iterator I = Str.begin(), E = Str.end(); 00056 00057 // Initialize 00058 Type = isInput; 00059 isEarlyClobber = false; 00060 MatchingInput = -1; 00061 isCommutative = false; 00062 isIndirect = false; 00063 00064 // Parse prefixes. 00065 if (*I == '~') { 00066 Type = isClobber; 00067 ++I; 00068 } else if (*I == '=') { 00069 ++I; 00070 Type = isOutput; 00071 } 00072 00073 if (*I == '*') { 00074 isIndirect = true; 00075 ++I; 00076 } 00077 00078 if (I == E) return true; // Just a prefix, like "==" or "~". 00079 00080 // Parse the modifiers. 00081 bool DoneWithModifiers = false; 00082 while (!DoneWithModifiers) { 00083 switch (*I) { 00084 default: 00085 DoneWithModifiers = true; 00086 break; 00087 case '&': // Early clobber. 00088 if (Type != isOutput || // Cannot early clobber anything but output. 00089 isEarlyClobber) // Reject &&&&&& 00090 return true; 00091 isEarlyClobber = true; 00092 break; 00093 case '%': // Commutative. 00094 if (Type == isClobber || // Cannot commute clobbers. 00095 isCommutative) // Reject %%%%% 00096 return true; 00097 isCommutative = true; 00098 break; 00099 case '#': // Comment. 00100 case '*': // Register preferencing. 00101 return true; // Not supported. 00102 } 00103 00104 if (!DoneWithModifiers) { 00105 ++I; 00106 if (I == E) return true; // Just prefixes and modifiers! 00107 } 00108 } 00109 00110 // Parse the various constraints. 00111 while (I != E) { 00112 if (*I == '{') { // Physical register reference. 00113 // Find the end of the register name. 00114 std::string::const_iterator ConstraintEnd = std::find(I+1, E, '}'); 00115 if (ConstraintEnd == E) return true; // "{foo" 00116 Codes.push_back(std::string(I, ConstraintEnd+1)); 00117 I = ConstraintEnd+1; 00118 } else if (isdigit(*I)) { // Matching Constraint 00119 // Maximal munch numbers. 00120 std::string::const_iterator NumStart = I; 00121 while (I != E && isdigit(*I)) 00122 ++I; 00123 Codes.push_back(std::string(NumStart, I)); 00124 unsigned N = atoi(Codes.back().c_str()); 00125 // Check that this is a valid matching constraint! 00126 if (N >= ConstraintsSoFar.size() || ConstraintsSoFar[N].Type != isOutput|| 00127 Type != isInput) 00128 return true; // Invalid constraint number. 00129 00130 // If Operand N already has a matching input, reject this. An output 00131 // can't be constrained to the same value as multiple inputs. 00132 if (ConstraintsSoFar[N].hasMatchingInput()) 00133 return true; 00134 00135 // Note that operand #n has a matching input. 00136 ConstraintsSoFar[N].MatchingInput = ConstraintsSoFar.size(); 00137 } else { 00138 // Single letter constraint. 00139 Codes.push_back(std::string(I, I+1)); 00140 ++I; 00141 } 00142 } 00143 00144 return false; 00145 } 00146 00147 std::vector<InlineAsm::ConstraintInfo> 00148 InlineAsm::ParseConstraints(const std::string &Constraints) { 00149 std::vector<ConstraintInfo> Result; 00150 00151 // Scan the constraints string. 00152 for (std::string::const_iterator I = Constraints.begin(), 00153 E = Constraints.end(); I != E; ) { 00154 ConstraintInfo Info; 00155 00156 // Find the end of this constraint. 00157 std::string::const_iterator ConstraintEnd = std::find(I, E, ','); 00158 00159 if (ConstraintEnd == I || // Empty constraint like ",," 00160 Info.Parse(std::string(I, ConstraintEnd), Result)) { 00161 Result.clear(); // Erroneous constraint? 00162 break; 00163 } 00164 00165 Result.push_back(Info); 00166 00167 // ConstraintEnd may be either the next comma or the end of the string. In 00168 // the former case, we skip the comma. 00169 I = ConstraintEnd; 00170 if (I != E) { 00171 ++I; 00172 if (I == E) { Result.clear(); break; } // don't allow "xyz," 00173 } 00174 } 00175 00176 return Result; 00177 } 00178 00179 00180 /// Verify - Verify that the specified constraint string is reasonable for the 00181 /// specified function type, and otherwise validate the constraint string. 00182 bool InlineAsm::Verify(const FunctionType *Ty, const std::string &ConstStr) { 00183 if (Ty->isVarArg()) return false; 00184 00185 std::vector<ConstraintInfo> Constraints = ParseConstraints(ConstStr); 00186 00187 // Error parsing constraints. 00188 if (Constraints.empty() && !ConstStr.empty()) return false; 00189 00190 unsigned NumOutputs = 0, NumInputs = 0, NumClobbers = 0; 00191 unsigned NumIndirect = 0; 00192 00193 for (unsigned i = 0, e = Constraints.size(); i != e; ++i) { 00194 switch (Constraints[i].Type) { 00195 case InlineAsm::isOutput: 00196 if ((NumInputs-NumIndirect) != 0 || NumClobbers != 0) 00197 return false; // outputs before inputs and clobbers. 00198 if (!Constraints[i].isIndirect) { 00199 ++NumOutputs; 00200 break; 00201 } 00202 ++NumIndirect; 00203 // FALLTHROUGH for Indirect Outputs. 00204 case InlineAsm::isInput: 00205 if (NumClobbers) return false; // inputs before clobbers. 00206 ++NumInputs; 00207 break; 00208 case InlineAsm::isClobber: 00209 ++NumClobbers; 00210 break; 00211 } 00212 } 00213 00214 switch (NumOutputs) { 00215 case 0: 00216 if (Ty->getReturnType() != Type::VoidTy) return false; 00217 break; 00218 case 1: 00219 if (isa<StructType>(Ty->getReturnType())) return false; 00220 break; 00221 default: 00222 const StructType *STy = dyn_cast<StructType>(Ty->getReturnType()); 00223 if (STy == 0 || STy->getNumElements() != NumOutputs) 00224 return false; 00225 break; 00226 } 00227 00228 if (Ty->getNumParams() != NumInputs) return false; 00229 return true; 00230 } 00231