24 #include "llvm/ADT/ArrayRef.h"
25 #include "llvm/ADT/StringSet.h"
26 #include "llvm/MC/MCParser/MCAsmParser.h"
27 using namespace clang;
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)) {
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);
103 if (
Expr *E = dyn_cast_or_null<Expr>(Child))
104 WorkList.push_back(E);
114 bool is_input_expr) {
120 } EType = ExprSafeType;
125 EType = ExprBitfield;
127 EType = ExprVectorElt;
129 EType = ExprGlobalRegVar;
131 if (EType != ExprSafeType) {
132 S.
Diag(E->
getLocStart(), diag::err_asm_non_addr_value_in_memory_constraint)
146 if (
const DeclRefExpr *AsmDeclRef = dyn_cast<DeclRefExpr>(Expression)) {
148 const VarDecl *Variable = dyn_cast<
VarDecl>(AsmDeclRef->getDecl());
150 if (AsmLabelAttr *
Attr = Variable->
getAttr<AsmLabelAttr>())
165 llvm::StringSet<> InOutVars;
168 for (
unsigned int i = 0; i < Exprs.size(); ++i) {
169 StringRef Constraint = Constraints[i]->
getString();
173 InOutVars.insert(InOutReg);
177 for (
int i = 0; i < NumClobbers; ++i) {
178 StringRef Clobber = Clobbers[i]->
getString();
181 if (Clobber ==
"cc" || Clobber ==
"memory")
185 if (InOutVars.count(Clobber))
186 return Clobbers[i]->getLocStart();
192 bool IsVolatile,
unsigned NumOutputs,
197 unsigned NumClobbers = clobbers.size();
212 Context, AsmLoc, IsSimple, IsVolatile, NumOutputs, NumInputs, Names,
213 Constraints, Exprs.data(), AsmString, NumClobbers, Clobbers, RParenLoc);
217 for (
unsigned i = 0; i != NumOutputs; i++) {
221 StringRef OutputName;
223 OutputName = Names[i]->
getName();
228 diag::err_asm_invalid_output_constraint)
229 << Info.getConstraintStr());
231 ExprResult ER = CheckPlaceholderExpr(Exprs[i]);
237 Expr *OutputExpr = Exprs[i];
244 if (Info.allowsMemory() &&
248 OutputConstraintInfos.push_back(Info);
265 if (!getLangOpts().HeinousExtensions) {
277 if (RequireCompleteType(OutputExpr->
getLocStart(), Exprs[i]->getType(),
278 diag::err_dereference_incomplete_type))
283 diag::err_asm_invalid_lvalue_in_output)
291 diag::err_asm_invalid_output_size)
292 << Info.getConstraintStr());
297 for (
unsigned i = NumOutputs, e = NumOutputs + NumInputs; i != e; i++) {
303 InputName = Names[i]->
getName();
309 diag::err_asm_invalid_input_constraint)
310 << Info.getConstraintStr());
313 ExprResult ER = CheckPlaceholderExpr(Exprs[i]);
318 Expr *InputExpr = Exprs[i];
325 if (Info.allowsMemory() &&
330 if (Info.allowsMemory() && !Info.allowsRegister()) {
333 diag::err_asm_invalid_lvalue_in_input)
334 << Info.getConstraintStr()
336 }
else if (Info.requiresImmediateConstant() && !Info.allowsRegister()) {
343 if (!Info.isValidAsmImmediate(Result))
345 diag::err_invalid_asm_value_for_constraint)
346 << Result.toString(10) << Info.getConstraintStr()
355 Exprs[i] = Result.
get();
358 if (Info.allowsRegister()) {
361 diag::err_asm_invalid_type_in_input)
362 << InputExpr->
getType() << Info.getConstraintStr()
367 InputConstraintInfos.push_back(Info);
369 const Type *Ty = Exprs[i]->getType().getTypePtr();
373 if (!Ty->
isVoidType() || !Info.allowsMemory())
374 if (RequireCompleteType(InputExpr->
getLocStart(), Exprs[i]->getType(),
375 diag::err_dereference_incomplete_type))
382 diag::err_asm_invalid_input_size)
383 << Info.getConstraintStr());
387 for (
unsigned i = 0; i != NumClobbers; i++) {
391 StringRef Clobber = Literal->
getString();
395 diag::err_asm_unknown_register_name) << Clobber);
400 NumInputs, Names, Constraints, Exprs.data(),
401 AsmString, NumClobbers, Clobbers, RParenLoc);
407 Diag(getLocationOfStringLiteralByte(AsmString, DiagOffs), DiagID)
413 for (
unsigned i = 0, e = Pieces.size(); i != e; ++i) {
423 if (ConstraintIdx >= NumOperands) {
426 for (
unsigned Cnt = ConstraintIdx - NumOperands; I !=
E; ++
I)
427 if (OutputConstraintInfos[I].isReadWrite() && Cnt-- == 0) {
432 assert(I !=
E &&
"Invalid operand number should have been caught in "
433 " AnalyzeAsmString");
438 const Type *Ty = Exprs[ConstraintIdx]->getType().getTypePtr();
443 std::string SuggestedModifier;
446 SuggestedModifier)) {
447 Diag(Exprs[ConstraintIdx]->getLocStart(),
448 diag::warn_asm_mismatched_size_modifier);
450 if (!SuggestedModifier.empty()) {
452 diag::note_asm_missing_constraint_modifier)
453 << SuggestedModifier;
454 SuggestedModifier =
"%" + SuggestedModifier + Piece.
getString();
462 unsigned NumAlternatives = ~0U;
463 for (
unsigned i = 0, e = OutputConstraintInfos.size(); i != e; ++i) {
466 unsigned AltCount = ConstraintStr.count(
',') + 1;
467 if (NumAlternatives == ~0U)
468 NumAlternatives = AltCount;
469 else if (NumAlternatives != AltCount)
471 diag::err_asm_unexpected_constraint_alternatives)
472 << NumAlternatives << AltCount);
476 for (
unsigned i = 0, e = InputConstraintInfos.size(); i != e; ++i) {
479 unsigned AltCount = ConstraintStr.count(
',') + 1;
480 if (NumAlternatives == ~0U)
481 NumAlternatives = AltCount;
482 else if (NumAlternatives != AltCount)
484 diag::err_asm_unexpected_constraint_alternatives)
485 << NumAlternatives << AltCount);
493 unsigned InputOpNo = i+NumOutputs;
494 Expr *OutputExpr = Exprs[TiedTo];
495 Expr *InputExpr = Exprs[InputOpNo];
498 assert(TiedTo < InputMatchedToOutput.size() &&
"TiedTo value out of range");
499 if (InputMatchedToOutput[TiedTo] != ~0U) {
501 diag::err_asm_input_duplicate_match)
504 diag::note_asm_input_duplicate_first)
508 InputMatchedToOutput[TiedTo] = i;
521 AD_Int, AD_FP, AD_Other
522 } InputDomain, OutputDomain;
525 InputDomain = AD_Int;
529 InputDomain = AD_Other;
532 OutputDomain = AD_Int;
534 OutputDomain = AD_FP;
536 OutputDomain = AD_Other;
546 if (OutSize == InSize && InputDomain == OutputDomain &&
547 InputDomain != AD_Other)
553 bool SmallerValueMentioned =
false;
561 SmallerValueMentioned |= InSize < OutSize;
566 SmallerValueMentioned |= OutSize < InSize;
572 if (!SmallerValueMentioned && InputDomain != AD_Other &&
573 OutputConstraintInfos[TiedTo].allowsRegister())
580 if (InputDomain == AD_Int && OutputDomain == AD_Int &&
584 (OutTy->
isBooleanType() ? CK_IntegralToBoolean : CK_IntegralCast);
585 InputExpr = ImpCastExprToType(InputExpr, OutTy, castKind).get();
586 Exprs[InputOpNo] = InputExpr;
592 diag::err_asm_tying_incompatible_types)
603 return Diag(ConstraintLoc, diag::error_inoutput_conflict_with_clobber);
609 llvm::InlineAsmIdentifierInfo &Info) {
615 Info.Length = Info.Size / Info.Type;
622 llvm::InlineAsmIdentifierInfo &Info,
623 bool IsUnevaluatedContext) {
626 if (IsUnevaluatedContext)
627 PushExpressionEvaluationContext(
628 ExpressionEvaluationContext::UnevaluatedAbstract,
629 ReuseLambdaContextDecl);
637 if (IsUnevaluatedContext)
638 PopExpressionEvaluationContext();
640 if (!Result.
isUsable())
return Result;
642 Result = CheckPlaceholderExpr(Result.
get());
643 if (!Result.
isUsable())
return Result;
661 if (RequireCompleteExprType(Result.
get(), diag::err_asm_incomplete_type)) {
669 Info.IsVarDecl =
true;
678 Member.split(Members,
".");
689 for (StringRef NextMember : Members) {
691 if (
VarDecl *VD = dyn_cast<VarDecl>(FoundDecl))
694 MarkAnyDeclReferenced(TD->getLocation(), TD,
false);
696 }
else if (
TypeDecl *TD = dyn_cast<TypeDecl>(FoundDecl))
698 else if (
FieldDecl *TD = dyn_cast<FieldDecl>(FoundDecl))
703 if (RequireCompleteType(AsmLoc,
QualType(RT, 0),
704 diag::err_asm_incomplete_type))
710 if (!LookupQualifiedName(FieldResult, RT->
getDecl()))
713 if (!FieldResult.isSingleResult())
715 FoundDecl = FieldResult.getFoundDecl();
733 llvm::InlineAsmIdentifierInfo &Info,
745 nullptr, NameInfo,
nullptr);
756 if (!LookupQualifiedName(FieldResult, RT->
getDecl()))
772 Info.OpDecl = Result.
get();
777 Info.IsVarDecl =
true;
785 unsigned NumOutputs,
unsigned NumInputs,
790 bool IsSimple = (NumOutputs != 0 || NumInputs != 0);
791 getCurFunction()->setHasBranchProtectedScope();
794 true, AsmToks, NumOutputs, NumInputs,
795 Constraints, Exprs, AsmString,
803 LabelDecl*
Label = LookupOrCreateLabel(PP.getIdentifierInfo(ExternalLabelName),
811 std::string InternalName;
812 llvm::raw_string_ostream OS(InternalName);
818 OS <<
"__MSASMLABEL_.${:uid}__";
819 for (
char C : ExternalLabelName) {
This represents a GCC inline-assembly statement extension.
FunctionDecl - An instance of this class is created to represent a function declaration or definition...
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.
A (possibly-)qualified type.
SourceLocation getBegin() const
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)
const LangOptions & getLangOpts() const
Stmt - This represents one statement.
StmtResult ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, bool IsVolatile, unsigned NumOutputs, unsigned NumInputs, IdentifierInfo **Names, MultiExprArg Constraints, MultiExprArg Exprs, Expr *AsmString, MultiExprArg Clobbers, SourceLocation RParenLoc)
ActionResult< Expr * > ExprResult
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
Emit a diagnostic.
The base class of the type hierarchy.
bool validateOutputConstraint(ConstraintInfo &Info) const
Represents an array type, per C99 6.7.5.2 - Array Declarators.
bool validateInputConstraint(MutableArrayRef< ConstraintInfo > OutputConstraints, ConstraintInfo &info) const
bool isBooleanType() const
SourceLocation getLocStart() const LLVM_READONLY
void setInputExpr(unsigned i, Expr *E)
VarDecl - An instance of this class is created to represent a variable declaration or definition...
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.
static void fillInlineAsmTypeInfo(const ASTContext &Context, QualType T, llvm::InlineAsmIdentifierInfo &Info)
const std::string & getConstraintStr() const
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.
bool refersToGlobalRegisterVar() const
Returns whether this expression refers to a global register variable.
One of these records is kept for each identifier that is lexed.
unsigned getNumInputs() 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.
FieldDecl - An instance of this class is created by Sema::ActOnField to represent a member of a struc...
void setName(DeclarationName N)
setName - Sets the embedded declaration name.
bool hasSameType(QualType T1, QualType T2) const
Determine whether the given types T1 and T2 are equivalent.
virtual bool validateOutputSize(StringRef, unsigned) const
bool refersToVectorElement() const
Returns whether this expression refers to a vector element.
static bool isOperandMentioned(unsigned OpNo, ArrayRef< GCCAsmStmt::AsmStringPiece > AsmStrPieces)
isOperandMentioned - Return true if the specified operand # is mentioned anywhere in the decomposed a...
StorageClass getStorageClass() const
Returns the storage class as written in the source.
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
CharUnits - This is an opaque type for sizes expressed in character units.
static bool CheckAsmLValue(const Expr *E, Sema &S)
CheckAsmLValue - GNU C has an extremely ugly extension whereby they silently ignore "noop" casts in p...
bool isValidGCCRegisterName(StringRef Name) const
Returns whether the passed in string is a valid register name according to GCC.
const ArrayType * getAsArrayType(QualType T) const
Type Query functions.
TypeDecl - Represents a declaration of a type.
bool isValueDependent() const
isValueDependent - Determines whether this expression is value-dependent (C++ [temp.dep.constexpr]).
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
getFieldOffset - Get the offset of the given field index, in bits.
Represents a C++ nested-name-specifier or a global scope specifier.
bool isIncompleteType(NamedDecl **Def=nullptr) const
Types are partitioned into 3 broad categories (C99 6.2.5p1): object types, function types...
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
detail::InMemoryDirectory::const_iterator I
ExprResult LookupInlineAsmVarDeclField(Expr *RefExpr, StringRef Member, llvm::InlineAsmIdentifierInfo &Info, SourceLocation AsmLoc)
Sema - This implements semantic analysis and AST building for C.
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.
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.
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
Exposes information about the current target.
ValueDecl - Represent the declaration of a variable (in which case it is an lvalue) a function (in wh...
Expr - This represents one expression.
StringRef getName() const
Return the actual identifier string.
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...
bool isValidClobber(StringRef Name) const
Returns whether the passed in string is a valid clobber in an inline asm statement.
virtual StringRef getConstraintRegister(const StringRef &Constraint, const StringRef &Expression) const
Defines the clang::Preprocessor interface.
bool isMSAsmLabel() const
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...
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
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
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...
This represents a Microsoft inline-assembly statement extension.
void setLocation(SourceLocation L)
unsigned getTiedOperand() const
ActionResult - This structure is used while parsing/acting on expressions, stmts, etc...
Encodes a location in the source.
char getModifier() const
getModifier - Get the modifier for this operand, if present.
IdentifierInfo & get(StringRef Name)
Return the identifier token info for the specified named identifier.
static StringRef extractRegisterName(const Expr *Expression, const TargetInfo &Target)
bool isValid() const
Return true if this is a valid SourceLocation object.
LabelDecl - Represents the declaration of a label.
CharSourceRange getRange() const
bool LookupInlineAsmField(StringRef Base, StringRef Member, unsigned &Offset, SourceLocation AsmLoc)
Expr * getInputExpr(unsigned i)
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.
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
AnalyzeAsmString - Analyze the asm string of the current asm, decomposing it into pieces...
IndirectFieldDecl - An instance of this class is created to represent a field injected from an anonym...
bool hasTiedOperand() const
Return true if this input operand is a matching constraint that ties it to an output operand...
bool isLValue() const
isLValue - True if this expression is an "l-value" according to the rules of the current language...
StringRef getString() const
detail::InMemoryDirectory::const_iterator E
DeclarationNameInfo - A collector data type for bundling together a DeclarationName and the correspnd...
bool DeclAttrsMatchCUDAMode(const LangOptions &LangOpts, Decl *D)
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 helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
const T * getAs() const
Member-template getAs<specific type>'.
StringRef getNormalizedGCCRegisterName(StringRef Name, bool ReturnCanonical=false) const
Returns the "normalized" GCC register name.
bool isFunctionType() const
unsigned getOperandNo() const
unsigned getFieldIndex() const
getFieldIndex - Returns the index of this field within its record, as appropriate for passing to ASTR...
void markUsed(ASTContext &C)
Mark the declaration used, in the sense of odr-use.
void setLoc(SourceLocation L)
setLoc - Sets the main location of the declaration name.
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...
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.
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)
A reference to a declared variable, function, enum, etc.
QualType getElementType() const
void setMSAsmLabelResolved()
NamedDecl - This represents a decl with a name.
SourceLocation getLocStart() const LLVM_READONLY
Attr - This represents one attribute.
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
bool isPointerType() const