05/01/1993 09:00 AM
Computer Science
Optimizing compilers produce code that impedes source-level debugging. Examples are given in which optimization changes the behavior of a program even when the optimizer is correct, showing that in some circumstances it is not possible to completely debug an unoptimized version of a program. Source-level debuggers designed for unoptimized code may mislead the debugger user when invoked on optimized code. One situation that can mislead the user is a mismatch between where the user expects a breakpoint to be located and the breakpoint\'s actual location. A mismatch may occur due to statement reordering or discontiguous code generated from a statement. This work describes a mapping between statements and breakpoint locations that ameliorates this problem. The mapping enables debugger behavior on optimized code that approximates debugger behavior on unoptimized code closely enough that the user need not make severe changes in debugging strategies. This work presents a method of determining when this has occurred, proves the method correct, and shows how a debugger can describe the relevant effects of optimization. The determination method is more general than previously published methods, handling global optimization, flow graph transformations, and not being tightly coupled to optimizations performed by a particular compiler. The information a compiler must make available to the debugger for this task is also described. A third situation that can mislead the user is when optimization has eliminated information in the run-time (procedure activation) stack that the debugger uses (on some architectures) to provide a call stack trace. This work gives several methods of providing the expected stack trace when the run-time stack does not contain this information.