aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/clang/lib/CodeGen/CGStmt.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2021-08-22 19:00:43 +0000
committerDimitry Andric <dim@FreeBSD.org>2021-11-13 20:39:49 +0000
commitfe6060f10f634930ff71b7c50291ddc610da2475 (patch)
tree1483580c790bd4d27b6500a7542b5ee00534d3cc /contrib/llvm-project/clang/lib/CodeGen/CGStmt.cpp
parentb61bce17f346d79cecfd8f195a64b10f77be43b1 (diff)
parent344a3780b2e33f6ca763666c380202b18aab72a3 (diff)
downloadsrc-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.cpp246
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());