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