24 #include "llvm/ADT/ArrayRef.h" 25 #include "llvm/ADT/StringSet.h" 26 #include "llvm/MC/MCParser/MCAsmParser.h" 27 using namespace clang;
68 for (
unsigned p = 0, e = AsmStrPieces.size(); p != e; ++p) {
85 if (!Func->
hasAttr<NakedAttr>())
89 WorkList.push_back(E);
90 while (WorkList.size()) {
91 Expr *E = WorkList.pop_back_val();
92 if (isa<CXXThisExpr>(E)) {
94 S.
Diag(Func->
getAttr<NakedAttr>()->getLocation(), diag::note_attribute);
98 if (isa<ParmVarDecl>(DRE->getDecl())) {
99 S.
Diag(DRE->getLocStart(), diag::err_asm_naked_parm_ref);
100 S.
Diag(Func->
getAttr<NakedAttr>()->getLocation(), diag::note_attribute);
105 if (
Expr *E = dyn_cast_or_null<Expr>(Child))
106 WorkList.push_back(E);
116 bool is_input_expr) {
122 } EType = ExprSafeType;
127 EType = ExprBitfield;
129 EType = ExprVectorElt;
131 EType = ExprGlobalRegVar;
133 if (EType != ExprSafeType) {
134 S.
Diag(E->
getLocStart(), diag::err_asm_non_addr_value_in_memory_constraint)
148 if (
const DeclRefExpr *AsmDeclRef = dyn_cast<DeclRefExpr>(Expression)) {
150 const VarDecl *Variable = dyn_cast<
VarDecl>(AsmDeclRef->getDecl());
152 if (AsmLabelAttr *
Attr = Variable->
getAttr<AsmLabelAttr>())
167 llvm::StringSet<> InOutVars;
170 for (
unsigned int i = 0; i < Exprs.size(); ++i) {
171 StringRef Constraint = Constraints[i]->
getString();
175 InOutVars.insert(InOutReg);
179 for (
int i = 0; i < NumClobbers; ++i) {
180 StringRef Clobber = Clobbers[i]->
getString();
183 if (Clobber ==
"cc" || Clobber ==
"memory")
187 if (InOutVars.count(Clobber))
188 return Clobbers[i]->getLocStart();
194 bool IsVolatile,
unsigned NumOutputs,
199 unsigned NumClobbers = clobbers.size();
214 Context, AsmLoc, IsSimple, IsVolatile, NumOutputs, NumInputs, Names,
215 Constraints, Exprs.data(), AsmString, NumClobbers, Clobbers, RParenLoc);
219 for (
unsigned i = 0; i != NumOutputs; i++) {
223 StringRef OutputName;
225 OutputName = Names[i]->
getName();
230 diag::err_asm_invalid_output_constraint)
231 << Info.getConstraintStr());
233 ExprResult ER = CheckPlaceholderExpr(Exprs[i]);
239 Expr *OutputExpr = Exprs[i];
246 if (Info.allowsMemory() &&
250 OutputConstraintInfos.push_back(Info);
267 if (!getLangOpts().HeinousExtensions) {
279 if (RequireCompleteType(OutputExpr->
getLocStart(), Exprs[i]->getType(),
280 diag::err_dereference_incomplete_type))
285 diag::err_asm_invalid_lvalue_in_output)
293 diag::err_asm_invalid_output_size)
294 << Info.getConstraintStr());
299 for (
unsigned i = NumOutputs, e = NumOutputs + NumInputs; i != e; i++) {
305 InputName = Names[i]->
getName();
311 diag::err_asm_invalid_input_constraint)
312 << Info.getConstraintStr());
315 ExprResult ER = CheckPlaceholderExpr(Exprs[i]);
320 Expr *InputExpr = Exprs[i];
327 if (Info.allowsMemory() &&
332 if (Info.allowsMemory() && !Info.allowsRegister()) {
335 diag::err_asm_invalid_lvalue_in_input)
336 << Info.getConstraintStr()
338 }
else if (Info.requiresImmediateConstant() && !Info.allowsRegister()) {
345 if (!Info.isValidAsmImmediate(Result))
347 diag::err_invalid_asm_value_for_constraint)
348 << Result.toString(10) << Info.getConstraintStr()
353 ExprResult Result = DefaultFunctionArrayLvalueConversion(Exprs[i]);
357 Exprs[i] = Result.
get();
360 if (Info.allowsRegister()) {
363 diag::err_asm_invalid_type_in_input)
364 << InputExpr->
getType() << Info.getConstraintStr()
369 InputConstraintInfos.push_back(Info);
371 const Type *Ty = Exprs[i]->getType().getTypePtr();
375 if (!Ty->
isVoidType() || !Info.allowsMemory())
376 if (RequireCompleteType(InputExpr->
getLocStart(), Exprs[i]->getType(),
377 diag::err_dereference_incomplete_type))
384 diag::err_asm_invalid_input_size)
385 << Info.getConstraintStr());
389 for (
unsigned i = 0; i != NumClobbers; i++) {
393 StringRef Clobber = Literal->
getString();
397 diag::err_asm_unknown_register_name) << Clobber);
401 new (Context)
GCCAsmStmt(Context, AsmLoc, IsSimple, IsVolatile, NumOutputs,
402 NumInputs, Names, Constraints, Exprs.data(),
403 AsmString, NumClobbers, Clobbers, RParenLoc);
409 Diag(getLocationOfStringLiteralByte(AsmString, DiagOffs), DiagID)
415 for (
unsigned i = 0, e = Pieces.size(); i != e; ++i) {
425 if (ConstraintIdx >= NumOperands) {
428 for (
unsigned Cnt = ConstraintIdx - NumOperands; I != E; ++I)
429 if (OutputConstraintInfos[I].isReadWrite() && Cnt-- == 0) {
434 assert(I != E &&
"Invalid operand number should have been caught in " 435 " AnalyzeAsmString");
440 const Type *Ty = Exprs[ConstraintIdx]->getType().getTypePtr();
445 std::string SuggestedModifier;
448 SuggestedModifier)) {
449 Diag(Exprs[ConstraintIdx]->getLocStart(),
450 diag::warn_asm_mismatched_size_modifier);
452 if (!SuggestedModifier.empty()) {
454 diag::note_asm_missing_constraint_modifier)
455 << SuggestedModifier;
456 SuggestedModifier =
"%" + SuggestedModifier + Piece.
getString();
464 unsigned NumAlternatives = ~0U;
465 for (
unsigned i = 0, e = OutputConstraintInfos.size(); i != e; ++i) {
468 unsigned AltCount = ConstraintStr.count(
',') + 1;
469 if (NumAlternatives == ~0U)
470 NumAlternatives = AltCount;
471 else if (NumAlternatives != AltCount)
473 diag::err_asm_unexpected_constraint_alternatives)
474 << NumAlternatives << AltCount);
478 for (
unsigned i = 0, e = InputConstraintInfos.size(); i != e; ++i) {
481 unsigned AltCount = ConstraintStr.count(
',') + 1;
482 if (NumAlternatives == ~0U)
483 NumAlternatives = AltCount;
484 else if (NumAlternatives != AltCount)
486 diag::err_asm_unexpected_constraint_alternatives)
487 << NumAlternatives << AltCount);
495 unsigned InputOpNo = i+NumOutputs;
496 Expr *OutputExpr = Exprs[TiedTo];
497 Expr *InputExpr = Exprs[InputOpNo];
500 assert(TiedTo < InputMatchedToOutput.size() &&
"TiedTo value out of range");
501 if (InputMatchedToOutput[TiedTo] != ~0U) {
503 diag::err_asm_input_duplicate_match)
506 diag::note_asm_input_duplicate_first)
510 InputMatchedToOutput[TiedTo] = i;
523 AD_Int, AD_FP, AD_Other
524 } InputDomain, OutputDomain;
527 InputDomain = AD_Int;
531 InputDomain = AD_Other;
534 OutputDomain = AD_Int;
536 OutputDomain = AD_FP;
538 OutputDomain = AD_Other;
548 if (OutSize == InSize && InputDomain == OutputDomain &&
549 InputDomain != AD_Other)
555 bool SmallerValueMentioned =
false;
563 SmallerValueMentioned |= InSize < OutSize;
568 SmallerValueMentioned |= OutSize < InSize;
574 if (!SmallerValueMentioned && InputDomain != AD_Other &&
575 OutputConstraintInfos[TiedTo].allowsRegister())
582 if (InputDomain == AD_Int && OutputDomain == AD_Int &&
586 (OutTy->
isBooleanType() ? CK_IntegralToBoolean : CK_IntegralCast);
587 InputExpr = ImpCastExprToType(InputExpr, OutTy, castKind).get();
588 Exprs[InputOpNo] = InputExpr;
594 diag::err_asm_tying_incompatible_types)
605 return Diag(ConstraintLoc, diag::error_inoutput_conflict_with_clobber);
611 llvm::InlineAsmIdentifierInfo &Info) {
615 return Info.setLabel(Res);
618 return Info.setEnum(Eval.
Val.
getInt().getSExtValue());
619 return Info.setLabel(Res);
622 unsigned Type = Size;
625 bool IsGlobalLV =
false;
628 Info.setVar(Res, IsGlobalLV, Size, Type);
634 bool IsUnevaluatedContext) {
636 if (IsUnevaluatedContext)
637 PushExpressionEvaluationContext(
638 ExpressionEvaluationContext::UnevaluatedAbstract,
639 ReuseLambdaContextDecl);
641 ExprResult Result = ActOnIdExpression(getCurScope(), SS, TemplateKWLoc, Id,
647 if (IsUnevaluatedContext)
648 PopExpressionEvaluationContext();
650 if (!Result.
isUsable())
return Result;
652 Result = CheckPlaceholderExpr(Result.
get());
653 if (!Result.
isUsable())
return Result;
671 if (RequireCompleteExprType(Result.
get(), diag::err_asm_incomplete_type)) {
682 Member.split(Members,
".");
687 if (getLangOpts().
CPlusPlus && Base.equals(
"this")) {
688 if (
const Type *PT = getCurrentThisType().getTypePtrOrNull())
689 FoundDecl = PT->getPointeeType()->getAsTagDecl();
700 for (StringRef NextMember : Members) {
702 if (
VarDecl *VD = dyn_cast<VarDecl>(FoundDecl))
705 MarkAnyDeclReferenced(TD->getLocation(), TD,
false);
707 QualType QT = TD->getUnderlyingType();
711 }
else if (
TypeDecl *TD = dyn_cast<TypeDecl>(FoundDecl))
713 else if (
FieldDecl *TD = dyn_cast<FieldDecl>(FoundDecl))
718 if (RequireCompleteType(AsmLoc,
QualType(RT, 0),
719 diag::err_asm_incomplete_type))
725 if (!LookupQualifiedName(FieldResult, RT->
getDecl()))
728 if (!FieldResult.isSingleResult())
730 FoundDecl = FieldResult.getFoundDecl();
758 nullptr, NameInfo,
nullptr);
769 if (!LookupQualifiedName(FieldResult, RT->
getDecl()))
790 unsigned NumOutputs,
unsigned NumInputs,
795 bool IsSimple = (NumOutputs != 0 || NumInputs != 0);
796 setFunctionHasBranchProtectedScope();
798 new (Context)
MSAsmStmt(Context, AsmLoc, LBraceLoc, IsSimple,
799 true, AsmToks, NumOutputs, NumInputs,
800 Constraints, Exprs, AsmString,
808 LabelDecl*
Label = LookupOrCreateLabel(PP.getIdentifierInfo(ExternalLabelName),
816 std::string InternalName;
817 llvm::raw_string_ostream OS(InternalName);
823 OS <<
"__MSASMLABEL_.${:uid}__";
824 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
bool EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx) const
EvaluateAsRValue - Return true if this is a constant which we can fold to an rvalue using any crazy t...
PointerType - C99 6.7.5.1 - Pointer Declarators.
A (possibly-)qualified type.
static CXXDependentScopeMemberExpr * Create(const ASTContext &C, Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, NamedDecl *FirstQualifierFoundInScope, DeclarationNameInfo MemberNameInfo, const TemplateArgumentListInfo *TemplateArgs)
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...
The base class of the type hierarchy.
bool validateInputConstraint(MutableArrayRef< ConstraintInfo > OutputConstraints, ConstraintInfo &info) const
const TargetInfo & getTargetInfo() const
SourceLocation getLocStart() const LLVM_READONLY
void setInputExpr(unsigned i, Expr *E)
bool EvaluateAsInt(llvm::APSInt &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects) const
EvaluateAsInt - Return true if this is a constant which we can fold and convert to an integer...
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
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.
static bool CheckAsmLValue(const Expr *E, Sema &S)
CheckAsmLValue - GNU C has an extremely ugly extension whereby they silently ignore "noop" casts in p...
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.
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 ...
Expr - 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.
Defines the clang::TypeLoc interface and its subclasses.
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.
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)
SourceLocation getLocStart() const LLVM_READONLY
ExprResult LookupInlineAsmVarDeclField(Expr *RefExpr, StringRef Member, SourceLocation AsmLoc)
Represents the declaration of a label.
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]).
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
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.