24 #include "llvm/ADT/ArrayRef.h"
25 #include "llvm/ADT/BitVector.h"
26 #include "llvm/MC/MCParser/MCAsmParser.h"
27 using namespace clang;
50 S.
Diag(E2->getLocStart(), diag::err_invalid_asm_cast_lvalue)
51 << E->getSourceRange();
53 S.
Diag(E2->getLocStart(), diag::warn_invalid_asm_cast_lvalue)
54 << E->getSourceRange();
67 for (
unsigned p = 0, e = AsmStrPieces.size();
p != e; ++
p) {
83 if (!Func->
hasAttr<NakedAttr>())
87 WorkList.push_back(E);
88 while (WorkList.size()) {
89 Expr *E = WorkList.pop_back_val();
90 if (isa<CXXThisExpr>(E)) {
91 S.
Diag(E->getLocStart(), diag::err_asm_naked_this_ref);
92 S.
Diag(Func->
getAttr<NakedAttr>()->getLocation(), diag::note_attribute);
96 if (isa<ParmVarDecl>(DRE->getDecl())) {
97 S.
Diag(DRE->getLocStart(), diag::err_asm_naked_parm_ref);
98 S.
Diag(Func->
getAttr<NakedAttr>()->getLocation(), diag::note_attribute);
102 for (
Stmt *Child : E->children()) {
103 if (
Expr *E = dyn_cast_or_null<Expr>(Child))
104 WorkList.push_back(E);
111 bool IsVolatile,
unsigned NumOutputs,
116 unsigned NumClobbers = clobbers.size();
127 bool ValidateConstraints =
130 for (
unsigned i = 0; i != NumOutputs; i++) {
134 StringRef OutputName;
136 OutputName = Names[i]->
getName();
139 if (ValidateConstraints &&
142 diag::err_asm_invalid_output_constraint)
143 << Info.getConstraintStr());
145 ExprResult ER = CheckPlaceholderExpr(Exprs[i]);
151 Expr *OutputExpr = Exprs[i];
160 diag::err_asm_bitfield_in_memory_constraint)
162 << Info.getConstraintStr()
163 << OutputExpr->getSourceRange());
165 OutputConstraintInfos.push_back(Info);
182 if (!getLangOpts().HeinousExtensions) {
183 Diag(LVal->getLocStart(), diag::err_invalid_asm_cast_lvalue)
184 << OutputExpr->getSourceRange();
186 Diag(LVal->getLocStart(), diag::warn_invalid_asm_cast_lvalue)
187 << OutputExpr->getSourceRange();
194 if (RequireCompleteType(OutputExpr->getLocStart(), Exprs[i]->getType(),
195 diag::err_dereference_incomplete_type))
199 diag::err_asm_invalid_lvalue_in_output)
200 << OutputExpr->getSourceRange());
207 diag::err_asm_invalid_output_size)
208 << Info.getConstraintStr());
213 for (
unsigned i = NumOutputs, e = NumOutputs + NumInputs; i != e; i++) {
219 InputName = Names[i]->
getName();
222 if (ValidateConstraints &&
224 OutputConstraintInfos.data(), NumOutputs, Info)) {
226 diag::err_asm_invalid_input_constraint)
227 << Info.getConstraintStr());
230 ExprResult ER = CheckPlaceholderExpr(Exprs[i]);
235 Expr *InputExpr = Exprs[i];
244 diag::err_asm_bitfield_in_memory_constraint)
246 << Info.getConstraintStr()
247 << InputExpr->getSourceRange());
250 if (Info.allowsMemory() && !Info.allowsRegister()) {
253 diag::err_asm_invalid_lvalue_in_input)
254 << Info.getConstraintStr()
255 << InputExpr->getSourceRange());
256 }
else if (Info.requiresImmediateConstant() && !Info.allowsRegister()) {
261 Diag(InputExpr->getLocStart(), diag::err_asm_immediate_expected)
262 << Info.getConstraintStr() << InputExpr->getSourceRange());
263 if (Result.slt(Info.getImmConstantMin()) ||
264 Result.sgt(Info.getImmConstantMax()))
266 diag::err_invalid_asm_value_for_constraint)
267 << Result.toString(10) << Info.getConstraintStr()
268 << InputExpr->getSourceRange());
276 Exprs[i] = Result.
get();
279 if (Info.allowsRegister()) {
282 diag::err_asm_invalid_type_in_input)
283 << InputExpr->
getType() << Info.getConstraintStr()
284 << InputExpr->getSourceRange());
288 InputConstraintInfos.push_back(Info);
290 const Type *Ty = Exprs[i]->getType().getTypePtr();
294 if (!Ty->
isVoidType() || !Info.allowsMemory())
295 if (RequireCompleteType(InputExpr->getLocStart(), Exprs[i]->getType(),
296 diag::err_dereference_incomplete_type))
303 diag::err_asm_invalid_input_size)
304 << Info.getConstraintStr());
308 for (
unsigned i = 0; i != NumClobbers; i++) {
312 StringRef Clobber = Literal->
getString();
316 diag::err_asm_unknown_register_name) << Clobber);
321 NumInputs, Names, Constraints, Exprs.data(),
322 AsmString, NumClobbers, Clobbers, RParenLoc);
328 Diag(getLocationOfStringLiteralByte(AsmString, DiagOffs), DiagID)
329 << AsmString->getSourceRange();
334 for (
unsigned i = 0, e = Pieces.size(); i != e; ++i) {
344 if (ConstraintIdx >= NumOperands) {
347 for (
unsigned Cnt = ConstraintIdx - NumOperands; I != E; ++I)
348 if (OutputConstraintInfos[I].isReadWrite() && Cnt-- == 0) {
353 assert(I != E &&
"Invalid operand number should have been caught in "
354 " AnalyzeAsmString");
359 const Type *Ty = Exprs[ConstraintIdx]->getType().getTypePtr();
364 std::string SuggestedModifier;
367 SuggestedModifier)) {
368 Diag(Exprs[ConstraintIdx]->getLocStart(),
369 diag::warn_asm_mismatched_size_modifier);
371 if (!SuggestedModifier.empty()) {
373 diag::note_asm_missing_constraint_modifier)
374 << SuggestedModifier;
375 SuggestedModifier =
"%" + SuggestedModifier + Piece.
getString();
383 unsigned NumAlternatives = ~0U;
384 for (
unsigned i = 0, e = OutputConstraintInfos.size(); i != e; ++i) {
387 unsigned AltCount = ConstraintStr.count(
',') + 1;
388 if (NumAlternatives == ~0U)
389 NumAlternatives = AltCount;
390 else if (NumAlternatives != AltCount)
392 diag::err_asm_unexpected_constraint_alternatives)
393 << NumAlternatives << AltCount);
395 for (
unsigned i = 0, e = InputConstraintInfos.size(); i != e; ++i) {
398 unsigned AltCount = ConstraintStr.count(
',') + 1;
399 if (NumAlternatives == ~0U)
400 NumAlternatives = AltCount;
401 else if (NumAlternatives != AltCount)
403 diag::err_asm_unexpected_constraint_alternatives)
404 << NumAlternatives << AltCount);
412 unsigned InputOpNo = i+NumOutputs;
413 Expr *OutputExpr = Exprs[TiedTo];
414 Expr *InputExpr = Exprs[InputOpNo];
427 AD_Int, AD_FP, AD_Other
428 } InputDomain, OutputDomain;
431 InputDomain = AD_Int;
435 InputDomain = AD_Other;
438 OutputDomain = AD_Int;
440 OutputDomain = AD_FP;
442 OutputDomain = AD_Other;
452 if (OutSize == InSize && InputDomain == OutputDomain &&
453 InputDomain != AD_Other)
459 bool SmallerValueMentioned =
false;
467 SmallerValueMentioned |= InSize < OutSize;
472 SmallerValueMentioned |= OutSize < InSize;
478 if (!SmallerValueMentioned && InputDomain != AD_Other &&
479 OutputConstraintInfos[TiedTo].allowsRegister())
486 if (InputDomain == AD_Int && OutputDomain == AD_Int &&
491 InputExpr = ImpCastExprToType(InputExpr, OutTy, castKind).get();
492 Exprs[InputOpNo] = InputExpr;
497 Diag(InputExpr->getLocStart(),
498 diag::err_asm_tying_incompatible_types)
499 << InTy << OutTy << OutputExpr->getSourceRange()
500 << InputExpr->getSourceRange();
510 llvm::InlineAsmIdentifierInfo &Info,
511 bool IsUnevaluatedContext) {
514 if (IsUnevaluatedContext)
515 PushExpressionEvaluationContext(UnevaluatedAbstract,
516 ReuseLambdaContextDecl);
524 if (IsUnevaluatedContext)
525 PopExpressionEvaluationContext();
527 if (!Result.
isUsable())
return Result;
529 Result = CheckPlaceholderExpr(Result.
get());
530 if (!Result.
isUsable())
return Result;
550 if (RequireCompleteExprType(Result.
get(), diag::err_asm_incomplete_type)) {
559 Info.Length = Info.Size / Info.Type;
564 Info.IsVarDecl =
true;
583 if (
VarDecl *VD = dyn_cast<VarDecl>(FoundDecl))
586 MarkAnyDeclReferenced(TD->getLocation(), TD,
false);
588 }
else if (
TypeDecl *TD = dyn_cast<TypeDecl>(FoundDecl))
593 if (RequireCompleteType(AsmLoc,
QualType(RT, 0), 0))
599 if (!LookupQualifiedName(FieldResult, RT->
getDecl()))
618 unsigned NumOutputs,
unsigned NumInputs,
623 bool IsSimple = (NumOutputs != 0 || NumInputs != 0);
624 getCurFunction()->setHasBranchProtectedScope();
627 true, AsmToks, NumOutputs, NumInputs,
628 Constraints, Exprs, AsmString,
636 LabelDecl* Label = LookupOrCreateLabel(PP.getIdentifierInfo(ExternalLabelName),
644 std::string InternalName;
645 llvm::raw_string_ostream OS(InternalName);
649 OS <<
"__MSASMLABEL_." << MSAsmLabelNameCounter++ <<
"__" << ExternalLabelName;
unsigned getNumOutputs() const
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
bool isEvaluatable(const ASTContext &Ctx) const
SourceLocation getBegin() const
const LangOptions & getLangOpts() const
StmtResult ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, bool IsVolatile, unsigned NumOutputs, unsigned NumInputs, IdentifierInfo **Names, MultiExprArg Constraints, MultiExprArg Exprs, Expr *AsmString, MultiExprArg Clobbers, SourceLocation RParenLoc)
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
Emit a diagnostic.
bool validateOutputConstraint(ConstraintInfo &Info) const
bool isBooleanType() const
SourceLocation getLocStart() const LLVM_READONLY
void setInputExpr(unsigned i, Expr *E)
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
virtual bool validateConstraintModifier(StringRef, char, unsigned, std::string &) const
Defines the clang::Expr interface and subclasses for C++ expressions.
const std::string & getConstraintStr() const
unsigned getNumInputs() const
bool hasSameType(QualType T1, QualType T2) const
Determine whether the given types T1 and T2 are equivalent.
virtual bool validateOutputSize(StringRef, unsigned) const
static bool isOperandMentioned(unsigned OpNo, ArrayRef< GCCAsmStmt::AsmStringPiece > AsmStrPieces)
LabelDecl * GetOrCreateMSAsmLabel(StringRef ExternalLabelName, SourceLocation Location, bool AlwaysCreate)
virtual bool validateInputSize(StringRef, unsigned) const
Type(TypeClass tc, QualType canon, bool Dependent, bool InstantiationDependent, bool VariablyModified, bool ContainsUnexpandedParameterPack)
Represents a C++ unqualified-id that has been parsed.
Represents the results of name lookup.
const TargetInfo & getTargetInfo() const
static bool CheckAsmLValue(const Expr *E, Sema &S)
const ArrayType * getAsArrayType(QualType T) const
SourceLocation getLocStart() const LLVM_READONLY
bool isValueDependent() const
Expr * getOutputExpr(unsigned i)
RecordDecl * getDecl() const
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D...
uint64_t getFieldOffset(unsigned FieldNo) const
Represents a C++ nested-name-specifier or a global scope specifier.
bool isIncompleteType(NamedDecl **Def=nullptr) const
Def If non-NULL, and the type refers to some kind of declaration that can be completed (such as a C s...
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
Sema - This implements semantic analysis and AST building for C.
Expr * IgnoreParenNoopCasts(ASTContext &Ctx) LLVM_READONLY
CastKind
CastKind - The kind of operation required for a conversion.
ExprResult LookupInlineAsmIdentifier(CXXScopeSpec &SS, SourceLocation TemplateKWLoc, UnqualifiedId &Id, llvm::InlineAsmIdentifierInfo &Info, bool IsUnevaluatedContext)
static bool CheckNakedParmReference(Expr *E, Sema &S)
bool isRealFloatingType() const
Floating point categories.
StringRef getName() const
Return the actual identifier string.
bool isValidClobber(StringRef Name) const
Returns whether the passed in string is a valid clobber in an inline asm statement.
Defines the clang::Preprocessor interface.
bool isMSAsmLabel() const
isModifiableLvalueResult isModifiableLvalue(ASTContext &Ctx, SourceLocation *Loc=nullptr) const
Defines the clang::TypeLoc interface and its subclasses.
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
bool isDependentType() const
bool EvaluateAsInt(llvm::APSInt &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects) const
void setLocation(SourceLocation L)
unsigned getTiedOperand() const
The result type of a method or function.
Encodes a location in the source. The SourceManager can decode this to get at the full include stack...
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
CharSourceRange getRange() const
bool LookupInlineAsmField(StringRef Base, StringRef Member, unsigned &Offset, SourceLocation AsmLoc)
Expr * getInputExpr(unsigned i)
bool isTypeDependent() const
ActionResult< CXXBaseSpecifier * > BaseResult
bool refersToBitField() const
Returns true if this expression is a gl-value that potentially refers to a bit-field.
Base class for declarations which introduce a typedef-name.
unsigned AnalyzeAsmString(SmallVectorImpl< AsmStringPiece > &Pieces, const ASTContext &C, unsigned &DiagOffs) const
static __inline__ uint32_t volatile uint32_t * p
bool hasTiedOperand() const
Return true if this input operand is a matching constraint that ties it to an output operand...
StringRef getString() const
bool DeclAttrsMatchCUDAMode(const LangOptions &LangOpts, Decl *D)
bool isFunctionType() const
unsigned getOperandNo() const
unsigned getFieldIndex() const
void markUsed(ASTContext &C)
Mark the declaration used, in the sense of odr-use.
const std::string & getString() const
void setMSAsmLabel(StringRef Name)
DeclContext * CurContext
CurContext - This is the current declaration context of parsing.
static FixItHint CreateReplacement(CharSourceRange RemoveRange, StringRef Code)
Create a code modification hint that replaces the given source range with the given code string...
Defines the clang::TargetInfo interface.
StmtResult 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)
bool validateInputConstraint(ConstraintInfo *OutputConstraints, unsigned NumOutputs, ConstraintInfo &info) const
A reference to a declared variable, function, enum, etc. [C99 6.5.1p2].
QualType getElementType() const
void setMSAsmLabelResolved()
bool isIntegerType() const
bool isPointerType() const