Coverage Report

Created: 2019-07-24 05:18

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