118 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			LLVM
		
	
	
	
			
		
		
	
	
			118 lines
		
	
	
		
			3.2 KiB
		
	
	
	
		
			LLVM
		
	
	
	
; RUN: opt %s -passes='cgscc(inline)' -S | FileCheck %s
 | 
						|
 | 
						|
declare void @external_func()
 | 
						|
declare void @abort()
 | 
						|
 | 
						|
@exception_inner = external global i8
 | 
						|
@exception_outer = external global i8
 | 
						|
@condition = external global i1
 | 
						|
 | 
						|
 | 
						|
; Check for a bug in which multiple "resume" instructions in the
 | 
						|
; inlined function caused "catch i8* @exception_outer" to appear
 | 
						|
; multiple times in the resulting landingpad.
 | 
						|
 | 
						|
define internal void @inner_multiple_resume() personality i8* null {
 | 
						|
  invoke void @external_func()
 | 
						|
      to label %cont unwind label %lpad
 | 
						|
cont:
 | 
						|
  ret void
 | 
						|
lpad:
 | 
						|
  %lp = landingpad i32
 | 
						|
      catch i8* @exception_inner
 | 
						|
  %cond = load i1, i1* @condition
 | 
						|
  br i1 %cond, label %resume1, label %resume2
 | 
						|
resume1:
 | 
						|
  resume i32 1
 | 
						|
resume2:
 | 
						|
  resume i32 2
 | 
						|
}
 | 
						|
 | 
						|
define void @outer_multiple_resume() personality i8* null {
 | 
						|
  invoke void @inner_multiple_resume()
 | 
						|
      to label %cont unwind label %lpad
 | 
						|
cont:
 | 
						|
  ret void
 | 
						|
lpad:
 | 
						|
  %lp = landingpad i32
 | 
						|
      catch i8* @exception_outer
 | 
						|
  resume i32 %lp
 | 
						|
}
 | 
						|
; CHECK: define void @outer_multiple_resume()
 | 
						|
; CHECK: %lp.i = landingpad
 | 
						|
; CHECK-NEXT: catch i8* @exception_inner
 | 
						|
; CHECK-NEXT: catch i8* @exception_outer
 | 
						|
; Check that there isn't another "catch" clause:
 | 
						|
; CHECK-NEXT: load
 | 
						|
 | 
						|
 | 
						|
; Check for a bug in which having a "resume" and a "call" in the
 | 
						|
; inlined function caused "catch i8* @exception_outer" to appear
 | 
						|
; multiple times in the resulting landingpad.
 | 
						|
 | 
						|
define internal void @inner_resume_and_call() personality i8* null {
 | 
						|
  call void @external_func()
 | 
						|
  invoke void @external_func()
 | 
						|
      to label %cont unwind label %lpad
 | 
						|
cont:
 | 
						|
  ret void
 | 
						|
lpad:
 | 
						|
  %lp = landingpad i32
 | 
						|
      catch i8* @exception_inner
 | 
						|
  resume i32 %lp
 | 
						|
}
 | 
						|
 | 
						|
define void @outer_resume_and_call() personality i8* null {
 | 
						|
  invoke void @inner_resume_and_call()
 | 
						|
      to label %cont unwind label %lpad
 | 
						|
cont:
 | 
						|
  ret void
 | 
						|
lpad:
 | 
						|
  %lp = landingpad i32
 | 
						|
      catch i8* @exception_outer
 | 
						|
  resume i32 %lp
 | 
						|
}
 | 
						|
; CHECK: define void @outer_resume_and_call()
 | 
						|
; CHECK: %lp.i = landingpad
 | 
						|
; CHECK-NEXT: catch i8* @exception_inner
 | 
						|
; CHECK-NEXT: catch i8* @exception_outer
 | 
						|
; Check that there isn't another "catch" clause:
 | 
						|
; CHECK-NEXT: br
 | 
						|
 | 
						|
 | 
						|
; Check what happens if the inlined function contains an "invoke" but
 | 
						|
; no "resume".  In this case, the inlined landingpad does not need to
 | 
						|
; include the "catch i8* @exception_outer" clause from the outer
 | 
						|
; function (since the outer function's landingpad will not be
 | 
						|
; reachable), but it's OK to include this clause.
 | 
						|
 | 
						|
define internal void @inner_no_resume_or_call() personality i8* null {
 | 
						|
  invoke void @external_func()
 | 
						|
      to label %cont unwind label %lpad
 | 
						|
cont:
 | 
						|
  ret void
 | 
						|
lpad:
 | 
						|
  %lp = landingpad i32
 | 
						|
      catch i8* @exception_inner
 | 
						|
  ; A landingpad might have no "resume" if a C++ destructor aborts.
 | 
						|
  call void @abort() noreturn nounwind
 | 
						|
  unreachable
 | 
						|
}
 | 
						|
 | 
						|
define void @outer_no_resume_or_call() personality i8* null {
 | 
						|
  invoke void @inner_no_resume_or_call()
 | 
						|
      to label %cont unwind label %lpad
 | 
						|
cont:
 | 
						|
  ret void
 | 
						|
lpad:
 | 
						|
  %lp = landingpad i32
 | 
						|
      catch i8* @exception_outer
 | 
						|
  resume i32 %lp
 | 
						|
}
 | 
						|
; CHECK: define void @outer_no_resume_or_call()
 | 
						|
; CHECK: %lp.i = landingpad
 | 
						|
; CHECK-NEXT: catch i8* @exception_inner
 | 
						|
; CHECK-NEXT: catch i8* @exception_outer
 | 
						|
; Check that there isn't another "catch" clause:
 | 
						|
; CHECK-NEXT: call void @abort()
 |