Skip to content
This repository has been archived by the owner on Mar 28, 2020. It is now read-only.

Commit

Permalink
Merge remote-tracking branch 'origin/swift-5.1-branch' into stable
Browse files Browse the repository at this point in the history
  • Loading branch information
swift-ci committed Mar 23, 2019
2 parents 6c55728 + 8bae514 commit 2c09040
Show file tree
Hide file tree
Showing 24 changed files with 241 additions and 104 deletions.
9 changes: 0 additions & 9 deletions lib/CodeGen/CGExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1288,8 +1288,6 @@ LValue CodeGenFunction::EmitLValue(const Expr *E) {
return EmitCXXBindTemporaryLValue(cast<CXXBindTemporaryExpr>(E));
case Expr::CXXUuidofExprClass:
return EmitCXXUuidofLValue(cast<CXXUuidofExpr>(E));
case Expr::LambdaExprClass:
return EmitLambdaLValue(cast<LambdaExpr>(E));

case Expr::ExprWithCleanupsClass: {
const auto *cleanups = cast<ExprWithCleanups>(E);
Expand Down Expand Up @@ -4549,13 +4547,6 @@ CodeGenFunction::EmitCXXBindTemporaryLValue(const CXXBindTemporaryExpr *E) {
return MakeAddrLValue(Slot.getAddress(), E->getType(), AlignmentSource::Decl);
}

LValue
CodeGenFunction::EmitLambdaLValue(const LambdaExpr *E) {
AggValueSlot Slot = CreateAggTemp(E->getType(), "temp.lvalue");
EmitLambdaExpr(E, Slot);
return MakeAddrLValue(Slot.getAddress(), E->getType(), AlignmentSource::Decl);
}

LValue CodeGenFunction::EmitObjCMessageExprLValue(const ObjCMessageExpr *E) {
RValue RV = EmitObjCMessageExpr(E);

Expand Down
47 changes: 46 additions & 1 deletion lib/CodeGen/CGExprAgg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1264,7 +1264,52 @@ void AggExprEmitter::VisitCXXInheritedCtorInitExpr(
void
AggExprEmitter::VisitLambdaExpr(LambdaExpr *E) {
AggValueSlot Slot = EnsureSlot(E->getType());
CGF.EmitLambdaExpr(E, Slot);
LValue SlotLV = CGF.MakeAddrLValue(Slot.getAddress(), E->getType());

// We'll need to enter cleanup scopes in case any of the element
// initializers throws an exception.
SmallVector<EHScopeStack::stable_iterator, 16> Cleanups;
llvm::Instruction *CleanupDominator = nullptr;

CXXRecordDecl::field_iterator CurField = E->getLambdaClass()->field_begin();
for (LambdaExpr::const_capture_init_iterator i = E->capture_init_begin(),
e = E->capture_init_end();
i != e; ++i, ++CurField) {
// Emit initialization
LValue LV = CGF.EmitLValueForFieldInitialization(SlotLV, *CurField);
if (CurField->hasCapturedVLAType()) {
CGF.EmitLambdaVLACapture(CurField->getCapturedVLAType(), LV);
continue;
}

EmitInitializationToLValue(*i, LV);

// Push a destructor if necessary.
if (QualType::DestructionKind DtorKind =
CurField->getType().isDestructedType()) {
assert(LV.isSimple());
if (CGF.needsEHCleanup(DtorKind)) {
if (!CleanupDominator)
CleanupDominator = CGF.Builder.CreateAlignedLoad(
CGF.Int8Ty,
llvm::Constant::getNullValue(CGF.Int8PtrTy),
CharUnits::One()); // placeholder

CGF.pushDestroy(EHCleanup, LV.getAddress(), CurField->getType(),
CGF.getDestroyer(DtorKind), false);
Cleanups.push_back(CGF.EHStack.stable_begin());
}
}
}

// Deactivate all the partial cleanups in reverse order, which
// generally means popping them.
for (unsigned i = Cleanups.size(); i != 0; --i)
CGF.DeactivateCleanupBlock(Cleanups[i-1], CleanupDominator);

// Destroy the placeholder if we made one.
if (CleanupDominator)
CleanupDominator->eraseFromParent();
}

void AggExprEmitter::VisitExprWithCleanups(ExprWithCleanups *E) {
Expand Down
18 changes: 0 additions & 18 deletions lib/CodeGen/CGExprCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2252,21 +2252,3 @@ llvm::Value *CodeGenFunction::EmitDynamicCast(Address ThisAddr,

return Value;
}

void CodeGenFunction::EmitLambdaExpr(const LambdaExpr *E, AggValueSlot Slot) {
LValue SlotLV = MakeAddrLValue(Slot.getAddress(), E->getType());

CXXRecordDecl::field_iterator CurField = E->getLambdaClass()->field_begin();
for (LambdaExpr::const_capture_init_iterator i = E->capture_init_begin(),
e = E->capture_init_end();
i != e; ++i, ++CurField) {
// Emit initialization
LValue LV = EmitLValueForFieldInitialization(SlotLV, *CurField);
if (CurField->hasCapturedVLAType()) {
auto VAT = CurField->getCapturedVLAType();
EmitStoreThroughLValue(RValue::get(VLASizeMap[VAT->getSizeExpr()]), LV);
} else {
EmitInitializerForField(*CurField, LV, *i);
}
}
}
29 changes: 16 additions & 13 deletions lib/CodeGen/CGObjC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1959,12 +1959,10 @@ static void setARCRuntimeFunctionLinkage(CodeGenModule &CGM,
/// Perform an operation having the signature
/// i8* (i8*)
/// where a null input causes a no-op and returns null.
static llvm::Value *emitARCValueOperation(CodeGenFunction &CGF,
llvm::Value *value,
llvm::Type *returnType,
llvm::Constant *&fn,
llvm::Intrinsic::ID IntID,
bool isTailCall = false) {
static llvm::Value *emitARCValueOperation(
CodeGenFunction &CGF, llvm::Value *value, llvm::Type *returnType,
llvm::Constant *&fn, llvm::Intrinsic::ID IntID,
llvm::CallInst::TailCallKind tailKind = llvm::CallInst::TCK_None) {
if (isa<llvm::ConstantPointerNull>(value))
return value;

Expand All @@ -1979,8 +1977,7 @@ static llvm::Value *emitARCValueOperation(CodeGenFunction &CGF,

// Call the function.
llvm::CallInst *call = CGF.EmitNounwindRuntimeCall(fn, value);
if (isTailCall)
call->setTailCall();
call->setTailCallKind(tailKind);

// Cast the result back to the original type.
return CGF.Builder.CreateBitCast(call, origType);
Expand Down Expand Up @@ -2195,9 +2192,15 @@ static void emitAutoreleasedReturnValueMarker(CodeGenFunction &CGF) {
llvm::Value *
CodeGenFunction::EmitARCRetainAutoreleasedReturnValue(llvm::Value *value) {
emitAutoreleasedReturnValueMarker(*this);
return emitARCValueOperation(*this, value, nullptr,
CGM.getObjCEntrypoints().objc_retainAutoreleasedReturnValue,
llvm::Intrinsic::objc_retainAutoreleasedReturnValue);
llvm::CallInst::TailCallKind tailKind =
CGM.getTargetCodeGenInfo()
.shouldSuppressTailCallsOfRetainAutoreleasedReturnValue()
? llvm::CallInst::TCK_NoTail
: llvm::CallInst::TCK_None;
return emitARCValueOperation(
*this, value, nullptr,
CGM.getObjCEntrypoints().objc_retainAutoreleasedReturnValue,
llvm::Intrinsic::objc_retainAutoreleasedReturnValue, tailKind);
}

/// Claim a possibly-autoreleased return value at +0. This is only
Expand Down Expand Up @@ -2334,7 +2337,7 @@ CodeGenFunction::EmitARCAutoreleaseReturnValue(llvm::Value *value) {
return emitARCValueOperation(*this, value, nullptr,
CGM.getObjCEntrypoints().objc_autoreleaseReturnValue,
llvm::Intrinsic::objc_autoreleaseReturnValue,
/*isTailCall*/ true);
llvm::CallInst::TCK_Tail);
}

/// Do a fused retain/autorelease of the given object.
Expand All @@ -2344,7 +2347,7 @@ CodeGenFunction::EmitARCRetainAutoreleaseReturnValue(llvm::Value *value) {
return emitARCValueOperation(*this, value, nullptr,
CGM.getObjCEntrypoints().objc_retainAutoreleaseReturnValue,
llvm::Intrinsic::objc_retainAutoreleaseReturnValue,
/*isTailCall*/ true);
llvm::CallInst::TCK_Tail);
}

/// Do a fused retain/autorelease of the given object.
Expand Down
6 changes: 3 additions & 3 deletions lib/CodeGen/CodeGenFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -1835,6 +1835,9 @@ class CodeGenFunction : public CodeGenTypeCache {
void EmitLambdaBlockInvokeBody();
void EmitLambdaDelegatingInvokeBody(const CXXMethodDecl *MD);
void EmitLambdaStaticInvokeBody(const CXXMethodDecl *MD);
void EmitLambdaVLACapture(const VariableArrayType *VAT, LValue LV) {
EmitStoreThroughLValue(RValue::get(VLASizeMap[VAT->getSizeExpr()]), LV);
}
void EmitAsanPrologueOrEpilogue(bool Prologue);

/// Emit the unified return block, trying to avoid its emission when
Expand Down Expand Up @@ -3549,7 +3552,6 @@ class CodeGenFunction : public CodeGenTypeCache {

LValue EmitCXXConstructLValue(const CXXConstructExpr *E);
LValue EmitCXXBindTemporaryLValue(const CXXBindTemporaryExpr *E);
LValue EmitLambdaLValue(const LambdaExpr *E);
LValue EmitCXXTypeidLValue(const CXXTypeidExpr *E);
LValue EmitCXXUuidofLValue(const CXXUuidofExpr *E);

Expand Down Expand Up @@ -3973,8 +3975,6 @@ class CodeGenFunction : public CodeGenTypeCache {

void EmitCXXThrowExpr(const CXXThrowExpr *E, bool KeepInsertionPoint = true);

void EmitLambdaExpr(const LambdaExpr *E, AggValueSlot Dest);

RValue EmitAtomicExpr(AtomicExpr *E);

//===--------------------------------------------------------------------===//
Expand Down
6 changes: 6 additions & 0 deletions lib/CodeGen/TargetInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2254,6 +2254,12 @@ class X86_64TargetCodeGenInfo : public TargetCodeGenInfo {
return static_cast<const X86_64ABIInfo&>(TargetCodeGenInfo::getABIInfo());
}

/// Disable tail call on x86-64. The epilogue code before the tail jump blocks
/// the autoreleaseRV/retainRV optimization.
bool shouldSuppressTailCallsOfRetainAutoreleasedReturnValue() const override {
return true;
}

int getDwarfEHStackPointer(CodeGen::CodeGenModule &CGM) const override {
return 7;
}
Expand Down
6 changes: 6 additions & 0 deletions lib/CodeGen/TargetInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,12 @@ class TargetCodeGenInfo {
return "";
}

/// Determine whether a call to objc_retainAutoreleasedReturnValue should be
/// marked as 'notail'.
virtual bool shouldSuppressTailCallsOfRetainAutoreleasedReturnValue() const {
return false;
}

/// Return a constant used by UBSan as a signature to identify functions
/// possessing type information, or 0 if the platform is unsupported.
virtual llvm::Constant *
Expand Down
104 changes: 104 additions & 0 deletions test/CodeGenCXX/cxx1y-init-captures-eh.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// RUN: %clang_cc1 -std=c++1y -triple x86_64-linux-gnu -fexceptions -fcxx-exceptions -emit-llvm %s -o - | FileCheck %s

struct S {
S();
~S();
};

struct T {
T() noexcept;
~T();
int n;
};

// CHECK-LABEL: define void @_Z1fv(
void f() {
// CHECK: call void @_ZN1SC1Ev(
// CHECK: invoke void @__cxa_throw
//
// Ensure we call the lambda destructor here, and do not call the destructor
// for the capture.
// CHECK: landingpad
// CHECK-NOT: _ZN1SD
// CHECK: call void @"_ZZ1fvEN3$_0D1Ev"(
// CHECK-NOT: _ZN1SD
// CHECK: resume
[s = S()] {}, throw 0;

// CHECK: }
}

// CHECK-LABEL: define void @_Z1gv(
void g() {
// CHECK: call void @_ZN1SC1Ev(
// CHECK: invoke void @__cxa_throw
//
// Ensure we call the lambda destructor here, and do not call the destructor
// for the capture.
// CHECK: landingpad
// CHECK-NOT: @"_ZZ1gvEN3$_0D1Ev"(
// CHECK: call void @_ZN1SD1Ev(
// CHECK-NOT: @"_ZZ1gvEN3$_0D1Ev"(
// CHECK: resume
[s = S(), t = (throw 0, 1)] {};

// CHECK: }
}

void x() noexcept;
void y() noexcept;

// CHECK-LABEL: define void @_Z1hbb(
void h(bool b1, bool b2) {
// CHECK: {{.*}} = alloca i1,
// CHECK: %[[S_ISACTIVE:.*]] = alloca i1,
// CHECK: {{.*}} = alloca i1,

// lambda init: s and t, branch on b1
// CHECK: call void @_ZN1SC1Ev(
// CHECK: store i1 true, i1* %[[S_ISACTIVE]], align 1
// CHECK: call void @_ZN1TC1Ev(
// CHECK: br i1

// throw 1
// CHECK: invoke void @__cxa_throw

// completion of lambda init, branch on b2
// CHECK: store i32 42,
// CHECK: store i1 false, i1* %[[S_ISACTIVE]], align 1
// CHECK: br i1

// throw 2
// CHECK: invoke void @__cxa_throw

// end of full-expression
// CHECK: call void @_Z1xv(
// CHECK: call void @"_ZZ1hbbEN3$_2D1Ev"(
// CHECK: call void @_ZN1TD1Ev(
// CHECK: call void @_Z1yv(
// CHECK: ret void

// cleanups for throw 1
// CHECK: landingpad
// CHECK-NOT: @"_ZZ1hbbEN3$_2D1Ev"(
// CHECK: br

// cleanups for throw 2
// CHECK: landingpad
// CHECK: call void @"_ZZ1hbbEN3$_2D1Ev"(
// CHECK: br

// common cleanup code
// CHECK: call void @_ZN1TD1Ev(
// CHECK: load i1, i1* %[[S_ISACTIVE]],
// CHECK: br i1

// CHECK: call void @_ZN1SD1Ev(
// CHECK: br

// CHECK: resume
[s = S(), t = T().n, u = (b1 ? throw 1 : 42)] {}, (b2 ? throw 2 : 0), x();
y();

// CHECK: }
}
8 changes: 4 additions & 4 deletions test/CodeGenObjC/arc-blocks.m
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ void test4(void) {
// CHECK-NEXT: store i32 838860800, i32* [[T0]]
// CHECK: [[SLOT:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* [[VAR]], i32 0, i32 6
// CHECK-NEXT: [[T0:%.*]] = call i8* @test4_source()
// CHECK-NEXT: [[T1:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T0]])
// CHECK-NEXT: [[T1:%.*]] = notail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T0]])
// CHECK-NEXT: store i8* [[T1]], i8** [[SLOT]]
// CHECK-NEXT: [[SLOT:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* [[VAR]], i32 0, i32 6
// 0x42800000 - has signature, copy/dispose helpers, as well as BLOCK_HAS_EXTENDED_LAYOUT
Expand Down Expand Up @@ -181,7 +181,7 @@ void test5(void) {
// CHECK-NEXT: [[VARPTR1:%.*]] = bitcast i8** [[VAR]] to i8*
// CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 8, i8* [[VARPTR1]])
// CHECK: [[T0:%.*]] = call i8* @test5_source()
// CHECK-NEXT: [[T1:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T0]])
// CHECK-NEXT: [[T1:%.*]] = notail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T0]])
// CHECK-NEXT: store i8* [[T1]], i8** [[VAR]],
// CHECK-NEXT: call void @llvm.objc.release(i8* [[T1]])
// 0x40800000 - has signature but no copy/dispose, as well as BLOCK_HAS_EXTENDED_LAYOUT
Expand Down Expand Up @@ -212,7 +212,7 @@ void test6(void) {
// CHECK-NEXT: store i32 1107296256, i32* [[T0]]
// CHECK: [[SLOT:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* [[VAR]], i32 0, i32 6
// CHECK-NEXT: [[T0:%.*]] = call i8* @test6_source()
// CHECK-NEXT: [[T1:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T0]])
// CHECK-NEXT: [[T1:%.*]] = notail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T0]])
// CHECK-NEXT: call i8* @llvm.objc.initWeak(i8** [[SLOT]], i8* [[T1]])
// CHECK-NEXT: call void @llvm.objc.release(i8* [[T1]])
// CHECK-NEXT: [[SLOT:%.*]] = getelementptr inbounds [[BYREF_T]], [[BYREF_T]]* [[VAR]], i32 0, i32 6
Expand Down Expand Up @@ -258,7 +258,7 @@ void test7(void) {
// CHECK: [[VAR:%.*]] = alloca i8*,
// CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
// CHECK: [[T0:%.*]] = call i8* @test7_source()
// CHECK-NEXT: [[T1:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T0]])
// CHECK-NEXT: [[T1:%.*]] = notail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T0]])
// CHECK-NEXT: call i8* @llvm.objc.initWeak(i8** [[VAR]], i8* [[T1]])
// CHECK-NEXT: call void @llvm.objc.release(i8* [[T1]])
// 0x42800000 - has signature, copy/dispose helpers, as well as BLOCK_HAS_EXTENDED_LAYOUT
Expand Down
2 changes: 1 addition & 1 deletion test/CodeGenObjC/arc-foreach.m
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ void test2(Test2 *a) {
// CHECK-LP64-LABEL: define void @test2(
// CHECK-LP64: [[T0:%.*]] = call [[ARRAY_T]]* bitcast (i8* (i8*, i8*, ...)* @objc_msgSend to [[ARRAY_T]]* (i8*, i8*)*)(
// CHECK-LP64-NEXT: [[T1:%.*]] = bitcast [[ARRAY_T]]* [[T0]] to i8*
// CHECK-LP64-NEXT: [[T2:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T1]])
// CHECK-LP64-NEXT: [[T2:%.*]] = notail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T1]])
// CHECK-LP64-NEXT: [[COLL:%.*]] = bitcast i8* [[T2]] to [[ARRAY_T]]*

// Make sure it's not immediately released before starting the iteration.
Expand Down
6 changes: 3 additions & 3 deletions test/CodeGenObjC/arc-literals.m
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ void test_array(id a, id b) {
// CHECK-NEXT: [[T1:%.*]] = bitcast [[CLASS_T]]* [[T0]] to i8*
// CHECK-NEXT: [[T2:%.*]] = bitcast [2 x i8*]* [[OBJECTS]] to i8**
// CHECK-NEXT: [[T3:%.*]] = call i8* bitcast ({{.*@objc_msgSend.*}})(i8* [[T1]], i8* [[SEL]], i8** [[T2]], i64 2)
// CHECK-NEXT: [[T4:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T3]])
// CHECK-NEXT: [[T4:%.*]] = notail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T3]])
// CHECK: call void (...) @llvm.objc.clang.arc.use(i8* [[V0]], i8* [[V1]])
id arr = @[a, b];

Expand Down Expand Up @@ -103,7 +103,7 @@ void test_dictionary(id k1, id o1, id k2, id o2) {
// CHECK-NEXT: [[T2:%.*]] = bitcast [2 x i8*]* [[OBJECTS]] to i8**
// CHECK-NEXT: [[T3:%.*]] = bitcast [2 x i8*]* [[KEYS]] to i8**
// CHECK-NEXT: [[T4:%.*]] = call i8* bitcast ({{.*@objc_msgSend.*}})(i8* [[T1]], i8* [[SEL]], i8** [[T2]], i8** [[T3]], i64 2)
// CHECK-NEXT: [[T5:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T4]])
// CHECK-NEXT: [[T5:%.*]] = notail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T4]])
// CHECK-NEXT: call void (...) @llvm.objc.clang.arc.use(i8* [[V0]], i8* [[V1]], i8* [[V2]], i8* [[V3]])

id dict = @{ k1 : o1, k2 : o2 };
Expand Down Expand Up @@ -135,7 +135,7 @@ void test_property(B *b) {
// CHECK-NEXT: [[T1:%.*]] = bitcast
// CHECK-NEXT: [[T2:%.*]] = call [[B:%.*]]* bitcast ({{.*}} @objc_msgSend to {{.*}})(i8* [[T1]], i8* [[SEL]])
// CHECK-NEXT: [[T3:%.*]] = bitcast [[B]]* [[T2]] to i8*
// CHECK-NEXT: [[T4:%.*]] = call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T3]])
// CHECK-NEXT: [[T4:%.*]] = notail call i8* @llvm.objc.retainAutoreleasedReturnValue(i8* [[T3]])
// CHECK-NEXT: [[V0:%.*]] = bitcast i8* [[T4]] to [[B]]*
// CHECK-NEXT: [[V1:%.*]] = bitcast [[B]]* [[V0]] to i8*

Expand Down
Loading

0 comments on commit 2c09040

Please sign in to comment.