head	1.1;
branch	1.1.1;
access;
symbols
	netbsd-11-0-RC4:1.1.1.5
	netbsd-11-0-RC3:1.1.1.5
	netbsd-11-0-RC2:1.1.1.5
	netbsd-11-0-RC1:1.1.1.5
	perseant-exfatfs-base-20250801:1.1.1.5
	netbsd-11:1.1.1.5.0.24
	netbsd-11-base:1.1.1.5
	netbsd-10-1-RELEASE:1.1.1.5
	perseant-exfatfs-base-20240630:1.1.1.5
	perseant-exfatfs:1.1.1.5.0.22
	perseant-exfatfs-base:1.1.1.5
	netbsd-8-3-RELEASE:1.1.1.5
	netbsd-9-4-RELEASE:1.1.1.5
	netbsd-10-0-RELEASE:1.1.1.5
	netbsd-10-0-RC6:1.1.1.5
	netbsd-10-0-RC5:1.1.1.5
	netbsd-10-0-RC4:1.1.1.5
	netbsd-10-0-RC3:1.1.1.5
	netbsd-10-0-RC2:1.1.1.5
	netbsd-10-0-RC1:1.1.1.5
	netbsd-10:1.1.1.5.0.20
	netbsd-10-base:1.1.1.5
	netbsd-9-3-RELEASE:1.1.1.5
	cjep_sun2x:1.1.1.5.0.18
	cjep_sun2x-base:1.1.1.5
	cjep_staticlib_x-base1:1.1.1.5
	netbsd-9-2-RELEASE:1.1.1.5
	cjep_staticlib_x:1.1.1.5.0.16
	cjep_staticlib_x-base:1.1.1.5
	netbsd-9-1-RELEASE:1.1.1.5
	phil-wifi-20200421:1.1.1.5
	phil-wifi-20200411:1.1.1.5
	phil-wifi-20200406:1.1.1.5
	netbsd-8-2-RELEASE:1.1.1.5
	netbsd-9-0-RELEASE:1.1.1.5
	netbsd-9-0-RC2:1.1.1.5
	netbsd-9-0-RC1:1.1.1.5
	netbsd-9:1.1.1.5.0.14
	netbsd-9-base:1.1.1.5
	netbsd-8-1-RELEASE:1.1.1.5
	netbsd-8-1-RC1:1.1.1.5
	pgoyette-compat-merge-20190127:1.1.1.5
	pgoyette-compat-20190127:1.1.1.5
	pgoyette-compat-20190118:1.1.1.5
	pgoyette-compat-1226:1.1.1.5
	pgoyette-compat-1126:1.1.1.5
	pgoyette-compat-1020:1.1.1.5
	pgoyette-compat-0930:1.1.1.5
	pgoyette-compat-0906:1.1.1.5
	netbsd-7-2-RELEASE:1.1.1.4
	pgoyette-compat-0728:1.1.1.5
	netbsd-8-0-RELEASE:1.1.1.5
	pgoyette-compat-0625:1.1.1.5
	netbsd-8-0-RC2:1.1.1.5
	pgoyette-compat-0521:1.1.1.5
	pgoyette-compat-0502:1.1.1.5
	pgoyette-compat-0422:1.1.1.5
	netbsd-8-0-RC1:1.1.1.5
	pgoyette-compat-0415:1.1.1.5
	pgoyette-compat-0407:1.1.1.5
	pgoyette-compat-0330:1.1.1.5
	pgoyette-compat-0322:1.1.1.5
	pgoyette-compat-0315:1.1.1.5
	netbsd-7-1-2-RELEASE:1.1.1.4
	pgoyette-compat:1.1.1.5.0.12
	pgoyette-compat-base:1.1.1.5
	netbsd-7-1-1-RELEASE:1.1.1.4
	perseant-stdc-iso10646:1.1.1.5.0.10
	perseant-stdc-iso10646-base:1.1.1.5
	netbsd-8:1.1.1.5.0.8
	netbsd-8-base:1.1.1.5
	prg-localcount2-base3:1.1.1.5
	prg-localcount2-base2:1.1.1.5
	prg-localcount2-base1:1.1.1.5
	prg-localcount2:1.1.1.5.0.6
	prg-localcount2-base:1.1.1.5
	pgoyette-localcount-20170426:1.1.1.5
	bouyer-socketcan-base1:1.1.1.5
	pgoyette-localcount-20170320:1.1.1.5
	netbsd-7-1:1.1.1.4.0.10
	netbsd-7-1-RELEASE:1.1.1.4
	netbsd-7-1-RC2:1.1.1.4
	netbsd-7-nhusb-base-20170116:1.1.1.4
	bouyer-socketcan:1.1.1.5.0.4
	bouyer-socketcan-base:1.1.1.5
	pgoyette-localcount-20170107:1.1.1.5
	netbsd-7-1-RC1:1.1.1.4
	pgoyette-localcount-20161104:1.1.1.5
	netbsd-7-0-2-RELEASE:1.1.1.4
	localcount-20160914:1.1.1.5
	netbsd-7-nhusb:1.1.1.4.0.8
	netbsd-7-nhusb-base:1.1.1.4
	pgoyette-localcount-20160806:1.1.1.5
	pgoyette-localcount-20160726:1.1.1.5
	pgoyette-localcount:1.1.1.5.0.2
	pgoyette-localcount-base:1.1.1.5
	netbsd-7-0-1-RELEASE:1.1.1.4
	netbsd-7-0:1.1.1.4.0.6
	netbsd-7-0-RELEASE:1.1.1.4
	netbsd-7-0-RC3:1.1.1.4
	netbsd-7-0-RC2:1.1.1.4
	netbsd-7-0-RC1:1.1.1.4
	clang-237755:1.1.1.4
	clang-232565:1.1.1.4
	clang-227398:1.1.1.4
	tls-maxphys-base:1.1.1.4
	tls-maxphys:1.1.1.4.0.4
	netbsd-7:1.1.1.4.0.2
	netbsd-7-base:1.1.1.4
	clang-215315:1.1.1.4
	clang-209886:1.1.1.4
	yamt-pagecache:1.1.1.3.0.4
	yamt-pagecache-base9:1.1.1.3
	tls-earlyentropy:1.1.1.3.0.2
	tls-earlyentropy-base:1.1.1.4
	riastradh-xf86-video-intel-2-7-1-pre-2-21-15:1.1.1.3
	riastradh-drm2-base3:1.1.1.3
	clang-202566:1.1.1.3
	clang-201163:1.1.1.3
	clang-199312:1.1.1.2
	clang-198450:1.1.1.1
	clang-196603:1.1.1.1
	clang-195771:1.1.1.1
	LLVM:1.1.1;
locks; strict;
comment	@// @;


1.1
date	2013.11.28.14.14.58;	author joerg;	state Exp;
branches
	1.1.1.1;
next	;
commitid	ow8OybrawrB1f3fx;

1.1.1.1
date	2013.11.28.14.14.58;	author joerg;	state Exp;
branches;
next	1.1.1.2;
commitid	ow8OybrawrB1f3fx;

1.1.1.2
date	2014.01.15.21.26.09;	author joerg;	state Exp;
branches;
next	1.1.1.3;
commitid	NQXlzzA0SPkc5glx;

1.1.1.3
date	2014.02.14.20.07.35;	author joerg;	state Exp;
branches
	1.1.1.3.2.1
	1.1.1.3.4.1;
next	1.1.1.4;
commitid	annVkZ1sc17rF6px;

1.1.1.4
date	2014.05.30.18.14.47;	author joerg;	state Exp;
branches
	1.1.1.4.4.1;
next	1.1.1.5;
commitid	8q0kdlBlCn09GACx;

1.1.1.5
date	2016.02.27.22.22.58;	author joerg;	state dead;
branches;
next	;
commitid	DKbhbwSVAW5DxBWy;

1.1.1.3.2.1
date	2014.08.10.07.08.14;	author tls;	state Exp;
branches;
next	;
commitid	t01A1TLTYxkpGMLx;

1.1.1.3.4.1
date	2014.02.14.20.07.35;	author yamt;	state dead;
branches;
next	1.1.1.3.4.2;
commitid	WSrDtL5nYAUyiyBx;

1.1.1.3.4.2
date	2014.05.22.16.18.57;	author yamt;	state Exp;
branches;
next	;
commitid	WSrDtL5nYAUyiyBx;

1.1.1.4.4.1
date	2014.05.30.18.14.47;	author tls;	state dead;
branches;
next	1.1.1.4.4.2;
commitid	jTnpym9Qu0o4R1Nx;

1.1.1.4.4.2
date	2014.08.19.23.47.58;	author tls;	state Exp;
branches;
next	;
commitid	jTnpym9Qu0o4R1Nx;


desc
@@


1.1
log
@Initial revision
@
text
@// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 -mconstructor-aliases -cxx-abi microsoft -fexceptions -fno-rtti | FileCheck -check-prefix WIN32 %s

struct A {
  A();
  ~A();
  int a;
};

A getA();

int TakesTwo(A a, A b);
void HasEHCleanup() {
  TakesTwo(getA(), getA());
}

// With exceptions, we need to clean up at least one of these temporaries.
// WIN32: define void @@"\01?HasEHCleanup@@@@YAXXZ"() {{.*}} {
//    First one doesn't have any cleanups, no need for invoke.
// WIN32:   call void @@"\01?getA@@@@YA?AUA@@@@XZ"(%struct.A* sret %{{.*}})
//    If this call throws, we have to cleanup the first temporary.
// WIN32:   invoke void @@"\01?getA@@@@YA?AUA@@@@XZ"(%struct.A* sret %{{.*}})
//    If this call throws, we already popped our cleanups
// WIN32:   call i32 @@"\01?TakesTwo@@@@YAHUA@@@@0@@Z"
// WIN32:   ret void
//
//    There should be one dtor call for unwinding from the second getA.
// WIN32:   invoke x86_thiscallcc void @@"\01??1A@@@@QAE@@XZ"
// WIN32: }

void TakeRef(const A &a);
int HasDeactivatedCleanups() {
  return TakesTwo((TakeRef(A()), A()), (TakeRef(A()), A()));
}

// WIN32: define i32 @@"\01?HasDeactivatedCleanups@@@@YAHXZ"() {{.*}} {
// WIN32:   %[[isactive:.*]] = alloca i1
// WIN32:   call x86_thiscallcc %struct.A* @@"\01??0A@@@@QAE@@XZ"
// WIN32:   invoke void @@"\01?TakeRef@@@@YAXABUA@@@@@@Z"
// WIN32:   invoke x86_thiscallcc %struct.A* @@"\01??0A@@@@QAE@@XZ"(%struct.A* %[[arg1:.*]])
// WIN32:   store i1 true, i1* %[[isactive]]
// WIN32:   invoke x86_thiscallcc %struct.A* @@"\01??0A@@@@QAE@@XZ"
// WIN32:   invoke void @@"\01?TakeRef@@@@YAXABUA@@@@@@Z"
// WIN32:   invoke x86_thiscallcc %struct.A* @@"\01??0A@@@@QAE@@XZ"
// WIN32:   store i1 false, i1* %[[isactive]]
// WIN32:   invoke i32 @@"\01?TakesTwo@@@@YAHUA@@@@0@@Z"
//        Destroy the two const ref temporaries.
// WIN32:   invoke x86_thiscallcc void @@"\01??1A@@@@QAE@@XZ"
// WIN32:   call x86_thiscallcc void @@"\01??1A@@@@QAE@@XZ"
// WIN32:   ret i32
//
//        Conditionally destroy arg1.
// WIN32:   %[[cond:.*]] = load i1* %[[isactive]]
// WIN32:   br i1 %[[cond]]
// WIN32:   invoke x86_thiscallcc void @@"\01??1A@@@@QAE@@XZ"(%struct.A* %[[arg1]])
// WIN32: }

// Test putting the cleanups inside a conditional.
int CouldThrow();
int HasConditionalCleanup(bool cond) {
  return (cond ? TakesTwo(A(), A()) : CouldThrow());
}

// WIN32: define i32 @@"\01?HasConditionalCleanup@@@@YAH_N@@Z"(i1 zeroext %{{.*}}) {{.*}} {
// WIN32:   store i1 false
// WIN32:   br i1
//        No cleanups, so we call and then activate a cleanup if it succeeds.
// WIN32:   call x86_thiscallcc %struct.A* @@"\01??0A@@@@QAE@@XZ"(%struct.A* %[[arg1:.*]])
// WIN32:   store i1 true
//        Now we have a cleanup for the first aggregate, so we invoke.
// WIN32:   invoke x86_thiscallcc %struct.A* @@"\01??0A@@@@QAE@@XZ"(%struct.A* %{{.*}})
//        Now we have no cleanups because TakeTwo will destruct both args.
// WIN32:   call i32 @@"\01?TakesTwo@@@@YAHUA@@@@0@@Z"
//        Still no cleanups, so call.
// WIN32:   call i32 @@"\01?CouldThrow@@@@YAHXZ"()
//        Somewhere in the landing pad for our single invoke, call the dtor.
// WIN32:   invoke x86_thiscallcc void @@"\01??1A@@@@QAE@@XZ"(%struct.A* %[[arg1]])
// WIN32: }

// Now test both.
int HasConditionalDeactivatedCleanups(bool cond) {
  return (cond ? TakesTwo((TakeRef(A()), A()), (TakeRef(A()), A())) : CouldThrow());
}

// WIN32: define i32 @@"\01?HasConditionalDeactivatedCleanups@@@@YAH_N@@Z"{{.*}} {
// WIN32:   %[[arg1:.*]] = alloca %struct.A, align 4
// WIN32:   alloca i1
// WIN32:   %[[arg1_cond:.*]] = alloca i1
//        Start all four cleanups as deactivated.
// WIN32:   store i1 false
// WIN32:   store i1 false
// WIN32:   store i1 false
// WIN32:   store i1 false
// WIN32:   br i1
//        True condition.
// WIN32:   call x86_thiscallcc %struct.A* @@"\01??0A@@@@QAE@@XZ"
// WIN32:   store i1 true
// WIN32:   invoke void @@"\01?TakeRef@@@@YAXABUA@@@@@@Z"
// WIN32:   invoke x86_thiscallcc %struct.A* @@"\01??0A@@@@QAE@@XZ"(%struct.A* %[[arg1]])
// WIN32:   store i1 true, i1* %[[arg1_cond]]
// WIN32:   invoke x86_thiscallcc %struct.A* @@"\01??0A@@@@QAE@@XZ"
// WIN32:   store i1 true
// WIN32:   invoke void @@"\01?TakeRef@@@@YAXABUA@@@@@@Z"
// WIN32:   invoke x86_thiscallcc %struct.A* @@"\01??0A@@@@QAE@@XZ"
// WIN32:   store i1 true
// WIN32:   store i1 false, i1* %[[arg1_cond]]
// WIN32:   invoke i32 @@"\01?TakesTwo@@@@YAHUA@@@@0@@Z"
//        False condition.
// WIN32:   invoke i32 @@"\01?CouldThrow@@@@YAHXZ"()
//        Two normal cleanups for TakeRef args.
// WIN32:   invoke x86_thiscallcc void @@"\01??1A@@@@QAE@@XZ"
// WIN32:   call x86_thiscallcc void @@"\01??1A@@@@QAE@@XZ"
// WIN32:   ret i32
//
//        Somewhere in the landing pad soup, we conditionally destroy arg1.
// WIN32:   %[[isactive:.*]] = load i1* %[[arg1_cond]]
// WIN32:   br i1 %[[isactive]]
// WIN32:   invoke x86_thiscallcc void @@"\01??1A@@@@QAE@@XZ"(%struct.A* %[[arg1]])
// WIN32: }

namespace crash_on_partial_destroy {
struct A {
  virtual ~A();
};

struct B : virtual A {
  // Has an implicit destructor.
};

struct C : B {
  C();
};

void foo();
// We used to crash when emitting this.
C::C() { foo(); }

// Verify that we don't bother with a vbtable lookup when adjusting the this
// pointer to call a base destructor from a constructor while unwinding.
// WIN32-LABEL: define {{.*}} @@"\01??0C@@crash_on_partial_destroy@@@@QAE@@XZ"{{.*}} {
// WIN32:      landingpad
//
//        We shouldn't do any vbptr loads, just constant GEPs.
// WIN32-NOT:  load
// WIN32:      getelementptr i8* %{{.*}}, i32 4
// WIN32-NOT:  load
// WIN32:      bitcast i8* %{{.*}} to %"struct.crash_on_partial_destroy::B"*
// WIN32:      invoke x86_thiscallcc void @@"\01??1B@@crash_on_partial_destroy@@@@UAE@@XZ"
//
// WIN32-NOT:  load
// WIN32:      bitcast %"struct.crash_on_partial_destroy::C"* %{{.*}} to i8*
// WIN32-NOT:  load
// WIN32:      getelementptr inbounds i8* %{{.*}}, i64 4
// WIN32-NOT:  load
// WIN32:      bitcast i8* %{{.*}} to %"struct.crash_on_partial_destroy::A"*
// WIN32:      invoke x86_thiscallcc void @@"\01??1A@@crash_on_partial_destroy@@@@UAE@@XZ"
// WIN32: }
}
@


1.1.1.1
log
@Import Clang 3.4rc1 r195771.
@
text
@@


1.1.1.2
log
@Import Clang 3.5svn r199312
@
text
@d1 1
a1 1
// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fexceptions -fno-rtti | FileCheck -check-prefix WIN32 %s
@


1.1.1.3
log
@Import Clang 3.5svn r201163.
@
text
@d17 3
a19 4
// WIN32-LABEL: define void @@"\01?HasEHCleanup@@@@YAXXZ"() {{.*}} {
// WIN32:   %[[base:.*]] = call i8* @@llvm.stacksave()
//    If this call throws, we have to restore the stack.
// WIN32:   invoke void @@"\01?getA@@@@YA?AUA@@@@XZ"(%struct.A* sret %{{.*}})
d22 2
a23 3
//    If this call throws, we have to cleanup the stacksave.
// WIN32:   invoke i32 @@"\01?TakesTwo@@@@YAHUA@@@@0@@Z"
// WIN32:   call void @@llvm.stackrestore(i8* %[[base]])
a27 2
// WIN32-NOT: @@"\01??1A@@@@QAE@@XZ"
// WIN32:   call void @@llvm.stackrestore
d35 1
a35 1
// WIN32-LABEL: define i32 @@"\01?HasDeactivatedCleanups@@@@YAHXZ"() {{.*}} {
d37 1
a37 4
// WIN32:   call i8* @@llvm.stacksave()
// WIN32:   %[[argmem:.*]] = alloca [[argmem_ty:<{ %struct.A, %struct.A }>]], inalloca
// WIN32:   %[[arg1:.*]] = getelementptr inbounds [[argmem_ty]]* %[[argmem]], i32 0, i32 1
// WIN32:   invoke x86_thiscallcc %struct.A* @@"\01??0A@@@@QAE@@XZ"
d39 1
a39 2
//
// WIN32:   invoke x86_thiscallcc %struct.A* @@"\01??0A@@@@QAE@@XZ"(%struct.A* %[[arg1]])
a40 2
//
// WIN32:   %[[arg0:.*]] = getelementptr inbounds [[argmem_ty]]* %[[argmem]], i32 0, i32 0
d45 1
a45 3
//
// WIN32:   invoke i32 @@"\01?TakesTwo@@@@YAHUA@@@@0@@Z"([[argmem_ty]]* inalloca %[[argmem]])
// WIN32:   call void @@llvm.stackrestore
d48 1
a48 1
// WIN32:   invoke x86_thiscallcc void @@"\01??1A@@@@QAE@@XZ"
d63 1
a63 1
// WIN32-LABEL: define i32 @@"\01?HasConditionalCleanup@@@@YAH_N@@Z"(i1 zeroext %{{.*}}) {{.*}} {
d66 2
a67 2
// WIN32:   call i8* @@llvm.stacksave()
// WIN32:   invoke x86_thiscallcc %struct.A* @@"\01??0A@@@@QAE@@XZ"(%struct.A* %{{.*}})
d69 1
d71 3
a73 3
// WIN32:   invoke i32 @@"\01?TakesTwo@@@@YAHUA@@@@0@@Z"
// WIN32:   call void @@llvm.stackrestore
//
d75 2
a76 5
//
//        Only one dtor in the invoke for arg1
// WIN32:   invoke x86_thiscallcc void @@"\01??1A@@@@QAE@@XZ"({{.*}})
// WIN32-NOT: invoke x86_thiscallcc void @@"\01??1A@@@@QAE@@XZ"
// WIN32:   call void @@llvm.stackrestore
d84 2
a85 1
// WIN32-LABEL: define i32 @@"\01?HasConditionalDeactivatedCleanups@@@@YAH_N@@Z"{{.*}} {
d95 1
a95 1
// WIN32:   invoke x86_thiscallcc %struct.A* @@"\01??0A@@@@QAE@@XZ"
d98 1
a98 1
// WIN32:   invoke x86_thiscallcc %struct.A* @@"\01??0A@@@@QAE@@XZ"
d111 1
a111 1
// WIN32:   invoke x86_thiscallcc void @@"\01??1A@@@@QAE@@XZ"
d117 1
a117 1
// WIN32:   invoke x86_thiscallcc void @@"\01??1A@@@@QAE@@XZ"
@


1.1.1.3.2.1
log
@Rebase.
@
text
@d42 1
a42 1
// WIN32:   %[[argmem:.*]] = alloca inalloca [[argmem_ty:<{ %struct.A, %struct.A }>]]
@


1.1.1.4
log
@Import Clang 3.5svn r209886.
@
text
@d42 1
a42 1
// WIN32:   %[[argmem:.*]] = alloca inalloca [[argmem_ty:<{ %struct.A, %struct.A }>]]
@


1.1.1.5
log
@Mark files without clang-261930 as dead.
@
text
@@


1.1.1.4.4.1
log
@file microsoft-abi-exceptions.cpp was added on branch tls-maxphys on 2014-08-19 23:47:58 +0000
@
text
@d1 170
@


1.1.1.4.4.2
log
@Rebase to HEAD as of a few days ago.
@
text
@a0 170
// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fexceptions -fno-rtti | FileCheck -check-prefix WIN32 %s

struct A {
  A();
  ~A();
  int a;
};

A getA();

int TakesTwo(A a, A b);
void HasEHCleanup() {
  TakesTwo(getA(), getA());
}

// With exceptions, we need to clean up at least one of these temporaries.
// WIN32-LABEL: define void @@"\01?HasEHCleanup@@@@YAXXZ"() {{.*}} {
// WIN32:   %[[base:.*]] = call i8* @@llvm.stacksave()
//    If this call throws, we have to restore the stack.
// WIN32:   invoke void @@"\01?getA@@@@YA?AUA@@@@XZ"(%struct.A* sret %{{.*}})
//    If this call throws, we have to cleanup the first temporary.
// WIN32:   invoke void @@"\01?getA@@@@YA?AUA@@@@XZ"(%struct.A* sret %{{.*}})
//    If this call throws, we have to cleanup the stacksave.
// WIN32:   invoke i32 @@"\01?TakesTwo@@@@YAHUA@@@@0@@Z"
// WIN32:   call void @@llvm.stackrestore(i8* %[[base]])
// WIN32:   ret void
//
//    There should be one dtor call for unwinding from the second getA.
// WIN32:   invoke x86_thiscallcc void @@"\01??1A@@@@QAE@@XZ"
// WIN32-NOT: @@"\01??1A@@@@QAE@@XZ"
// WIN32:   call void @@llvm.stackrestore
// WIN32: }

void TakeRef(const A &a);
int HasDeactivatedCleanups() {
  return TakesTwo((TakeRef(A()), A()), (TakeRef(A()), A()));
}

// WIN32-LABEL: define i32 @@"\01?HasDeactivatedCleanups@@@@YAHXZ"() {{.*}} {
// WIN32:   %[[isactive:.*]] = alloca i1
// WIN32:   call i8* @@llvm.stacksave()
// WIN32:   %[[argmem:.*]] = alloca inalloca [[argmem_ty:<{ %struct.A, %struct.A }>]]
// WIN32:   %[[arg1:.*]] = getelementptr inbounds [[argmem_ty]]* %[[argmem]], i32 0, i32 1
// WIN32:   invoke x86_thiscallcc %struct.A* @@"\01??0A@@@@QAE@@XZ"
// WIN32:   invoke void @@"\01?TakeRef@@@@YAXABUA@@@@@@Z"
//
// WIN32:   invoke x86_thiscallcc %struct.A* @@"\01??0A@@@@QAE@@XZ"(%struct.A* %[[arg1]])
// WIN32:   store i1 true, i1* %[[isactive]]
//
// WIN32:   %[[arg0:.*]] = getelementptr inbounds [[argmem_ty]]* %[[argmem]], i32 0, i32 0
// WIN32:   invoke x86_thiscallcc %struct.A* @@"\01??0A@@@@QAE@@XZ"
// WIN32:   invoke void @@"\01?TakeRef@@@@YAXABUA@@@@@@Z"
// WIN32:   invoke x86_thiscallcc %struct.A* @@"\01??0A@@@@QAE@@XZ"
// WIN32:   store i1 false, i1* %[[isactive]]
//
// WIN32:   invoke i32 @@"\01?TakesTwo@@@@YAHUA@@@@0@@Z"([[argmem_ty]]* inalloca %[[argmem]])
// WIN32:   call void @@llvm.stackrestore
//        Destroy the two const ref temporaries.
// WIN32:   invoke x86_thiscallcc void @@"\01??1A@@@@QAE@@XZ"
// WIN32:   invoke x86_thiscallcc void @@"\01??1A@@@@QAE@@XZ"
// WIN32:   ret i32
//
//        Conditionally destroy arg1.
// WIN32:   %[[cond:.*]] = load i1* %[[isactive]]
// WIN32:   br i1 %[[cond]]
// WIN32:   invoke x86_thiscallcc void @@"\01??1A@@@@QAE@@XZ"(%struct.A* %[[arg1]])
// WIN32: }

// Test putting the cleanups inside a conditional.
int CouldThrow();
int HasConditionalCleanup(bool cond) {
  return (cond ? TakesTwo(A(), A()) : CouldThrow());
}

// WIN32-LABEL: define i32 @@"\01?HasConditionalCleanup@@@@YAH_N@@Z"(i1 zeroext %{{.*}}) {{.*}} {
// WIN32:   store i1 false
// WIN32:   br i1
// WIN32:   call i8* @@llvm.stacksave()
// WIN32:   invoke x86_thiscallcc %struct.A* @@"\01??0A@@@@QAE@@XZ"(%struct.A* %{{.*}})
// WIN32:   store i1 true
// WIN32:   invoke x86_thiscallcc %struct.A* @@"\01??0A@@@@QAE@@XZ"(%struct.A* %{{.*}})
// WIN32:   invoke i32 @@"\01?TakesTwo@@@@YAHUA@@@@0@@Z"
// WIN32:   call void @@llvm.stackrestore
//
// WIN32:   call i32 @@"\01?CouldThrow@@@@YAHXZ"()
//
//        Only one dtor in the invoke for arg1
// WIN32:   invoke x86_thiscallcc void @@"\01??1A@@@@QAE@@XZ"({{.*}})
// WIN32-NOT: invoke x86_thiscallcc void @@"\01??1A@@@@QAE@@XZ"
// WIN32:   call void @@llvm.stackrestore
// WIN32: }

// Now test both.
int HasConditionalDeactivatedCleanups(bool cond) {
  return (cond ? TakesTwo((TakeRef(A()), A()), (TakeRef(A()), A())) : CouldThrow());
}

// WIN32-LABEL: define i32 @@"\01?HasConditionalDeactivatedCleanups@@@@YAH_N@@Z"{{.*}} {
// WIN32:   alloca i1
// WIN32:   %[[arg1_cond:.*]] = alloca i1
//        Start all four cleanups as deactivated.
// WIN32:   store i1 false
// WIN32:   store i1 false
// WIN32:   store i1 false
// WIN32:   store i1 false
// WIN32:   br i1
//        True condition.
// WIN32:   invoke x86_thiscallcc %struct.A* @@"\01??0A@@@@QAE@@XZ"
// WIN32:   store i1 true
// WIN32:   invoke void @@"\01?TakeRef@@@@YAXABUA@@@@@@Z"
// WIN32:   invoke x86_thiscallcc %struct.A* @@"\01??0A@@@@QAE@@XZ"
// WIN32:   store i1 true, i1* %[[arg1_cond]]
// WIN32:   invoke x86_thiscallcc %struct.A* @@"\01??0A@@@@QAE@@XZ"
// WIN32:   store i1 true
// WIN32:   invoke void @@"\01?TakeRef@@@@YAXABUA@@@@@@Z"
// WIN32:   invoke x86_thiscallcc %struct.A* @@"\01??0A@@@@QAE@@XZ"
// WIN32:   store i1 true
// WIN32:   store i1 false, i1* %[[arg1_cond]]
// WIN32:   invoke i32 @@"\01?TakesTwo@@@@YAHUA@@@@0@@Z"
//        False condition.
// WIN32:   invoke i32 @@"\01?CouldThrow@@@@YAHXZ"()
//        Two normal cleanups for TakeRef args.
// WIN32:   invoke x86_thiscallcc void @@"\01??1A@@@@QAE@@XZ"
// WIN32:   invoke x86_thiscallcc void @@"\01??1A@@@@QAE@@XZ"
// WIN32:   ret i32
//
//        Somewhere in the landing pad soup, we conditionally destroy arg1.
// WIN32:   %[[isactive:.*]] = load i1* %[[arg1_cond]]
// WIN32:   br i1 %[[isactive]]
// WIN32:   invoke x86_thiscallcc void @@"\01??1A@@@@QAE@@XZ"
// WIN32: }

namespace crash_on_partial_destroy {
struct A {
  virtual ~A();
};

struct B : virtual A {
  // Has an implicit destructor.
};

struct C : B {
  C();
};

void foo();
// We used to crash when emitting this.
C::C() { foo(); }

// Verify that we don't bother with a vbtable lookup when adjusting the this
// pointer to call a base destructor from a constructor while unwinding.
// WIN32-LABEL: define {{.*}} @@"\01??0C@@crash_on_partial_destroy@@@@QAE@@XZ"{{.*}} {
// WIN32:      landingpad
//
//        We shouldn't do any vbptr loads, just constant GEPs.
// WIN32-NOT:  load
// WIN32:      getelementptr i8* %{{.*}}, i32 4
// WIN32-NOT:  load
// WIN32:      bitcast i8* %{{.*}} to %"struct.crash_on_partial_destroy::B"*
// WIN32:      invoke x86_thiscallcc void @@"\01??1B@@crash_on_partial_destroy@@@@UAE@@XZ"
//
// WIN32-NOT:  load
// WIN32:      bitcast %"struct.crash_on_partial_destroy::C"* %{{.*}} to i8*
// WIN32-NOT:  load
// WIN32:      getelementptr inbounds i8* %{{.*}}, i64 4
// WIN32-NOT:  load
// WIN32:      bitcast i8* %{{.*}} to %"struct.crash_on_partial_destroy::A"*
// WIN32:      invoke x86_thiscallcc void @@"\01??1A@@crash_on_partial_destroy@@@@UAE@@XZ"
// WIN32: }
}
@


1.1.1.3.4.1
log
@file microsoft-abi-exceptions.cpp was added on branch yamt-pagecache on 2014-05-22 16:18:57 +0000
@
text
@d1 170
@


1.1.1.3.4.2
log
@sync with head.

for a reference, the tree before this commit was tagged
as yamt-pagecache-tag8.

this commit was splitted into small chunks to avoid
a limitation of cvs.  ("Protocol error: too many arguments")
@
text
@a0 170
// RUN: %clang_cc1 -emit-llvm %s -o - -triple=i386-pc-win32 -mconstructor-aliases -fexceptions -fno-rtti | FileCheck -check-prefix WIN32 %s

struct A {
  A();
  ~A();
  int a;
};

A getA();

int TakesTwo(A a, A b);
void HasEHCleanup() {
  TakesTwo(getA(), getA());
}

// With exceptions, we need to clean up at least one of these temporaries.
// WIN32-LABEL: define void @@"\01?HasEHCleanup@@@@YAXXZ"() {{.*}} {
// WIN32:   %[[base:.*]] = call i8* @@llvm.stacksave()
//    If this call throws, we have to restore the stack.
// WIN32:   invoke void @@"\01?getA@@@@YA?AUA@@@@XZ"(%struct.A* sret %{{.*}})
//    If this call throws, we have to cleanup the first temporary.
// WIN32:   invoke void @@"\01?getA@@@@YA?AUA@@@@XZ"(%struct.A* sret %{{.*}})
//    If this call throws, we have to cleanup the stacksave.
// WIN32:   invoke i32 @@"\01?TakesTwo@@@@YAHUA@@@@0@@Z"
// WIN32:   call void @@llvm.stackrestore(i8* %[[base]])
// WIN32:   ret void
//
//    There should be one dtor call for unwinding from the second getA.
// WIN32:   invoke x86_thiscallcc void @@"\01??1A@@@@QAE@@XZ"
// WIN32-NOT: @@"\01??1A@@@@QAE@@XZ"
// WIN32:   call void @@llvm.stackrestore
// WIN32: }

void TakeRef(const A &a);
int HasDeactivatedCleanups() {
  return TakesTwo((TakeRef(A()), A()), (TakeRef(A()), A()));
}

// WIN32-LABEL: define i32 @@"\01?HasDeactivatedCleanups@@@@YAHXZ"() {{.*}} {
// WIN32:   %[[isactive:.*]] = alloca i1
// WIN32:   call i8* @@llvm.stacksave()
// WIN32:   %[[argmem:.*]] = alloca [[argmem_ty:<{ %struct.A, %struct.A }>]], inalloca
// WIN32:   %[[arg1:.*]] = getelementptr inbounds [[argmem_ty]]* %[[argmem]], i32 0, i32 1
// WIN32:   invoke x86_thiscallcc %struct.A* @@"\01??0A@@@@QAE@@XZ"
// WIN32:   invoke void @@"\01?TakeRef@@@@YAXABUA@@@@@@Z"
//
// WIN32:   invoke x86_thiscallcc %struct.A* @@"\01??0A@@@@QAE@@XZ"(%struct.A* %[[arg1]])
// WIN32:   store i1 true, i1* %[[isactive]]
//
// WIN32:   %[[arg0:.*]] = getelementptr inbounds [[argmem_ty]]* %[[argmem]], i32 0, i32 0
// WIN32:   invoke x86_thiscallcc %struct.A* @@"\01??0A@@@@QAE@@XZ"
// WIN32:   invoke void @@"\01?TakeRef@@@@YAXABUA@@@@@@Z"
// WIN32:   invoke x86_thiscallcc %struct.A* @@"\01??0A@@@@QAE@@XZ"
// WIN32:   store i1 false, i1* %[[isactive]]
//
// WIN32:   invoke i32 @@"\01?TakesTwo@@@@YAHUA@@@@0@@Z"([[argmem_ty]]* inalloca %[[argmem]])
// WIN32:   call void @@llvm.stackrestore
//        Destroy the two const ref temporaries.
// WIN32:   invoke x86_thiscallcc void @@"\01??1A@@@@QAE@@XZ"
// WIN32:   invoke x86_thiscallcc void @@"\01??1A@@@@QAE@@XZ"
// WIN32:   ret i32
//
//        Conditionally destroy arg1.
// WIN32:   %[[cond:.*]] = load i1* %[[isactive]]
// WIN32:   br i1 %[[cond]]
// WIN32:   invoke x86_thiscallcc void @@"\01??1A@@@@QAE@@XZ"(%struct.A* %[[arg1]])
// WIN32: }

// Test putting the cleanups inside a conditional.
int CouldThrow();
int HasConditionalCleanup(bool cond) {
  return (cond ? TakesTwo(A(), A()) : CouldThrow());
}

// WIN32-LABEL: define i32 @@"\01?HasConditionalCleanup@@@@YAH_N@@Z"(i1 zeroext %{{.*}}) {{.*}} {
// WIN32:   store i1 false
// WIN32:   br i1
// WIN32:   call i8* @@llvm.stacksave()
// WIN32:   invoke x86_thiscallcc %struct.A* @@"\01??0A@@@@QAE@@XZ"(%struct.A* %{{.*}})
// WIN32:   store i1 true
// WIN32:   invoke x86_thiscallcc %struct.A* @@"\01??0A@@@@QAE@@XZ"(%struct.A* %{{.*}})
// WIN32:   invoke i32 @@"\01?TakesTwo@@@@YAHUA@@@@0@@Z"
// WIN32:   call void @@llvm.stackrestore
//
// WIN32:   call i32 @@"\01?CouldThrow@@@@YAHXZ"()
//
//        Only one dtor in the invoke for arg1
// WIN32:   invoke x86_thiscallcc void @@"\01??1A@@@@QAE@@XZ"({{.*}})
// WIN32-NOT: invoke x86_thiscallcc void @@"\01??1A@@@@QAE@@XZ"
// WIN32:   call void @@llvm.stackrestore
// WIN32: }

// Now test both.
int HasConditionalDeactivatedCleanups(bool cond) {
  return (cond ? TakesTwo((TakeRef(A()), A()), (TakeRef(A()), A())) : CouldThrow());
}

// WIN32-LABEL: define i32 @@"\01?HasConditionalDeactivatedCleanups@@@@YAH_N@@Z"{{.*}} {
// WIN32:   alloca i1
// WIN32:   %[[arg1_cond:.*]] = alloca i1
//        Start all four cleanups as deactivated.
// WIN32:   store i1 false
// WIN32:   store i1 false
// WIN32:   store i1 false
// WIN32:   store i1 false
// WIN32:   br i1
//        True condition.
// WIN32:   invoke x86_thiscallcc %struct.A* @@"\01??0A@@@@QAE@@XZ"
// WIN32:   store i1 true
// WIN32:   invoke void @@"\01?TakeRef@@@@YAXABUA@@@@@@Z"
// WIN32:   invoke x86_thiscallcc %struct.A* @@"\01??0A@@@@QAE@@XZ"
// WIN32:   store i1 true, i1* %[[arg1_cond]]
// WIN32:   invoke x86_thiscallcc %struct.A* @@"\01??0A@@@@QAE@@XZ"
// WIN32:   store i1 true
// WIN32:   invoke void @@"\01?TakeRef@@@@YAXABUA@@@@@@Z"
// WIN32:   invoke x86_thiscallcc %struct.A* @@"\01??0A@@@@QAE@@XZ"
// WIN32:   store i1 true
// WIN32:   store i1 false, i1* %[[arg1_cond]]
// WIN32:   invoke i32 @@"\01?TakesTwo@@@@YAHUA@@@@0@@Z"
//        False condition.
// WIN32:   invoke i32 @@"\01?CouldThrow@@@@YAHXZ"()
//        Two normal cleanups for TakeRef args.
// WIN32:   invoke x86_thiscallcc void @@"\01??1A@@@@QAE@@XZ"
// WIN32:   invoke x86_thiscallcc void @@"\01??1A@@@@QAE@@XZ"
// WIN32:   ret i32
//
//        Somewhere in the landing pad soup, we conditionally destroy arg1.
// WIN32:   %[[isactive:.*]] = load i1* %[[arg1_cond]]
// WIN32:   br i1 %[[isactive]]
// WIN32:   invoke x86_thiscallcc void @@"\01??1A@@@@QAE@@XZ"
// WIN32: }

namespace crash_on_partial_destroy {
struct A {
  virtual ~A();
};

struct B : virtual A {
  // Has an implicit destructor.
};

struct C : B {
  C();
};

void foo();
// We used to crash when emitting this.
C::C() { foo(); }

// Verify that we don't bother with a vbtable lookup when adjusting the this
// pointer to call a base destructor from a constructor while unwinding.
// WIN32-LABEL: define {{.*}} @@"\01??0C@@crash_on_partial_destroy@@@@QAE@@XZ"{{.*}} {
// WIN32:      landingpad
//
//        We shouldn't do any vbptr loads, just constant GEPs.
// WIN32-NOT:  load
// WIN32:      getelementptr i8* %{{.*}}, i32 4
// WIN32-NOT:  load
// WIN32:      bitcast i8* %{{.*}} to %"struct.crash_on_partial_destroy::B"*
// WIN32:      invoke x86_thiscallcc void @@"\01??1B@@crash_on_partial_destroy@@@@UAE@@XZ"
//
// WIN32-NOT:  load
// WIN32:      bitcast %"struct.crash_on_partial_destroy::C"* %{{.*}} to i8*
// WIN32-NOT:  load
// WIN32:      getelementptr inbounds i8* %{{.*}}, i64 4
// WIN32-NOT:  load
// WIN32:      bitcast i8* %{{.*}} to %"struct.crash_on_partial_destroy::A"*
// WIN32:      invoke x86_thiscallcc void @@"\01??1A@@crash_on_partial_destroy@@@@UAE@@XZ"
// WIN32: }
}
@


