Coverage Report

Created: 2017-10-03 07:32

/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/lib/IR/InlineAsm.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- InlineAsm.cpp - Implement the InlineAsm class ----------------------===//
2
//
3
//                     The LLVM Compiler Infrastructure
4
//
5
// This file is distributed under the University of Illinois Open Source
6
// License. See LICENSE.TXT for details.
7
//
8
//===----------------------------------------------------------------------===//
9
//
10
// This file implements the InlineAsm class.
11
//
12
//===----------------------------------------------------------------------===//
13
14
#include "llvm/IR/InlineAsm.h"
15
#include "ConstantsContext.h"
16
#include "LLVMContextImpl.h"
17
#include "llvm/ADT/StringRef.h"
18
#include "llvm/IR/DerivedTypes.h"
19
#include "llvm/IR/LLVMContext.h"
20
#include "llvm/IR/Value.h"
21
#include "llvm/Support/Casting.h"
22
#include "llvm/Support/Compiler.h"
23
#include <algorithm>
24
#include <cassert>
25
#include <cctype>
26
#include <cstddef>
27
#include <cstdlib>
28
29
using namespace llvm;
30
31
InlineAsm::InlineAsm(FunctionType *FTy, const std::string &asmString,
32
                     const std::string &constraints, bool hasSideEffects,
33
                     bool isAlignStack, AsmDialect asmDialect)
34
    : Value(PointerType::getUnqual(FTy), Value::InlineAsmVal),
35
      AsmString(asmString), Constraints(constraints), FTy(FTy),
36
      HasSideEffects(hasSideEffects), IsAlignStack(isAlignStack),
37
4.62k
      Dialect(asmDialect) {
38
4.62k
  // Do various checks on the constraint string and type.
39
4.62k
  assert(Verify(getFunctionType(), constraints) &&
40
4.62k
         "Function type not legal for constraints!");
41
4.62k
}
42
43
InlineAsm *InlineAsm::get(FunctionType *FTy, StringRef AsmString,
44
                          StringRef Constraints, bool hasSideEffects,
45
12.8k
                          bool isAlignStack, AsmDialect asmDialect) {
46
12.8k
  InlineAsmKeyType Key(AsmString, Constraints, FTy, hasSideEffects,
47
12.8k
                       isAlignStack, asmDialect);
48
12.8k
  LLVMContextImpl *pImpl = FTy->getContext().pImpl;
49
12.8k
  return pImpl->InlineAsms.getOrCreate(PointerType::getUnqual(FTy), Key);
50
12.8k
}
51
52
0
void InlineAsm::destroyConstant() {
53
0
  getType()->getContext().pImpl->InlineAsms.remove(this);
54
0
  delete this;
55
0
}
56
57
10.7k
FunctionType *InlineAsm::getFunctionType() const {
58
10.7k
  return FTy;
59
10.7k
}
60
    
61
/// Parse - Analyze the specified string (e.g. "==&{eax}") and fill in the
62
/// fields in this structure.  If the constraint string is not understood,
63
/// return true, otherwise return false.
64
bool InlineAsm::ConstraintInfo::Parse(StringRef Str,
65
249k
                     InlineAsm::ConstraintInfoVector &ConstraintsSoFar) {
66
249k
  StringRef::iterator I = Str.begin(), E = Str.end();
67
249k
  unsigned multipleAlternativeCount = Str.count('|') + 1;
68
249k
  unsigned multipleAlternativeIndex = 0;
69
249k
  ConstraintCodeVector *pCodes = &Codes;
70
249k
71
249k
  // Initialize
72
249k
  isMultipleAlternative = multipleAlternativeCount > 1;
73
249k
  if (
isMultipleAlternative249k
) {
74
1.10k
    multipleAlternatives.resize(multipleAlternativeCount);
75
1.10k
    pCodes = &multipleAlternatives[0].Codes;
76
1.10k
  }
77
249k
  Type = isInput;
78
249k
  isEarlyClobber = false;
79
249k
  MatchingInput = -1;
80
249k
  isCommutative = false;
81
249k
  isIndirect = false;
82
249k
  currentAlternativeIndex = 0;
83
249k
  
84
249k
  // Parse prefixes.
85
249k
  if (
*I == '~'249k
) {
86
221k
    Type = isClobber;
87
221k
    ++I;
88
221k
89
221k
    // '{' must immediately follow '~'.
90
221k
    if (
I != E && 221k
*I != '{'221k
)
91
1
      return true;
92
27.9k
  } else 
if (27.9k
*I == '='27.9k
) {
93
15.5k
    ++I;
94
15.5k
    Type = isOutput;
95
15.5k
  }
96
249k
97
249k
  
if (249k
*I == '*'249k
) {
98
1.59k
    isIndirect = true;
99
1.59k
    ++I;
100
1.59k
  }
101
249k
102
249k
  if (
I == E249k
)
return true0
; // Just a prefix, like "==" or "~".
103
249k
  
104
249k
  // Parse the modifiers.
105
249k
  bool DoneWithModifiers = false;
106
500k
  while (
!DoneWithModifiers500k
) {
107
250k
    switch (*I) {
108
249k
    default:
109
249k
      DoneWithModifiers = true;
110
249k
      break;
111
797
    case '&':     // Early clobber.
112
797
      if (Type != isOutput ||      // Cannot early clobber anything but output.
113
797
          isEarlyClobber)          // Reject &&&&&&
114
0
        return true;
115
797
      isEarlyClobber = true;
116
797
      break;
117
9
    case '%':     // Commutative.
118
9
      if (Type == isClobber ||     // Cannot commute clobbers.
119
9
          isCommutative)           // Reject %%%%%
120
0
        return true;
121
9
      isCommutative = true;
122
9
      break;
123
0
    case '#':     // Comment.
124
0
    case '*':     // Register preferencing.
125
0
      return true;     // Not supported.
126
250k
    }
127
250k
    
128
250k
    
if (250k
!DoneWithModifiers250k
) {
129
806
      ++I;
130
806
      if (
I == E806
)
return true0
; // Just prefixes and modifiers!
131
806
    }
132
250k
  }
133
249k
  
134
249k
  // Parse the various constraints.
135
638k
  
while (249k
I != E638k
) {
136
388k
    if (
*I == '{'388k
) { // Physical register reference.
137
362k
      // Find the end of the register name.
138
362k
      StringRef::iterator ConstraintEnd = std::find(I+1, E, '}');
139
362k
      if (
ConstraintEnd == E362k
)
return true0
; // "{foo"
140
362k
      pCodes->push_back(StringRef(I, ConstraintEnd+1 - I));
141
362k
      I = ConstraintEnd+1;
142
388k
    } else 
if (25.8k
isdigit(static_cast<unsigned char>(*I))25.8k
) { // Matching Constraint
143
879
      // Maximal munch numbers.
144
879
      StringRef::iterator NumStart = I;
145
1.79k
      while (
I != E && 1.79k
isdigit(static_cast<unsigned char>(*I))927
)
146
919
        ++I;
147
879
      pCodes->push_back(StringRef(NumStart, I - NumStart));
148
879
      unsigned N = atoi(pCodes->back().c_str());
149
879
      // Check that this is a valid matching constraint!
150
879
      if (
N >= ConstraintsSoFar.size() || 879
ConstraintsSoFar[N].Type != isOutput879
||
151
879
          Type != isInput)
152
0
        return true;  // Invalid constraint number.
153
879
      
154
879
      // If Operand N already has a matching input, reject this.  An output
155
879
      // can't be constrained to the same value as multiple inputs.
156
879
      
if (879
isMultipleAlternative879
) {
157
1
        if (multipleAlternativeIndex >=
158
1
            ConstraintsSoFar[N].multipleAlternatives.size())
159
1
          return true;
160
0
        InlineAsm::SubConstraintInfo &scInfo =
161
0
          ConstraintsSoFar[N].multipleAlternatives[multipleAlternativeIndex];
162
0
        if (scInfo.MatchingInput != -1)
163
0
          return true;
164
0
        // Note that operand #n has a matching input.
165
0
        scInfo.MatchingInput = ConstraintsSoFar.size();
166
879
      } else {
167
878
        if (ConstraintsSoFar[N].hasMatchingInput() &&
168
4
            (size_t)ConstraintsSoFar[N].MatchingInput !=
169
4
                ConstraintsSoFar.size())
170
0
          return true;
171
878
        // Note that operand #n has a matching input.
172
878
        ConstraintsSoFar[N].MatchingInput = ConstraintsSoFar.size();
173
878
        }
174
25.8k
    } else 
if (25.0k
*I == '|'25.0k
) {
175
1.24k
      multipleAlternativeIndex++;
176
1.24k
      pCodes = &multipleAlternatives[multipleAlternativeIndex].Codes;
177
1.24k
      ++I;
178
25.0k
    } else 
if (23.7k
*I == '^'23.7k
) {
179
396
      // Multi-letter constraint
180
396
      // FIXME: For now assuming these are 2-character constraints.
181
396
      pCodes->push_back(StringRef(I+1, 2));
182
396
      I += 3;
183
23.7k
    } else {
184
23.3k
      // Single letter constraint.
185
23.3k
      pCodes->push_back(StringRef(I, 1));
186
23.3k
      ++I;
187
23.3k
    }
188
388k
  }
189
249k
190
249k
  return false;
191
249k
}
192
193
/// selectAlternative - Point this constraint to the alternative constraint
194
/// indicated by the index.
195
831
void InlineAsm::ConstraintInfo::selectAlternative(unsigned index) {
196
831
  if (
index < multipleAlternatives.size()831
) {
197
831
    currentAlternativeIndex = index;
198
831
    InlineAsm::SubConstraintInfo &scInfo =
199
831
      multipleAlternatives[currentAlternativeIndex];
200
831
    MatchingInput = scInfo.MatchingInput;
201
831
    Codes = scInfo.Codes;
202
831
  }
203
831
}
204
205
InlineAsm::ConstraintInfoVector
206
42.7k
InlineAsm::ParseConstraints(StringRef Constraints) {
207
42.7k
  ConstraintInfoVector Result;
208
42.7k
  
209
42.7k
  // Scan the constraints string.
210
42.7k
  for (StringRef::iterator I = Constraints.begin(),
211
292k
         E = Constraints.end(); 
I != E292k
; ) {
212
249k
    ConstraintInfo Info;
213
249k
214
249k
    // Find the end of this constraint.
215
249k
    StringRef::iterator ConstraintEnd = std::find(I, E, ',');
216
249k
217
249k
    if (ConstraintEnd == I ||  // Empty constraint like ",,"
218
249k
        
Info.Parse(StringRef(I, ConstraintEnd-I), Result)249k
) {
219
2
      Result.clear();          // Erroneous constraint?
220
2
      break;
221
2
    }
222
249k
223
249k
    Result.push_back(Info);
224
249k
    
225
249k
    // ConstraintEnd may be either the next comma or the end of the string.  In
226
249k
    // the former case, we skip the comma.
227
249k
    I = ConstraintEnd;
228
249k
    if (
I != E249k
) {
229
208k
      ++I;
230
208k
      if (
I == E208k
) {
231
0
        Result.clear();
232
0
        break;
233
0
      } // don't allow "xyz,"
234
208k
    }
235
249k
  }
236
42.7k
  
237
42.7k
  return Result;
238
42.7k
}
239
240
/// Verify - Verify that the specified constraint string is reasonable for the
241
/// specified function type, and otherwise validate the constraint string.
242
8.69k
bool InlineAsm::Verify(FunctionType *Ty, StringRef ConstStr) {
243
8.69k
  if (
Ty->isVarArg()8.69k
)
return false0
;
244
8.69k
  
245
8.69k
  ConstraintInfoVector Constraints = ParseConstraints(ConstStr);
246
8.69k
  
247
8.69k
  // Error parsing constraints.
248
8.69k
  if (
Constraints.empty() && 8.69k
!ConstStr.empty()435
)
return false2
;
249
8.69k
  
250
8.69k
  unsigned NumOutputs = 0, NumInputs = 0, NumClobbers = 0;
251
8.69k
  unsigned NumIndirect = 0;
252
8.69k
  
253
62.9k
  for (unsigned i = 0, e = Constraints.size(); 
i != e62.9k
;
++i54.3k
) {
254
54.3k
    switch (Constraints[i].Type) {
255
3.69k
    case InlineAsm::isOutput:
256
3.69k
      if (
(NumInputs-NumIndirect) != 0 || 3.69k
NumClobbers != 03.69k
)
257
0
        return false;  // outputs before inputs and clobbers.
258
3.69k
      
if (3.69k
!Constraints[i].isIndirect3.69k
) {
259
3.47k
        ++NumOutputs;
260
3.47k
        break;
261
3.47k
      }
262
220
      ++NumIndirect;
263
220
      LLVM_FALLTHROUGH; // We fall through for Indirect Outputs.
264
3.23k
    case InlineAsm::isInput:
265
3.23k
      if (
NumClobbers3.23k
)
return false0
; // inputs before clobbers.
266
3.23k
      ++NumInputs;
267
3.23k
      break;
268
47.5k
    case InlineAsm::isClobber:
269
47.5k
      ++NumClobbers;
270
47.5k
      break;
271
54.3k
    }
272
54.3k
  }
273
8.69k
  
274
8.69k
  switch (NumOutputs) {
275
5.47k
  case 0:
276
5.47k
    if (
!Ty->getReturnType()->isVoidTy()5.47k
)
return false0
;
277
5.47k
    break;
278
3.12k
  case 1:
279
3.12k
    if (
Ty->getReturnType()->isStructTy()3.12k
)
return false0
;
280
3.12k
    break;
281
100
  default:
282
100
    StructType *STy = dyn_cast<StructType>(Ty->getReturnType());
283
100
    if (
!STy || 100
STy->getNumElements() != NumOutputs100
)
284
0
      return false;
285
100
    break;
286
8.69k
  }      
287
8.69k
  
288
8.69k
  
if (8.69k
Ty->getNumParams() != NumInputs8.69k
)
return false0
;
289
8.69k
  return true;
290
8.69k
}