diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2021-08-22 19:00:43 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2021-11-13 20:39:49 +0000 |
commit | fe6060f10f634930ff71b7c50291ddc610da2475 (patch) | |
tree | 1483580c790bd4d27b6500a7542b5ee00534d3cc /contrib/llvm-project/clang/lib/CodeGen/CGStmt.cpp | |
parent | b61bce17f346d79cecfd8f195a64b10f77be43b1 (diff) | |
parent | 344a3780b2e33f6ca763666c380202b18aab72a3 (diff) | |
download | src-fe6060f10f634930ff71b7c50291ddc610da2475.tar.gz src-fe6060f10f634930ff71b7c50291ddc610da2475.zip |
Diffstat (limited to 'contrib/llvm-project/clang/lib/CodeGen/CGStmt.cpp')
-rw-r--r-- | contrib/llvm-project/clang/lib/CodeGen/CGStmt.cpp | 246 |
1 files changed, 172 insertions, 74 deletions
diff --git a/contrib/llvm-project/clang/lib/CodeGen/CGStmt.cpp b/contrib/llvm-project/clang/lib/CodeGen/CGStmt.cpp index a1a72a9f668d..aeb319ca1581 100644 --- a/contrib/llvm-project/clang/lib/CodeGen/CGStmt.cpp +++ b/contrib/llvm-project/clang/lib/CodeGen/CGStmt.cpp @@ -16,6 +16,8 @@ #include "CodeGenModule.h" #include "TargetInfo.h" #include "clang/AST/Attr.h" +#include "clang/AST/Expr.h" +#include "clang/AST/Stmt.h" #include "clang/AST/StmtVisitor.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/DiagnosticSema.h" @@ -194,12 +196,21 @@ void CodeGenFunction::EmitStmt(const Stmt *S, ArrayRef<const Attr *> Attrs) { case Stmt::SEHTryStmtClass: EmitSEHTryStmt(cast<SEHTryStmt>(*S)); break; + case Stmt::OMPCanonicalLoopClass: + EmitOMPCanonicalLoop(cast<OMPCanonicalLoop>(S)); + break; case Stmt::OMPParallelDirectiveClass: EmitOMPParallelDirective(cast<OMPParallelDirective>(*S)); break; case Stmt::OMPSimdDirectiveClass: EmitOMPSimdDirective(cast<OMPSimdDirective>(*S)); break; + case Stmt::OMPTileDirectiveClass: + EmitOMPTileDirective(cast<OMPTileDirective>(*S)); + break; + case Stmt::OMPUnrollDirectiveClass: + EmitOMPUnrollDirective(cast<OMPUnrollDirective>(*S)); + break; case Stmt::OMPForDirectiveClass: EmitOMPForDirective(cast<OMPForDirective>(*S)); break; @@ -369,6 +380,15 @@ void CodeGenFunction::EmitStmt(const Stmt *S, ArrayRef<const Attr *> Attrs) { EmitOMPTargetTeamsDistributeSimdDirective( cast<OMPTargetTeamsDistributeSimdDirective>(*S)); break; + case Stmt::OMPInteropDirectiveClass: + llvm_unreachable("Interop directive not supported yet."); + break; + case Stmt::OMPDispatchDirectiveClass: + llvm_unreachable("Dispatch directive not supported yet."); + break; + case Stmt::OMPMaskedDirectiveClass: + EmitOMPMaskedDirective(cast<OMPMaskedDirective>(*S)); + break; } } @@ -629,17 +649,30 @@ void CodeGenFunction::LexicalScope::rescopeLabels() { void CodeGenFunction::EmitLabelStmt(const LabelStmt &S) { EmitLabel(S.getDecl()); + + // IsEHa - emit eha.scope.begin if it's a side entry of a scope + if (getLangOpts().EHAsynch && S.isSideEntry()) + EmitSehCppScopeBegin(); + EmitStmt(S.getSubStmt()); } void CodeGenFunction::EmitAttributedStmt(const AttributedStmt &S) { bool nomerge = false; - for (const auto *A : S.getAttrs()) + const CallExpr *musttail = nullptr; + + for (const auto *A : S.getAttrs()) { if (A->getKind() == attr::NoMerge) { nomerge = true; - break; } + if (A->getKind() == attr::MustTail) { + const Stmt *Sub = S.getSubStmt(); + const ReturnStmt *R = cast<ReturnStmt>(Sub); + musttail = cast<CallExpr>(R->getRetValue()->IgnoreParens()); + } + } SaveAndRestore<bool> save_nomerge(InNoMergeAttributedStmt, nomerge); + SaveAndRestore<const CallExpr *> save_musttail(MustTailCall, musttail); EmitStmt(S.getSubStmt(), S.getAttrs()); } @@ -791,20 +824,14 @@ void CodeGenFunction::EmitWhileStmt(const WhileStmt &S, // while(1) is common, avoid extra exit blocks. Be sure // to correctly handle break/continue though. - bool EmitBoolCondBranch = true; - bool LoopMustProgress = false; - if (llvm::ConstantInt *C = dyn_cast<llvm::ConstantInt>(BoolCondVal)) { - if (C->isOne()) { - EmitBoolCondBranch = false; - FnIsMustProgress = false; - } - } else if (LanguageRequiresProgress()) - LoopMustProgress = true; - + llvm::ConstantInt *C = dyn_cast<llvm::ConstantInt>(BoolCondVal); + bool CondIsConstInt = C != nullptr; + bool EmitBoolCondBranch = !CondIsConstInt || !C->isOne(); const SourceRange &R = S.getSourceRange(); LoopStack.push(LoopHeader.getBlock(), CGM.getContext(), CGM.getCodeGenOpts(), WhileAttrs, SourceLocToDebugLoc(R.getBegin()), - SourceLocToDebugLoc(R.getEnd()), LoopMustProgress); + SourceLocToDebugLoc(R.getEnd()), + checkIfLoopMustProgress(CondIsConstInt)); // As long as the condition is true, go to the loop body. llvm::BasicBlock *LoopBody = createBasicBlock("while.body"); @@ -812,8 +839,11 @@ void CodeGenFunction::EmitWhileStmt(const WhileStmt &S, llvm::BasicBlock *ExitBlock = LoopExit.getBlock(); if (ConditionScope.requiresCleanups()) ExitBlock = createBasicBlock("while.exit"); - llvm::MDNode *Weights = createProfileOrBranchWeightsForLoop( - S.getCond(), getProfileCount(S.getBody()), S.getBody()); + llvm::MDNode *Weights = + createProfileWeightsForLoop(S.getCond(), getProfileCount(S.getBody())); + if (!Weights && CGM.getCodeGenOpts().OptimizationLevel) + BoolCondVal = emitCondLikelihoodViaExpectIntrinsic( + BoolCondVal, Stmt::getLikelihood(S.getBody())); Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock, Weights); if (ExitBlock != LoopExit.getBlock()) { @@ -892,20 +922,15 @@ void CodeGenFunction::EmitDoStmt(const DoStmt &S, // "do {} while (0)" is common in macros, avoid extra blocks. Be sure // to correctly handle break/continue though. - bool EmitBoolCondBranch = true; - bool LoopMustProgress = false; - if (llvm::ConstantInt *C = dyn_cast<llvm::ConstantInt>(BoolCondVal)) { - if (C->isZero()) - EmitBoolCondBranch = false; - else if (C->isOne()) - FnIsMustProgress = false; - } else if (LanguageRequiresProgress()) - LoopMustProgress = true; + llvm::ConstantInt *C = dyn_cast<llvm::ConstantInt>(BoolCondVal); + bool CondIsConstInt = C; + bool EmitBoolCondBranch = !C || !C->isZero(); const SourceRange &R = S.getSourceRange(); LoopStack.push(LoopBody, CGM.getContext(), CGM.getCodeGenOpts(), DoAttrs, SourceLocToDebugLoc(R.getBegin()), - SourceLocToDebugLoc(R.getEnd()), LoopMustProgress); + SourceLocToDebugLoc(R.getEnd()), + checkIfLoopMustProgress(CondIsConstInt)); // As long as the condition is true, iterate the loop. if (EmitBoolCondBranch) { @@ -939,43 +964,47 @@ void CodeGenFunction::EmitForStmt(const ForStmt &S, // Start the loop with a block that tests the condition. // If there's an increment, the continue scope will be overwritten // later. - JumpDest Continue = getJumpDestInCurrentScope("for.cond"); - llvm::BasicBlock *CondBlock = Continue.getBlock(); + JumpDest CondDest = getJumpDestInCurrentScope("for.cond"); + llvm::BasicBlock *CondBlock = CondDest.getBlock(); EmitBlock(CondBlock); - bool LoopMustProgress = false; Expr::EvalResult Result; - if (LanguageRequiresProgress()) { - if (!S.getCond()) { - FnIsMustProgress = false; - } else if (!S.getCond()->EvaluateAsInt(Result, getContext())) { - LoopMustProgress = true; - } - } + bool CondIsConstInt = + !S.getCond() || S.getCond()->EvaluateAsInt(Result, getContext()); const SourceRange &R = S.getSourceRange(); LoopStack.push(CondBlock, CGM.getContext(), CGM.getCodeGenOpts(), ForAttrs, SourceLocToDebugLoc(R.getBegin()), - SourceLocToDebugLoc(R.getEnd()), LoopMustProgress); - - // If the for loop doesn't have an increment we can just use the - // condition as the continue block. Otherwise we'll need to create - // a block for it (in the current scope, i.e. in the scope of the - // condition), and that we will become our continue block. - if (S.getInc()) - Continue = getJumpDestInCurrentScope("for.inc"); - - // Store the blocks to use for break and continue. - BreakContinueStack.push_back(BreakContinue(LoopExit, Continue)); + SourceLocToDebugLoc(R.getEnd()), + checkIfLoopMustProgress(CondIsConstInt)); // Create a cleanup scope for the condition variable cleanups. LexicalScope ConditionScope(*this, S.getSourceRange()); + // If the for loop doesn't have an increment we can just use the condition as + // the continue block. Otherwise, if there is no condition variable, we can + // form the continue block now. If there is a condition variable, we can't + // form the continue block until after we've emitted the condition, because + // the condition is in scope in the increment, but Sema's jump diagnostics + // ensure that there are no continues from the condition variable that jump + // to the loop increment. + JumpDest Continue; + if (!S.getInc()) + Continue = CondDest; + else if (!S.getConditionVariable()) + Continue = getJumpDestInCurrentScope("for.inc"); + BreakContinueStack.push_back(BreakContinue(LoopExit, Continue)); + if (S.getCond()) { // If the for statement has a condition scope, emit the local variable // declaration. if (S.getConditionVariable()) { EmitDecl(*S.getConditionVariable()); + + // We have entered the condition variable's scope, so we're now able to + // jump to the continue block. + Continue = S.getInc() ? getJumpDestInCurrentScope("for.inc") : CondDest; + BreakContinueStack.back().ContinueBlock = Continue; } llvm::BasicBlock *ExitBlock = LoopExit.getBlock(); @@ -990,12 +1019,11 @@ void CodeGenFunction::EmitForStmt(const ForStmt &S, // C99 6.8.5p2/p4: The first substatement is executed if the expression // compares unequal to 0. The condition must be a scalar type. llvm::Value *BoolCondVal = EvaluateExprAsBool(S.getCond()); - llvm::MDNode *Weights = createProfileOrBranchWeightsForLoop( - S.getCond(), getProfileCount(S.getBody()), S.getBody()); - - if (llvm::ConstantInt *C = dyn_cast<llvm::ConstantInt>(BoolCondVal)) - if (C->isOne()) - FnIsMustProgress = false; + llvm::MDNode *Weights = + createProfileWeightsForLoop(S.getCond(), getProfileCount(S.getBody())); + if (!Weights && CGM.getCodeGenOpts().OptimizationLevel) + BoolCondVal = emitCondLikelihoodViaExpectIntrinsic( + BoolCondVal, Stmt::getLikelihood(S.getBody())); Builder.CreateCondBr(BoolCondVal, ForBody, ExitBlock, Weights); @@ -1076,8 +1104,11 @@ CodeGenFunction::EmitCXXForRangeStmt(const CXXForRangeStmt &S, // The body is executed if the expression, contextually converted // to bool, is true. llvm::Value *BoolCondVal = EvaluateExprAsBool(S.getCond()); - llvm::MDNode *Weights = createProfileOrBranchWeightsForLoop( - S.getCond(), getProfileCount(S.getBody()), S.getBody()); + llvm::MDNode *Weights = + createProfileWeightsForLoop(S.getCond(), getProfileCount(S.getBody())); + if (!Weights && CGM.getCodeGenOpts().OptimizationLevel) + BoolCondVal = emitCondLikelihoodViaExpectIntrinsic( + BoolCondVal, Stmt::getLikelihood(S.getBody())); Builder.CreateCondBr(BoolCondVal, ForBody, ExitBlock, Weights); if (ExitBlock != LoopExit.getBlock()) { @@ -1145,6 +1176,38 @@ struct SaveRetExprRAII { }; } // namespace +/// If we have 'return f(...);', where both caller and callee are SwiftAsync, +/// codegen it as 'tail call ...; ret void;'. +static void makeTailCallIfSwiftAsync(const CallExpr *CE, CGBuilderTy &Builder, + const CGFunctionInfo *CurFnInfo) { + auto calleeQualType = CE->getCallee()->getType(); + const FunctionType *calleeType = nullptr; + if (calleeQualType->isFunctionPointerType() || + calleeQualType->isFunctionReferenceType() || + calleeQualType->isBlockPointerType() || + calleeQualType->isMemberFunctionPointerType()) { + calleeType = calleeQualType->getPointeeType()->castAs<FunctionType>(); + } else if (auto *ty = dyn_cast<FunctionType>(calleeQualType)) { + calleeType = ty; + } else if (auto CMCE = dyn_cast<CXXMemberCallExpr>(CE)) { + if (auto methodDecl = CMCE->getMethodDecl()) { + // getMethodDecl() doesn't handle member pointers at the moment. + calleeType = methodDecl->getType()->castAs<FunctionType>(); + } else { + return; + } + } else { + return; + } + if (calleeType->getCallConv() == CallingConv::CC_SwiftAsync && + (CurFnInfo->getASTCallingConvention() == CallingConv::CC_SwiftAsync)) { + auto CI = cast<llvm::CallInst>(&Builder.GetInsertBlock()->back()); + CI->setTailCallKind(llvm::CallInst::TCK_MustTail); + Builder.CreateRetVoid(); + Builder.ClearInsertionPoint(); + } +} + /// EmitReturnStmt - Note that due to GCC extensions, this can have an operand /// if the function returns void, or may be missing one if the function returns /// non-void. Fun stuff :). @@ -1203,8 +1266,11 @@ void CodeGenFunction::EmitReturnStmt(const ReturnStmt &S) { } else if (!ReturnValue.isValid() || (RV && RV->getType()->isVoidType())) { // Make sure not to return anything, but evaluate the expression // for side effects. - if (RV) + if (RV) { EmitAnyExpr(RV); + if (auto *CE = dyn_cast<CallExpr>(RV)) + makeTailCallIfSwiftAsync(CE, Builder, CurFnInfo); + } } else if (!RV) { // Do nothing (return value is left uninitialized) } else if (FnRetTy->isReferenceType()) { @@ -1351,7 +1417,7 @@ void CodeGenFunction::EmitCaseStmtRange(const CaseStmt &S, // this case. (*SwitchWeights)[0] += ThisCount; } else if (SwitchLikelihood) - Weights = createBranchWeights(LH); + Cond = emitCondLikelihoodViaExpectIntrinsic(Cond, LH); Builder.CreateCondBr(Cond, CaseDest, FalseDest, Weights); @@ -2092,7 +2158,7 @@ static llvm::MDNode *getAsmSrcLocInfo(const StringLiteral *Str, SmallVector<llvm::Metadata *, 8> Locs; // Add the location of the first line to the MDNode. Locs.push_back(llvm::ConstantAsMetadata::get(llvm::ConstantInt::get( - CGF.Int32Ty, Str->getBeginLoc().getRawEncoding()))); + CGF.Int64Ty, Str->getBeginLoc().getRawEncoding()))); StringRef StrVal = Str->getString(); if (!StrVal.empty()) { const SourceManager &SM = CGF.CGM.getContext().getSourceManager(); @@ -2107,7 +2173,7 @@ static llvm::MDNode *getAsmSrcLocInfo(const StringLiteral *Str, SourceLocation LineLoc = Str->getLocationOfByte( i + 1, SM, LangOpts, CGF.getTarget(), &StartToken, &ByteOffset); Locs.push_back(llvm::ConstantAsMetadata::get( - llvm::ConstantInt::get(CGF.Int32Ty, LineLoc.getRawEncoding()))); + llvm::ConstantInt::get(CGF.Int64Ty, LineLoc.getRawEncoding()))); } } @@ -2115,13 +2181,15 @@ static llvm::MDNode *getAsmSrcLocInfo(const StringLiteral *Str, } static void UpdateAsmCallInst(llvm::CallBase &Result, bool HasSideEffect, - bool ReadOnly, bool ReadNone, bool NoMerge, - const AsmStmt &S, + bool HasUnwindClobber, bool ReadOnly, + bool ReadNone, bool NoMerge, const AsmStmt &S, const std::vector<llvm::Type *> &ResultRegTypes, CodeGenFunction &CGF, std::vector<llvm::Value *> &RegResults) { - Result.addAttribute(llvm::AttributeList::FunctionIndex, - llvm::Attribute::NoUnwind); + if (!HasUnwindClobber) + Result.addAttribute(llvm::AttributeList::FunctionIndex, + llvm::Attribute::NoUnwind); + if (NoMerge) Result.addAttribute(llvm::AttributeList::FunctionIndex, llvm::Attribute::NoMerge); @@ -2142,8 +2210,8 @@ static void UpdateAsmCallInst(llvm::CallBase &Result, bool HasSideEffect, getAsmSrcLocInfo(gccAsmStmt->getAsmString(), CGF)); else { // At least put the line number on MS inline asm blobs. - llvm::Constant *Loc = llvm::ConstantInt::get(CGF.Int32Ty, - S.getAsmLoc().getRawEncoding()); + llvm::Constant *Loc = + llvm::ConstantInt::get(CGF.Int64Ty, S.getAsmLoc().getRawEncoding()); Result.setMetadata("srcloc", llvm::MDNode::get(CGF.getLLVMContext(), llvm::ConstantAsMetadata::get(Loc))); @@ -2468,13 +2536,18 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { } Constraints += InOutConstraints; + bool HasUnwindClobber = false; + // Clobbers for (unsigned i = 0, e = S.getNumClobbers(); i != e; i++) { StringRef Clobber = S.getClobber(i); if (Clobber == "memory") ReadOnly = ReadNone = false; - else if (Clobber != "cc") { + else if (Clobber == "unwind") { + HasUnwindClobber = true; + continue; + } else if (Clobber != "cc") { Clobber = getTarget().getNormalizedGCCRegisterName(Clobber); if (CGM.getCodeGenOpts().StackClashProtector && getTarget().isSPRegName(Clobber)) { @@ -2483,6 +2556,23 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { } } + if (isa<MSAsmStmt>(&S)) { + if (Clobber == "eax" || Clobber == "edx") { + if (Constraints.find("=&A") != std::string::npos) + continue; + std::string::size_type position1 = + Constraints.find("={" + Clobber.str() + "}"); + if (position1 != std::string::npos) { + Constraints.insert(position1 + 1, "&"); + continue; + } + std::string::size_type position2 = Constraints.find("=A"); + if (position2 != std::string::npos) { + Constraints.insert(position2 + 1, "&"); + continue; + } + } + } if (!Constraints.empty()) Constraints += ','; @@ -2491,6 +2581,9 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { Constraints += '}'; } + assert(!(HasUnwindClobber && IsGCCAsmGoto) && + "unwind clobber can't be used with asm goto"); + // Add machine specific clobbers std::string MachineClobbers = getTarget().getClobbers(); if (!MachineClobbers.empty()) { @@ -2513,23 +2606,28 @@ void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) { bool HasSideEffect = S.isVolatile() || S.getNumOutputs() == 0; llvm::InlineAsm::AsmDialect AsmDialect = isa<MSAsmStmt>(&S) ? llvm::InlineAsm::AD_Intel : llvm::InlineAsm::AD_ATT; - llvm::InlineAsm *IA = - llvm::InlineAsm::get(FTy, AsmString, Constraints, HasSideEffect, - /* IsAlignStack */ false, AsmDialect); + llvm::InlineAsm *IA = llvm::InlineAsm::get( + FTy, AsmString, Constraints, HasSideEffect, + /* IsAlignStack */ false, AsmDialect, HasUnwindClobber); std::vector<llvm::Value*> RegResults; if (IsGCCAsmGoto) { llvm::CallBrInst *Result = Builder.CreateCallBr(IA, Fallthrough, Transfer, Args); EmitBlock(Fallthrough); - UpdateAsmCallInst(cast<llvm::CallBase>(*Result), HasSideEffect, ReadOnly, - ReadNone, InNoMergeAttributedStmt, S, ResultRegTypes, - *this, RegResults); + UpdateAsmCallInst(cast<llvm::CallBase>(*Result), HasSideEffect, false, + ReadOnly, ReadNone, InNoMergeAttributedStmt, S, + ResultRegTypes, *this, RegResults); + } else if (HasUnwindClobber) { + llvm::CallBase *Result = EmitCallOrInvoke(IA, Args, ""); + UpdateAsmCallInst(*Result, HasSideEffect, true, ReadOnly, ReadNone, + InNoMergeAttributedStmt, S, ResultRegTypes, *this, + RegResults); } else { llvm::CallInst *Result = Builder.CreateCall(IA, Args, getBundlesForFunclet(IA)); - UpdateAsmCallInst(cast<llvm::CallBase>(*Result), HasSideEffect, ReadOnly, - ReadNone, InNoMergeAttributedStmt, S, ResultRegTypes, - *this, RegResults); + UpdateAsmCallInst(cast<llvm::CallBase>(*Result), HasSideEffect, false, + ReadOnly, ReadNone, InNoMergeAttributedStmt, S, + ResultRegTypes, *this, RegResults); } assert(RegResults.size() == ResultRegTypes.size()); |