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