1 //===-- InlineAsm.cpp - Implement the InlineAsm class ---------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file was developed by Chris Lattner and is distributed under the
6 // University of Illinois Open Source License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file implements the InlineAsm class.
12 //===----------------------------------------------------------------------===//
14 #include "llvm/InlineAsm.h"
15 #include "llvm/DerivedTypes.h"
20 // Implement the first virtual method in this class in this file so the
21 // InlineAsm vtable is emitted here.
22 InlineAsm::~InlineAsm() {
26 // NOTE: when memoizing the function type, we have to be careful to handle the
27 // case when the type gets refined.
29 InlineAsm
*InlineAsm::get(const FunctionType
*Ty
, const std::string
&AsmString
,
30 const std::string
&Constraints
, bool hasSideEffects
) {
32 return new InlineAsm(Ty
, AsmString
, Constraints
, hasSideEffects
);
35 InlineAsm::InlineAsm(const FunctionType
*Ty
, const std::string
&asmString
,
36 const std::string
&constraints
, bool hasSideEffects
)
37 : Value(PointerType::get(Ty
), Value::InlineAsmVal
), AsmString(asmString
),
38 Constraints(constraints
), HasSideEffects(hasSideEffects
) {
40 // Do various checks on the constraint string and type.
41 assert(Verify(Ty
, constraints
) && "Function type not legal for constraints!");
44 const FunctionType
*InlineAsm::getFunctionType() const {
45 return cast
<FunctionType
>(getType()->getElementType());
48 /// Parse - Analyze the specified string (e.g. "==&{eax}") and fill in the
49 /// fields in this structure. If the constraint string is not understood,
50 /// return true, otherwise return false.
51 bool InlineAsm::ConstraintInfo::Parse(const std::string
&Str
,
52 std::vector
<InlineAsm::ConstraintInfo
> &ConstraintsSoFar
) {
53 std::string::const_iterator I
= Str
.begin(), E
= Str
.end();
57 isEarlyClobber
= false;
58 hasMatchingInput
= false;
59 isCommutative
= false;
66 } else if (*I
== '=') {
76 if (I
== E
) return true; // Just a prefix, like "==" or "~".
78 // Parse the modifiers.
79 bool DoneWithModifiers
= false;
80 while (!DoneWithModifiers
) {
83 DoneWithModifiers
= true;
85 case '&': // Early clobber.
86 if (Type
!= isOutput
|| // Cannot early clobber anything but output.
87 isEarlyClobber
) // Reject &&&&&&
89 isEarlyClobber
= true;
91 case '%': // Commutative.
92 if (Type
== isClobber
|| // Cannot commute clobbers.
93 isCommutative
) // Reject %%%%%
98 case '*': // Register preferencing.
99 return true; // Not supported.
102 if (!DoneWithModifiers
) {
104 if (I
== E
) return true; // Just prefixes and modifiers!
108 // Parse the various constraints.
110 if (*I
== '{') { // Physical register reference.
111 // Find the end of the register name.
112 std::string::const_iterator ConstraintEnd
= std::find(I
+1, E
, '}');
113 if (ConstraintEnd
== E
) return true; // "{foo"
114 Codes
.push_back(std::string(I
, ConstraintEnd
+1));
116 } else if (isdigit(*I
)) { // Matching Constraint
117 // Maximal munch numbers.
118 std::string::const_iterator NumStart
= I
;
119 while (I
!= E
&& isdigit(*I
))
121 Codes
.push_back(std::string(NumStart
, I
));
122 unsigned N
= atoi(Codes
.back().c_str());
123 // Check that this is a valid matching constraint!
124 if (N
>= ConstraintsSoFar
.size() || ConstraintsSoFar
[N
].Type
!= isOutput
||
126 return true; // Invalid constraint number.
128 // Note that operand #n has a matching input.
129 ConstraintsSoFar
[N
].hasMatchingInput
= true;
131 // Single letter constraint.
132 Codes
.push_back(std::string(I
, I
+1));
140 std::vector
<InlineAsm::ConstraintInfo
>
141 InlineAsm::ParseConstraints(const std::string
&Constraints
) {
142 std::vector
<ConstraintInfo
> Result
;
144 // Scan the constraints string.
145 for (std::string::const_iterator I
= Constraints
.begin(),
146 E
= Constraints
.end(); I
!= E
; ) {
149 // Find the end of this constraint.
150 std::string::const_iterator ConstraintEnd
= std::find(I
, E
, ',');
152 if (ConstraintEnd
== I
|| // Empty constraint like ",,"
153 Info
.Parse(std::string(I
, ConstraintEnd
), Result
)) {
154 Result
.clear(); // Erroneous constraint?
158 Result
.push_back(Info
);
160 // ConstraintEnd may be either the next comma or the end of the string. In
161 // the former case, we skip the comma.
165 if (I
== E
) { Result
.clear(); break; } // don't allow "xyz,"
173 /// Verify - Verify that the specified constraint string is reasonable for the
174 /// specified function type, and otherwise validate the constraint string.
175 bool InlineAsm::Verify(const FunctionType
*Ty
, const std::string
&ConstStr
) {
176 if (Ty
->isVarArg()) return false;
178 std::vector
<ConstraintInfo
> Constraints
= ParseConstraints(ConstStr
);
180 // Error parsing constraints.
181 if (Constraints
.empty() && !ConstStr
.empty()) return false;
183 unsigned NumOutputs
= 0, NumInputs
= 0, NumClobbers
= 0;
185 for (unsigned i
= 0, e
= Constraints
.size(); i
!= e
; ++i
) {
186 switch (Constraints
[i
].Type
) {
187 case InlineAsm::isOutput
:
188 if (!Constraints
[i
].isIndirect
) {
189 if (NumInputs
|| NumClobbers
) return false; // outputs come first.
193 // FALLTHROUGH for Indirect Outputs.
194 case InlineAsm::isInput
:
195 if (NumClobbers
) return false; // inputs before clobbers.
198 case InlineAsm::isClobber
:
204 if (NumOutputs
> 1) return false; // Only one result allowed so far.
206 if ((Ty
->getReturnType() != Type::VoidTy
) != NumOutputs
)
207 return false; // NumOutputs = 1 iff has a result type.
209 if (Ty
->getNumParams() != NumInputs
) return false;
213 DEFINING_FILE_FOR(InlineAsm
)