xref: /aosp_15_r20/external/clang/lib/Sema/SemaStmtAsm.cpp (revision 67e74705e28f6214e480b399dd47ea732279e315)
1*67e74705SXin Li //===--- SemaStmtAsm.cpp - Semantic Analysis for Asm Statements -----------===//
2*67e74705SXin Li //
3*67e74705SXin Li //                     The LLVM Compiler Infrastructure
4*67e74705SXin Li //
5*67e74705SXin Li // This file is distributed under the University of Illinois Open Source
6*67e74705SXin Li // License. See LICENSE.TXT for details.
7*67e74705SXin Li //
8*67e74705SXin Li //===----------------------------------------------------------------------===//
9*67e74705SXin Li //
10*67e74705SXin Li //  This file implements semantic analysis for inline asm statements.
11*67e74705SXin Li //
12*67e74705SXin Li //===----------------------------------------------------------------------===//
13*67e74705SXin Li 
14*67e74705SXin Li #include "clang/Sema/SemaInternal.h"
15*67e74705SXin Li #include "clang/AST/ExprCXX.h"
16*67e74705SXin Li #include "clang/AST/RecordLayout.h"
17*67e74705SXin Li #include "clang/AST/TypeLoc.h"
18*67e74705SXin Li #include "clang/Basic/TargetInfo.h"
19*67e74705SXin Li #include "clang/Lex/Preprocessor.h"
20*67e74705SXin Li #include "clang/Sema/Initialization.h"
21*67e74705SXin Li #include "clang/Sema/Lookup.h"
22*67e74705SXin Li #include "clang/Sema/Scope.h"
23*67e74705SXin Li #include "clang/Sema/ScopeInfo.h"
24*67e74705SXin Li #include "llvm/ADT/ArrayRef.h"
25*67e74705SXin Li #include "llvm/ADT/BitVector.h"
26*67e74705SXin Li #include "llvm/MC/MCParser/MCAsmParser.h"
27*67e74705SXin Li using namespace clang;
28*67e74705SXin Li using namespace sema;
29*67e74705SXin Li 
30*67e74705SXin Li /// CheckAsmLValue - GNU C has an extremely ugly extension whereby they silently
31*67e74705SXin Li /// ignore "noop" casts in places where an lvalue is required by an inline asm.
32*67e74705SXin Li /// We emulate this behavior when -fheinous-gnu-extensions is specified, but
33*67e74705SXin Li /// provide a strong guidance to not use it.
34*67e74705SXin Li ///
35*67e74705SXin Li /// This method checks to see if the argument is an acceptable l-value and
36*67e74705SXin Li /// returns false if it is a case we can handle.
CheckAsmLValue(const Expr * E,Sema & S)37*67e74705SXin Li static bool CheckAsmLValue(const Expr *E, Sema &S) {
38*67e74705SXin Li   // Type dependent expressions will be checked during instantiation.
39*67e74705SXin Li   if (E->isTypeDependent())
40*67e74705SXin Li     return false;
41*67e74705SXin Li 
42*67e74705SXin Li   if (E->isLValue())
43*67e74705SXin Li     return false;  // Cool, this is an lvalue.
44*67e74705SXin Li 
45*67e74705SXin Li   // Okay, this is not an lvalue, but perhaps it is the result of a cast that we
46*67e74705SXin Li   // are supposed to allow.
47*67e74705SXin Li   const Expr *E2 = E->IgnoreParenNoopCasts(S.Context);
48*67e74705SXin Li   if (E != E2 && E2->isLValue()) {
49*67e74705SXin Li     if (!S.getLangOpts().HeinousExtensions)
50*67e74705SXin Li       S.Diag(E2->getLocStart(), diag::err_invalid_asm_cast_lvalue)
51*67e74705SXin Li         << E->getSourceRange();
52*67e74705SXin Li     else
53*67e74705SXin Li       S.Diag(E2->getLocStart(), diag::warn_invalid_asm_cast_lvalue)
54*67e74705SXin Li         << E->getSourceRange();
55*67e74705SXin Li     // Accept, even if we emitted an error diagnostic.
56*67e74705SXin Li     return false;
57*67e74705SXin Li   }
58*67e74705SXin Li 
59*67e74705SXin Li   // None of the above, just randomly invalid non-lvalue.
60*67e74705SXin Li   return true;
61*67e74705SXin Li }
62*67e74705SXin Li 
63*67e74705SXin Li /// isOperandMentioned - Return true if the specified operand # is mentioned
64*67e74705SXin Li /// anywhere in the decomposed asm string.
isOperandMentioned(unsigned OpNo,ArrayRef<GCCAsmStmt::AsmStringPiece> AsmStrPieces)65*67e74705SXin Li static bool isOperandMentioned(unsigned OpNo,
66*67e74705SXin Li                          ArrayRef<GCCAsmStmt::AsmStringPiece> AsmStrPieces) {
67*67e74705SXin Li   for (unsigned p = 0, e = AsmStrPieces.size(); p != e; ++p) {
68*67e74705SXin Li     const GCCAsmStmt::AsmStringPiece &Piece = AsmStrPieces[p];
69*67e74705SXin Li     if (!Piece.isOperand()) continue;
70*67e74705SXin Li 
71*67e74705SXin Li     // If this is a reference to the input and if the input was the smaller
72*67e74705SXin Li     // one, then we have to reject this asm.
73*67e74705SXin Li     if (Piece.getOperandNo() == OpNo)
74*67e74705SXin Li       return true;
75*67e74705SXin Li   }
76*67e74705SXin Li   return false;
77*67e74705SXin Li }
78*67e74705SXin Li 
CheckNakedParmReference(Expr * E,Sema & S)79*67e74705SXin Li static bool CheckNakedParmReference(Expr *E, Sema &S) {
80*67e74705SXin Li   FunctionDecl *Func = dyn_cast<FunctionDecl>(S.CurContext);
81*67e74705SXin Li   if (!Func)
82*67e74705SXin Li     return false;
83*67e74705SXin Li   if (!Func->hasAttr<NakedAttr>())
84*67e74705SXin Li     return false;
85*67e74705SXin Li 
86*67e74705SXin Li   SmallVector<Expr*, 4> WorkList;
87*67e74705SXin Li   WorkList.push_back(E);
88*67e74705SXin Li   while (WorkList.size()) {
89*67e74705SXin Li     Expr *E = WorkList.pop_back_val();
90*67e74705SXin Li     if (isa<CXXThisExpr>(E)) {
91*67e74705SXin Li       S.Diag(E->getLocStart(), diag::err_asm_naked_this_ref);
92*67e74705SXin Li       S.Diag(Func->getAttr<NakedAttr>()->getLocation(), diag::note_attribute);
93*67e74705SXin Li       return true;
94*67e74705SXin Li     }
95*67e74705SXin Li     if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
96*67e74705SXin Li       if (isa<ParmVarDecl>(DRE->getDecl())) {
97*67e74705SXin Li         S.Diag(DRE->getLocStart(), diag::err_asm_naked_parm_ref);
98*67e74705SXin Li         S.Diag(Func->getAttr<NakedAttr>()->getLocation(), diag::note_attribute);
99*67e74705SXin Li         return true;
100*67e74705SXin Li       }
101*67e74705SXin Li     }
102*67e74705SXin Li     for (Stmt *Child : E->children()) {
103*67e74705SXin Li       if (Expr *E = dyn_cast_or_null<Expr>(Child))
104*67e74705SXin Li         WorkList.push_back(E);
105*67e74705SXin Li     }
106*67e74705SXin Li   }
107*67e74705SXin Li   return false;
108*67e74705SXin Li }
109*67e74705SXin Li 
110*67e74705SXin Li /// \brief Returns true if given expression is not compatible with inline
111*67e74705SXin Li /// assembly's memory constraint; false otherwise.
checkExprMemoryConstraintCompat(Sema & S,Expr * E,TargetInfo::ConstraintInfo & Info,bool is_input_expr)112*67e74705SXin Li static bool checkExprMemoryConstraintCompat(Sema &S, Expr *E,
113*67e74705SXin Li                                             TargetInfo::ConstraintInfo &Info,
114*67e74705SXin Li                                             bool is_input_expr) {
115*67e74705SXin Li   enum {
116*67e74705SXin Li     ExprBitfield = 0,
117*67e74705SXin Li     ExprVectorElt,
118*67e74705SXin Li     ExprGlobalRegVar,
119*67e74705SXin Li     ExprSafeType
120*67e74705SXin Li   } EType = ExprSafeType;
121*67e74705SXin Li 
122*67e74705SXin Li   // Bitfields, vector elements and global register variables are not
123*67e74705SXin Li   // compatible.
124*67e74705SXin Li   if (E->refersToBitField())
125*67e74705SXin Li     EType = ExprBitfield;
126*67e74705SXin Li   else if (E->refersToVectorElement())
127*67e74705SXin Li     EType = ExprVectorElt;
128*67e74705SXin Li   else if (E->refersToGlobalRegisterVar())
129*67e74705SXin Li     EType = ExprGlobalRegVar;
130*67e74705SXin Li 
131*67e74705SXin Li   if (EType != ExprSafeType) {
132*67e74705SXin Li     S.Diag(E->getLocStart(), diag::err_asm_non_addr_value_in_memory_constraint)
133*67e74705SXin Li         << EType << is_input_expr << Info.getConstraintStr()
134*67e74705SXin Li         << E->getSourceRange();
135*67e74705SXin Li     return true;
136*67e74705SXin Li   }
137*67e74705SXin Li 
138*67e74705SXin Li   return false;
139*67e74705SXin Li }
140*67e74705SXin Li 
ActOnGCCAsmStmt(SourceLocation AsmLoc,bool IsSimple,bool IsVolatile,unsigned NumOutputs,unsigned NumInputs,IdentifierInfo ** Names,MultiExprArg constraints,MultiExprArg Exprs,Expr * asmString,MultiExprArg clobbers,SourceLocation RParenLoc)141*67e74705SXin Li StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple,
142*67e74705SXin Li                                  bool IsVolatile, unsigned NumOutputs,
143*67e74705SXin Li                                  unsigned NumInputs, IdentifierInfo **Names,
144*67e74705SXin Li                                  MultiExprArg constraints, MultiExprArg Exprs,
145*67e74705SXin Li                                  Expr *asmString, MultiExprArg clobbers,
146*67e74705SXin Li                                  SourceLocation RParenLoc) {
147*67e74705SXin Li   unsigned NumClobbers = clobbers.size();
148*67e74705SXin Li   StringLiteral **Constraints =
149*67e74705SXin Li     reinterpret_cast<StringLiteral**>(constraints.data());
150*67e74705SXin Li   StringLiteral *AsmString = cast<StringLiteral>(asmString);
151*67e74705SXin Li   StringLiteral **Clobbers = reinterpret_cast<StringLiteral**>(clobbers.data());
152*67e74705SXin Li 
153*67e74705SXin Li   SmallVector<TargetInfo::ConstraintInfo, 4> OutputConstraintInfos;
154*67e74705SXin Li 
155*67e74705SXin Li   // The parser verifies that there is a string literal here.
156*67e74705SXin Li   assert(AsmString->isAscii());
157*67e74705SXin Li 
158*67e74705SXin Li   // If we're compiling CUDA file and function attributes indicate that it's not
159*67e74705SXin Li   // for this compilation side, skip all the checks.
160*67e74705SXin Li   if (!DeclAttrsMatchCUDAMode(getLangOpts(), getCurFunctionDecl())) {
161*67e74705SXin Li     GCCAsmStmt *NS = new (Context) GCCAsmStmt(
162*67e74705SXin Li         Context, AsmLoc, IsSimple, IsVolatile, NumOutputs, NumInputs, Names,
163*67e74705SXin Li         Constraints, Exprs.data(), AsmString, NumClobbers, Clobbers, RParenLoc);
164*67e74705SXin Li     return NS;
165*67e74705SXin Li   }
166*67e74705SXin Li 
167*67e74705SXin Li   for (unsigned i = 0; i != NumOutputs; i++) {
168*67e74705SXin Li     StringLiteral *Literal = Constraints[i];
169*67e74705SXin Li     assert(Literal->isAscii());
170*67e74705SXin Li 
171*67e74705SXin Li     StringRef OutputName;
172*67e74705SXin Li     if (Names[i])
173*67e74705SXin Li       OutputName = Names[i]->getName();
174*67e74705SXin Li 
175*67e74705SXin Li     TargetInfo::ConstraintInfo Info(Literal->getString(), OutputName);
176*67e74705SXin Li     if (!Context.getTargetInfo().validateOutputConstraint(Info))
177*67e74705SXin Li       return StmtError(Diag(Literal->getLocStart(),
178*67e74705SXin Li                             diag::err_asm_invalid_output_constraint)
179*67e74705SXin Li                        << Info.getConstraintStr());
180*67e74705SXin Li 
181*67e74705SXin Li     ExprResult ER = CheckPlaceholderExpr(Exprs[i]);
182*67e74705SXin Li     if (ER.isInvalid())
183*67e74705SXin Li       return StmtError();
184*67e74705SXin Li     Exprs[i] = ER.get();
185*67e74705SXin Li 
186*67e74705SXin Li     // Check that the output exprs are valid lvalues.
187*67e74705SXin Li     Expr *OutputExpr = Exprs[i];
188*67e74705SXin Li 
189*67e74705SXin Li     // Referring to parameters is not allowed in naked functions.
190*67e74705SXin Li     if (CheckNakedParmReference(OutputExpr, *this))
191*67e74705SXin Li       return StmtError();
192*67e74705SXin Li 
193*67e74705SXin Li     // Check that the output expression is compatible with memory constraint.
194*67e74705SXin Li     if (Info.allowsMemory() &&
195*67e74705SXin Li         checkExprMemoryConstraintCompat(*this, OutputExpr, Info, false))
196*67e74705SXin Li       return StmtError();
197*67e74705SXin Li 
198*67e74705SXin Li     OutputConstraintInfos.push_back(Info);
199*67e74705SXin Li 
200*67e74705SXin Li     // If this is dependent, just continue.
201*67e74705SXin Li     if (OutputExpr->isTypeDependent())
202*67e74705SXin Li       continue;
203*67e74705SXin Li 
204*67e74705SXin Li     Expr::isModifiableLvalueResult IsLV =
205*67e74705SXin Li         OutputExpr->isModifiableLvalue(Context, /*Loc=*/nullptr);
206*67e74705SXin Li     switch (IsLV) {
207*67e74705SXin Li     case Expr::MLV_Valid:
208*67e74705SXin Li       // Cool, this is an lvalue.
209*67e74705SXin Li       break;
210*67e74705SXin Li     case Expr::MLV_ArrayType:
211*67e74705SXin Li       // This is OK too.
212*67e74705SXin Li       break;
213*67e74705SXin Li     case Expr::MLV_LValueCast: {
214*67e74705SXin Li       const Expr *LVal = OutputExpr->IgnoreParenNoopCasts(Context);
215*67e74705SXin Li       if (!getLangOpts().HeinousExtensions) {
216*67e74705SXin Li         Diag(LVal->getLocStart(), diag::err_invalid_asm_cast_lvalue)
217*67e74705SXin Li             << OutputExpr->getSourceRange();
218*67e74705SXin Li       } else {
219*67e74705SXin Li         Diag(LVal->getLocStart(), diag::warn_invalid_asm_cast_lvalue)
220*67e74705SXin Li             << OutputExpr->getSourceRange();
221*67e74705SXin Li       }
222*67e74705SXin Li       // Accept, even if we emitted an error diagnostic.
223*67e74705SXin Li       break;
224*67e74705SXin Li     }
225*67e74705SXin Li     case Expr::MLV_IncompleteType:
226*67e74705SXin Li     case Expr::MLV_IncompleteVoidType:
227*67e74705SXin Li       if (RequireCompleteType(OutputExpr->getLocStart(), Exprs[i]->getType(),
228*67e74705SXin Li                               diag::err_dereference_incomplete_type))
229*67e74705SXin Li         return StmtError();
230*67e74705SXin Li     default:
231*67e74705SXin Li       return StmtError(Diag(OutputExpr->getLocStart(),
232*67e74705SXin Li                             diag::err_asm_invalid_lvalue_in_output)
233*67e74705SXin Li                        << OutputExpr->getSourceRange());
234*67e74705SXin Li     }
235*67e74705SXin Li 
236*67e74705SXin Li     unsigned Size = Context.getTypeSize(OutputExpr->getType());
237*67e74705SXin Li     if (!Context.getTargetInfo().validateOutputSize(Literal->getString(),
238*67e74705SXin Li                                                     Size))
239*67e74705SXin Li       return StmtError(Diag(OutputExpr->getLocStart(),
240*67e74705SXin Li                             diag::err_asm_invalid_output_size)
241*67e74705SXin Li                        << Info.getConstraintStr());
242*67e74705SXin Li   }
243*67e74705SXin Li 
244*67e74705SXin Li   SmallVector<TargetInfo::ConstraintInfo, 4> InputConstraintInfos;
245*67e74705SXin Li 
246*67e74705SXin Li   for (unsigned i = NumOutputs, e = NumOutputs + NumInputs; i != e; i++) {
247*67e74705SXin Li     StringLiteral *Literal = Constraints[i];
248*67e74705SXin Li     assert(Literal->isAscii());
249*67e74705SXin Li 
250*67e74705SXin Li     StringRef InputName;
251*67e74705SXin Li     if (Names[i])
252*67e74705SXin Li       InputName = Names[i]->getName();
253*67e74705SXin Li 
254*67e74705SXin Li     TargetInfo::ConstraintInfo Info(Literal->getString(), InputName);
255*67e74705SXin Li     if (!Context.getTargetInfo().validateInputConstraint(OutputConstraintInfos,
256*67e74705SXin Li                                                          Info)) {
257*67e74705SXin Li       return StmtError(Diag(Literal->getLocStart(),
258*67e74705SXin Li                             diag::err_asm_invalid_input_constraint)
259*67e74705SXin Li                        << Info.getConstraintStr());
260*67e74705SXin Li     }
261*67e74705SXin Li 
262*67e74705SXin Li     ExprResult ER = CheckPlaceholderExpr(Exprs[i]);
263*67e74705SXin Li     if (ER.isInvalid())
264*67e74705SXin Li       return StmtError();
265*67e74705SXin Li     Exprs[i] = ER.get();
266*67e74705SXin Li 
267*67e74705SXin Li     Expr *InputExpr = Exprs[i];
268*67e74705SXin Li 
269*67e74705SXin Li     // Referring to parameters is not allowed in naked functions.
270*67e74705SXin Li     if (CheckNakedParmReference(InputExpr, *this))
271*67e74705SXin Li       return StmtError();
272*67e74705SXin Li 
273*67e74705SXin Li     // Check that the input expression is compatible with memory constraint.
274*67e74705SXin Li     if (Info.allowsMemory() &&
275*67e74705SXin Li         checkExprMemoryConstraintCompat(*this, InputExpr, Info, true))
276*67e74705SXin Li       return StmtError();
277*67e74705SXin Li 
278*67e74705SXin Li     // Only allow void types for memory constraints.
279*67e74705SXin Li     if (Info.allowsMemory() && !Info.allowsRegister()) {
280*67e74705SXin Li       if (CheckAsmLValue(InputExpr, *this))
281*67e74705SXin Li         return StmtError(Diag(InputExpr->getLocStart(),
282*67e74705SXin Li                               diag::err_asm_invalid_lvalue_in_input)
283*67e74705SXin Li                          << Info.getConstraintStr()
284*67e74705SXin Li                          << InputExpr->getSourceRange());
285*67e74705SXin Li     } else if (Info.requiresImmediateConstant() && !Info.allowsRegister()) {
286*67e74705SXin Li       if (!InputExpr->isValueDependent()) {
287*67e74705SXin Li         llvm::APSInt Result;
288*67e74705SXin Li         if (!InputExpr->EvaluateAsInt(Result, Context))
289*67e74705SXin Li            return StmtError(
290*67e74705SXin Li                Diag(InputExpr->getLocStart(), diag::err_asm_immediate_expected)
291*67e74705SXin Li                 << Info.getConstraintStr() << InputExpr->getSourceRange());
292*67e74705SXin Li          if (!Info.isValidAsmImmediate(Result))
293*67e74705SXin Li            return StmtError(Diag(InputExpr->getLocStart(),
294*67e74705SXin Li                                  diag::err_invalid_asm_value_for_constraint)
295*67e74705SXin Li                             << Result.toString(10) << Info.getConstraintStr()
296*67e74705SXin Li                             << InputExpr->getSourceRange());
297*67e74705SXin Li       }
298*67e74705SXin Li 
299*67e74705SXin Li     } else {
300*67e74705SXin Li       ExprResult Result = DefaultFunctionArrayLvalueConversion(Exprs[i]);
301*67e74705SXin Li       if (Result.isInvalid())
302*67e74705SXin Li         return StmtError();
303*67e74705SXin Li 
304*67e74705SXin Li       Exprs[i] = Result.get();
305*67e74705SXin Li     }
306*67e74705SXin Li 
307*67e74705SXin Li     if (Info.allowsRegister()) {
308*67e74705SXin Li       if (InputExpr->getType()->isVoidType()) {
309*67e74705SXin Li         return StmtError(Diag(InputExpr->getLocStart(),
310*67e74705SXin Li                               diag::err_asm_invalid_type_in_input)
311*67e74705SXin Li           << InputExpr->getType() << Info.getConstraintStr()
312*67e74705SXin Li           << InputExpr->getSourceRange());
313*67e74705SXin Li       }
314*67e74705SXin Li     }
315*67e74705SXin Li 
316*67e74705SXin Li     InputConstraintInfos.push_back(Info);
317*67e74705SXin Li 
318*67e74705SXin Li     const Type *Ty = Exprs[i]->getType().getTypePtr();
319*67e74705SXin Li     if (Ty->isDependentType())
320*67e74705SXin Li       continue;
321*67e74705SXin Li 
322*67e74705SXin Li     if (!Ty->isVoidType() || !Info.allowsMemory())
323*67e74705SXin Li       if (RequireCompleteType(InputExpr->getLocStart(), Exprs[i]->getType(),
324*67e74705SXin Li                               diag::err_dereference_incomplete_type))
325*67e74705SXin Li         return StmtError();
326*67e74705SXin Li 
327*67e74705SXin Li     unsigned Size = Context.getTypeSize(Ty);
328*67e74705SXin Li     if (!Context.getTargetInfo().validateInputSize(Literal->getString(),
329*67e74705SXin Li                                                    Size))
330*67e74705SXin Li       return StmtError(Diag(InputExpr->getLocStart(),
331*67e74705SXin Li                             diag::err_asm_invalid_input_size)
332*67e74705SXin Li                        << Info.getConstraintStr());
333*67e74705SXin Li   }
334*67e74705SXin Li 
335*67e74705SXin Li   // Check that the clobbers are valid.
336*67e74705SXin Li   for (unsigned i = 0; i != NumClobbers; i++) {
337*67e74705SXin Li     StringLiteral *Literal = Clobbers[i];
338*67e74705SXin Li     assert(Literal->isAscii());
339*67e74705SXin Li 
340*67e74705SXin Li     StringRef Clobber = Literal->getString();
341*67e74705SXin Li 
342*67e74705SXin Li     if (!Context.getTargetInfo().isValidClobber(Clobber))
343*67e74705SXin Li       return StmtError(Diag(Literal->getLocStart(),
344*67e74705SXin Li                   diag::err_asm_unknown_register_name) << Clobber);
345*67e74705SXin Li   }
346*67e74705SXin Li 
347*67e74705SXin Li   GCCAsmStmt *NS =
348*67e74705SXin Li     new (Context) GCCAsmStmt(Context, AsmLoc, IsSimple, IsVolatile, NumOutputs,
349*67e74705SXin Li                              NumInputs, Names, Constraints, Exprs.data(),
350*67e74705SXin Li                              AsmString, NumClobbers, Clobbers, RParenLoc);
351*67e74705SXin Li   // Validate the asm string, ensuring it makes sense given the operands we
352*67e74705SXin Li   // have.
353*67e74705SXin Li   SmallVector<GCCAsmStmt::AsmStringPiece, 8> Pieces;
354*67e74705SXin Li   unsigned DiagOffs;
355*67e74705SXin Li   if (unsigned DiagID = NS->AnalyzeAsmString(Pieces, Context, DiagOffs)) {
356*67e74705SXin Li     Diag(getLocationOfStringLiteralByte(AsmString, DiagOffs), DiagID)
357*67e74705SXin Li            << AsmString->getSourceRange();
358*67e74705SXin Li     return StmtError();
359*67e74705SXin Li   }
360*67e74705SXin Li 
361*67e74705SXin Li   // Validate constraints and modifiers.
362*67e74705SXin Li   for (unsigned i = 0, e = Pieces.size(); i != e; ++i) {
363*67e74705SXin Li     GCCAsmStmt::AsmStringPiece &Piece = Pieces[i];
364*67e74705SXin Li     if (!Piece.isOperand()) continue;
365*67e74705SXin Li 
366*67e74705SXin Li     // Look for the correct constraint index.
367*67e74705SXin Li     unsigned ConstraintIdx = Piece.getOperandNo();
368*67e74705SXin Li     unsigned NumOperands = NS->getNumOutputs() + NS->getNumInputs();
369*67e74705SXin Li 
370*67e74705SXin Li     // Look for the (ConstraintIdx - NumOperands + 1)th constraint with
371*67e74705SXin Li     // modifier '+'.
372*67e74705SXin Li     if (ConstraintIdx >= NumOperands) {
373*67e74705SXin Li       unsigned I = 0, E = NS->getNumOutputs();
374*67e74705SXin Li 
375*67e74705SXin Li       for (unsigned Cnt = ConstraintIdx - NumOperands; I != E; ++I)
376*67e74705SXin Li         if (OutputConstraintInfos[I].isReadWrite() && Cnt-- == 0) {
377*67e74705SXin Li           ConstraintIdx = I;
378*67e74705SXin Li           break;
379*67e74705SXin Li         }
380*67e74705SXin Li 
381*67e74705SXin Li       assert(I != E && "Invalid operand number should have been caught in "
382*67e74705SXin Li                        " AnalyzeAsmString");
383*67e74705SXin Li     }
384*67e74705SXin Li 
385*67e74705SXin Li     // Now that we have the right indexes go ahead and check.
386*67e74705SXin Li     StringLiteral *Literal = Constraints[ConstraintIdx];
387*67e74705SXin Li     const Type *Ty = Exprs[ConstraintIdx]->getType().getTypePtr();
388*67e74705SXin Li     if (Ty->isDependentType() || Ty->isIncompleteType())
389*67e74705SXin Li       continue;
390*67e74705SXin Li 
391*67e74705SXin Li     unsigned Size = Context.getTypeSize(Ty);
392*67e74705SXin Li     std::string SuggestedModifier;
393*67e74705SXin Li     if (!Context.getTargetInfo().validateConstraintModifier(
394*67e74705SXin Li             Literal->getString(), Piece.getModifier(), Size,
395*67e74705SXin Li             SuggestedModifier)) {
396*67e74705SXin Li       Diag(Exprs[ConstraintIdx]->getLocStart(),
397*67e74705SXin Li            diag::warn_asm_mismatched_size_modifier);
398*67e74705SXin Li 
399*67e74705SXin Li       if (!SuggestedModifier.empty()) {
400*67e74705SXin Li         auto B = Diag(Piece.getRange().getBegin(),
401*67e74705SXin Li                       diag::note_asm_missing_constraint_modifier)
402*67e74705SXin Li                  << SuggestedModifier;
403*67e74705SXin Li         SuggestedModifier = "%" + SuggestedModifier + Piece.getString();
404*67e74705SXin Li         B.AddFixItHint(FixItHint::CreateReplacement(Piece.getRange(),
405*67e74705SXin Li                                                     SuggestedModifier));
406*67e74705SXin Li       }
407*67e74705SXin Li     }
408*67e74705SXin Li   }
409*67e74705SXin Li 
410*67e74705SXin Li   // Validate tied input operands for type mismatches.
411*67e74705SXin Li   unsigned NumAlternatives = ~0U;
412*67e74705SXin Li   for (unsigned i = 0, e = OutputConstraintInfos.size(); i != e; ++i) {
413*67e74705SXin Li     TargetInfo::ConstraintInfo &Info = OutputConstraintInfos[i];
414*67e74705SXin Li     StringRef ConstraintStr = Info.getConstraintStr();
415*67e74705SXin Li     unsigned AltCount = ConstraintStr.count(',') + 1;
416*67e74705SXin Li     if (NumAlternatives == ~0U)
417*67e74705SXin Li       NumAlternatives = AltCount;
418*67e74705SXin Li     else if (NumAlternatives != AltCount)
419*67e74705SXin Li       return StmtError(Diag(NS->getOutputExpr(i)->getLocStart(),
420*67e74705SXin Li                             diag::err_asm_unexpected_constraint_alternatives)
421*67e74705SXin Li                        << NumAlternatives << AltCount);
422*67e74705SXin Li   }
423*67e74705SXin Li   SmallVector<size_t, 4> InputMatchedToOutput(OutputConstraintInfos.size(),
424*67e74705SXin Li                                               ~0U);
425*67e74705SXin Li   for (unsigned i = 0, e = InputConstraintInfos.size(); i != e; ++i) {
426*67e74705SXin Li     TargetInfo::ConstraintInfo &Info = InputConstraintInfos[i];
427*67e74705SXin Li     StringRef ConstraintStr = Info.getConstraintStr();
428*67e74705SXin Li     unsigned AltCount = ConstraintStr.count(',') + 1;
429*67e74705SXin Li     if (NumAlternatives == ~0U)
430*67e74705SXin Li       NumAlternatives = AltCount;
431*67e74705SXin Li     else if (NumAlternatives != AltCount)
432*67e74705SXin Li       return StmtError(Diag(NS->getInputExpr(i)->getLocStart(),
433*67e74705SXin Li                             diag::err_asm_unexpected_constraint_alternatives)
434*67e74705SXin Li                        << NumAlternatives << AltCount);
435*67e74705SXin Li 
436*67e74705SXin Li     // If this is a tied constraint, verify that the output and input have
437*67e74705SXin Li     // either exactly the same type, or that they are int/ptr operands with the
438*67e74705SXin Li     // same size (int/long, int*/long, are ok etc).
439*67e74705SXin Li     if (!Info.hasTiedOperand()) continue;
440*67e74705SXin Li 
441*67e74705SXin Li     unsigned TiedTo = Info.getTiedOperand();
442*67e74705SXin Li     unsigned InputOpNo = i+NumOutputs;
443*67e74705SXin Li     Expr *OutputExpr = Exprs[TiedTo];
444*67e74705SXin Li     Expr *InputExpr = Exprs[InputOpNo];
445*67e74705SXin Li 
446*67e74705SXin Li     // Make sure no more than one input constraint matches each output.
447*67e74705SXin Li     assert(TiedTo < InputMatchedToOutput.size() && "TiedTo value out of range");
448*67e74705SXin Li     if (InputMatchedToOutput[TiedTo] != ~0U) {
449*67e74705SXin Li       Diag(NS->getInputExpr(i)->getLocStart(),
450*67e74705SXin Li            diag::err_asm_input_duplicate_match)
451*67e74705SXin Li           << TiedTo;
452*67e74705SXin Li       Diag(NS->getInputExpr(InputMatchedToOutput[TiedTo])->getLocStart(),
453*67e74705SXin Li            diag::note_asm_input_duplicate_first)
454*67e74705SXin Li           << TiedTo;
455*67e74705SXin Li       return StmtError();
456*67e74705SXin Li     }
457*67e74705SXin Li     InputMatchedToOutput[TiedTo] = i;
458*67e74705SXin Li 
459*67e74705SXin Li     if (OutputExpr->isTypeDependent() || InputExpr->isTypeDependent())
460*67e74705SXin Li       continue;
461*67e74705SXin Li 
462*67e74705SXin Li     QualType InTy = InputExpr->getType();
463*67e74705SXin Li     QualType OutTy = OutputExpr->getType();
464*67e74705SXin Li     if (Context.hasSameType(InTy, OutTy))
465*67e74705SXin Li       continue;  // All types can be tied to themselves.
466*67e74705SXin Li 
467*67e74705SXin Li     // Decide if the input and output are in the same domain (integer/ptr or
468*67e74705SXin Li     // floating point.
469*67e74705SXin Li     enum AsmDomain {
470*67e74705SXin Li       AD_Int, AD_FP, AD_Other
471*67e74705SXin Li     } InputDomain, OutputDomain;
472*67e74705SXin Li 
473*67e74705SXin Li     if (InTy->isIntegerType() || InTy->isPointerType())
474*67e74705SXin Li       InputDomain = AD_Int;
475*67e74705SXin Li     else if (InTy->isRealFloatingType())
476*67e74705SXin Li       InputDomain = AD_FP;
477*67e74705SXin Li     else
478*67e74705SXin Li       InputDomain = AD_Other;
479*67e74705SXin Li 
480*67e74705SXin Li     if (OutTy->isIntegerType() || OutTy->isPointerType())
481*67e74705SXin Li       OutputDomain = AD_Int;
482*67e74705SXin Li     else if (OutTy->isRealFloatingType())
483*67e74705SXin Li       OutputDomain = AD_FP;
484*67e74705SXin Li     else
485*67e74705SXin Li       OutputDomain = AD_Other;
486*67e74705SXin Li 
487*67e74705SXin Li     // They are ok if they are the same size and in the same domain.  This
488*67e74705SXin Li     // allows tying things like:
489*67e74705SXin Li     //   void* to int*
490*67e74705SXin Li     //   void* to int            if they are the same size.
491*67e74705SXin Li     //   double to long double   if they are the same size.
492*67e74705SXin Li     //
493*67e74705SXin Li     uint64_t OutSize = Context.getTypeSize(OutTy);
494*67e74705SXin Li     uint64_t InSize = Context.getTypeSize(InTy);
495*67e74705SXin Li     if (OutSize == InSize && InputDomain == OutputDomain &&
496*67e74705SXin Li         InputDomain != AD_Other)
497*67e74705SXin Li       continue;
498*67e74705SXin Li 
499*67e74705SXin Li     // If the smaller input/output operand is not mentioned in the asm string,
500*67e74705SXin Li     // then we can promote the smaller one to a larger input and the asm string
501*67e74705SXin Li     // won't notice.
502*67e74705SXin Li     bool SmallerValueMentioned = false;
503*67e74705SXin Li 
504*67e74705SXin Li     // If this is a reference to the input and if the input was the smaller
505*67e74705SXin Li     // one, then we have to reject this asm.
506*67e74705SXin Li     if (isOperandMentioned(InputOpNo, Pieces)) {
507*67e74705SXin Li       // This is a use in the asm string of the smaller operand.  Since we
508*67e74705SXin Li       // codegen this by promoting to a wider value, the asm will get printed
509*67e74705SXin Li       // "wrong".
510*67e74705SXin Li       SmallerValueMentioned |= InSize < OutSize;
511*67e74705SXin Li     }
512*67e74705SXin Li     if (isOperandMentioned(TiedTo, Pieces)) {
513*67e74705SXin Li       // If this is a reference to the output, and if the output is the larger
514*67e74705SXin Li       // value, then it's ok because we'll promote the input to the larger type.
515*67e74705SXin Li       SmallerValueMentioned |= OutSize < InSize;
516*67e74705SXin Li     }
517*67e74705SXin Li 
518*67e74705SXin Li     // If the smaller value wasn't mentioned in the asm string, and if the
519*67e74705SXin Li     // output was a register, just extend the shorter one to the size of the
520*67e74705SXin Li     // larger one.
521*67e74705SXin Li     if (!SmallerValueMentioned && InputDomain != AD_Other &&
522*67e74705SXin Li         OutputConstraintInfos[TiedTo].allowsRegister())
523*67e74705SXin Li       continue;
524*67e74705SXin Li 
525*67e74705SXin Li     // Either both of the operands were mentioned or the smaller one was
526*67e74705SXin Li     // mentioned.  One more special case that we'll allow: if the tied input is
527*67e74705SXin Li     // integer, unmentioned, and is a constant, then we'll allow truncating it
528*67e74705SXin Li     // down to the size of the destination.
529*67e74705SXin Li     if (InputDomain == AD_Int && OutputDomain == AD_Int &&
530*67e74705SXin Li         !isOperandMentioned(InputOpNo, Pieces) &&
531*67e74705SXin Li         InputExpr->isEvaluatable(Context)) {
532*67e74705SXin Li       CastKind castKind =
533*67e74705SXin Li         (OutTy->isBooleanType() ? CK_IntegralToBoolean : CK_IntegralCast);
534*67e74705SXin Li       InputExpr = ImpCastExprToType(InputExpr, OutTy, castKind).get();
535*67e74705SXin Li       Exprs[InputOpNo] = InputExpr;
536*67e74705SXin Li       NS->setInputExpr(i, InputExpr);
537*67e74705SXin Li       continue;
538*67e74705SXin Li     }
539*67e74705SXin Li 
540*67e74705SXin Li     Diag(InputExpr->getLocStart(),
541*67e74705SXin Li          diag::err_asm_tying_incompatible_types)
542*67e74705SXin Li       << InTy << OutTy << OutputExpr->getSourceRange()
543*67e74705SXin Li       << InputExpr->getSourceRange();
544*67e74705SXin Li     return StmtError();
545*67e74705SXin Li   }
546*67e74705SXin Li 
547*67e74705SXin Li   return NS;
548*67e74705SXin Li }
549*67e74705SXin Li 
fillInlineAsmTypeInfo(const ASTContext & Context,QualType T,llvm::InlineAsmIdentifierInfo & Info)550*67e74705SXin Li static void fillInlineAsmTypeInfo(const ASTContext &Context, QualType T,
551*67e74705SXin Li                                   llvm::InlineAsmIdentifierInfo &Info) {
552*67e74705SXin Li   // Compute the type size (and array length if applicable?).
553*67e74705SXin Li   Info.Type = Info.Size = Context.getTypeSizeInChars(T).getQuantity();
554*67e74705SXin Li   if (T->isArrayType()) {
555*67e74705SXin Li     const ArrayType *ATy = Context.getAsArrayType(T);
556*67e74705SXin Li     Info.Type = Context.getTypeSizeInChars(ATy->getElementType()).getQuantity();
557*67e74705SXin Li     Info.Length = Info.Size / Info.Type;
558*67e74705SXin Li   }
559*67e74705SXin Li }
560*67e74705SXin Li 
LookupInlineAsmIdentifier(CXXScopeSpec & SS,SourceLocation TemplateKWLoc,UnqualifiedId & Id,llvm::InlineAsmIdentifierInfo & Info,bool IsUnevaluatedContext)561*67e74705SXin Li ExprResult Sema::LookupInlineAsmIdentifier(CXXScopeSpec &SS,
562*67e74705SXin Li                                            SourceLocation TemplateKWLoc,
563*67e74705SXin Li                                            UnqualifiedId &Id,
564*67e74705SXin Li                                            llvm::InlineAsmIdentifierInfo &Info,
565*67e74705SXin Li                                            bool IsUnevaluatedContext) {
566*67e74705SXin Li   Info.clear();
567*67e74705SXin Li 
568*67e74705SXin Li   if (IsUnevaluatedContext)
569*67e74705SXin Li     PushExpressionEvaluationContext(UnevaluatedAbstract,
570*67e74705SXin Li                                     ReuseLambdaContextDecl);
571*67e74705SXin Li 
572*67e74705SXin Li   ExprResult Result = ActOnIdExpression(getCurScope(), SS, TemplateKWLoc, Id,
573*67e74705SXin Li                                         /*trailing lparen*/ false,
574*67e74705SXin Li                                         /*is & operand*/ false,
575*67e74705SXin Li                                         /*CorrectionCandidateCallback=*/nullptr,
576*67e74705SXin Li                                         /*IsInlineAsmIdentifier=*/ true);
577*67e74705SXin Li 
578*67e74705SXin Li   if (IsUnevaluatedContext)
579*67e74705SXin Li     PopExpressionEvaluationContext();
580*67e74705SXin Li 
581*67e74705SXin Li   if (!Result.isUsable()) return Result;
582*67e74705SXin Li 
583*67e74705SXin Li   Result = CheckPlaceholderExpr(Result.get());
584*67e74705SXin Li   if (!Result.isUsable()) return Result;
585*67e74705SXin Li 
586*67e74705SXin Li   // Referring to parameters is not allowed in naked functions.
587*67e74705SXin Li   if (CheckNakedParmReference(Result.get(), *this))
588*67e74705SXin Li     return ExprError();
589*67e74705SXin Li 
590*67e74705SXin Li   QualType T = Result.get()->getType();
591*67e74705SXin Li 
592*67e74705SXin Li   if (T->isDependentType()) {
593*67e74705SXin Li     return Result;
594*67e74705SXin Li   }
595*67e74705SXin Li 
596*67e74705SXin Li   // Any sort of function type is fine.
597*67e74705SXin Li   if (T->isFunctionType()) {
598*67e74705SXin Li     return Result;
599*67e74705SXin Li   }
600*67e74705SXin Li 
601*67e74705SXin Li   // Otherwise, it needs to be a complete type.
602*67e74705SXin Li   if (RequireCompleteExprType(Result.get(), diag::err_asm_incomplete_type)) {
603*67e74705SXin Li     return ExprError();
604*67e74705SXin Li   }
605*67e74705SXin Li 
606*67e74705SXin Li   fillInlineAsmTypeInfo(Context, T, Info);
607*67e74705SXin Li 
608*67e74705SXin Li   // We can work with the expression as long as it's not an r-value.
609*67e74705SXin Li   if (!Result.get()->isRValue())
610*67e74705SXin Li     Info.IsVarDecl = true;
611*67e74705SXin Li 
612*67e74705SXin Li   return Result;
613*67e74705SXin Li }
614*67e74705SXin Li 
LookupInlineAsmField(StringRef Base,StringRef Member,unsigned & Offset,SourceLocation AsmLoc)615*67e74705SXin Li bool Sema::LookupInlineAsmField(StringRef Base, StringRef Member,
616*67e74705SXin Li                                 unsigned &Offset, SourceLocation AsmLoc) {
617*67e74705SXin Li   Offset = 0;
618*67e74705SXin Li   SmallVector<StringRef, 2> Members;
619*67e74705SXin Li   Member.split(Members, ".");
620*67e74705SXin Li 
621*67e74705SXin Li   LookupResult BaseResult(*this, &Context.Idents.get(Base), SourceLocation(),
622*67e74705SXin Li                           LookupOrdinaryName);
623*67e74705SXin Li 
624*67e74705SXin Li   if (!LookupName(BaseResult, getCurScope()))
625*67e74705SXin Li     return true;
626*67e74705SXin Li 
627*67e74705SXin Li   if(!BaseResult.isSingleResult())
628*67e74705SXin Li     return true;
629*67e74705SXin Li   NamedDecl *FoundDecl = BaseResult.getFoundDecl();
630*67e74705SXin Li   for (StringRef NextMember : Members) {
631*67e74705SXin Li     const RecordType *RT = nullptr;
632*67e74705SXin Li     if (VarDecl *VD = dyn_cast<VarDecl>(FoundDecl))
633*67e74705SXin Li       RT = VD->getType()->getAs<RecordType>();
634*67e74705SXin Li     else if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(FoundDecl)) {
635*67e74705SXin Li       MarkAnyDeclReferenced(TD->getLocation(), TD, /*OdrUse=*/false);
636*67e74705SXin Li       RT = TD->getUnderlyingType()->getAs<RecordType>();
637*67e74705SXin Li     } else if (TypeDecl *TD = dyn_cast<TypeDecl>(FoundDecl))
638*67e74705SXin Li       RT = TD->getTypeForDecl()->getAs<RecordType>();
639*67e74705SXin Li     else if (FieldDecl *TD = dyn_cast<FieldDecl>(FoundDecl))
640*67e74705SXin Li       RT = TD->getType()->getAs<RecordType>();
641*67e74705SXin Li     if (!RT)
642*67e74705SXin Li       return true;
643*67e74705SXin Li 
644*67e74705SXin Li     if (RequireCompleteType(AsmLoc, QualType(RT, 0),
645*67e74705SXin Li                             diag::err_asm_incomplete_type))
646*67e74705SXin Li       return true;
647*67e74705SXin Li 
648*67e74705SXin Li     LookupResult FieldResult(*this, &Context.Idents.get(NextMember),
649*67e74705SXin Li                              SourceLocation(), LookupMemberName);
650*67e74705SXin Li 
651*67e74705SXin Li     if (!LookupQualifiedName(FieldResult, RT->getDecl()))
652*67e74705SXin Li       return true;
653*67e74705SXin Li 
654*67e74705SXin Li     if (!FieldResult.isSingleResult())
655*67e74705SXin Li       return true;
656*67e74705SXin Li     FoundDecl = FieldResult.getFoundDecl();
657*67e74705SXin Li 
658*67e74705SXin Li     // FIXME: Handle IndirectFieldDecl?
659*67e74705SXin Li     FieldDecl *FD = dyn_cast<FieldDecl>(FoundDecl);
660*67e74705SXin Li     if (!FD)
661*67e74705SXin Li       return true;
662*67e74705SXin Li 
663*67e74705SXin Li     const ASTRecordLayout &RL = Context.getASTRecordLayout(RT->getDecl());
664*67e74705SXin Li     unsigned i = FD->getFieldIndex();
665*67e74705SXin Li     CharUnits Result = Context.toCharUnitsFromBits(RL.getFieldOffset(i));
666*67e74705SXin Li     Offset += (unsigned)Result.getQuantity();
667*67e74705SXin Li   }
668*67e74705SXin Li 
669*67e74705SXin Li   return false;
670*67e74705SXin Li }
671*67e74705SXin Li 
672*67e74705SXin Li ExprResult
LookupInlineAsmVarDeclField(Expr * E,StringRef Member,llvm::InlineAsmIdentifierInfo & Info,SourceLocation AsmLoc)673*67e74705SXin Li Sema::LookupInlineAsmVarDeclField(Expr *E, StringRef Member,
674*67e74705SXin Li                                   llvm::InlineAsmIdentifierInfo &Info,
675*67e74705SXin Li                                   SourceLocation AsmLoc) {
676*67e74705SXin Li   Info.clear();
677*67e74705SXin Li 
678*67e74705SXin Li   QualType T = E->getType();
679*67e74705SXin Li   if (T->isDependentType()) {
680*67e74705SXin Li     DeclarationNameInfo NameInfo;
681*67e74705SXin Li     NameInfo.setLoc(AsmLoc);
682*67e74705SXin Li     NameInfo.setName(&Context.Idents.get(Member));
683*67e74705SXin Li     return CXXDependentScopeMemberExpr::Create(
684*67e74705SXin Li         Context, E, T, /*IsArrow=*/false, AsmLoc, NestedNameSpecifierLoc(),
685*67e74705SXin Li         SourceLocation(),
686*67e74705SXin Li         /*FirstQualifierInScope=*/nullptr, NameInfo, /*TemplateArgs=*/nullptr);
687*67e74705SXin Li   }
688*67e74705SXin Li 
689*67e74705SXin Li   const RecordType *RT = T->getAs<RecordType>();
690*67e74705SXin Li   // FIXME: Diagnose this as field access into a scalar type.
691*67e74705SXin Li   if (!RT)
692*67e74705SXin Li     return ExprResult();
693*67e74705SXin Li 
694*67e74705SXin Li   LookupResult FieldResult(*this, &Context.Idents.get(Member), AsmLoc,
695*67e74705SXin Li                            LookupMemberName);
696*67e74705SXin Li 
697*67e74705SXin Li   if (!LookupQualifiedName(FieldResult, RT->getDecl()))
698*67e74705SXin Li     return ExprResult();
699*67e74705SXin Li 
700*67e74705SXin Li   // Only normal and indirect field results will work.
701*67e74705SXin Li   ValueDecl *FD = dyn_cast<FieldDecl>(FieldResult.getFoundDecl());
702*67e74705SXin Li   if (!FD)
703*67e74705SXin Li     FD = dyn_cast<IndirectFieldDecl>(FieldResult.getFoundDecl());
704*67e74705SXin Li   if (!FD)
705*67e74705SXin Li     return ExprResult();
706*67e74705SXin Li 
707*67e74705SXin Li   // Make an Expr to thread through OpDecl.
708*67e74705SXin Li   ExprResult Result = BuildMemberReferenceExpr(
709*67e74705SXin Li       E, E->getType(), AsmLoc, /*IsArrow=*/false, CXXScopeSpec(),
710*67e74705SXin Li       SourceLocation(), nullptr, FieldResult, nullptr, nullptr);
711*67e74705SXin Li   if (Result.isInvalid())
712*67e74705SXin Li     return Result;
713*67e74705SXin Li   Info.OpDecl = Result.get();
714*67e74705SXin Li 
715*67e74705SXin Li   fillInlineAsmTypeInfo(Context, Result.get()->getType(), Info);
716*67e74705SXin Li 
717*67e74705SXin Li   // Fields are "variables" as far as inline assembly is concerned.
718*67e74705SXin Li   Info.IsVarDecl = true;
719*67e74705SXin Li 
720*67e74705SXin Li   return Result;
721*67e74705SXin Li }
722*67e74705SXin Li 
ActOnMSAsmStmt(SourceLocation AsmLoc,SourceLocation LBraceLoc,ArrayRef<Token> AsmToks,StringRef AsmString,unsigned NumOutputs,unsigned NumInputs,ArrayRef<StringRef> Constraints,ArrayRef<StringRef> Clobbers,ArrayRef<Expr * > Exprs,SourceLocation EndLoc)723*67e74705SXin Li StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc, SourceLocation LBraceLoc,
724*67e74705SXin Li                                 ArrayRef<Token> AsmToks,
725*67e74705SXin Li                                 StringRef AsmString,
726*67e74705SXin Li                                 unsigned NumOutputs, unsigned NumInputs,
727*67e74705SXin Li                                 ArrayRef<StringRef> Constraints,
728*67e74705SXin Li                                 ArrayRef<StringRef> Clobbers,
729*67e74705SXin Li                                 ArrayRef<Expr*> Exprs,
730*67e74705SXin Li                                 SourceLocation EndLoc) {
731*67e74705SXin Li   bool IsSimple = (NumOutputs != 0 || NumInputs != 0);
732*67e74705SXin Li   getCurFunction()->setHasBranchProtectedScope();
733*67e74705SXin Li   MSAsmStmt *NS =
734*67e74705SXin Li     new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, IsSimple,
735*67e74705SXin Li                             /*IsVolatile*/ true, AsmToks, NumOutputs, NumInputs,
736*67e74705SXin Li                             Constraints, Exprs, AsmString,
737*67e74705SXin Li                             Clobbers, EndLoc);
738*67e74705SXin Li   return NS;
739*67e74705SXin Li }
740*67e74705SXin Li 
GetOrCreateMSAsmLabel(StringRef ExternalLabelName,SourceLocation Location,bool AlwaysCreate)741*67e74705SXin Li LabelDecl *Sema::GetOrCreateMSAsmLabel(StringRef ExternalLabelName,
742*67e74705SXin Li                                        SourceLocation Location,
743*67e74705SXin Li                                        bool AlwaysCreate) {
744*67e74705SXin Li   LabelDecl* Label = LookupOrCreateLabel(PP.getIdentifierInfo(ExternalLabelName),
745*67e74705SXin Li                                          Location);
746*67e74705SXin Li 
747*67e74705SXin Li   if (Label->isMSAsmLabel()) {
748*67e74705SXin Li     // If we have previously created this label implicitly, mark it as used.
749*67e74705SXin Li     Label->markUsed(Context);
750*67e74705SXin Li   } else {
751*67e74705SXin Li     // Otherwise, insert it, but only resolve it if we have seen the label itself.
752*67e74705SXin Li     std::string InternalName;
753*67e74705SXin Li     llvm::raw_string_ostream OS(InternalName);
754*67e74705SXin Li     // Create an internal name for the label.  The name should not be a valid mangled
755*67e74705SXin Li     // name, and should be unique.  We use a dot to make the name an invalid mangled
756*67e74705SXin Li     // name.
757*67e74705SXin Li     OS << "__MSASMLABEL_." << MSAsmLabelNameCounter++ << "__";
758*67e74705SXin Li     for (auto it = ExternalLabelName.begin(); it != ExternalLabelName.end();
759*67e74705SXin Li          ++it) {
760*67e74705SXin Li       OS << *it;
761*67e74705SXin Li       if (*it == '$') {
762*67e74705SXin Li         // We escape '$' in asm strings by replacing it with "$$"
763*67e74705SXin Li         OS << '$';
764*67e74705SXin Li       }
765*67e74705SXin Li     }
766*67e74705SXin Li     Label->setMSAsmLabel(OS.str());
767*67e74705SXin Li   }
768*67e74705SXin Li   if (AlwaysCreate) {
769*67e74705SXin Li     // The label might have been created implicitly from a previously encountered
770*67e74705SXin Li     // goto statement.  So, for both newly created and looked up labels, we mark
771*67e74705SXin Li     // them as resolved.
772*67e74705SXin Li     Label->setMSAsmLabelResolved();
773*67e74705SXin Li   }
774*67e74705SXin Li   // Adjust their location for being able to generate accurate diagnostics.
775*67e74705SXin Li   Label->setLocation(Location);
776*67e74705SXin Li 
777*67e74705SXin Li   return Label;
778*67e74705SXin Li }
779