This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH 3/6] Allow jumps in epilogues


On 03/23/2011 09:48 AM, Bernd Schmidt wrote:
>> With no more code than this, I cannot believe you're generating correct
>> unwind info anymore.
> 
> Why not? Are you worried about the code at the destination of the jump?
> That should be preceded by another block falling through into it which
> also has a NOTE_INSN_EPILOGUE_BEG.
> 
> If that isn't the problem you have in mind, what is and how can we test
> for it?

	body
	body
	restore r1	XXX
	restore r2	XXX
	jmp L2		XXX

L1:	body		YYY
	body		YYY
	restore r2

L2:	restore r3
	return

Assume for the moment that "restore" on this target is something that
can't be delayed or repeated.  E.g. a pop, rather than a move which
leaves the saved value in memory at a unknown offset from the CFA.

This means we have to emit unwind directives immediately after the 
restore insn and cannot delay the epilogue unwind until we deallocate
the entire stack frame.

This means that your patch either gets the unwind info wrong for
the XXX sequence or the YYY sequence.

Correct unwind info would look like

	body
	body
	.cfi_remember_state
	restore r1
	.cfi_restore r1
	restore r2
	.cfi_restore r2
	jmp L2
	.cfi_restore_state

L1:	body
	body
	restore r2
	.cfi_restore r2

L2:	// validate the unwind info across the CFG making sure that the incoming
	// edges contain the same unwind info here.
	restore r3
	.cfi_restore r3
	return

In general, with shrink-wrapping, we can have essentially arbitrary
differences in unwind info between blocks that are sequential.  We have
to be prepared to fully adjust the unwind state between blocks.

Assume a { x } is the set of registers saved into the stack frame in a
given block.  We have both incoming and outgoing sets.

foo:				// in: { }
	cmp	r1,r2
	jne	L1		// out: { }

L0:				// in: { }
	save r8
	save r9
	body
	...			// out: { r8, r9 }

L2:				// in: { r8, r9, r10 }
	body
	body
	...			// out: { r8, r9, r10 }

L1:				// in: { }
	save r8
	save r9
	save r10
	body
	...			// out: { r8, r9, r10 }

L3:				// in: { r8, r9, r10 }
	restore r10		// out: { r8, r9 }

L4:				// in: { r8, r9 }
	restore r9
	restore r8
	return

This layout requires more than just .cfi_remember_state/restore_state
between blocks.  We have to be prepared to emit full unwind info at
any point.  Assume cfi info marked with XXX exists between basic blocks
to fixup the transition points:

L0:	save r8
	save r9
	.cfi_offset r8,x
	.cfi_offset r9,y
	body
	
	.cfi_offset r10,z	XXX

L2:	body
	body

	.cfi_restore r8		XXX
	.cfi_restore r9		XXX
	.cfi_restore r10	XXX

L1:	save r8
	save r9
	save r10
	.cfi_offset r8,x
	.cfi_offset r9,y
	.cfi_offset r10,z
	body

If this isn't clear, please ask questions.  The problem of unwinding is
way more complicated than what you appear to be assuming.


r~


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]