diff options
Diffstat (limited to 'contrib/llvm-project/clang/lib/Sema/SemaStmtAsm.cpp')
-rw-r--r-- | contrib/llvm-project/clang/lib/Sema/SemaStmtAsm.cpp | 109 |
1 files changed, 69 insertions, 40 deletions
diff --git a/contrib/llvm-project/clang/lib/Sema/SemaStmtAsm.cpp b/contrib/llvm-project/clang/lib/Sema/SemaStmtAsm.cpp index 243d0b921cd7..83351b703c15 100644 --- a/contrib/llvm-project/clang/lib/Sema/SemaStmtAsm.cpp +++ b/contrib/llvm-project/clang/lib/Sema/SemaStmtAsm.cpp @@ -22,8 +22,10 @@ #include "clang/Sema/ScopeInfo.h" #include "clang/Sema/SemaInternal.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSet.h" #include "llvm/MC/MCParser/MCAsmParser.h" +#include <optional> using namespace clang; using namespace sema; @@ -254,7 +256,7 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, SmallVector<TargetInfo::ConstraintInfo, 4> OutputConstraintInfos; // The parser verifies that there is a string literal here. - assert(AsmString->isAscii()); + assert(AsmString->isOrdinary()); FunctionDecl *FD = dyn_cast<FunctionDecl>(getCurLexicalContext()); llvm::StringMap<bool> FeatureMap; @@ -262,14 +264,15 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, for (unsigned i = 0; i != NumOutputs; i++) { StringLiteral *Literal = Constraints[i]; - assert(Literal->isAscii()); + assert(Literal->isOrdinary()); StringRef OutputName; if (Names[i]) OutputName = Names[i]->getName(); TargetInfo::ConstraintInfo Info(Literal->getString(), OutputName); - if (!Context.getTargetInfo().validateOutputConstraint(Info)) { + if (!Context.getTargetInfo().validateOutputConstraint(Info) && + !(LangOpts.HIPStdPar && LangOpts.CUDAIsDevice)) { targetDiag(Literal->getBeginLoc(), diag::err_asm_invalid_output_constraint) << Info.getConstraintStr(); @@ -296,9 +299,9 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, checkExprMemoryConstraintCompat(*this, OutputExpr, Info, false)) return StmtError(); - // Disallow _ExtInt, since the backends tend to have difficulties with - // non-normal sizes. - if (OutputExpr->getType()->isExtIntType()) + // Disallow bit-precise integer types, since the backends tend to have + // difficulties with abnormal sizes. + if (OutputExpr->getType()->isBitIntType()) return StmtError( Diag(OutputExpr->getBeginLoc(), diag::err_asm_invalid_type) << OutputExpr->getType() << 0 /*Input*/ @@ -330,7 +333,7 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, if (RequireCompleteType(OutputExpr->getBeginLoc(), Exprs[i]->getType(), diag::err_dereference_incomplete_type)) return StmtError(); - LLVM_FALLTHROUGH; + [[fallthrough]]; default: return StmtError(Diag(OutputExpr->getBeginLoc(), diag::err_asm_invalid_lvalue_in_output) @@ -353,7 +356,7 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, for (unsigned i = NumOutputs, e = NumOutputs + NumInputs; i != e; i++) { StringLiteral *Literal = Constraints[i]; - assert(Literal->isAscii()); + assert(Literal->isOrdinary()); StringRef InputName; if (Names[i]) @@ -377,6 +380,11 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, Expr *InputExpr = Exprs[i]; + if (InputExpr->getType()->isMemberPointerType()) + return StmtError(Diag(InputExpr->getBeginLoc(), + diag::err_asm_pmf_through_constraint_not_permitted) + << InputExpr->getSourceRange()); + // Referring to parameters is not allowed in naked functions. if (CheckNakedParmReference(InputExpr, *this)) return StmtError(); @@ -393,30 +401,31 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, diag::err_asm_invalid_lvalue_in_input) << Info.getConstraintStr() << InputExpr->getSourceRange()); - } else if (Info.requiresImmediateConstant() && !Info.allowsRegister()) { - if (!InputExpr->isValueDependent()) { - Expr::EvalResult EVResult; - if (InputExpr->EvaluateAsRValue(EVResult, Context, true)) { - // For compatibility with GCC, we also allow pointers that would be - // integral constant expressions if they were cast to int. - llvm::APSInt IntResult; - if (EVResult.Val.toIntegralConstant(IntResult, InputExpr->getType(), - Context)) - if (!Info.isValidAsmImmediate(IntResult)) - return StmtError(Diag(InputExpr->getBeginLoc(), - diag::err_invalid_asm_value_for_constraint) - << toString(IntResult, 10) - << Info.getConstraintStr() - << InputExpr->getSourceRange()); - } - } - } else { ExprResult Result = DefaultFunctionArrayLvalueConversion(Exprs[i]); if (Result.isInvalid()) return StmtError(); - Exprs[i] = Result.get(); + InputExpr = Exprs[i] = Result.get(); + + if (Info.requiresImmediateConstant() && !Info.allowsRegister()) { + if (!InputExpr->isValueDependent()) { + Expr::EvalResult EVResult; + if (InputExpr->EvaluateAsRValue(EVResult, Context, true)) { + // For compatibility with GCC, we also allow pointers that would be + // integral constant expressions if they were cast to int. + llvm::APSInt IntResult; + if (EVResult.Val.toIntegralConstant(IntResult, InputExpr->getType(), + Context)) + if (!Info.isValidAsmImmediate(IntResult)) + return StmtError( + Diag(InputExpr->getBeginLoc(), + diag::err_invalid_asm_value_for_constraint) + << toString(IntResult, 10) << Info.getConstraintStr() + << InputExpr->getSourceRange()); + } + } + } } if (Info.allowsRegister()) { @@ -428,7 +437,7 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, } } - if (InputExpr->getType()->isExtIntType()) + if (InputExpr->getType()->isBitIntType()) return StmtError( Diag(InputExpr->getBeginLoc(), diag::err_asm_invalid_type) << InputExpr->getType() << 1 /*Output*/ @@ -453,12 +462,12 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, << Info.getConstraintStr(); } - Optional<SourceLocation> UnwindClobberLoc; + std::optional<SourceLocation> UnwindClobberLoc; // Check that the clobbers are valid. for (unsigned i = 0; i != NumClobbers; i++) { StringLiteral *Literal = Clobbers[i]; - assert(Literal->isAscii()); + assert(Literal->isOrdinary()); StringRef Clobber = Literal->getString(); @@ -666,8 +675,17 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, // output was a register, just extend the shorter one to the size of the // larger one. if (!SmallerValueMentioned && InputDomain != AD_Other && - OutputConstraintInfos[TiedTo].allowsRegister()) + OutputConstraintInfos[TiedTo].allowsRegister()) { + // FIXME: GCC supports the OutSize to be 128 at maximum. Currently codegen + // crash when the size larger than the register size. So we limit it here. + if (OutTy->isStructureType() && + Context.getIntTypeForBitwidth(OutSize, /*Signed*/ false).isNull()) { + targetDiag(OutputExpr->getExprLoc(), diag::err_store_value_to_reg); + return NS; + } + continue; + } // Either both of the operands were mentioned or the smaller one was // mentioned. One more special case that we'll allow: if the tied input is @@ -706,10 +724,7 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, NamedOperandList.emplace_back( std::make_pair(Names[i]->getName(), Exprs[i])); // Sort NamedOperandList. - std::stable_sort(NamedOperandList.begin(), NamedOperandList.end(), - [](const NamedOperand &LHS, const NamedOperand &RHS) { - return LHS.first < RHS.first; - }); + llvm::stable_sort(NamedOperandList, llvm::less_first()); // Find adjacent duplicate operand. SmallVector<NamedOperand, 4>::iterator Found = std::adjacent_find(begin(NamedOperandList), end(NamedOperandList), @@ -726,6 +741,9 @@ StmtResult Sema::ActOnGCCAsmStmt(SourceLocation AsmLoc, bool IsSimple, } if (NS->isAsmGoto()) setFunctionHasBranchIntoScope(); + + CleanupVarDeclMarking(); + DiscardCleanupsInEvaluationContext(); return NS; } @@ -922,13 +940,24 @@ StmtResult Sema::ActOnMSAsmStmt(SourceLocation AsmLoc, SourceLocation LBraceLoc, bool IsSimple = (NumOutputs != 0 || NumInputs != 0); setFunctionHasBranchProtectedScope(); + bool InvalidOperand = false; for (uint64_t I = 0; I < NumOutputs + NumInputs; ++I) { - if (Exprs[I]->getType()->isExtIntType()) - return StmtError( - Diag(Exprs[I]->getBeginLoc(), diag::err_asm_invalid_type) - << Exprs[I]->getType() << (I < NumOutputs) - << Exprs[I]->getSourceRange()); + Expr *E = Exprs[I]; + if (E->getType()->isBitIntType()) { + InvalidOperand = true; + Diag(E->getBeginLoc(), diag::err_asm_invalid_type) + << E->getType() << (I < NumOutputs) + << E->getSourceRange(); + } else if (E->refersToBitField()) { + InvalidOperand = true; + FieldDecl *BitField = E->getSourceBitField(); + Diag(E->getBeginLoc(), diag::err_ms_asm_bitfield_unsupported) + << E->getSourceRange(); + Diag(BitField->getLocation(), diag::note_bitfield_decl); + } } + if (InvalidOperand) + return StmtError(); MSAsmStmt *NS = new (Context) MSAsmStmt(Context, AsmLoc, LBraceLoc, IsSimple, |