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~