Coverage Report

Created: 2020-02-15 09:57

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