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