1 //===--- SemaStmtAsm.cpp - Semantic Analysis for Asm Statements -----------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file implements semantic analysis for inline asm statements.
11 //===----------------------------------------------------------------------===//
13 #include "clang/AST/ExprCXX.h"
14 #include "clang/AST/RecordLayout.h"
15 #include "clang/AST/TypeLoc.h"
16 #include "clang/Basic/TargetInfo.h"
17 #include "clang/Lex/Preprocessor.h"
18 #include "clang/Sema/Initialization.h"
19 #include "clang/Sema/Lookup.h"
20 #include "clang/Sema/Scope.h"
21 #include "clang/Sema/ScopeInfo.h"
22 #include "llvm/ADT/ArrayRef.h"
23 #include "llvm/ADT/StringExtras.h"
24 #include "llvm/ADT/StringSet.h"
25 #include "llvm/MC/MCParser/MCAsmParser.h"
27 using namespace clang
;
30 /// Remove the upper-level LValueToRValue cast from an expression.
31 static void removeLValueToRValueCast(Expr
*E
) {
33 Expr
*ExprUnderCast
= nullptr;
34 SmallVector
<Expr
*, 8> ParentsToUpdate
;
37 ParentsToUpdate
.push_back(Parent
);
38 if (auto *ParenE
= dyn_cast
<ParenExpr
>(Parent
)) {
39 Parent
= ParenE
->getSubExpr();
43 Expr
*Child
= nullptr;
44 CastExpr
*ParentCast
= dyn_cast
<CastExpr
>(Parent
);
46 Child
= ParentCast
->getSubExpr();
50 if (auto *CastE
= dyn_cast
<CastExpr
>(Child
))
51 if (CastE
->getCastKind() == CK_LValueToRValue
) {
52 ExprUnderCast
= CastE
->getSubExpr();
53 // LValueToRValue cast inside GCCAsmStmt requires an explicit cast.
54 ParentCast
->setSubExpr(ExprUnderCast
);
60 // Update parent expressions to have same ValueType as the underlying.
61 assert(ExprUnderCast
&&
62 "Should be reachable only if LValueToRValue cast was found!");
63 auto ValueKind
= ExprUnderCast
->getValueKind();
64 for (Expr
*E
: ParentsToUpdate
)
65 E
->setValueKind(ValueKind
);
68 /// Emit a warning about usage of "noop"-like casts for lvalues (GNU extension)
69 /// and fix the argument with removing LValueToRValue cast from the expression.
70 static void emitAndFixInvalidAsmCastLValue(const Expr
*LVal
, Expr
*BadArgument
,
72 S
.Diag(LVal
->getBeginLoc(), diag::warn_invalid_asm_cast_lvalue
)
73 << BadArgument
->getSourceRange();
74 removeLValueToRValueCast(BadArgument
);
77 /// CheckAsmLValue - GNU C has an extremely ugly extension whereby they silently
78 /// ignore "noop" casts in places where an lvalue is required by an inline asm.
79 /// We emulate this behavior when -fheinous-gnu-extensions is specified, but
80 /// provide a strong guidance to not use it.
82 /// This method checks to see if the argument is an acceptable l-value and
83 /// returns false if it is a case we can handle.
84 static bool CheckAsmLValue(Expr
*E
, Sema
&S
) {
85 // Type dependent expressions will be checked during instantiation.
86 if (E
->isTypeDependent())
90 return false; // Cool, this is an lvalue.
92 // Okay, this is not an lvalue, but perhaps it is the result of a cast that we
93 // are supposed to allow.
94 const Expr
*E2
= E
->IgnoreParenNoopCasts(S
.Context
);
95 if (E
!= E2
&& E2
->isLValue()) {
96 emitAndFixInvalidAsmCastLValue(E2
, E
, S
);
97 // Accept, even if we emitted an error diagnostic.
101 // None of the above, just randomly invalid non-lvalue.
105 /// isOperandMentioned - Return true if the specified operand # is mentioned
106 /// anywhere in the decomposed asm string.
108 isOperandMentioned(unsigned OpNo
,
109 ArrayRef
<GCCAsmStmt::AsmStringPiece
> AsmStrPieces
) {
110 for (unsigned p
= 0, e
= AsmStrPieces
.size(); p
!= e
; ++p
) {
111 const GCCAsmStmt::AsmStringPiece
&Piece
= AsmStrPieces
[p
];
112 if (!Piece
.isOperand())
115 // If this is a reference to the input and if the input was the smaller
116 // one, then we have to reject this asm.
117 if (Piece
.getOperandNo() == OpNo
)
123 static bool CheckNakedParmReference(Expr
*E
, Sema
&S
) {
124 FunctionDecl
*Func
= dyn_cast
<FunctionDecl
>(S
.CurContext
);
127 if (!Func
->hasAttr
<NakedAttr
>())
130 SmallVector
<Expr
*, 4> WorkList
;
131 WorkList
.push_back(E
);
132 while (WorkList
.size()) {
133 Expr
*E
= WorkList
.pop_back_val();
134 if (isa
<CXXThisExpr
>(E
)) {
135 S
.Diag(E
->getBeginLoc(), diag::err_asm_naked_this_ref
);
136 S
.Diag(Func
->getAttr
<NakedAttr
>()->getLocation(), diag::note_attribute
);
139 if (DeclRefExpr
*DRE
= dyn_cast
<DeclRefExpr
>(E
)) {
140 if (isa
<ParmVarDecl
>(DRE
->getDecl())) {
141 S
.Diag(DRE
->getBeginLoc(), diag::err_asm_naked_parm_ref
);
142 S
.Diag(Func
->getAttr
<NakedAttr
>()->getLocation(), diag::note_attribute
);
146 for (Stmt
*Child
: E
->children()) {
147 if (Expr
*E
= dyn_cast_or_null
<Expr
>(Child
))
148 WorkList
.push_back(E
);
154 /// Returns true if given expression is not compatible with inline
155 /// assembly's memory constraint; false otherwise.
156 static bool checkExprMemoryConstraintCompat(Sema
&S
, Expr
*E
,
157 TargetInfo::ConstraintInfo
&Info
,
158 bool is_input_expr
) {
164 } EType
= ExprSafeType
;
166 // Bitfields, vector elements and global register variables are not
168 if (E
->refersToBitField())
169 EType
= ExprBitfield
;
170 else if (E
->refersToVectorElement())
171 EType
= ExprVectorElt
;
172 else if (E
->refersToGlobalRegisterVar())
173 EType
= ExprGlobalRegVar
;
175 if (EType
!= ExprSafeType
) {
176 S
.Diag(E
->getBeginLoc(), diag::err_asm_non_addr_value_in_memory_constraint
)
177 << EType
<< is_input_expr
<< Info
.getConstraintStr()
178 << E
->getSourceRange();
185 // Extracting the register name from the Expression value,
186 // if there is no register name to extract, returns ""
187 static StringRef
extractRegisterName(const Expr
*Expression
,
188 const TargetInfo
&Target
) {
189 Expression
= Expression
->IgnoreImpCasts();
190 if (const DeclRefExpr
*AsmDeclRef
= dyn_cast
<DeclRefExpr
>(Expression
)) {
191 // Handle cases where the expression is a variable
192 const VarDecl
*Variable
= dyn_cast
<VarDecl
>(AsmDeclRef
->getDecl());
193 if (Variable
&& Variable
->getStorageClass() == SC_Register
) {
194 if (AsmLabelAttr
*Attr
= Variable
->getAttr
<AsmLabelAttr
>())
195 if (Target
.isValidGCCRegisterName(Attr
->getLabel()))
196 return Target
.getNormalizedGCCRegisterName(Attr
->getLabel(), true);
202 // Checks if there is a conflict between the input and output lists with the
203 // clobbers list. If there's a conflict, returns the location of the
204 // conflicted clobber, else returns nullptr
205 static SourceLocation
206 getClobberConflictLocation(MultiExprArg Exprs
, StringLiteral
**Constraints
,
207 StringLiteral
**Clobbers
, int NumClobbers
,
209 const TargetInfo
&Target
, ASTContext
&Cont
) {
210 llvm::StringSet
<> InOutVars
;
211 // Collect all the input and output registers from the extended asm
212 // statement in order to check for conflicts with the clobber list
213 for (unsigned int i
= 0; i
< Exprs
.size() - NumLabels
; ++i
) {
214 StringRef Constraint
= Constraints
[i
]->getString();
215 StringRef InOutReg
= Target
.getConstraintRegister(
216 Constraint
, extractRegisterName(Exprs
[i
], Target
));
218 InOutVars
.insert(InOutReg
);
220 // Check for each item in the clobber list if it conflicts with the input
222 for (int i
= 0; i
< NumClobbers
; ++i
) {
223 StringRef Clobber
= Clobbers
[i
]->getString();
224 // We only check registers, therefore we don't check cc and memory
226 if (Clobber
== "cc" || Clobber
== "memory" || Clobber
== "unwind")
228 Clobber
= Target
.getNormalizedGCCRegisterName(Clobber
, true);
229 // Go over the output's registers we collected
230 if (InOutVars
.count(Clobber
))
231 return Clobbers
[i
]->getBeginLoc();
233 return SourceLocation();
236 StmtResult
Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc
, bool IsSimple
,
237 bool IsVolatile
, unsigned NumOutputs
,
238 unsigned NumInputs
, IdentifierInfo
**Names
,
239 MultiExprArg constraints
, MultiExprArg Exprs
,
240 Expr
*asmString
, MultiExprArg clobbers
,
242 SourceLocation RParenLoc
) {
243 unsigned NumClobbers
= clobbers
.size();
244 StringLiteral
**Constraints
=
245 reinterpret_cast<StringLiteral
**>(constraints
.data());
246 StringLiteral
*AsmString
= cast
<StringLiteral
>(asmString
);
247 StringLiteral
**Clobbers
= reinterpret_cast<StringLiteral
**>(clobbers
.data());
249 SmallVector
<TargetInfo::ConstraintInfo
, 4> OutputConstraintInfos
;
251 // The parser verifies that there is a string literal here.
252 assert(AsmString
->isOrdinary());
254 FunctionDecl
*FD
= dyn_cast
<FunctionDecl
>(getCurLexicalContext());
255 llvm::StringMap
<bool> FeatureMap
;
256 Context
.getFunctionFeatureMap(FeatureMap
, FD
);
258 for (unsigned i
= 0; i
!= NumOutputs
; i
++) {
259 StringLiteral
*Literal
= Constraints
[i
];
260 assert(Literal
->isOrdinary());
262 StringRef OutputName
;
264 OutputName
= Names
[i
]->getName();
266 TargetInfo::ConstraintInfo
Info(Literal
->getString(), OutputName
);
267 if (!Context
.getTargetInfo().validateOutputConstraint(Info
) &&
268 !(LangOpts
.HIPStdPar
&& LangOpts
.CUDAIsDevice
)) {
269 targetDiag(Literal
->getBeginLoc(),
270 diag::err_asm_invalid_output_constraint
)
271 << Info
.getConstraintStr();
273 GCCAsmStmt(Context
, AsmLoc
, IsSimple
, IsVolatile
, NumOutputs
,
274 NumInputs
, Names
, Constraints
, Exprs
.data(), AsmString
,
275 NumClobbers
, Clobbers
, NumLabels
, RParenLoc
);
278 ExprResult ER
= CheckPlaceholderExpr(Exprs
[i
]);
283 // Check that the output exprs are valid lvalues.
284 Expr
*OutputExpr
= Exprs
[i
];
286 // Referring to parameters is not allowed in naked functions.
287 if (CheckNakedParmReference(OutputExpr
, *this))
290 // Check that the output expression is compatible with memory constraint.
291 if (Info
.allowsMemory() &&
292 checkExprMemoryConstraintCompat(*this, OutputExpr
, Info
, false))
295 // Disallow bit-precise integer types, since the backends tend to have
296 // difficulties with abnormal sizes.
297 if (OutputExpr
->getType()->isBitIntType())
299 Diag(OutputExpr
->getBeginLoc(), diag::err_asm_invalid_type
)
300 << OutputExpr
->getType() << 0 /*Input*/
301 << OutputExpr
->getSourceRange());
303 OutputConstraintInfos
.push_back(Info
);
305 // If this is dependent, just continue.
306 if (OutputExpr
->isTypeDependent())
309 Expr::isModifiableLvalueResult IsLV
=
310 OutputExpr
->isModifiableLvalue(Context
, /*Loc=*/nullptr);
312 case Expr::MLV_Valid
:
313 // Cool, this is an lvalue.
315 case Expr::MLV_ArrayType
:
318 case Expr::MLV_LValueCast
: {
319 const Expr
*LVal
= OutputExpr
->IgnoreParenNoopCasts(Context
);
320 emitAndFixInvalidAsmCastLValue(LVal
, OutputExpr
, *this);
321 // Accept, even if we emitted an error diagnostic.
324 case Expr::MLV_IncompleteType
:
325 case Expr::MLV_IncompleteVoidType
:
326 if (RequireCompleteType(OutputExpr
->getBeginLoc(), Exprs
[i
]->getType(),
327 diag::err_dereference_incomplete_type
))
331 return StmtError(Diag(OutputExpr
->getBeginLoc(),
332 diag::err_asm_invalid_lvalue_in_output
)
333 << OutputExpr
->getSourceRange());
336 unsigned Size
= Context
.getTypeSize(OutputExpr
->getType());
337 if (!Context
.getTargetInfo().validateOutputSize(
338 FeatureMap
, Literal
->getString(), Size
)) {
339 targetDiag(OutputExpr
->getBeginLoc(), diag::err_asm_invalid_output_size
)
340 << Info
.getConstraintStr();
342 GCCAsmStmt(Context
, AsmLoc
, IsSimple
, IsVolatile
, NumOutputs
,
343 NumInputs
, Names
, Constraints
, Exprs
.data(), AsmString
,
344 NumClobbers
, Clobbers
, NumLabels
, RParenLoc
);
348 SmallVector
<TargetInfo::ConstraintInfo
, 4> InputConstraintInfos
;
350 for (unsigned i
= NumOutputs
, e
= NumOutputs
+ NumInputs
; i
!= e
; i
++) {
351 StringLiteral
*Literal
= Constraints
[i
];
352 assert(Literal
->isOrdinary());
356 InputName
= Names
[i
]->getName();
358 TargetInfo::ConstraintInfo
Info(Literal
->getString(), InputName
);
359 if (!Context
.getTargetInfo().validateInputConstraint(OutputConstraintInfos
,
361 targetDiag(Literal
->getBeginLoc(), diag::err_asm_invalid_input_constraint
)
362 << Info
.getConstraintStr();
364 GCCAsmStmt(Context
, AsmLoc
, IsSimple
, IsVolatile
, NumOutputs
,
365 NumInputs
, Names
, Constraints
, Exprs
.data(), AsmString
,
366 NumClobbers
, Clobbers
, NumLabels
, RParenLoc
);
369 ExprResult ER
= CheckPlaceholderExpr(Exprs
[i
]);
374 Expr
*InputExpr
= Exprs
[i
];
376 if (InputExpr
->getType()->isMemberPointerType())
377 return StmtError(Diag(InputExpr
->getBeginLoc(),
378 diag::err_asm_pmf_through_constraint_not_permitted
)
379 << InputExpr
->getSourceRange());
381 // Referring to parameters is not allowed in naked functions.
382 if (CheckNakedParmReference(InputExpr
, *this))
385 // Check that the input expression is compatible with memory constraint.
386 if (Info
.allowsMemory() &&
387 checkExprMemoryConstraintCompat(*this, InputExpr
, Info
, true))
390 // Only allow void types for memory constraints.
391 if (Info
.allowsMemory() && !Info
.allowsRegister()) {
392 if (CheckAsmLValue(InputExpr
, *this))
393 return StmtError(Diag(InputExpr
->getBeginLoc(),
394 diag::err_asm_invalid_lvalue_in_input
)
395 << Info
.getConstraintStr()
396 << InputExpr
->getSourceRange());
398 ExprResult Result
= DefaultFunctionArrayLvalueConversion(Exprs
[i
]);
399 if (Result
.isInvalid())
402 InputExpr
= Exprs
[i
] = Result
.get();
404 if (Info
.requiresImmediateConstant() && !Info
.allowsRegister()) {
405 if (!InputExpr
->isValueDependent()) {
406 Expr::EvalResult EVResult
;
407 if (InputExpr
->EvaluateAsRValue(EVResult
, Context
, true)) {
408 // For compatibility with GCC, we also allow pointers that would be
409 // integral constant expressions if they were cast to int.
410 llvm::APSInt IntResult
;
411 if (EVResult
.Val
.toIntegralConstant(IntResult
, InputExpr
->getType(),
413 if (!Info
.isValidAsmImmediate(IntResult
))
415 Diag(InputExpr
->getBeginLoc(),
416 diag::err_invalid_asm_value_for_constraint
)
417 << toString(IntResult
, 10) << Info
.getConstraintStr()
418 << InputExpr
->getSourceRange());
424 if (Info
.allowsRegister()) {
425 if (InputExpr
->getType()->isVoidType()) {
427 Diag(InputExpr
->getBeginLoc(), diag::err_asm_invalid_type_in_input
)
428 << InputExpr
->getType() << Info
.getConstraintStr()
429 << InputExpr
->getSourceRange());
433 if (InputExpr
->getType()->isBitIntType())
435 Diag(InputExpr
->getBeginLoc(), diag::err_asm_invalid_type
)
436 << InputExpr
->getType() << 1 /*Output*/
437 << InputExpr
->getSourceRange());
439 InputConstraintInfos
.push_back(Info
);
441 const Type
*Ty
= Exprs
[i
]->getType().getTypePtr();
442 if (Ty
->isDependentType())
445 if (!Ty
->isVoidType() || !Info
.allowsMemory())
446 if (RequireCompleteType(InputExpr
->getBeginLoc(), Exprs
[i
]->getType(),
447 diag::err_dereference_incomplete_type
))
450 unsigned Size
= Context
.getTypeSize(Ty
);
451 if (!Context
.getTargetInfo().validateInputSize(FeatureMap
,
452 Literal
->getString(), Size
))
453 return targetDiag(InputExpr
->getBeginLoc(),
454 diag::err_asm_invalid_input_size
)
455 << Info
.getConstraintStr();
458 std::optional
<SourceLocation
> UnwindClobberLoc
;
460 // Check that the clobbers are valid.
461 for (unsigned i
= 0; i
!= NumClobbers
; i
++) {
462 StringLiteral
*Literal
= Clobbers
[i
];
463 assert(Literal
->isOrdinary());
465 StringRef Clobber
= Literal
->getString();
467 if (!Context
.getTargetInfo().isValidClobber(Clobber
)) {
468 targetDiag(Literal
->getBeginLoc(), diag::err_asm_unknown_register_name
)
471 GCCAsmStmt(Context
, AsmLoc
, IsSimple
, IsVolatile
, NumOutputs
,
472 NumInputs
, Names
, Constraints
, Exprs
.data(), AsmString
,
473 NumClobbers
, Clobbers
, NumLabels
, RParenLoc
);
476 if (Clobber
== "unwind") {
477 UnwindClobberLoc
= Literal
->getBeginLoc();
481 // Using unwind clobber and asm-goto together is not supported right now.
482 if (UnwindClobberLoc
&& NumLabels
> 0) {
483 targetDiag(*UnwindClobberLoc
, diag::err_asm_unwind_and_goto
);
485 GCCAsmStmt(Context
, AsmLoc
, IsSimple
, IsVolatile
, NumOutputs
, NumInputs
,
486 Names
, Constraints
, Exprs
.data(), AsmString
, NumClobbers
,
487 Clobbers
, NumLabels
, RParenLoc
);
491 new (Context
) GCCAsmStmt(Context
, AsmLoc
, IsSimple
, IsVolatile
, NumOutputs
,
492 NumInputs
, Names
, Constraints
, Exprs
.data(),
493 AsmString
, NumClobbers
, Clobbers
, NumLabels
,
495 // Validate the asm string, ensuring it makes sense given the operands we
497 SmallVector
<GCCAsmStmt::AsmStringPiece
, 8> Pieces
;
499 if (unsigned DiagID
= NS
->AnalyzeAsmString(Pieces
, Context
, DiagOffs
)) {
500 targetDiag(getLocationOfStringLiteralByte(AsmString
, DiagOffs
), DiagID
)
501 << AsmString
->getSourceRange();
505 // Validate constraints and modifiers.
506 for (unsigned i
= 0, e
= Pieces
.size(); i
!= e
; ++i
) {
507 GCCAsmStmt::AsmStringPiece
&Piece
= Pieces
[i
];
508 if (!Piece
.isOperand()) continue;
510 // Look for the correct constraint index.
511 unsigned ConstraintIdx
= Piece
.getOperandNo();
512 unsigned NumOperands
= NS
->getNumOutputs() + NS
->getNumInputs();
513 // Labels are the last in the Exprs list.
514 if (NS
->isAsmGoto() && ConstraintIdx
>= NumOperands
)
516 // Look for the (ConstraintIdx - NumOperands + 1)th constraint with
518 if (ConstraintIdx
>= NumOperands
) {
519 unsigned I
= 0, E
= NS
->getNumOutputs();
521 for (unsigned Cnt
= ConstraintIdx
- NumOperands
; I
!= E
; ++I
)
522 if (OutputConstraintInfos
[I
].isReadWrite() && Cnt
-- == 0) {
527 assert(I
!= E
&& "Invalid operand number should have been caught in "
528 " AnalyzeAsmString");
531 // Now that we have the right indexes go ahead and check.
532 StringLiteral
*Literal
= Constraints
[ConstraintIdx
];
533 const Type
*Ty
= Exprs
[ConstraintIdx
]->getType().getTypePtr();
534 if (Ty
->isDependentType() || Ty
->isIncompleteType())
537 unsigned Size
= Context
.getTypeSize(Ty
);
538 std::string SuggestedModifier
;
539 if (!Context
.getTargetInfo().validateConstraintModifier(
540 Literal
->getString(), Piece
.getModifier(), Size
,
541 SuggestedModifier
)) {
542 targetDiag(Exprs
[ConstraintIdx
]->getBeginLoc(),
543 diag::warn_asm_mismatched_size_modifier
);
545 if (!SuggestedModifier
.empty()) {
546 auto B
= targetDiag(Piece
.getRange().getBegin(),
547 diag::note_asm_missing_constraint_modifier
)
548 << SuggestedModifier
;
549 SuggestedModifier
= "%" + SuggestedModifier
+ Piece
.getString();
550 B
<< FixItHint::CreateReplacement(Piece
.getRange(), SuggestedModifier
);
555 // Validate tied input operands for type mismatches.
556 unsigned NumAlternatives
= ~0U;
557 for (unsigned i
= 0, e
= OutputConstraintInfos
.size(); i
!= e
; ++i
) {
558 TargetInfo::ConstraintInfo
&Info
= OutputConstraintInfos
[i
];
559 StringRef ConstraintStr
= Info
.getConstraintStr();
560 unsigned AltCount
= ConstraintStr
.count(',') + 1;
561 if (NumAlternatives
== ~0U) {
562 NumAlternatives
= AltCount
;
563 } else if (NumAlternatives
!= AltCount
) {
564 targetDiag(NS
->getOutputExpr(i
)->getBeginLoc(),
565 diag::err_asm_unexpected_constraint_alternatives
)
566 << NumAlternatives
<< AltCount
;
570 SmallVector
<size_t, 4> InputMatchedToOutput(OutputConstraintInfos
.size(),
572 for (unsigned i
= 0, e
= InputConstraintInfos
.size(); i
!= e
; ++i
) {
573 TargetInfo::ConstraintInfo
&Info
= InputConstraintInfos
[i
];
574 StringRef ConstraintStr
= Info
.getConstraintStr();
575 unsigned AltCount
= ConstraintStr
.count(',') + 1;
576 if (NumAlternatives
== ~0U) {
577 NumAlternatives
= AltCount
;
578 } else if (NumAlternatives
!= AltCount
) {
579 targetDiag(NS
->getInputExpr(i
)->getBeginLoc(),
580 diag::err_asm_unexpected_constraint_alternatives
)
581 << NumAlternatives
<< AltCount
;
585 // If this is a tied constraint, verify that the output and input have
586 // either exactly the same type, or that they are int/ptr operands with the
587 // same size (int/long, int*/long, are ok etc).
588 if (!Info
.hasTiedOperand()) continue;
590 unsigned TiedTo
= Info
.getTiedOperand();
591 unsigned InputOpNo
= i
+NumOutputs
;
592 Expr
*OutputExpr
= Exprs
[TiedTo
];
593 Expr
*InputExpr
= Exprs
[InputOpNo
];
595 // Make sure no more than one input constraint matches each output.
596 assert(TiedTo
< InputMatchedToOutput
.size() && "TiedTo value out of range");
597 if (InputMatchedToOutput
[TiedTo
] != ~0U) {
598 targetDiag(NS
->getInputExpr(i
)->getBeginLoc(),
599 diag::err_asm_input_duplicate_match
)
601 targetDiag(NS
->getInputExpr(InputMatchedToOutput
[TiedTo
])->getBeginLoc(),
602 diag::note_asm_input_duplicate_first
)
606 InputMatchedToOutput
[TiedTo
] = i
;
608 if (OutputExpr
->isTypeDependent() || InputExpr
->isTypeDependent())
611 QualType InTy
= InputExpr
->getType();
612 QualType OutTy
= OutputExpr
->getType();
613 if (Context
.hasSameType(InTy
, OutTy
))
614 continue; // All types can be tied to themselves.
616 // Decide if the input and output are in the same domain (integer/ptr or
619 AD_Int
, AD_FP
, AD_Other
620 } InputDomain
, OutputDomain
;
622 if (InTy
->isIntegerType() || InTy
->isPointerType())
623 InputDomain
= AD_Int
;
624 else if (InTy
->isRealFloatingType())
627 InputDomain
= AD_Other
;
629 if (OutTy
->isIntegerType() || OutTy
->isPointerType())
630 OutputDomain
= AD_Int
;
631 else if (OutTy
->isRealFloatingType())
632 OutputDomain
= AD_FP
;
634 OutputDomain
= AD_Other
;
636 // They are ok if they are the same size and in the same domain. This
637 // allows tying things like:
639 // void* to int if they are the same size.
640 // double to long double if they are the same size.
642 uint64_t OutSize
= Context
.getTypeSize(OutTy
);
643 uint64_t InSize
= Context
.getTypeSize(InTy
);
644 if (OutSize
== InSize
&& InputDomain
== OutputDomain
&&
645 InputDomain
!= AD_Other
)
648 // If the smaller input/output operand is not mentioned in the asm string,
649 // then we can promote the smaller one to a larger input and the asm string
651 bool SmallerValueMentioned
= false;
653 // If this is a reference to the input and if the input was the smaller
654 // one, then we have to reject this asm.
655 if (isOperandMentioned(InputOpNo
, Pieces
)) {
656 // This is a use in the asm string of the smaller operand. Since we
657 // codegen this by promoting to a wider value, the asm will get printed
659 SmallerValueMentioned
|= InSize
< OutSize
;
661 if (isOperandMentioned(TiedTo
, Pieces
)) {
662 // If this is a reference to the output, and if the output is the larger
663 // value, then it's ok because we'll promote the input to the larger type.
664 SmallerValueMentioned
|= OutSize
< InSize
;
667 // If the smaller value wasn't mentioned in the asm string, and if the
668 // output was a register, just extend the shorter one to the size of the
670 if (!SmallerValueMentioned
&& InputDomain
!= AD_Other
&&
671 OutputConstraintInfos
[TiedTo
].allowsRegister()) {
672 // FIXME: GCC supports the OutSize to be 128 at maximum. Currently codegen
673 // crash when the size larger than the register size. So we limit it here.
674 if (OutTy
->isStructureType() &&
675 Context
.getIntTypeForBitwidth(OutSize
, /*Signed*/ false).isNull()) {
676 targetDiag(OutputExpr
->getExprLoc(), diag::err_store_value_to_reg
);
683 // Either both of the operands were mentioned or the smaller one was
684 // mentioned. One more special case that we'll allow: if the tied input is
685 // integer, unmentioned, and is a constant, then we'll allow truncating it
686 // down to the size of the destination.
687 if (InputDomain
== AD_Int
&& OutputDomain
== AD_Int
&&
688 !isOperandMentioned(InputOpNo
, Pieces
) &&
689 InputExpr
->isEvaluatable(Context
)) {
691 (OutTy
->isBooleanType() ? CK_IntegralToBoolean
: CK_IntegralCast
);
692 InputExpr
= ImpCastExprToType(InputExpr
, OutTy
, castKind
).get();
693 Exprs
[InputOpNo
] = InputExpr
;
694 NS
->setInputExpr(i
, InputExpr
);
698 targetDiag(InputExpr
->getBeginLoc(), diag::err_asm_tying_incompatible_types
)
699 << InTy
<< OutTy
<< OutputExpr
->getSourceRange()
700 << InputExpr
->getSourceRange();
704 // Check for conflicts between clobber list and input or output lists
705 SourceLocation ConstraintLoc
=
706 getClobberConflictLocation(Exprs
, Constraints
, Clobbers
, NumClobbers
,
708 Context
.getTargetInfo(), Context
);
709 if (ConstraintLoc
.isValid())
710 targetDiag(ConstraintLoc
, diag::error_inoutput_conflict_with_clobber
);
712 // Check for duplicate asm operand name between input, output and label lists.
713 typedef std::pair
<StringRef
, Expr
*> NamedOperand
;
714 SmallVector
<NamedOperand
, 4> NamedOperandList
;
715 for (unsigned i
= 0, e
= NumOutputs
+ NumInputs
+ NumLabels
; i
!= e
; ++i
)
717 NamedOperandList
.emplace_back(
718 std::make_pair(Names
[i
]->getName(), Exprs
[i
]));
719 // Sort NamedOperandList.
720 llvm::stable_sort(NamedOperandList
, llvm::less_first());
721 // Find adjacent duplicate operand.
722 SmallVector
<NamedOperand
, 4>::iterator Found
=
723 std::adjacent_find(begin(NamedOperandList
), end(NamedOperandList
),
724 [](const NamedOperand
&LHS
, const NamedOperand
&RHS
) {
725 return LHS
.first
== RHS
.first
;
727 if (Found
!= NamedOperandList
.end()) {
728 Diag((Found
+ 1)->second
->getBeginLoc(),
729 diag::error_duplicate_asm_operand_name
)
730 << (Found
+ 1)->first
;
731 Diag(Found
->second
->getBeginLoc(), diag::note_duplicate_asm_operand_name
)
736 setFunctionHasBranchIntoScope();
738 CleanupVarDeclMarking();
739 DiscardCleanupsInEvaluationContext();
743 void Sema::FillInlineAsmIdentifierInfo(Expr
*Res
,
744 llvm::InlineAsmIdentifierInfo
&Info
) {
745 QualType T
= Res
->getType();
746 Expr::EvalResult Eval
;
747 if (T
->isFunctionType() || T
->isDependentType())
748 return Info
.setLabel(Res
);
749 if (Res
->isPRValue()) {
750 bool IsEnum
= isa
<clang::EnumType
>(T
);
751 if (DeclRefExpr
*DRE
= dyn_cast
<clang::DeclRefExpr
>(Res
))
752 if (DRE
->getDecl()->getKind() == Decl::EnumConstant
)
754 if (IsEnum
&& Res
->EvaluateAsRValue(Eval
, Context
))
755 return Info
.setEnum(Eval
.Val
.getInt().getSExtValue());
757 return Info
.setLabel(Res
);
759 unsigned Size
= Context
.getTypeSizeInChars(T
).getQuantity();
760 unsigned Type
= Size
;
761 if (const auto *ATy
= Context
.getAsArrayType(T
))
762 Type
= Context
.getTypeSizeInChars(ATy
->getElementType()).getQuantity();
763 bool IsGlobalLV
= false;
764 if (Res
->EvaluateAsLValue(Eval
, Context
))
765 IsGlobalLV
= Eval
.isGlobalLValue();
766 Info
.setVar(Res
, IsGlobalLV
, Size
, Type
);
769 ExprResult
Sema::LookupInlineAsmIdentifier(CXXScopeSpec
&SS
,
770 SourceLocation TemplateKWLoc
,
772 bool IsUnevaluatedContext
) {
774 if (IsUnevaluatedContext
)
775 PushExpressionEvaluationContext(
776 ExpressionEvaluationContext::UnevaluatedAbstract
,
777 ReuseLambdaContextDecl
);
779 ExprResult Result
= ActOnIdExpression(getCurScope(), SS
, TemplateKWLoc
, Id
,
780 /*trailing lparen*/ false,
781 /*is & operand*/ false,
782 /*CorrectionCandidateCallback=*/nullptr,
783 /*IsInlineAsmIdentifier=*/ true);
785 if (IsUnevaluatedContext
)
786 PopExpressionEvaluationContext();
788 if (!Result
.isUsable()) return Result
;
790 Result
= CheckPlaceholderExpr(Result
.get());
791 if (!Result
.isUsable()) return Result
;
793 // Referring to parameters is not allowed in naked functions.
794 if (CheckNakedParmReference(Result
.get(), *this))
797 QualType T
= Result
.get()->getType();
799 if (T
->isDependentType()) {
803 // Any sort of function type is fine.
804 if (T
->isFunctionType()) {
808 // Otherwise, it needs to be a complete type.
809 if (RequireCompleteExprType(Result
.get(), diag::err_asm_incomplete_type
)) {
816 bool Sema::LookupInlineAsmField(StringRef Base
, StringRef Member
,
817 unsigned &Offset
, SourceLocation AsmLoc
) {
819 SmallVector
<StringRef
, 2> Members
;
820 Member
.split(Members
, ".");
822 NamedDecl
*FoundDecl
= nullptr;
824 // MS InlineAsm uses 'this' as a base
825 if (getLangOpts().CPlusPlus
&& Base
== "this") {
826 if (const Type
*PT
= getCurrentThisType().getTypePtrOrNull())
827 FoundDecl
= PT
->getPointeeType()->getAsTagDecl();
829 LookupResult
BaseResult(*this, &Context
.Idents
.get(Base
), SourceLocation(),
831 if (LookupName(BaseResult
, getCurScope()) && BaseResult
.isSingleResult())
832 FoundDecl
= BaseResult
.getFoundDecl();
838 for (StringRef NextMember
: Members
) {
839 const RecordType
*RT
= nullptr;
840 if (VarDecl
*VD
= dyn_cast
<VarDecl
>(FoundDecl
))
841 RT
= VD
->getType()->getAs
<RecordType
>();
842 else if (TypedefNameDecl
*TD
= dyn_cast
<TypedefNameDecl
>(FoundDecl
)) {
843 MarkAnyDeclReferenced(TD
->getLocation(), TD
, /*OdrUse=*/false);
844 // MS InlineAsm often uses struct pointer aliases as a base
845 QualType QT
= TD
->getUnderlyingType();
846 if (const auto *PT
= QT
->getAs
<PointerType
>())
847 QT
= PT
->getPointeeType();
848 RT
= QT
->getAs
<RecordType
>();
849 } else if (TypeDecl
*TD
= dyn_cast
<TypeDecl
>(FoundDecl
))
850 RT
= TD
->getTypeForDecl()->getAs
<RecordType
>();
851 else if (FieldDecl
*TD
= dyn_cast
<FieldDecl
>(FoundDecl
))
852 RT
= TD
->getType()->getAs
<RecordType
>();
856 if (RequireCompleteType(AsmLoc
, QualType(RT
, 0),
857 diag::err_asm_incomplete_type
))
860 LookupResult
FieldResult(*this, &Context
.Idents
.get(NextMember
),
861 SourceLocation(), LookupMemberName
);
863 if (!LookupQualifiedName(FieldResult
, RT
->getDecl()))
866 if (!FieldResult
.isSingleResult())
868 FoundDecl
= FieldResult
.getFoundDecl();
870 // FIXME: Handle IndirectFieldDecl?
871 FieldDecl
*FD
= dyn_cast
<FieldDecl
>(FoundDecl
);
875 const ASTRecordLayout
&RL
= Context
.getASTRecordLayout(RT
->getDecl());
876 unsigned i
= FD
->getFieldIndex();
877 CharUnits Result
= Context
.toCharUnitsFromBits(RL
.getFieldOffset(i
));
878 Offset
+= (unsigned)Result
.getQuantity();
885 Sema::LookupInlineAsmVarDeclField(Expr
*E
, StringRef Member
,
886 SourceLocation AsmLoc
) {
888 QualType T
= E
->getType();
889 if (T
->isDependentType()) {
890 DeclarationNameInfo NameInfo
;
891 NameInfo
.setLoc(AsmLoc
);
892 NameInfo
.setName(&Context
.Idents
.get(Member
));
893 return CXXDependentScopeMemberExpr::Create(
894 Context
, E
, T
, /*IsArrow=*/false, AsmLoc
, NestedNameSpecifierLoc(),
896 /*FirstQualifierFoundInScope=*/nullptr, NameInfo
, /*TemplateArgs=*/nullptr);
899 const RecordType
*RT
= T
->getAs
<RecordType
>();
900 // FIXME: Diagnose this as field access into a scalar type.
904 LookupResult
FieldResult(*this, &Context
.Idents
.get(Member
), AsmLoc
,
907 if (!LookupQualifiedName(FieldResult
, RT
->getDecl()))
910 // Only normal and indirect field results will work.
911 ValueDecl
*FD
= dyn_cast
<FieldDecl
>(FieldResult
.getFoundDecl());
913 FD
= dyn_cast
<IndirectFieldDecl
>(FieldResult
.getFoundDecl());
917 // Make an Expr to thread through OpDecl.
918 ExprResult Result
= BuildMemberReferenceExpr(
919 E
, E
->getType(), AsmLoc
, /*IsArrow=*/false, CXXScopeSpec(),
920 SourceLocation(), nullptr, FieldResult
, nullptr, nullptr);
925 StmtResult
Sema::ActOnMSAsmStmt(SourceLocation AsmLoc
, SourceLocation LBraceLoc
,
926 ArrayRef
<Token
> AsmToks
,
928 unsigned NumOutputs
, unsigned NumInputs
,
929 ArrayRef
<StringRef
> Constraints
,
930 ArrayRef
<StringRef
> Clobbers
,
931 ArrayRef
<Expr
*> Exprs
,
932 SourceLocation EndLoc
) {
933 bool IsSimple
= (NumOutputs
!= 0 || NumInputs
!= 0);
934 setFunctionHasBranchProtectedScope();
936 bool InvalidOperand
= false;
937 for (uint64_t I
= 0; I
< NumOutputs
+ NumInputs
; ++I
) {
939 if (E
->getType()->isBitIntType()) {
940 InvalidOperand
= true;
941 Diag(E
->getBeginLoc(), diag::err_asm_invalid_type
)
942 << E
->getType() << (I
< NumOutputs
)
943 << E
->getSourceRange();
944 } else if (E
->refersToBitField()) {
945 InvalidOperand
= true;
946 FieldDecl
*BitField
= E
->getSourceBitField();
947 Diag(E
->getBeginLoc(), diag::err_ms_asm_bitfield_unsupported
)
948 << E
->getSourceRange();
949 Diag(BitField
->getLocation(), diag::note_bitfield_decl
);
956 new (Context
) MSAsmStmt(Context
, AsmLoc
, LBraceLoc
, IsSimple
,
957 /*IsVolatile*/ true, AsmToks
, NumOutputs
, NumInputs
,
958 Constraints
, Exprs
, AsmString
,
963 LabelDecl
*Sema::GetOrCreateMSAsmLabel(StringRef ExternalLabelName
,
964 SourceLocation Location
,
966 LabelDecl
* Label
= LookupOrCreateLabel(PP
.getIdentifierInfo(ExternalLabelName
),
969 if (Label
->isMSAsmLabel()) {
970 // If we have previously created this label implicitly, mark it as used.
971 Label
->markUsed(Context
);
973 // Otherwise, insert it, but only resolve it if we have seen the label itself.
974 std::string InternalName
;
975 llvm::raw_string_ostream
OS(InternalName
);
976 // Create an internal name for the label. The name should not be a valid
977 // mangled name, and should be unique. We use a dot to make the name an
978 // invalid mangled name. We use LLVM's inline asm ${:uid} escape so that a
979 // unique label is generated each time this blob is emitted, even after
981 OS
<< "__MSASMLABEL_.${:uid}__";
982 for (char C
: ExternalLabelName
) {
984 // We escape '$' in asm strings by replacing it with "$$"
988 Label
->setMSAsmLabel(OS
.str());
991 // The label might have been created implicitly from a previously encountered
992 // goto statement. So, for both newly created and looked up labels, we mark
994 Label
->setMSAsmLabelResolved();
996 // Adjust their location for being able to generate accurate diagnostics.
997 Label
->setLocation(Location
);