1 //===-- InlineAsm.cpp - Implement the InlineAsm class ---------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file implements the InlineAsm class.
12 //===----------------------------------------------------------------------===//
14 #include "llvm/InlineAsm.h"
15 #include "ConstantsContext.h"
16 #include "LLVMContextImpl.h"
17 #include "llvm/DerivedTypes.h"
22 // Implement the first virtual method in this class in this file so the
23 // InlineAsm vtable is emitted here.
24 InlineAsm::~InlineAsm() {
28 InlineAsm
*InlineAsm::get(const FunctionType
*Ty
, StringRef AsmString
,
29 StringRef Constraints
, bool hasSideEffects
,
31 InlineAsmKeyType
Key(AsmString
, Constraints
, hasSideEffects
, isAlignStack
);
32 LLVMContextImpl
*pImpl
= Ty
->getContext().pImpl
;
33 return pImpl
->InlineAsms
.getOrCreate(PointerType::getUnqual(Ty
), Key
);
36 InlineAsm::InlineAsm(const PointerType
*Ty
, const std::string
&asmString
,
37 const std::string
&constraints
, bool hasSideEffects
,
39 : Value(Ty
, Value::InlineAsmVal
),
41 Constraints(constraints
), HasSideEffects(hasSideEffects
),
42 IsAlignStack(isAlignStack
) {
44 // Do various checks on the constraint string and type.
45 assert(Verify(getFunctionType(), constraints
) &&
46 "Function type not legal for constraints!");
49 void InlineAsm::destroyConstant() {
50 getType()->getContext().pImpl
->InlineAsms
.remove(this);
54 const FunctionType
*InlineAsm::getFunctionType() const {
55 return cast
<FunctionType
>(getType()->getElementType());
58 ///Default constructor.
59 InlineAsm::ConstraintInfo::ConstraintInfo() :
60 Type(isInput
), isEarlyClobber(false),
61 MatchingInput(-1), isCommutative(false),
62 isIndirect(false), isMultipleAlternative(false),
63 currentAlternativeIndex(0) {
67 InlineAsm::ConstraintInfo::ConstraintInfo(const ConstraintInfo
&other
) :
68 Type(other
.Type
), isEarlyClobber(other
.isEarlyClobber
),
69 MatchingInput(other
.MatchingInput
), isCommutative(other
.isCommutative
),
70 isIndirect(other
.isIndirect
), Codes(other
.Codes
),
71 isMultipleAlternative(other
.isMultipleAlternative
),
72 multipleAlternatives(other
.multipleAlternatives
),
73 currentAlternativeIndex(other
.currentAlternativeIndex
) {
76 /// Parse - Analyze the specified string (e.g. "==&{eax}") and fill in the
77 /// fields in this structure. If the constraint string is not understood,
78 /// return true, otherwise return false.
79 bool InlineAsm::ConstraintInfo::Parse(StringRef Str
,
80 InlineAsm::ConstraintInfoVector
&ConstraintsSoFar
) {
81 StringRef::iterator I
= Str
.begin(), E
= Str
.end();
82 unsigned multipleAlternativeCount
= Str
.count('|') + 1;
83 unsigned multipleAlternativeIndex
= 0;
84 ConstraintCodeVector
*pCodes
= &Codes
;
87 isMultipleAlternative
= (multipleAlternativeCount
> 1 ? true : false);
88 if (isMultipleAlternative
) {
89 multipleAlternatives
.resize(multipleAlternativeCount
);
90 pCodes
= &multipleAlternatives
[0].Codes
;
93 isEarlyClobber
= false;
95 isCommutative
= false;
97 currentAlternativeIndex
= 0;
103 } else if (*I
== '=') {
113 if (I
== E
) return true; // Just a prefix, like "==" or "~".
115 // Parse the modifiers.
116 bool DoneWithModifiers
= false;
117 while (!DoneWithModifiers
) {
120 DoneWithModifiers
= true;
122 case '&': // Early clobber.
123 if (Type
!= isOutput
|| // Cannot early clobber anything but output.
124 isEarlyClobber
) // Reject &&&&&&
126 isEarlyClobber
= true;
128 case '%': // Commutative.
129 if (Type
== isClobber
|| // Cannot commute clobbers.
130 isCommutative
) // Reject %%%%%
132 isCommutative
= true;
134 case '#': // Comment.
135 case '*': // Register preferencing.
136 return true; // Not supported.
139 if (!DoneWithModifiers
) {
141 if (I
== E
) return true; // Just prefixes and modifiers!
145 // Parse the various constraints.
147 if (*I
== '{') { // Physical register reference.
148 // Find the end of the register name.
149 StringRef::iterator ConstraintEnd
= std::find(I
+1, E
, '}');
150 if (ConstraintEnd
== E
) return true; // "{foo"
151 pCodes
->push_back(std::string(I
, ConstraintEnd
+1));
153 } else if (isdigit(*I
)) { // Matching Constraint
154 // Maximal munch numbers.
155 StringRef::iterator NumStart
= I
;
156 while (I
!= E
&& isdigit(*I
))
158 pCodes
->push_back(std::string(NumStart
, I
));
159 unsigned N
= atoi(pCodes
->back().c_str());
160 // Check that this is a valid matching constraint!
161 if (N
>= ConstraintsSoFar
.size() || ConstraintsSoFar
[N
].Type
!= isOutput
||
163 return true; // Invalid constraint number.
165 // If Operand N already has a matching input, reject this. An output
166 // can't be constrained to the same value as multiple inputs.
167 if (isMultipleAlternative
) {
168 InlineAsm::SubConstraintInfo
&scInfo
=
169 ConstraintsSoFar
[N
].multipleAlternatives
[multipleAlternativeIndex
];
170 if (scInfo
.MatchingInput
!= -1)
172 // Note that operand #n has a matching input.
173 scInfo
.MatchingInput
= ConstraintsSoFar
.size();
175 if (ConstraintsSoFar
[N
].hasMatchingInput())
177 // Note that operand #n has a matching input.
178 ConstraintsSoFar
[N
].MatchingInput
= ConstraintsSoFar
.size();
180 } else if (*I
== '|') {
181 multipleAlternativeIndex
++;
182 pCodes
= &multipleAlternatives
[multipleAlternativeIndex
].Codes
;
184 } else if (*I
== '^') {
185 // Multi-letter constraint
186 // FIXME: For now assuming these are 2-character constraints.
187 pCodes
->push_back(std::string(I
+1, I
+3));
190 // Single letter constraint.
191 pCodes
->push_back(std::string(I
, I
+1));
199 /// selectAlternative - Point this constraint to the alternative constraint
200 /// indicated by the index.
201 void InlineAsm::ConstraintInfo::selectAlternative(unsigned index
) {
202 if (index
< multipleAlternatives
.size()) {
203 currentAlternativeIndex
= index
;
204 InlineAsm::SubConstraintInfo
&scInfo
=
205 multipleAlternatives
[currentAlternativeIndex
];
206 MatchingInput
= scInfo
.MatchingInput
;
207 Codes
= scInfo
.Codes
;
211 InlineAsm::ConstraintInfoVector
212 InlineAsm::ParseConstraints(StringRef Constraints
) {
213 ConstraintInfoVector Result
;
215 // Scan the constraints string.
216 for (StringRef::iterator I
= Constraints
.begin(),
217 E
= Constraints
.end(); I
!= E
; ) {
220 // Find the end of this constraint.
221 StringRef::iterator ConstraintEnd
= std::find(I
, E
, ',');
223 if (ConstraintEnd
== I
|| // Empty constraint like ",,"
224 Info
.Parse(StringRef(I
, ConstraintEnd
-I
), Result
)) {
225 Result
.clear(); // Erroneous constraint?
229 Result
.push_back(Info
);
231 // ConstraintEnd may be either the next comma or the end of the string. In
232 // the former case, we skip the comma.
236 if (I
== E
) { Result
.clear(); break; } // don't allow "xyz,"
243 /// Verify - Verify that the specified constraint string is reasonable for the
244 /// specified function type, and otherwise validate the constraint string.
245 bool InlineAsm::Verify(const FunctionType
*Ty
, StringRef ConstStr
) {
246 if (Ty
->isVarArg()) return false;
248 ConstraintInfoVector Constraints
= ParseConstraints(ConstStr
);
250 // Error parsing constraints.
251 if (Constraints
.empty() && !ConstStr
.empty()) return false;
253 unsigned NumOutputs
= 0, NumInputs
= 0, NumClobbers
= 0;
254 unsigned NumIndirect
= 0;
256 for (unsigned i
= 0, e
= Constraints
.size(); i
!= e
; ++i
) {
257 switch (Constraints
[i
].Type
) {
258 case InlineAsm::isOutput
:
259 if ((NumInputs
-NumIndirect
) != 0 || NumClobbers
!= 0)
260 return false; // outputs before inputs and clobbers.
261 if (!Constraints
[i
].isIndirect
) {
266 // FALLTHROUGH for Indirect Outputs.
267 case InlineAsm::isInput
:
268 if (NumClobbers
) return false; // inputs before clobbers.
271 case InlineAsm::isClobber
:
277 switch (NumOutputs
) {
279 if (!Ty
->getReturnType()->isVoidTy()) return false;
282 if (Ty
->getReturnType()->isStructTy()) return false;
285 const StructType
*STy
= dyn_cast
<StructType
>(Ty
->getReturnType());
286 if (STy
== 0 || STy
->getNumElements() != NumOutputs
)
291 if (Ty
->getNumParams() != NumInputs
) return false;