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