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