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()) {
386 llvm::APSInt Result = EVResult.
Val.
getInt();
387 if (!Info.isValidAsmImmediate(Result))
389 diag::err_invalid_asm_value_for_constraint)
390 << Result.toString(10) << Info.getConstraintStr()
395 ExprResult Result = DefaultFunctionArrayLvalueConversion(Exprs[i]);
399 Exprs[i] = Result.
get();
402 if (Info.allowsRegister()) {
406 << InputExpr->
getType() << Info.getConstraintStr()
411 InputConstraintInfos.push_back(Info);
413 const Type *Ty = Exprs[i]->getType().getTypePtr();
417 if (!Ty->
isVoidType() || !Info.allowsMemory())
418 if (RequireCompleteType(InputExpr->
getBeginLoc(), Exprs[i]->getType(),
419 diag::err_dereference_incomplete_type))
427 << Info.getConstraintStr());
431 for (
unsigned i = 0; i != NumClobbers; i++) {
435 StringRef Clobber = Literal->
getString();
444 new (Context)
GCCAsmStmt(Context, AsmLoc, IsSimple, IsVolatile, NumOutputs,
445 NumInputs, Names, Constraints, Exprs.data(),
446 AsmString, NumClobbers, Clobbers, RParenLoc);
452 Diag(getLocationOfStringLiteralByte(AsmString, DiagOffs), DiagID)
458 for (
unsigned i = 0, e = Pieces.size(); i != e; ++i) {
468 if (ConstraintIdx >= NumOperands) {
471 for (
unsigned Cnt = ConstraintIdx - NumOperands; I != E; ++I)
472 if (OutputConstraintInfos[I].isReadWrite() && Cnt-- == 0) {
477 assert(I != E &&
"Invalid operand number should have been caught in " 478 " AnalyzeAsmString");
483 const Type *Ty = Exprs[ConstraintIdx]->getType().getTypePtr();
488 std::string SuggestedModifier;
491 SuggestedModifier)) {
492 Diag(Exprs[ConstraintIdx]->getBeginLoc(),
493 diag::warn_asm_mismatched_size_modifier);
495 if (!SuggestedModifier.empty()) {
497 diag::note_asm_missing_constraint_modifier)
498 << SuggestedModifier;
499 SuggestedModifier =
"%" + SuggestedModifier + Piece.
getString();
507 unsigned NumAlternatives = ~0U;
508 for (
unsigned i = 0, e = OutputConstraintInfos.size(); i != e; ++i) {
511 unsigned AltCount = ConstraintStr.count(
',') + 1;
512 if (NumAlternatives == ~0U)
513 NumAlternatives = AltCount;
514 else if (NumAlternatives != AltCount)
516 diag::err_asm_unexpected_constraint_alternatives)
517 << NumAlternatives << AltCount);
521 for (
unsigned i = 0, e = InputConstraintInfos.size(); i != e; ++i) {
524 unsigned AltCount = ConstraintStr.count(
',') + 1;
525 if (NumAlternatives == ~0U)
526 NumAlternatives = AltCount;
527 else if (NumAlternatives != AltCount)
529 diag::err_asm_unexpected_constraint_alternatives)
530 << NumAlternatives << AltCount);
538 unsigned InputOpNo = i+NumOutputs;
539 Expr *OutputExpr = Exprs[TiedTo];
540 Expr *InputExpr = Exprs[InputOpNo];
543 assert(TiedTo < InputMatchedToOutput.size() &&
"TiedTo value out of range");
544 if (InputMatchedToOutput[TiedTo] != ~0U) {
546 diag::err_asm_input_duplicate_match)
549 diag::note_asm_input_duplicate_first)
553 InputMatchedToOutput[TiedTo] = i;
566 AD_Int, AD_FP, AD_Other
567 } InputDomain, OutputDomain;
570 InputDomain = AD_Int;
574 InputDomain = AD_Other;
577 OutputDomain = AD_Int;
579 OutputDomain = AD_FP;
581 OutputDomain = AD_Other;
591 if (OutSize == InSize && InputDomain == OutputDomain &&
592 InputDomain != AD_Other)
598 bool SmallerValueMentioned =
false;
606 SmallerValueMentioned |= InSize < OutSize;
611 SmallerValueMentioned |= OutSize < InSize;
617 if (!SmallerValueMentioned && InputDomain != AD_Other &&
618 OutputConstraintInfos[TiedTo].allowsRegister())
625 if (InputDomain == AD_Int && OutputDomain == AD_Int &&
629 (OutTy->
isBooleanType() ? CK_IntegralToBoolean : CK_IntegralCast);
630 InputExpr = ImpCastExprToType(InputExpr, OutTy, castKind).get();
631 Exprs[InputOpNo] = InputExpr;
647 return Diag(ConstraintLoc, diag::error_inoutput_conflict_with_clobber);
653 llvm::InlineAsmIdentifierInfo &Info) {
657 return Info.setLabel(Res);
660 return Info.setEnum(Eval.
Val.
getInt().getSExtValue());
661 return Info.setLabel(Res);
664 unsigned Type = Size;
667 bool IsGlobalLV =
false;
670 Info.setVar(Res, IsGlobalLV, Size, Type);
676 bool IsUnevaluatedContext) {
678 if (IsUnevaluatedContext)
679 PushExpressionEvaluationContext(
680 ExpressionEvaluationContext::UnevaluatedAbstract,
681 ReuseLambdaContextDecl);
683 ExprResult Result = ActOnIdExpression(getCurScope(), SS, TemplateKWLoc, Id,
689 if (IsUnevaluatedContext)
690 PopExpressionEvaluationContext();
692 if (!Result.
isUsable())
return Result;
694 Result = CheckPlaceholderExpr(Result.
get());
695 if (!Result.
isUsable())
return Result;
713 if (RequireCompleteExprType(Result.
get(), diag::err_asm_incomplete_type)) {
724 Member.split(Members,
".");
729 if (getLangOpts().
CPlusPlus && Base.equals(
"this")) {
730 if (
const Type *PT = getCurrentThisType().getTypePtrOrNull())
731 FoundDecl = PT->getPointeeType()->getAsTagDecl();
742 for (StringRef NextMember : Members) {
744 if (
VarDecl *VD = dyn_cast<VarDecl>(FoundDecl))
747 MarkAnyDeclReferenced(TD->getLocation(), TD,
false);
749 QualType QT = TD->getUnderlyingType();
753 }
else if (
TypeDecl *TD = dyn_cast<TypeDecl>(FoundDecl))
755 else if (
FieldDecl *TD = dyn_cast<FieldDecl>(FoundDecl))
760 if (RequireCompleteType(AsmLoc,
QualType(RT, 0),
761 diag::err_asm_incomplete_type))
767 if (!LookupQualifiedName(FieldResult, RT->
getDecl()))
770 if (!FieldResult.isSingleResult())
772 FoundDecl = FieldResult.getFoundDecl();
800 nullptr, NameInfo,
nullptr);
811 if (!LookupQualifiedName(FieldResult, RT->
getDecl()))
832 unsigned NumOutputs,
unsigned NumInputs,
837 bool IsSimple = (NumOutputs != 0 || NumInputs != 0);
838 setFunctionHasBranchProtectedScope();
840 new (Context)
MSAsmStmt(Context, AsmLoc, LBraceLoc, IsSimple,
841 true, AsmToks, NumOutputs, NumInputs,
842 Constraints, Exprs, AsmString,
850 LabelDecl*
Label = LookupOrCreateLabel(PP.getIdentifierInfo(ExternalLabelName),
858 std::string InternalName;
859 llvm::raw_string_ostream OS(InternalName);
865 OS <<
"__MSASMLABEL_.${:uid}__";
866 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...
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.