Coverage Report

Created: 2020-09-22 08:39

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/Sema/SemaStmtAsm.cpp
Line
Count
Source (jump to first uncovered line)
1
//===--- SemaStmtAsm.cpp - Semantic Analysis for Asm Statements -----------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
//  This file implements semantic analysis for inline asm statements.
10
//
11
//===----------------------------------------------------------------------===//
12
13
#include "clang/AST/ExprCXX.h"
14
#include "clang/AST/GlobalDecl.h"
15
#include "clang/AST/RecordLayout.h"
16
#include "clang/AST/TypeLoc.h"
17
#include "clang/Basic/TargetInfo.h"
18
#include "clang/Lex/Preprocessor.h"
19
#include "clang/Sema/Initialization.h"
20
#include "clang/Sema/Lookup.h"
21
#include "clang/Sema/Scope.h"
22
#include "clang/Sema/ScopeInfo.h"
23
#include "clang/Sema/SemaInternal.h"
24
#include "llvm/ADT/ArrayRef.h"
25
#include "llvm/ADT/StringSet.h"
26
#include "llvm/MC/MCParser/MCAsmParser.h"
27
using namespace clang;
28
using namespace sema;
29
30
/// Remove the upper-level LValueToRValue cast from an expression.
31
6
static void removeLValueToRValueCast(Expr *E) {
32
6
  Expr *Parent = E;
33
6
  Expr *ExprUnderCast = nullptr;
34
6
  SmallVector<Expr *, 8> ParentsToUpdate;
35
36
7
  while (true) {
37
7
    ParentsToUpdate.push_back(Parent);
38
7
    if (auto *ParenE = dyn_cast<ParenExpr>(Parent)) {
39
1
      Parent = ParenE->getSubExpr();
40
1
      continue;
41
1
    }
42
43
6
    Expr *Child = nullptr;
44
6
    CastExpr *ParentCast = dyn_cast<CastExpr>(Parent);
45
6
    if (ParentCast)
46
6
      Child = ParentCast->getSubExpr();
47
0
    else
48
0
      return;
49
50
6
    if (auto *CastE = dyn_cast<CastExpr>(Child))
51
6
      if (CastE->getCastKind() == CK_LValueToRValue) {
52
6
        ExprUnderCast = CastE->getSubExpr();
53
        // LValueToRValue cast inside GCCAsmStmt requires an explicit cast.
54
6
        ParentCast->setSubExpr(ExprUnderCast);
55
6
        break;
56
6
      }
57
0
    Parent = Child;
58
0
  }
59
60
  // Update parent expressions to have same ValueType as the underlying.
61
6
  assert(ExprUnderCast &&
62
6
         "Should be reachable only if LValueToRValue cast was found!");
63
6
  auto ValueKind = ExprUnderCast->getValueKind();
64
6
  for (Expr *E : ParentsToUpdate)
65
7
    E->setValueKind(ValueKind);
66
6
}
67
68
/// Emit a warning about usage of "noop"-like casts for lvalues (GNU extension)
69
/// and fix the argument with removing LValueToRValue cast from the expression.
70
static void emitAndFixInvalidAsmCastLValue(const Expr *LVal, Expr *BadArgument,
71
6
                                           Sema &S) {
72
6
  if (!S.getLangOpts().HeinousExtensions) {
73
2
    S.Diag(LVal->getBeginLoc(), diag::err_invalid_asm_cast_lvalue)
74
2
        << BadArgument->getSourceRange();
75
4
  } else {
76
4
    S.Diag(LVal->getBeginLoc(), diag::warn_invalid_asm_cast_lvalue)
77
4
        << BadArgument->getSourceRange();
78
4
  }
79
6
  removeLValueToRValueCast(BadArgument);
80
6
}
81
82
/// CheckAsmLValue - GNU C has an extremely ugly extension whereby they silently
83
/// ignore "noop" casts in places where an lvalue is required by an inline asm.
84
/// We emulate this behavior when -fheinous-gnu-extensions is specified, but
85
/// provide a strong guidance to not use it.
86
///
87
/// This method checks to see if the argument is an acceptable l-value and
88
/// returns false if it is a case we can handle.
89
110
static bool CheckAsmLValue(Expr *E, Sema &S) {
90
  // Type dependent expressions will be checked during instantiation.
91
110
  if (E->isTypeDependent())
92
0
    return false;
93
94
110
  if (E->isLValue())
95
106
    return false;  // Cool, this is an lvalue.
96
97
  // Okay, this is not an lvalue, but perhaps it is the result of a cast that we
98
  // are supposed to allow.
99
4
  const Expr *E2 = E->IgnoreParenNoopCasts(S.Context);
100
4
  if (E != E2 && 
E2->isLValue()2
) {
101
2
    emitAndFixInvalidAsmCastLValue(E2, E, S);
102
    // Accept, even if we emitted an error diagnostic.
103
2
    return false;
104
2
  }
105
106
  // None of the above, just randomly invalid non-lvalue.
107
2
  return true;
108
2
}
109
110
/// isOperandMentioned - Return true if the specified operand # is mentioned
111
/// anywhere in the decomposed asm string.
112
static bool
113
isOperandMentioned(unsigned OpNo,
114
41
                   ArrayRef<GCCAsmStmt::AsmStringPiece> AsmStrPieces) {
115
98
  for (unsigned p = 0, e = AsmStrPieces.size(); p != e; 
++p57
) {
116
64
    const GCCAsmStmt::AsmStringPiece &Piece = AsmStrPieces[p];
117
64
    if (!Piece.isOperand())
118
46
      continue;
119
120
    // If this is a reference to the input and if the input was the smaller
121
    // one, then we have to reject this asm.
122
18
    if (Piece.getOperandNo() == OpNo)
123
7
      return true;
124
18
  }
125
34
  return false;
126
41
}
127
128
18.4k
static bool CheckNakedParmReference(Expr *E, Sema &S) {
129
18.4k
  FunctionDecl *Func = dyn_cast<FunctionDecl>(S.CurContext);
130
18.4k
  if (!Func)
131
0
    return false;
132
18.4k
  if (!Func->hasAttr<NakedAttr>())
133
18.4k
    return false;
134
135
9
  SmallVector<Expr*, 4> WorkList;
136
9
  WorkList.push_back(E);
137
15
  while (WorkList.size()) {
138
10
    Expr *E = WorkList.pop_back_val();
139
10
    if (isa<CXXThisExpr>(E)) {
140
1
      S.Diag(E->getBeginLoc(), diag::err_asm_naked_this_ref);
141
1
      S.Diag(Func->getAttr<NakedAttr>()->getLocation(), diag::note_attribute);
142
1
      return true;
143
1
    }
144
9
    if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
145
8
      if (isa<ParmVarDecl>(DRE->getDecl())) {
146
3
        S.Diag(DRE->getBeginLoc(), diag::err_asm_naked_parm_ref);
147
3
        S.Diag(Func->getAttr<NakedAttr>()->getLocation(), diag::note_attribute);
148
3
        return true;
149
3
      }
150
6
    }
151
6
    for (Stmt *Child : E->children()) {
152
1
      if (Expr *E = dyn_cast_or_null<Expr>(Child))
153
1
        WorkList.push_back(E);
154
1
    }
155
6
  }
156
5
  return false;
157
9
}
158
159
/// Returns true if given expression is not compatible with inline
160
/// assembly's memory constraint; false otherwise.
161
static bool checkExprMemoryConstraintCompat(Sema &S, Expr *E,
162
                                            TargetInfo::ConstraintInfo &Info,
163
906
                                            bool is_input_expr) {
164
906
  enum {
165
906
    ExprBitfield = 0,
166
906
    ExprVectorElt,
167
906
    ExprGlobalRegVar,
168
906
    ExprSafeType
169
906
  } EType = ExprSafeType;
170
171
  // Bitfields, vector elements and global register variables are not
172
  // compatible.
173
906
  if (E->refersToBitField())
174
2
    EType = ExprBitfield;
175
904
  else if (E->refersToVectorElement())
176
2
    EType = ExprVectorElt;
177
902
  else if (E->refersToGlobalRegisterVar())
178
2
    EType = ExprGlobalRegVar;
179
180
906
  if (EType != ExprSafeType) {
181
6
    S.Diag(E->getBeginLoc(), diag::err_asm_non_addr_value_in_memory_constraint)
182
6
        << EType << is_input_expr << Info.getConstraintStr()
183
6
        << E->getSourceRange();
184
6
    return true;
185
6
  }
186
187
900
  return false;
188
900
}
189
190
// Extracting the register name from the Expression value,
191
// if there is no register name to extract, returns ""
192
static StringRef extractRegisterName(const Expr *Expression,
193
17.8k
                                     const TargetInfo &Target) {
194
17.8k
  Expression = Expression->IgnoreImpCasts();
195
17.8k
  if (const DeclRefExpr *AsmDeclRef = dyn_cast<DeclRefExpr>(Expression)) {
196
    // Handle cases where the expression is a variable
197
9.53k
    const VarDecl *Variable = dyn_cast<VarDecl>(AsmDeclRef->getDecl());
198
9.53k
    if (Variable && 
Variable->getStorageClass() == SC_Register9.53k
) {
199
654
      if (AsmLabelAttr *Attr = Variable->getAttr<AsmLabelAttr>())
200
75
        if (Target.isValidGCCRegisterName(Attr->getLabel()))
201
75
          return Target.getNormalizedGCCRegisterName(Attr->getLabel(), true);
202
17.8k
    }
203
9.53k
  }
204
17.8k
  return "";
205
17.8k
}
206
207
// Checks if there is a conflict between the input and output lists with the
208
// clobbers list. If there's a conflict, returns the location of the
209
// conflicted clobber, else returns nullptr
210
static SourceLocation
211
getClobberConflictLocation(MultiExprArg Exprs, StringLiteral **Constraints,
212
                           StringLiteral **Clobbers, int NumClobbers,
213
                           unsigned NumLabels,
214
5.49k
                           const TargetInfo &Target, ASTContext &Cont) {
215
5.49k
  llvm::StringSet<> InOutVars;
216
  // Collect all the input and output registers from the extended asm
217
  // statement in order to check for conflicts with the clobber list
218
23.3k
  for (unsigned int i = 0; i < Exprs.size() - NumLabels; 
++i17.8k
) {
219
17.8k
    StringRef Constraint = Constraints[i]->getString();
220
17.8k
    StringRef InOutReg = Target.getConstraintRegister(
221
17.8k
        Constraint, extractRegisterName(Exprs[i], Target));
222
17.8k
    if (InOutReg != "")
223
8.35k
      InOutVars.insert(InOutReg);
224
17.8k
  }
225
  // Check for each item in the clobber list if it conflicts with the input
226
  // or output
227
8.70k
  for (int i = 0; i < NumClobbers; 
++i3.20k
) {
228
3.21k
    StringRef Clobber = Clobbers[i]->getString();
229
    // We only check registers, therefore we don't check cc and memory
230
    // clobbers
231
3.21k
    if (Clobber == "cc" || 
Clobber == "memory"2.22k
)
232
2.10k
      continue;
233
1.10k
    Clobber = Target.getNormalizedGCCRegisterName(Clobber, true);
234
    // Go over the output's registers we collected
235
1.10k
    if (InOutVars.count(Clobber))
236
12
      return Clobbers[i]->getBeginLoc();
237
1.10k
  }
238
5.48k
  return SourceLocation();
239
5.49k
}
240
241
StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
242
                                 bool IsVolatile, unsigned NumOutputs,
243
                                 unsigned NumInputs, IdentifierInfo **Names,
244
                                 MultiExprArg constraints, MultiExprArg Exprs,
245
                                 Expr *asmString, MultiExprArg clobbers,
246
                                 unsigned NumLabels,
247
5.86k
                                 SourceLocation RParenLoc) {
248
5.86k
  unsigned NumClobbers = clobbers.size();
249
5.86k
  StringLiteral **Constraints =
250
5.86k
    reinterpret_cast<StringLiteral**>(constraints.data());
251
5.86k
  StringLiteral *AsmString = cast<StringLiteral>(asmString);
252
5.86k
  StringLiteral **Clobbers = reinterpret_cast<StringLiteral**>(clobbers.data());
253
254
5.86k
  SmallVector<TargetInfo::ConstraintInfo, 4> OutputConstraintInfos;
255
256
  // The parser verifies that there is a string literal here.
257
5.86k
  assert(AsmString->isAscii());
258
259
5.86k
  FunctionDecl *FD = dyn_cast<FunctionDecl>(getCurLexicalContext());
260
5.86k
  llvm::StringMap<bool> FeatureMap;
261
5.86k
  Context.getFunctionFeatureMap(FeatureMap, FD);
262
263
13.3k
  for (unsigned i = 0; i != NumOutputs; 
i++7.50k
) {
264
7.63k
    StringLiteral *Literal = Constraints[i];
265
7.63k
    assert(Literal->isAscii());
266
267
7.63k
    StringRef OutputName;
268
7.63k
    if (Names[i])
269
304
      OutputName = Names[i]->getName();
270
271
7.63k
    TargetInfo::ConstraintInfo Info(Literal->getString(), OutputName);
272
7.63k
    if (!Context.getTargetInfo().validateOutputConstraint(Info)) {
273
86
      targetDiag(Literal->getBeginLoc(),
274
86
                 diag::err_asm_invalid_output_constraint)
275
86
          << Info.getConstraintStr();
276
86
      return new (Context)
277
86
          GCCAsmStmt(Context, AsmLoc, IsSimple, IsVolatile, NumOutputs,
278
86
                     NumInputs, Names, Constraints, Exprs.data(), AsmString,
279
86
                     NumClobbers, Clobbers, NumLabels, RParenLoc);
280
86
    }
281
282
7.55k
    ExprResult ER = CheckPlaceholderExpr(Exprs[i]);
283
7.55k
    if (ER.isInvalid())
284
0
      return StmtError();
285
7.55k
    Exprs[i] = ER.get();
286
287
    // Check that the output exprs are valid lvalues.
288
7.55k
    Expr *OutputExpr = Exprs[i];
289
290
    // Referring to parameters is not allowed in naked functions.
291
7.55k
    if (CheckNakedParmReference(OutputExpr, *this))
292
1
      return StmtError();
293
294
    // Check that the output expression is compatible with memory constraint.
295
7.55k
    if (Info.allowsMemory() &&
296
292
        checkExprMemoryConstraintCompat(*this, OutputExpr, Info, false))
297
3
      return StmtError();
298
299
    // Disallow _ExtInt, since the backends tend to have difficulties with
300
    // non-normal sizes.
301
7.54k
    if (OutputExpr->getType()->isExtIntType())
302
1
      return StmtError(
303
1
          Diag(OutputExpr->getBeginLoc(), diag::err_asm_invalid_type)
304
1
          << OutputExpr->getType() << 0 /*Input*/
305
1
          << OutputExpr->getSourceRange());
306
307
7.54k
    OutputConstraintInfos.push_back(Info);
308
309
    // If this is dependent, just continue.
310
7.54k
    if (OutputExpr->isTypeDependent())
311
2
      continue;
312
313
7.54k
    Expr::isModifiableLvalueResult IsLV =
314
7.54k
        OutputExpr->isModifiableLvalue(Context, /*Loc=*/nullptr);
315
7.54k
    switch (IsLV) {
316
7.53k
    case Expr::MLV_Valid:
317
      // Cool, this is an lvalue.
318
7.53k
      break;
319
2
    case Expr::MLV_ArrayType:
320
      // This is OK too.
321
2
      break;
322
4
    case Expr::MLV_LValueCast: {
323
4
      const Expr *LVal = OutputExpr->IgnoreParenNoopCasts(Context);
324
4
      emitAndFixInvalidAsmCastLValue(LVal, OutputExpr, *this);
325
      // Accept, even if we emitted an error diagnostic.
326
4
      break;
327
0
    }
328
1
    case Expr::MLV_IncompleteType:
329
1
    case Expr::MLV_IncompleteVoidType:
330
1
      if (RequireCompleteType(OutputExpr->getBeginLoc(), Exprs[i]->getType(),
331
1
                              diag::err_dereference_incomplete_type))
332
1
        return StmtError();
333
0
      LLVM_FALLTHROUGH;
334
4
    default:
335
4
      return StmtError(Diag(OutputExpr->getBeginLoc(),
336
4
                            diag::err_asm_invalid_lvalue_in_output)
337
4
                       << OutputExpr->getSourceRange());
338
7.53k
    }
339
340
7.53k
    unsigned Size = Context.getTypeSize(OutputExpr->getType());
341
7.53k
    if (!Context.getTargetInfo().validateOutputSize(
342
35
            FeatureMap, Literal->getString(), Size)) {
343
35
      targetDiag(OutputExpr->getBeginLoc(), diag::err_asm_invalid_output_size)
344
35
          << Info.getConstraintStr();
345
35
      return new (Context)
346
35
          GCCAsmStmt(Context, AsmLoc, IsSimple, IsVolatile, NumOutputs,
347
35
                     NumInputs, Names, Constraints, Exprs.data(), AsmString,
348
35
                     NumClobbers, Clobbers, NumLabels, RParenLoc);
349
35
    }
350
7.53k
  }
351
352
5.73k
  SmallVector<TargetInfo::ConstraintInfo, 4> InputConstraintInfos;
353
354
16.3k
  for (unsigned i = NumOutputs, e = NumOutputs + NumInputs; i != e; 
i++10.6k
) {
355
10.7k
    StringLiteral *Literal = Constraints[i];
356
10.7k
    assert(Literal->isAscii());
357
358
10.7k
    StringRef InputName;
359
10.7k
    if (Names[i])
360
439
      InputName = Names[i]->getName();
361
362
10.7k
    TargetInfo::ConstraintInfo Info(Literal->getString(), InputName);
363
10.7k
    if (!Context.getTargetInfo().validateInputConstraint(OutputConstraintInfos,
364
58
                                                         Info)) {
365
58
      targetDiag(Literal->getBeginLoc(), diag::err_asm_invalid_input_constraint)
366
58
          << Info.getConstraintStr();
367
58
      return new (Context)
368
58
          GCCAsmStmt(Context, AsmLoc, IsSimple, IsVolatile, NumOutputs,
369
58
                     NumInputs, Names, Constraints, Exprs.data(), AsmString,
370
58
                     NumClobbers, Clobbers, NumLabels, RParenLoc);
371
58
    }
372
373
10.7k
    ExprResult ER = CheckPlaceholderExpr(Exprs[i]);
374
10.7k
    if (ER.isInvalid())
375
0
      return StmtError();
376
10.7k
    Exprs[i] = ER.get();
377
378
10.7k
    Expr *InputExpr = Exprs[i];
379
380
    // Referring to parameters is not allowed in naked functions.
381
10.7k
    if (CheckNakedParmReference(InputExpr, *this))
382
2
      return StmtError();
383
384
    // Check that the input expression is compatible with memory constraint.
385
10.7k
    if (Info.allowsMemory() &&
386
614
        checkExprMemoryConstraintCompat(*this, InputExpr, Info, true))
387
3
      return StmtError();
388
389
    // Only allow void types for memory constraints.
390
10.7k
    if (Info.allowsMemory() && 
!Info.allowsRegister()611
) {
391
110
      if (CheckAsmLValue(InputExpr, *this))
392
2
        return StmtError(Diag(InputExpr->getBeginLoc(),
393
2
                              diag::err_asm_invalid_lvalue_in_input)
394
2
                         << Info.getConstraintStr()
395
2
                         << InputExpr->getSourceRange());
396
10.6k
    } else if (Info.requiresImmediateConstant() && 
!Info.allowsRegister()275
) {
397
245
      if (!InputExpr->isValueDependent()) {
398
241
        Expr::EvalResult EVResult;
399
241
        if (InputExpr->EvaluateAsRValue(EVResult, Context, true)) {
400
          // For compatibility with GCC, we also allow pointers that would be
401
          // integral constant expressions if they were cast to int.
402
233
          llvm::APSInt IntResult;
403
233
          if (EVResult.Val.toIntegralConstant(IntResult, InputExpr->getType(),
404
233
                                               Context))
405
233
            if (!Info.isValidAsmImmediate(IntResult))
406
74
              return StmtError(Diag(InputExpr->getBeginLoc(),
407
74
                                    diag::err_invalid_asm_value_for_constraint)
408
74
                               << IntResult.toString(10)
409
74
                               << Info.getConstraintStr()
410
74
                               << InputExpr->getSourceRange());
411
10.3k
        }
412
241
      }
413
414
10.3k
    } else {
415
10.3k
      ExprResult Result = DefaultFunctionArrayLvalueConversion(Exprs[i]);
416
10.3k
      if (Result.isInvalid())
417
0
        return StmtError();
418
419
10.3k
      Exprs[i] = Result.get();
420
10.3k
    }
421
422
10.6k
    if (Info.allowsRegister()) {
423
10.1k
      if (InputExpr->getType()->isVoidType()) {
424
3
        return StmtError(
425
3
            Diag(InputExpr->getBeginLoc(), diag::err_asm_invalid_type_in_input)
426
3
            << InputExpr->getType() << Info.getConstraintStr()
427
3
            << InputExpr->getSourceRange());
428
3
      }
429
10.6k
    }
430
431
10.6k
    if (InputExpr->getType()->isExtIntType())
432
1
      return StmtError(
433
1
          Diag(InputExpr->getBeginLoc(), diag::err_asm_invalid_type)
434
1
          << InputExpr->getType() << 1 /*Output*/
435
1
          << InputExpr->getSourceRange());
436
437
10.6k
    InputConstraintInfos.push_back(Info);
438
439
10.6k
    const Type *Ty = Exprs[i]->getType().getTypePtr();
440
10.6k
    if (Ty->isDependentType())
441
2
      continue;
442
443
10.6k
    if (!Ty->isVoidType() || 
!Info.allowsMemory()1
)
444
10.6k
      if (RequireCompleteType(InputExpr->getBeginLoc(), Exprs[i]->getType(),
445
10.6k
                              diag::err_dereference_incomplete_type))
446
1
        return StmtError();
447
448
10.6k
    unsigned Size = Context.getTypeSize(Ty);
449
10.6k
    if (!Context.getTargetInfo().validateInputSize(FeatureMap,
450
10.6k
                                                   Literal->getString(), Size))
451
35
      return StmtResult(
452
35
          targetDiag(InputExpr->getBeginLoc(), diag::err_asm_invalid_input_size)
453
35
          << Info.getConstraintStr());
454
10.6k
  }
455
456
  // Check that the clobbers are valid.
457
8.77k
  
for (unsigned i = 0; 5.55k
i != NumClobbers;
i++3.22k
) {
458
3.24k
    StringLiteral *Literal = Clobbers[i];
459
3.24k
    assert(Literal->isAscii());
460
461
3.24k
    StringRef Clobber = Literal->getString();
462
463
3.24k
    if (!Context.getTargetInfo().isValidClobber(Clobber)) {
464
24
      targetDiag(Literal->getBeginLoc(), diag::err_asm_unknown_register_name)
465
24
          << Clobber;
466
24
      return new (Context)
467
24
          GCCAsmStmt(Context, AsmLoc, IsSimple, IsVolatile, NumOutputs,
468
24
                     NumInputs, Names, Constraints, Exprs.data(), AsmString,
469
24
                     NumClobbers, Clobbers, NumLabels, RParenLoc);
470
24
    }
471
3.24k
  }
472
473
5.52k
  GCCAsmStmt *NS =
474
5.52k
    new (Context) GCCAsmStmt(Context, AsmLoc, IsSimple, IsVolatile, NumOutputs,
475
5.52k
                             NumInputs, Names, Constraints, Exprs.data(),
476
5.52k
                             AsmString, NumClobbers, Clobbers, NumLabels,
477
5.52k
                             RParenLoc);
478
  // Validate the asm string, ensuring it makes sense given the operands we
479
  // have.
480
5.52k
  SmallVector<GCCAsmStmt::AsmStringPiece, 8> Pieces;
481
5.52k
  unsigned DiagOffs;
482
5.52k
  if (unsigned DiagID = NS->AnalyzeAsmString(Pieces, Context, DiagOffs)) {
483
24
    targetDiag(getLocationOfStringLiteralByte(AsmString, DiagOffs), DiagID)
484
24
        << AsmString->getSourceRange();
485
24
    return NS;
486
24
  }
487
488
  // Validate constraints and modifiers.
489
28.3k
  
for (unsigned i = 0, e = Pieces.size(); 5.50k
i != e;
++i22.8k
) {
490
22.8k
    GCCAsmStmt::AsmStringPiece &Piece = Pieces[i];
491
22.8k
    if (!Piece.isOperand()) 
continue13.1k
;
492
493
    // Look for the correct constraint index.
494
9.63k
    unsigned ConstraintIdx = Piece.getOperandNo();
495
9.63k
    unsigned NumOperands = NS->getNumOutputs() + NS->getNumInputs();
496
    // Labels are the last in the Exprs list.
497
9.63k
    if (NS->isAsmGoto() && 
ConstraintIdx >= NumOperands168
)
498
59
      continue;
499
    // Look for the (ConstraintIdx - NumOperands + 1)th constraint with
500
    // modifier '+'.
501
9.57k
    if (ConstraintIdx >= NumOperands) {
502
3
      unsigned I = 0, E = NS->getNumOutputs();
503
504
3
      for (unsigned Cnt = ConstraintIdx - NumOperands; I != E; 
++I0
)
505
3
        if (OutputConstraintInfos[I].isReadWrite() && Cnt-- == 0) {
506
3
          ConstraintIdx = I;
507
3
          break;
508
3
        }
509
510
3
      assert(I != E && "Invalid operand number should have been caught in "
511
3
                       " AnalyzeAsmString");
512
3
    }
513
514
    // Now that we have the right indexes go ahead and check.
515
9.57k
    StringLiteral *Literal = Constraints[ConstraintIdx];
516
9.57k
    const Type *Ty = Exprs[ConstraintIdx]->getType().getTypePtr();
517
9.57k
    if (Ty->isDependentType() || 
Ty->isIncompleteType()9.57k
)
518
1
      continue;
519
520
9.57k
    unsigned Size = Context.getTypeSize(Ty);
521
9.57k
    std::string SuggestedModifier;
522
9.57k
    if (!Context.getTargetInfo().validateConstraintModifier(
523
9.57k
            Literal->getString(), Piece.getModifier(), Size,
524
24
            SuggestedModifier)) {
525
24
      targetDiag(Exprs[ConstraintIdx]->getBeginLoc(),
526
24
                 diag::warn_asm_mismatched_size_modifier);
527
528
24
      if (!SuggestedModifier.empty()) {
529
16
        auto B = targetDiag(Piece.getRange().getBegin(),
530
16
                            diag::note_asm_missing_constraint_modifier)
531
16
                 << SuggestedModifier;
532
16
        SuggestedModifier = "%" + SuggestedModifier + Piece.getString();
533
16
        B << FixItHint::CreateReplacement(Piece.getRange(), SuggestedModifier);
534
16
      }
535
24
    }
536
9.57k
  }
537
538
  // Validate tied input operands for type mismatches.
539
5.50k
  unsigned NumAlternatives = ~0U;
540
12.8k
  for (unsigned i = 0, e = OutputConstraintInfos.size(); i != e; 
++i7.37k
) {
541
7.37k
    TargetInfo::ConstraintInfo &Info = OutputConstraintInfos[i];
542
7.37k
    StringRef ConstraintStr = Info.getConstraintStr();
543
7.37k
    unsigned AltCount = ConstraintStr.count(',') + 1;
544
7.37k
    if (NumAlternatives == ~0U) {
545
3.92k
      NumAlternatives = AltCount;
546
3.45k
    } else if (NumAlternatives != AltCount) {
547
0
      targetDiag(NS->getOutputExpr(i)->getBeginLoc(),
548
0
                 diag::err_asm_unexpected_constraint_alternatives)
549
0
          << NumAlternatives << AltCount;
550
0
      return NS;
551
0
    }
552
7.37k
  }
553
5.50k
  SmallVector<size_t, 4> InputMatchedToOutput(OutputConstraintInfos.size(),
554
5.50k
                                              ~0U);
555
16.0k
  for (unsigned i = 0, e = InputConstraintInfos.size(); i != e; 
++i10.5k
) {
556
10.5k
    TargetInfo::ConstraintInfo &Info = InputConstraintInfos[i];
557
10.5k
    StringRef ConstraintStr = Info.getConstraintStr();
558
10.5k
    unsigned AltCount = ConstraintStr.count(',') + 1;
559
10.5k
    if (NumAlternatives == ~0U) {
560
368
      NumAlternatives = AltCount;
561
10.1k
    } else if (NumAlternatives != AltCount) {
562
1
      targetDiag(NS->getInputExpr(i)->getBeginLoc(),
563
1
                 diag::err_asm_unexpected_constraint_alternatives)
564
1
          << NumAlternatives << AltCount;
565
1
      return NS;
566
1
    }
567
568
    // If this is a tied constraint, verify that the output and input have
569
    // either exactly the same type, or that they are int/ptr operands with the
570
    // same size (int/long, int*/long, are ok etc).
571
10.5k
    if (!Info.hasTiedOperand()) 
continue10.3k
;
572
573
153
    unsigned TiedTo = Info.getTiedOperand();
574
153
    unsigned InputOpNo = i+NumOutputs;
575
153
    Expr *OutputExpr = Exprs[TiedTo];
576
153
    Expr *InputExpr = Exprs[InputOpNo];
577
578
    // Make sure no more than one input constraint matches each output.
579
153
    assert(TiedTo < InputMatchedToOutput.size() && "TiedTo value out of range");
580
153
    if (InputMatchedToOutput[TiedTo] != ~0U) {
581
1
      targetDiag(NS->getInputExpr(i)->getBeginLoc(),
582
1
                 diag::err_asm_input_duplicate_match)
583
1
          << TiedTo;
584
1
      targetDiag(NS->getInputExpr(InputMatchedToOutput[TiedTo])->getBeginLoc(),
585
1
                 diag::note_asm_input_duplicate_first)
586
1
          << TiedTo;
587
1
      return NS;
588
1
    }
589
152
    InputMatchedToOutput[TiedTo] = i;
590
591
152
    if (OutputExpr->isTypeDependent() || 
InputExpr->isTypeDependent()151
)
592
1
      continue;
593
594
151
    QualType InTy = InputExpr->getType();
595
151
    QualType OutTy = OutputExpr->getType();
596
151
    if (Context.hasSameType(InTy, OutTy))
597
130
      continue;  // All types can be tied to themselves.
598
599
    // Decide if the input and output are in the same domain (integer/ptr or
600
    // floating point.
601
21
    enum AsmDomain {
602
21
      AD_Int, AD_FP, AD_Other
603
21
    } InputDomain, OutputDomain;
604
605
21
    if (InTy->isIntegerType() || 
InTy->isPointerType()9
)
606
14
      InputDomain = AD_Int;
607
7
    else if (InTy->isRealFloatingType())
608
7
      InputDomain = AD_FP;
609
0
    else
610
0
      InputDomain = AD_Other;
611
612
21
    if (OutTy->isIntegerType() || 
OutTy->isPointerType()8
)
613
14
      OutputDomain = AD_Int;
614
7
    else if (OutTy->isRealFloatingType())
615
7
      OutputDomain = AD_FP;
616
0
    else
617
0
      OutputDomain = AD_Other;
618
619
    // They are ok if they are the same size and in the same domain.  This
620
    // allows tying things like:
621
    //   void* to int*
622
    //   void* to int            if they are the same size.
623
    //   double to long double   if they are the same size.
624
    //
625
21
    uint64_t OutSize = Context.getTypeSize(OutTy);
626
21
    uint64_t InSize = Context.getTypeSize(InTy);
627
21
    if (OutSize == InSize && 
InputDomain == OutputDomain2
&&
628
2
        InputDomain != AD_Other)
629
2
      continue;
630
631
    // If the smaller input/output operand is not mentioned in the asm string,
632
    // then we can promote the smaller one to a larger input and the asm string
633
    // won't notice.
634
19
    bool SmallerValueMentioned = false;
635
636
    // If this is a reference to the input and if the input was the smaller
637
    // one, then we have to reject this asm.
638
19
    if (isOperandMentioned(InputOpNo, Pieces)) {
639
      // This is a use in the asm string of the smaller operand.  Since we
640
      // codegen this by promoting to a wider value, the asm will get printed
641
      // "wrong".
642
2
      SmallerValueMentioned |= InSize < OutSize;
643
2
    }
644
19
    if (isOperandMentioned(TiedTo, Pieces)) {
645
      // If this is a reference to the output, and if the output is the larger
646
      // value, then it's ok because we'll promote the input to the larger type.
647
4
      SmallerValueMentioned |= OutSize < InSize;
648
4
    }
649
650
    // If the smaller value wasn't mentioned in the asm string, and if the
651
    // output was a register, just extend the shorter one to the size of the
652
    // larger one.
653
19
    if (!SmallerValueMentioned && 
InputDomain != AD_Other15
&&
654
15
        OutputConstraintInfos[TiedTo].allowsRegister())
655
15
      continue;
656
657
    // Either both of the operands were mentioned or the smaller one was
658
    // mentioned.  One more special case that we'll allow: if the tied input is
659
    // integer, unmentioned, and is a constant, then we'll allow truncating it
660
    // down to the size of the destination.
661
4
    if (InputDomain == AD_Int && 
OutputDomain == AD_Int3
&&
662
3
        !isOperandMentioned(InputOpNo, Pieces) &&
663
2
        InputExpr->isEvaluatable(Context)) {
664
2
      CastKind castKind =
665
1
        (OutTy->isBooleanType() ? CK_IntegralToBoolean : CK_IntegralCast);
666
2
      InputExpr = ImpCastExprToType(InputExpr, OutTy, castKind).get();
667
2
      Exprs[InputOpNo] = InputExpr;
668
2
      NS->setInputExpr(i, InputExpr);
669
2
      continue;
670
2
    }
671
672
2
    targetDiag(InputExpr->getBeginLoc(), diag::err_asm_tying_incompatible_types)
673
2
        << InTy << OutTy << OutputExpr->getSourceRange()
674
2
        << InputExpr->getSourceRange();
675
2
    return NS;
676
2
  }
677
678
  // Check for conflicts between clobber list and input or output lists
679
5.49k
  SourceLocation ConstraintLoc =
680
5.49k
      getClobberConflictLocation(Exprs, Constraints, Clobbers, NumClobbers,
681
5.49k
                                 NumLabels,
682
5.49k
                                 Context.getTargetInfo(), Context);
683
5.49k
  if (ConstraintLoc.isValid())
684
12
    targetDiag(ConstraintLoc, diag::error_inoutput_conflict_with_clobber);
685
686
  // Check for duplicate asm operand name between input, output and label lists.
687
5.49k
  typedef std::pair<StringRef , Expr *> NamedOperand;
688
5.49k
  SmallVector<NamedOperand, 4> NamedOperandList;
689
23.5k
  for (unsigned i = 0, e = NumOutputs + NumInputs + NumLabels; i != e; 
++i18.0k
)
690
18.0k
    if (Names[i])
691
757
      NamedOperandList.emplace_back(
692
757
          std::make_pair(Names[i]->getName(), Exprs[i]));
693
  // Sort NamedOperandList.
694
5.49k
  std::stable_sort(NamedOperandList.begin(), NamedOperandList.end(),
695
649
              [](const NamedOperand &LHS, const NamedOperand &RHS) {
696
649
                return LHS.first < RHS.first;
697
649
              });
698
  // Find adjacent duplicate operand.
699
5.49k
  SmallVector<NamedOperand, 4>::iterator Found =
700
5.49k
      std::adjacent_find(begin(NamedOperandList), end(NamedOperandList),
701
468
                         [](const NamedOperand &LHS, const NamedOperand &RHS) {
702
468
                           return LHS.first == RHS.first;
703
468
                         });
704
5.49k
  if (Found != NamedOperandList.end()) {
705
4
    Diag((Found + 1)->second->getBeginLoc(),
706
4
         diag::error_duplicate_asm_operand_name)
707
4
        << (Found + 1)->first;
708
4
    Diag(Found->second->getBeginLoc(), diag::note_duplicate_asm_operand_name)
709
4
        << Found->first;
710
4
    return StmtError();
711
4
  }
712
5.49k
  if (NS->isAsmGoto())
713
105
    setFunctionHasBranchIntoScope();
714
5.49k
  return NS;
715
5.49k
}
716
717
void Sema::FillInlineAsmIdentifierInfo(Expr *Res,
718
205
                                       llvm::InlineAsmIdentifierInfo &Info) {
719
205
  QualType T = Res->getType();
720
205
  Expr::EvalResult Eval;
721
205
  if (T->isFunctionType() || 
T->isDependentType()194
)
722
12
    return Info.setLabel(Res);
723
193
  if (Res->isRValue()) {
724
22
    bool IsEnum = isa<clang::EnumType>(T);
725
22
    if (DeclRefExpr *DRE = dyn_cast<clang::DeclRefExpr>(Res))
726
19
      if (DRE->getDecl()->getKind() == Decl::EnumConstant)
727
19
        IsEnum = true;
728
22
    if (IsEnum && 
Res->EvaluateAsRValue(Eval, Context)19
)
729
19
      return Info.setEnum(Eval.Val.getInt().getSExtValue());
730
731
3
    return Info.setLabel(Res);
732
3
  }
733
171
  unsigned Size = Context.getTypeSizeInChars(T).getQuantity();
734
171
  unsigned Type = Size;
735
171
  if (const auto *ATy = Context.getAsArrayType(T))
736
41
    Type = Context.getTypeSizeInChars(ATy->getElementType()).getQuantity();
737
171
  bool IsGlobalLV = false;
738
171
  if (Res->EvaluateAsLValue(Eval, Context))
739
35
    IsGlobalLV = Eval.isGlobalLValue();
740
171
  Info.setVar(Res, IsGlobalLV, Size, Type);
741
171
}
742
743
ExprResult Sema::LookupInlineAsmIdentifier(CXXScopeSpec &SS,
744
                                           SourceLocation TemplateKWLoc,
745
                                           UnqualifiedId &Id,
746
227
                                           bool IsUnevaluatedContext) {
747
748
227
  if (IsUnevaluatedContext)
749
33
    PushExpressionEvaluationContext(
750
33
        ExpressionEvaluationContext::UnevaluatedAbstract,
751
33
        ReuseLambdaContextDecl);
752
753
227
  ExprResult Result = ActOnIdExpression(getCurScope(), SS, TemplateKWLoc, Id,
754
227
                                        /*trailing lparen*/ false,
755
227
                                        /*is & operand*/ false,
756
227
                                        /*CorrectionCandidateCallback=*/nullptr,
757
227
                                        /*IsInlineAsmIdentifier=*/ true);
758
759
227
  if (IsUnevaluatedContext)
760
33
    PopExpressionEvaluationContext();
761
762
227
  if (!Result.isUsable()) 
return Result21
;
763
764
206
  Result = CheckPlaceholderExpr(Result.get());
765
206
  if (!Result.isUsable()) 
return Result0
;
766
767
  // Referring to parameters is not allowed in naked functions.
768
206
  if (CheckNakedParmReference(Result.get(), *this))
769
1
    return ExprError();
770
771
205
  QualType T = Result.get()->getType();
772
773
205
  if (T->isDependentType()) {
774
1
    return Result;
775
1
  }
776
777
  // Any sort of function type is fine.
778
204
  if (T->isFunctionType()) {
779
11
    return Result;
780
11
  }
781
782
  // Otherwise, it needs to be a complete type.
783
193
  if (RequireCompleteExprType(Result.get(), diag::err_asm_incomplete_type)) {
784
0
    return ExprError();
785
0
  }
786
787
193
  return Result;
788
193
}
789
790
bool Sema::LookupInlineAsmField(StringRef Base, StringRef Member,
791
25
                                unsigned &Offset, SourceLocation AsmLoc) {
792
25
  Offset = 0;
793
25
  SmallVector<StringRef, 2> Members;
794
25
  Member.split(Members, ".");
795
796
25
  NamedDecl *FoundDecl = nullptr;
797
798
  // MS InlineAsm uses 'this' as a base
799
25
  if (getLangOpts().CPlusPlus && 
Base.equals("this")7
) {
800
1
    if (const Type *PT = getCurrentThisType().getTypePtrOrNull())
801
1
      FoundDecl = PT->getPointeeType()->getAsTagDecl();
802
24
  } else {
803
24
    LookupResult BaseResult(*this, &Context.Idents.get(Base), SourceLocation(),
804
24
                            LookupOrdinaryName);
805
24
    if (LookupName(BaseResult, getCurScope()) && 
BaseResult.isSingleResult()22
)
806
22
      FoundDecl = BaseResult.getFoundDecl();
807
24
  }
808
809
25
  if (!FoundDecl)
810
2
    return true;
811
812
30
  
for (StringRef NextMember : Members)23
{
813
30
    const RecordType *RT = nullptr;
814
30
    if (VarDecl *VD = dyn_cast<VarDecl>(FoundDecl))
815
2
      RT = VD->getType()->getAs<RecordType>();
816
28
    else if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(FoundDecl)) {
817
18
      MarkAnyDeclReferenced(TD->getLocation(), TD, /*OdrUse=*/false);
818
      // MS InlineAsm often uses struct pointer aliases as a base
819
18
      QualType QT = TD->getUnderlyingType();
820
18
      if (const auto *PT = QT->getAs<PointerType>())
821
2
        QT = PT->getPointeeType();
822
18
      RT = QT->getAs<RecordType>();
823
10
    } else if (TypeDecl *TD = dyn_cast<TypeDecl>(FoundDecl))
824
3
      RT = TD->getTypeForDecl()->getAs<RecordType>();
825
7
    else if (FieldDecl *TD = dyn_cast<FieldDecl>(FoundDecl))
826
7
      RT = TD->getType()->getAs<RecordType>();
827
30
    if (!RT)
828
0
      return true;
829
830
30
    if (RequireCompleteType(AsmLoc, QualType(RT, 0),
831
30
                            diag::err_asm_incomplete_type))
832
0
      return true;
833
834
30
    LookupResult FieldResult(*this, &Context.Idents.get(NextMember),
835
30
                             SourceLocation(), LookupMemberName);
836
837
30
    if (!LookupQualifiedName(FieldResult, RT->getDecl()))
838
0
      return true;
839
840
30
    if (!FieldResult.isSingleResult())
841
1
      return true;
842
29
    FoundDecl = FieldResult.getFoundDecl();
843
844
    // FIXME: Handle IndirectFieldDecl?
845
29
    FieldDecl *FD = dyn_cast<FieldDecl>(FoundDecl);
846
29
    if (!FD)
847
0
      return true;
848
849
29
    const ASTRecordLayout &RL = Context.getASTRecordLayout(RT->getDecl());
850
29
    unsigned i = FD->getFieldIndex();
851
29
    CharUnits Result = Context.toCharUnitsFromBits(RL.getFieldOffset(i));
852
29
    Offset += (unsigned)Result.getQuantity();
853
29
  }
854
855
22
  return false;
856
23
}
857
858
ExprResult
859
Sema::LookupInlineAsmVarDeclField(Expr *E, StringRef Member,
860
42
                                  SourceLocation AsmLoc) {
861
862
42
  QualType T = E->getType();
863
42
  if (T->isDependentType()) {
864
2
    DeclarationNameInfo NameInfo;
865
2
    NameInfo.setLoc(AsmLoc);
866
2
    NameInfo.setName(&Context.Idents.get(Member));
867
2
    return CXXDependentScopeMemberExpr::Create(
868
2
        Context, E, T, /*IsArrow=*/false, AsmLoc, NestedNameSpecifierLoc(),
869
2
        SourceLocation(),
870
2
        /*FirstQualifierFoundInScope=*/nullptr, NameInfo, /*TemplateArgs=*/nullptr);
871
2
  }
872
873
40
  const RecordType *RT = T->getAs<RecordType>();
874
  // FIXME: Diagnose this as field access into a scalar type.
875
40
  if (!RT)
876
0
    return ExprResult();
877
878
40
  LookupResult FieldResult(*this, &Context.Idents.get(Member), AsmLoc,
879
40
                           LookupMemberName);
880
881
40
  if (!LookupQualifiedName(FieldResult, RT->getDecl()))
882
2
    return ExprResult();
883
884
  // Only normal and indirect field results will work.
885
38
  ValueDecl *FD = dyn_cast<FieldDecl>(FieldResult.getFoundDecl());
886
38
  if (!FD)
887
3
    FD = dyn_cast<IndirectFieldDecl>(FieldResult.getFoundDecl());
888
38
  if (!FD)
889
1
    return ExprResult();
890
891
  // Make an Expr to thread through OpDecl.
892
37
  ExprResult Result = BuildMemberReferenceExpr(
893
37
      E, E->getType(), AsmLoc, /*IsArrow=*/false, CXXScopeSpec(),
894
37
      SourceLocation(), nullptr, FieldResult, nullptr, nullptr);
895
896
37
  return Result;
897
37
}
898
899
StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc, SourceLocation LBraceLoc,
900
                                ArrayRef<Token> AsmToks,
901
                                StringRef AsmString,
902
                                unsigned NumOutputs, unsigned NumInputs,
903
                                ArrayRef<StringRef> Constraints,
904
                                ArrayRef<StringRef> Clobbers,
905
                                ArrayRef<Expr*> Exprs,
906
218
                                SourceLocation EndLoc) {
907
218
  bool IsSimple = (NumOutputs != 0 || 
NumInputs != 0202
);
908
218
  setFunctionHasBranchProtectedScope();
909
910
360
  for (uint64_t I = 0; I < NumOutputs + NumInputs; 
++I142
) {
911
144
    if (Exprs[I]->getType()->isExtIntType())
912
2
      return StmtError(
913
2
          Diag(Exprs[I]->getBeginLoc(), diag::err_asm_invalid_type)
914
2
          << Exprs[I]->getType() << (I < NumOutputs)
915
2
          << Exprs[I]->getSourceRange());
916
144
  }
917
918
216
  MSAsmStmt *NS =
919
216
    new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, IsSimple,
920
216
                            /*IsVolatile*/ true, AsmToks, NumOutputs, NumInputs,
921
216
                            Constraints, Exprs, AsmString,
922
216
                            Clobbers, EndLoc);
923
216
  return NS;
924
218
}
925
926
LabelDecl *Sema::GetOrCreateMSAsmLabel(StringRef ExternalLabelName,
927
                                       SourceLocation Location,
928
43
                                       bool AlwaysCreate) {
929
43
  LabelDecl* Label = LookupOrCreateLabel(PP.getIdentifierInfo(ExternalLabelName),
930
43
                                         Location);
931
932
43
  if (Label->isMSAsmLabel()) {
933
    // If we have previously created this label implicitly, mark it as used.
934
15
    Label->markUsed(Context);
935
28
  } else {
936
    // Otherwise, insert it, but only resolve it if we have seen the label itself.
937
28
    std::string InternalName;
938
28
    llvm::raw_string_ostream OS(InternalName);
939
    // Create an internal name for the label.  The name should not be a valid
940
    // mangled name, and should be unique.  We use a dot to make the name an
941
    // invalid mangled name. We use LLVM's inline asm ${:uid} escape so that a
942
    // unique label is generated each time this blob is emitted, even after
943
    // inlining or LTO.
944
28
    OS << "__MSASMLABEL_.${:uid}__";
945
211
    for (char C : ExternalLabelName) {
946
211
      OS << C;
947
      // We escape '$' in asm strings by replacing it with "$$"
948
211
      if (C == '$')
949
1
        OS << '$';
950
211
    }
951
28
    Label->setMSAsmLabel(OS.str());
952
28
  }
953
43
  if (AlwaysCreate) {
954
    // The label might have been created implicitly from a previously encountered
955
    // goto statement.  So, for both newly created and looked up labels, we mark
956
    // them as resolved.
957
18
    Label->setMSAsmLabelResolved();
958
18
  }
959
  // Adjust their location for being able to generate accurate diagnostics.
960
43
  Label->setLocation(Location);
961
962
43
  return Label;
963
43
}