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)
197 const VarDecl *Variable = dyn_cast<VarDecl>(AsmDeclRef->getDecl());
198 if (Variable && Variable->getStorageClass() ==
SC_Register) {
199 if (AsmLabelAttr *
Attr = Variable->getAttr<AsmLabelAttr>())
200 if (
Target.isValidGCCRegisterName(
Attr->getLabel()))
201 return Target.getNormalizedGCCRegisterName(
Attr->getLabel(),
true);
215 llvm::StringSet<> InOutVars;
218 for (
unsigned int i = 0; i < Exprs.size() - NumLabels; ++i) {
219 StringRef Constraint = Constraints[i]->
getString();
220 StringRef InOutReg =
Target.getConstraintRegister(
223 InOutVars.insert(InOutReg);
227 for (
int i = 0; i < NumClobbers; ++i) {
228 StringRef Clobber = Clobbers[i]->
getString();
231 if (Clobber ==
"cc" || Clobber ==
"memory")
233 Clobber =
Target.getNormalizedGCCRegisterName(Clobber,
true);
235 if (InOutVars.count(Clobber))
242 bool IsVolatile,
unsigned NumOutputs,
248 unsigned NumClobbers = clobbers.size();
259 FunctionDecl *FD = dyn_cast<FunctionDecl>(getCurLexicalContext());
260 llvm::StringMap<bool> FeatureMap;
263 for (
unsigned i = 0; i != NumOutputs; i++) {
267 StringRef OutputName;
269 OutputName = Names[i]->
getName();
274 diag::err_asm_invalid_output_constraint)
277 GCCAsmStmt(Context, AsmLoc, IsSimple, IsVolatile, NumOutputs,
278 NumInputs, Names, Constraints, Exprs.data(), AsmString,
279 NumClobbers, Clobbers, NumLabels, RParenLoc);
282 ExprResult ER = CheckPlaceholderExpr(Exprs[i]);
288 Expr *OutputExpr = Exprs[i];
307 OutputConstraintInfos.push_back(Info);
330 if (RequireCompleteType(OutputExpr->
getBeginLoc(), Exprs[i]->getType(),
331 diag::err_dereference_incomplete_type))
336 diag::err_asm_invalid_lvalue_in_output)
342 FeatureMap, Literal->
getString(), Size)) {
343 targetDiag(OutputExpr->
getBeginLoc(), diag::err_asm_invalid_output_size)
346 GCCAsmStmt(Context, AsmLoc, IsSimple, IsVolatile, NumOutputs,
347 NumInputs, Names, Constraints, Exprs.data(), AsmString,
348 NumClobbers, Clobbers, NumLabels, RParenLoc);
354 for (
unsigned i = NumOutputs, e = NumOutputs + NumInputs; i != e; i++) {
360 InputName = Names[i]->
getName();
365 targetDiag(Literal->
getBeginLoc(), diag::err_asm_invalid_input_constraint)
368 GCCAsmStmt(Context, AsmLoc, IsSimple, IsVolatile, NumOutputs,
369 NumInputs, Names, Constraints, Exprs.data(), AsmString,
370 NumClobbers, Clobbers, NumLabels, RParenLoc);
373 ExprResult ER = CheckPlaceholderExpr(Exprs[i]);
378 Expr *InputExpr = Exprs[i];
393 diag::err_asm_invalid_lvalue_in_input)
407 diag::err_invalid_asm_value_for_constraint)
408 << IntResult.toString(10)
415 ExprResult Result = DefaultFunctionArrayLvalueConversion(Exprs[i]);
416 if (Result.isInvalid())
419 Exprs[i] = Result.get();
437 InputConstraintInfos.push_back(Info);
439 const Type *Ty = Exprs[i]->getType().getTypePtr();
444 if (RequireCompleteType(InputExpr->
getBeginLoc(), Exprs[i]->getType(),
445 diag::err_dereference_incomplete_type))
452 diag::err_asm_invalid_input_size)
457 for (
unsigned i = 0; i != NumClobbers; i++) {
461 StringRef Clobber = Literal->
getString();
464 targetDiag(Literal->
getBeginLoc(), diag::err_asm_unknown_register_name)
467 GCCAsmStmt(Context, AsmLoc, IsSimple, IsVolatile, NumOutputs,
468 NumInputs, Names, Constraints, Exprs.data(), AsmString,
469 NumClobbers, Clobbers, NumLabels, RParenLoc);
474 new (Context)
GCCAsmStmt(Context, AsmLoc, IsSimple, IsVolatile, NumOutputs,
475 NumInputs, Names, Constraints, Exprs.data(),
476 AsmString, NumClobbers, Clobbers, NumLabels,
483 targetDiag(getLocationOfStringLiteralByte(AsmString, DiagOffs), DiagID)
489 for (
unsigned i = 0, e = Pieces.size(); i != e; ++i) {
497 if (NS->
isAsmGoto() && ConstraintIdx >= NumOperands)
501 if (ConstraintIdx >= NumOperands) {
504 for (
unsigned Cnt = ConstraintIdx - NumOperands; I != E; ++I)
505 if (OutputConstraintInfos[I].isReadWrite() && Cnt-- == 0) {
510 assert(I != E &&
"Invalid operand number should have been caught in "
511 " AnalyzeAsmString");
516 const Type *Ty = Exprs[ConstraintIdx]->getType().getTypePtr();
524 SuggestedModifier)) {
525 targetDiag(Exprs[ConstraintIdx]->getBeginLoc(),
526 diag::warn_asm_mismatched_size_modifier);
528 if (!SuggestedModifier.empty()) {
530 diag::note_asm_missing_constraint_modifier)
531 << SuggestedModifier;
532 SuggestedModifier =
"%" + SuggestedModifier + Piece.
getString();
539 unsigned NumAlternatives = ~0
U;
540 for (
unsigned i = 0, e = OutputConstraintInfos.size(); i != e; ++i) {
543 unsigned AltCount = ConstraintStr.count(
',') + 1;
544 if (NumAlternatives == ~0
U) {
545 NumAlternatives = AltCount;
546 }
else if (NumAlternatives != AltCount) {
548 diag::err_asm_unexpected_constraint_alternatives)
549 << NumAlternatives << AltCount;
555 for (
unsigned i = 0, e = InputConstraintInfos.size(); i != e; ++i) {
558 unsigned AltCount = ConstraintStr.count(
',') + 1;
559 if (NumAlternatives == ~0
U) {
560 NumAlternatives = AltCount;
561 }
else if (NumAlternatives != AltCount) {
563 diag::err_asm_unexpected_constraint_alternatives)
564 << NumAlternatives << AltCount;
574 unsigned InputOpNo = i+NumOutputs;
575 Expr *OutputExpr = Exprs[TiedTo];
576 Expr *InputExpr = Exprs[InputOpNo];
579 assert(TiedTo < InputMatchedToOutput.size() &&
"TiedTo value out of range");
580 if (InputMatchedToOutput[TiedTo] != ~0
U) {
582 diag::err_asm_input_duplicate_match)
585 diag::note_asm_input_duplicate_first)
589 InputMatchedToOutput[TiedTo] = i;
602 AD_Int, AD_FP, AD_Other
603 } InputDomain, OutputDomain;
606 InputDomain = AD_Int;
610 InputDomain = AD_Other;
613 OutputDomain = AD_Int;
615 OutputDomain = AD_FP;
617 OutputDomain = AD_Other;
627 if (OutSize == InSize && InputDomain == OutputDomain &&
628 InputDomain != AD_Other)
634 bool SmallerValueMentioned =
false;
642 SmallerValueMentioned |= InSize < OutSize;
647 SmallerValueMentioned |= OutSize < InSize;
653 if (!SmallerValueMentioned && InputDomain != AD_Other &&
654 OutputConstraintInfos[TiedTo].allowsRegister())
661 if (InputDomain == AD_Int && OutputDomain == AD_Int &&
665 (OutTy->
isBooleanType() ? CK_IntegralToBoolean : CK_IntegralCast);
666 InputExpr = ImpCastExprToType(InputExpr, OutTy, castKind).get();
667 Exprs[InputOpNo] = InputExpr;
672 targetDiag(InputExpr->
getBeginLoc(), diag::err_asm_tying_incompatible_types)
684 targetDiag(ConstraintLoc, diag::error_inoutput_conflict_with_clobber);
687 typedef std::pair<StringRef , Expr *> NamedOperand;
689 for (
unsigned i = 0, e = NumOutputs + NumInputs + NumLabels; i != e; ++i)
691 NamedOperandList.emplace_back(
692 std::make_pair(Names[i]->
getName(), Exprs[i]));
694 std::stable_sort(NamedOperandList.begin(), NamedOperandList.end(),
695 [](
const NamedOperand &LHS,
const NamedOperand &RHS) {
696 return LHS.first < RHS.first;
700 std::adjacent_find(begin(NamedOperandList), end(NamedOperandList),
701 [](
const NamedOperand &LHS,
const NamedOperand &RHS) {
702 return LHS.first == RHS.first;
704 if (Found != NamedOperandList.end()) {
705 Diag((Found + 1)->second->getBeginLoc(),
706 diag::error_duplicate_asm_operand_name)
707 << (Found + 1)->first;
708 Diag(Found->second->getBeginLoc(), diag::note_duplicate_asm_operand_name)
713 setFunctionHasBranchIntoScope();
718 llvm::InlineAsmIdentifierInfo &Info) {
722 return Info.setLabel(Res);
724 bool IsEnum = isa<clang::EnumType>(T);
725 if (
DeclRefExpr *DRE = dyn_cast<clang::DeclRefExpr>(Res))
726 if (DRE->getDecl()->getKind() == Decl::EnumConstant)
729 return Info.setEnum(Eval.
Val.
getInt().getSExtValue());
731 return Info.setLabel(Res);
734 unsigned Type = Size;
737 bool IsGlobalLV =
false;
740 Info.setVar(Res, IsGlobalLV, Size,
Type);
746 bool IsUnevaluatedContext) {
748 if (IsUnevaluatedContext)
749 PushExpressionEvaluationContext(
750 ExpressionEvaluationContext::UnevaluatedAbstract,
751 ReuseLambdaContextDecl);
753 ExprResult Result = ActOnIdExpression(getCurScope(), SS, TemplateKWLoc,
Id,
759 if (IsUnevaluatedContext)
760 PopExpressionEvaluationContext();
762 if (!Result.isUsable())
return Result;
764 Result = CheckPlaceholderExpr(Result.get());
765 if (!Result.isUsable())
return Result;
771 QualType T = Result.get()->getType();
783 if (RequireCompleteExprType(Result.get(), diag::err_asm_incomplete_type)) {
794 Member.split(Members,
".");
800 if (
const Type *PT = getCurrentThisType().getTypePtrOrNull())
801 FoundDecl = PT->getPointeeType()->getAsTagDecl();
812 for (StringRef NextMember : Members) {
814 if (
VarDecl *VD = dyn_cast<VarDecl>(FoundDecl))
817 MarkAnyDeclReferenced(TD->getLocation(), TD,
false);
819 QualType QT = TD->getUnderlyingType();
823 }
else if (
TypeDecl *TD = dyn_cast<TypeDecl>(FoundDecl))
825 else if (
FieldDecl *TD = dyn_cast<FieldDecl>(FoundDecl))
830 if (RequireCompleteType(AsmLoc,
QualType(RT, 0),
831 diag::err_asm_incomplete_type))
837 if (!LookupQualifiedName(FieldResult, RT->
getDecl()))
845 FieldDecl *FD = dyn_cast<FieldDecl>(FoundDecl);
870 nullptr, NameInfo,
nullptr);
881 if (!LookupQualifiedName(FieldResult, RT->
getDecl()))
887 FD = dyn_cast<IndirectFieldDecl>(FieldResult.
getFoundDecl());
902 unsigned NumOutputs,
unsigned NumInputs,
907 bool IsSimple = (NumOutputs != 0 || NumInputs != 0);
908 setFunctionHasBranchProtectedScope();
910 for (uint64_t I = 0; I < NumOutputs + NumInputs; ++I) {
911 if (Exprs[I]->getType()->isExtIntType())
913 Diag(Exprs[I]->getBeginLoc(), diag::err_asm_invalid_type)
914 << Exprs[I]->getType() << (I < NumOutputs)
919 new (Context)
MSAsmStmt(Context, AsmLoc, LBraceLoc, IsSimple,
920 true, AsmToks, NumOutputs, NumInputs,
921 Constraints, Exprs, AsmString,
929 LabelDecl*
Label = LookupOrCreateLabel(PP.getIdentifierInfo(ExternalLabelName),
932 if (
Label->isMSAsmLabel()) {
934 Label->markUsed(Context);
938 llvm::raw_string_ostream OS(InternalName);
944 OS <<
"__MSASMLABEL_.${:uid}__";
945 for (
char C : ExternalLabelName) {
951 Label->setMSAsmLabel(OS.str());
957 Label->setMSAsmLabelResolved();
960 Label->setLocation(Location);