24 #include "llvm/ADT/ArrayRef.h" 25 #include "llvm/ADT/StringSet.h" 26 #include "llvm/MC/MCParser/MCAsmParser.h" 27 using namespace clang;
33 Expr *ExprUnderCast =
nullptr;
37 ParentsToUpdate.push_back(Parent);
38 if (
auto *ParenE = dyn_cast<ParenExpr>(Parent)) {
39 Parent = ParenE->getSubExpr();
43 Expr *Child =
nullptr;
50 if (
auto *CastE = dyn_cast<CastExpr>(Child))
51 if (CastE->getCastKind() == CK_LValueToRValue) {
52 ExprUnderCast = CastE->getSubExpr();
61 assert(ExprUnderCast &&
62 "Should be reachable only if LValueToRValue cast was found!");
64 for (
Expr *E : ParentsToUpdate)
115 for (
unsigned p = 0, e = AsmStrPieces.size(); p != e; ++p) {
132 if (!Func->
hasAttr<NakedAttr>())
136 WorkList.push_back(E);
137 while (WorkList.size()) {
138 Expr *E = WorkList.pop_back_val();
139 if (isa<CXXThisExpr>(E)) {
141 S.
Diag(Func->
getAttr<NakedAttr>()->getLocation(), diag::note_attribute);
145 if (isa<ParmVarDecl>(DRE->getDecl())) {
146 S.
Diag(DRE->getBeginLoc(), diag::err_asm_naked_parm_ref);
147 S.
Diag(Func->
getAttr<NakedAttr>()->getLocation(), diag::note_attribute);
152 if (
Expr *E = dyn_cast_or_null<Expr>(Child))
153 WorkList.push_back(E);
163 bool is_input_expr) {
169 } EType = ExprSafeType;
174 EType = ExprBitfield;
176 EType = ExprVectorElt;
178 EType = ExprGlobalRegVar;
180 if (EType != ExprSafeType) {
181 S.
Diag(E->
getBeginLoc(), diag::err_asm_non_addr_value_in_memory_constraint)
195 if (
const DeclRefExpr *AsmDeclRef = dyn_cast<DeclRefExpr>(Expression)) {
197 const VarDecl *Variable = dyn_cast<
VarDecl>(AsmDeclRef->getDecl());
199 if (AsmLabelAttr *
Attr = Variable->
getAttr<AsmLabelAttr>())
214 llvm::StringSet<> InOutVars;
217 for (
unsigned int i = 0; i < Exprs.size(); ++i) {
218 StringRef Constraint = Constraints[i]->
getString();
222 InOutVars.insert(InOutReg);
226 for (
int i = 0; i < NumClobbers; ++i) {
227 StringRef Clobber = Clobbers[i]->
getString();
230 if (Clobber ==
"cc" || Clobber ==
"memory")
234 if (InOutVars.count(Clobber))
235 return Clobbers[i]->getBeginLoc();
241 bool IsVolatile,
unsigned NumOutputs,
246 unsigned NumClobbers = clobbers.size();
261 Context, AsmLoc, IsSimple, IsVolatile, NumOutputs, NumInputs, Names,
262 Constraints, Exprs.data(), AsmString, NumClobbers, Clobbers, RParenLoc);
266 for (
unsigned i = 0; i != NumOutputs; i++) {
270 StringRef OutputName;
272 OutputName = Names[i]->
getName();
278 << Info.getConstraintStr());
280 ExprResult ER = CheckPlaceholderExpr(Exprs[i]);
286 Expr *OutputExpr = Exprs[i];
293 if (Info.allowsMemory() &&
297 OutputConstraintInfos.push_back(Info);
320 if (RequireCompleteType(OutputExpr->
getBeginLoc(), Exprs[i]->getType(),
321 diag::err_dereference_incomplete_type))
326 diag::err_asm_invalid_lvalue_in_output)
335 << Info.getConstraintStr());
340 for (
unsigned i = NumOutputs, e = NumOutputs + NumInputs; i != e; i++) {
346 InputName = Names[i]->
getName();
353 << Info.getConstraintStr());
356 ExprResult ER = CheckPlaceholderExpr(Exprs[i]);
361 Expr *InputExpr = Exprs[i];
368 if (Info.allowsMemory() &&
373 if (Info.allowsMemory() && !Info.allowsRegister()) {
376 diag::err_asm_invalid_lvalue_in_input)
377 << Info.getConstraintStr()
379 }
else if (Info.requiresImmediateConstant() && !Info.allowsRegister()) {
389 llvm::APSInt IntResult;
396 if (!Info.isValidAsmImmediate(IntResult))
398 diag::err_invalid_asm_value_for_constraint)
399 << IntResult.toString(10) << Info.getConstraintStr()
404 ExprResult Result = DefaultFunctionArrayLvalueConversion(Exprs[i]);
408 Exprs[i] = Result.
get();
411 if (Info.allowsRegister()) {
415 << InputExpr->
getType() << Info.getConstraintStr()
420 InputConstraintInfos.push_back(Info);
422 const Type *Ty = Exprs[i]->getType().getTypePtr();
426 if (!Ty->
isVoidType() || !Info.allowsMemory())
427 if (RequireCompleteType(InputExpr->
getBeginLoc(), Exprs[i]->getType(),
428 diag::err_dereference_incomplete_type))
436 << Info.getConstraintStr());
440 for (
unsigned i = 0; i != NumClobbers; i++) {
444 StringRef Clobber = Literal->
getString();
453 new (Context)
GCCAsmStmt(Context, AsmLoc, IsSimple, IsVolatile, NumOutputs,
454 NumInputs, Names, Constraints, Exprs.data(),
455 AsmString, NumClobbers, Clobbers, RParenLoc);
461 Diag(getLocationOfStringLiteralByte(AsmString, DiagOffs), DiagID)
467 for (
unsigned i = 0, e = Pieces.size(); i != e; ++i) {
477 if (ConstraintIdx >= NumOperands) {
480 for (
unsigned Cnt = ConstraintIdx - NumOperands; I != E; ++I)
481 if (OutputConstraintInfos[I].isReadWrite() && Cnt-- == 0) {
486 assert(I != E &&
"Invalid operand number should have been caught in " 487 " AnalyzeAsmString");
492 const Type *Ty = Exprs[ConstraintIdx]->getType().getTypePtr();
497 std::string SuggestedModifier;
500 SuggestedModifier)) {
501 Diag(Exprs[ConstraintIdx]->getBeginLoc(),
502 diag::warn_asm_mismatched_size_modifier);
504 if (!SuggestedModifier.empty()) {
506 diag::note_asm_missing_constraint_modifier)
507 << SuggestedModifier;
508 SuggestedModifier =
"%" + SuggestedModifier + Piece.
getString();
516 unsigned NumAlternatives = ~0U;
517 for (
unsigned i = 0, e = OutputConstraintInfos.size(); i != e; ++i) {
520 unsigned AltCount = ConstraintStr.count(
',') + 1;
521 if (NumAlternatives == ~0U)
522 NumAlternatives = AltCount;
523 else if (NumAlternatives != AltCount)
525 diag::err_asm_unexpected_constraint_alternatives)
526 << NumAlternatives << AltCount);
530 for (
unsigned i = 0, e = InputConstraintInfos.size(); i != e; ++i) {
533 unsigned AltCount = ConstraintStr.count(
',') + 1;
534 if (NumAlternatives == ~0U)
535 NumAlternatives = AltCount;
536 else if (NumAlternatives != AltCount)
538 diag::err_asm_unexpected_constraint_alternatives)
539 << NumAlternatives << AltCount);
547 unsigned InputOpNo = i+NumOutputs;
548 Expr *OutputExpr = Exprs[TiedTo];
549 Expr *InputExpr = Exprs[InputOpNo];
552 assert(TiedTo < InputMatchedToOutput.size() &&
"TiedTo value out of range");
553 if (InputMatchedToOutput[TiedTo] != ~0U) {
555 diag::err_asm_input_duplicate_match)
558 diag::note_asm_input_duplicate_first)
562 InputMatchedToOutput[TiedTo] = i;
575 AD_Int, AD_FP, AD_Other
576 } InputDomain, OutputDomain;
579 InputDomain = AD_Int;
583 InputDomain = AD_Other;
586 OutputDomain = AD_Int;
588 OutputDomain = AD_FP;
590 OutputDomain = AD_Other;
600 if (OutSize == InSize && InputDomain == OutputDomain &&
601 InputDomain != AD_Other)
607 bool SmallerValueMentioned =
false;
615 SmallerValueMentioned |= InSize < OutSize;
620 SmallerValueMentioned |= OutSize < InSize;
626 if (!SmallerValueMentioned && InputDomain != AD_Other &&
627 OutputConstraintInfos[TiedTo].allowsRegister())
634 if (InputDomain == AD_Int && OutputDomain == AD_Int &&
638 (OutTy->
isBooleanType() ? CK_IntegralToBoolean : CK_IntegralCast);
639 InputExpr = ImpCastExprToType(InputExpr, OutTy, castKind).get();
640 Exprs[InputOpNo] = InputExpr;
656 return Diag(ConstraintLoc, diag::error_inoutput_conflict_with_clobber);
662 llvm::InlineAsmIdentifierInfo &Info) {
666 return Info.setLabel(Res);
669 return Info.setEnum(Eval.
Val.
getInt().getSExtValue());
670 return Info.setLabel(Res);
673 unsigned Type = Size;
676 bool IsGlobalLV =
false;
679 Info.setVar(Res, IsGlobalLV, Size, Type);
685 bool IsUnevaluatedContext) {
687 if (IsUnevaluatedContext)
688 PushExpressionEvaluationContext(
689 ExpressionEvaluationContext::UnevaluatedAbstract,
690 ReuseLambdaContextDecl);
692 ExprResult Result = ActOnIdExpression(getCurScope(), SS, TemplateKWLoc, Id,
698 if (IsUnevaluatedContext)
699 PopExpressionEvaluationContext();
701 if (!Result.
isUsable())
return Result;
703 Result = CheckPlaceholderExpr(Result.
get());
704 if (!Result.
isUsable())
return Result;
722 if (RequireCompleteExprType(Result.
get(), diag::err_asm_incomplete_type)) {
733 Member.split(Members,
".");
738 if (getLangOpts().
CPlusPlus && Base.equals(
"this")) {
739 if (
const Type *PT = getCurrentThisType().getTypePtrOrNull())
740 FoundDecl = PT->getPointeeType()->getAsTagDecl();
751 for (StringRef NextMember : Members) {
753 if (
VarDecl *VD = dyn_cast<VarDecl>(FoundDecl))
756 MarkAnyDeclReferenced(TD->getLocation(), TD,
false);
758 QualType QT = TD->getUnderlyingType();
762 }
else if (
TypeDecl *TD = dyn_cast<TypeDecl>(FoundDecl))
764 else if (
FieldDecl *TD = dyn_cast<FieldDecl>(FoundDecl))
769 if (RequireCompleteType(AsmLoc,
QualType(RT, 0),
770 diag::err_asm_incomplete_type))
776 if (!LookupQualifiedName(FieldResult, RT->
getDecl()))
779 if (!FieldResult.isSingleResult())
781 FoundDecl = FieldResult.getFoundDecl();
809 nullptr, NameInfo,
nullptr);
820 if (!LookupQualifiedName(FieldResult, RT->
getDecl()))
841 unsigned NumOutputs,
unsigned NumInputs,
846 bool IsSimple = (NumOutputs != 0 || NumInputs != 0);
847 setFunctionHasBranchProtectedScope();
849 new (Context)
MSAsmStmt(Context, AsmLoc, LBraceLoc, IsSimple,
850 true, AsmToks, NumOutputs, NumInputs,
851 Constraints, Exprs, AsmString,
859 LabelDecl*
Label = LookupOrCreateLabel(PP.getIdentifierInfo(ExternalLabelName),
867 std::string InternalName;
868 llvm::raw_string_ostream OS(InternalName);
874 OS <<
"__MSASMLABEL_.${:uid}__";
875 for (
char C : ExternalLabelName) {
This represents a GCC inline-assembly statement extension.
Represents a function declaration or definition.
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.
unsigned getNumInputs() const
PointerType - C99 6.7.5.1 - Pointer Declarators.
A (possibly-)qualified type.
void FillInlineAsmIdentifierInfo(Expr *Res, llvm::InlineAsmIdentifierInfo &Info)
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D...
Stmt - This represents one statement.
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee...
StmtResult ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, bool IsVolatile, unsigned NumOutputs, unsigned NumInputs, IdentifierInfo **Names, MultiExprArg Constraints, MultiExprArg Exprs, Expr *AsmString, MultiExprArg Clobbers, SourceLocation RParenLoc)
bool isRealFloatingType() const
Floating point categories.
StorageClass getStorageClass() const
Returns the storage class as written in the source.
unsigned getNumOutputs() const
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
Emit a diagnostic.
unsigned getFieldIndex() const
Returns the index of this field within its record, as appropriate for passing to ASTRecordLayout::get...
static void emitAndFixInvalidAsmCastLValue(const Expr *LVal, Expr *BadArgument, Sema &S)
Emit a warning about usage of "noop"-like casts for lvalues (GNU extension) and fix the argument with...
The base class of the type hierarchy.
bool validateInputConstraint(MutableArrayRef< ConstraintInfo > OutputConstraints, ConstraintInfo &info) const
const TargetInfo & getTargetInfo() const
void setInputExpr(unsigned i, Expr *E)
Represents a variable declaration or definition.
const T * getAs() const
Member-template getAs<specific type>'.
unsigned AnalyzeAsmString(SmallVectorImpl< AsmStringPiece > &Pieces, const ASTContext &C, unsigned &DiagOffs) const
AnalyzeAsmString - Analyze the asm string of the current asm, decomposing it into pieces...
Defines the clang::Expr interface and subclasses for C++ expressions.
static bool checkExprMemoryConstraintCompat(Sema &S, Expr *E, TargetInfo::ConstraintInfo &Info, bool is_input_expr)
Returns true if given expression is not compatible with inline assembly's memory constraint; false ot...
Expr * IgnoreImpCasts() LLVM_READONLY
IgnoreImpCasts - Skip past any implicit casts which might surround this expression.
One of these records is kept for each identifier that is lexed.
SourceLocation getBegin() const
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
A C++ nested-name-specifier augmented with source location information.
StringRef getNormalizedGCCRegisterName(StringRef Name, bool ReturnCanonical=false) const
Returns the "normalized" GCC register name.
virtual bool validateConstraintModifier(StringRef, char, unsigned, std::string &) const
SourceLocation getBeginLoc() const LLVM_READONLY
Represents a member of a struct/union/class.
CharSourceRange getRange() const
void setName(DeclarationName N)
setName - Sets the embedded declaration name.
static bool isOperandMentioned(unsigned OpNo, ArrayRef< GCCAsmStmt::AsmStringPiece > AsmStrPieces)
isOperandMentioned - Return true if the specified operand # is mentioned anywhere in the decomposed a...
LabelDecl * GetOrCreateMSAsmLabel(StringRef ExternalLabelName, SourceLocation Location, bool AlwaysCreate)
Represents a C++ unqualified-id that has been parsed.
Represents the results of name lookup.
bool refersToBitField() const
Returns true if this expression is a gl-value that potentially refers to a bit-field.
CharUnits - This is an opaque type for sizes expressed in character units.
APValue Val
Val - This is the value the expression can be folded to.
ExprValueKind getValueKind() const
getValueKind - The value kind that this expression produces.
Represents a declaration of a type.
virtual StringRef getConstraintRegister(StringRef Constraint, StringRef Expression) const
Extracts a register from the passed constraint (if it is a single-register constraint) and the asm la...
Expr * getOutputExpr(unsigned i)
Represents a C++ nested-name-specifier or a global scope specifier.
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
const LangOptions & getLangOpts() const
bool isTypeDependent() const
isTypeDependent - Determines whether this expression is type-dependent (C++ [temp.dep.expr]), which means that its type could change from one template instantiation to the next.
virtual bool isValidGCCRegisterName(StringRef Name) const
Returns whether the passed in string is a valid register name according to GCC.
ExprResult LookupInlineAsmIdentifier(CXXScopeSpec &SS, SourceLocation TemplateKWLoc, UnqualifiedId &Id, bool IsUnevaluatedContext)
Sema - This implements semantic analysis and AST building for C.
StringRef getString() const
bool EvaluateAsLValue(EvalResult &Result, const ASTContext &Ctx) const
EvaluateAsLValue - Evaluate an expression to see if we can fold it to an lvalue with link time known ...
bool isValidClobber(StringRef Name) const
Returns whether the passed in string is a valid clobber in an inline asm statement.
Expr * IgnoreParenNoopCasts(ASTContext &Ctx) LLVM_READONLY
IgnoreParenNoopCasts - Ignore parentheses and casts that do not change the value (including ptr->int ...
CastKind
CastKind - The kind of operation required for a conversion.
unsigned getOperandNo() const
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
static bool CheckNakedParmReference(Expr *E, Sema &S)
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
Exposes information about the current target.
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
This represents one expression.
static SourceLocation getClobberConflictLocation(MultiExprArg Exprs, StringLiteral **Constraints, StringLiteral **Clobbers, int NumClobbers, const TargetInfo &Target, ASTContext &Cont)
AsmStringPiece - this is part of a decomposed asm string specification (for use with the AnalyzeAsmSt...
Defines the clang::Preprocessor interface.
static CXXDependentScopeMemberExpr * Create(const ASTContext &Ctx, Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, NamedDecl *FirstQualifierFoundInScope, DeclarationNameInfo MemberNameInfo, const TemplateArgumentListInfo *TemplateArgs)
Defines the clang::TypeLoc interface and its subclasses.
void setValueKind(ExprValueKind Cat)
setValueKind - Set the value kind produced by this expression.
ActionResult< CXXBaseSpecifier * > BaseResult
This represents a Microsoft inline-assembly statement extension.
void setLocation(SourceLocation L)
RecordDecl * getDecl() const
uint64_t getFieldOffset(unsigned FieldNo) const
getFieldOffset - Get the offset of the given field index, in bits.
bool EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx, bool InConstantContext=false) const
EvaluateAsRValue - Return true if this is a constant which we can fold to an rvalue using any crazy t...
ActionResult - This structure is used while parsing/acting on expressions, stmts, etc...
bool isGlobalLValue() const
Encodes a location in the source.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
static StringRef extractRegisterName(const Expr *Expression, const TargetInfo &Target)
ExprResult LookupInlineAsmVarDeclField(Expr *RefExpr, StringRef Member, SourceLocation AsmLoc)
Represents the declaration of a label.
static void removeLValueToRValueCast(Expr *E)
Remove the upper-level LValueToRValue cast from an expression.
const std::string & getString() const
const ArrayType * getAsArrayType(QualType T) const
Type Query functions.
bool validateOutputConstraint(ConstraintInfo &Info) const
bool isValueDependent() const
isValueDependent - Determines whether this expression is value-dependent (C++ [temp.dep.constexpr]).
SourceLocation getBeginLoc() const LLVM_READONLY
bool isMSAsmLabel() const
bool LookupInlineAsmField(StringRef Base, StringRef Member, unsigned &Offset, SourceLocation AsmLoc)
bool isLValue() const
isLValue - True if this expression is an "l-value" according to the rules of the current language...
isModifiableLvalueResult isModifiableLvalue(ASTContext &Ctx, SourceLocation *Loc=nullptr) const
isModifiableLvalue - C99 6.3.2.1: an lvalue that does not have array type, does not have an incomplet...
bool refersToVectorElement() const
Returns whether this expression refers to a vector element.
Expr * getInputExpr(unsigned i)
StringRef getName() const
Return the actual identifier string.
Base class for declarations which introduce a typedef-name.
Dataflow Directional Tag Classes.
bool isValid() const
Return true if this is a valid SourceLocation object.
EvalResult is a struct with detailed info about an evaluated expression.
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)
Represents a field injected from an anonymous union/struct into the parent scope. ...
bool isBooleanType() const
char getModifier() const
getModifier - Get the modifier for this operand, if present.
bool hasTiedOperand() const
Return true if this input operand is a matching constraint that ties it to an output operand...
bool toIntegralConstant(APSInt &Result, QualType SrcTy, const ASTContext &Ctx) const
Try to convert this value to an integral constant.
DeclarationNameInfo - A collector data type for bundling together a DeclarationName and the correspnd...
const std::string & getConstraintStr() const
bool DeclAttrsMatchCUDAMode(const LangOptions &LangOpts, Decl *D)
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
bool isFunctionType() const
unsigned getTiedOperand() const
bool hasSameType(QualType T1, QualType T2) const
Determine whether the given types T1 and T2 are equivalent.
void markUsed(ASTContext &C)
Mark the declaration used, in the sense of odr-use.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
bool isIncompleteType(NamedDecl **Def=nullptr) const
Types are partitioned into 3 broad categories (C99 6.2.5p1): object types, function types...
void setLoc(SourceLocation L)
setLoc - Sets the main location of the declaration name.
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
bool refersToGlobalRegisterVar() const
Returns whether this expression refers to a global register variable.
ActionResult< Expr * > ExprResult
virtual bool validateOutputSize(StringRef, unsigned) const
static bool CheckAsmLValue(Expr *E, Sema &S)
CheckAsmLValue - GNU C has an extremely ugly extension whereby they silently ignore "noop" casts in p...
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...
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
StringLiteral - This represents a string literal expression, e.g.
Defines the clang::TargetInfo interface.
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
bool isEvaluatable(const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects) const
isEvaluatable - Call EvaluateAsRValue to see if this expression can be constant folded without side-e...
A reference to a declared variable, function, enum, etc.
bool isPointerType() const
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
void setMSAsmLabelResolved()
virtual bool validateInputSize(StringRef, unsigned) const
This represents a decl that may have a name.
Attr - This represents one attribute.