[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Support for Meta-Programming
> Stewart Greenhill <greenhil@murdoch.edu.au> writes:
>
> > At 09:37 PM 8/12/98 +0100, hartmut Goebel wrote:
> >
> > >some month ago I promissed to build in support for Meta-Programming (aka
> > >module Ref). Some weeks ago I had had a look at the code and encountered a
> > >problem:
> > >[...]
> >
> > I thought about this a while back when I was considering how to implement a
> > symbolic post-mortem debugger for OOC.
> >
> > For objects on the heap, it shouldn't be too hard. Using the existing
> > meta-programming features, you can get the module and type name for heap
> > objects. It should be possible to find the definitions for these objects by
> > looking up the symbol files. This can be done using modules from the
> > compiler front-end (eg. SymbolFile.MOD, Data.MOD, etc).
>
> Symbol files contain only the information exported (explicitly or
> implicitly) by a module. Type declarations that are both private to
> the module, and are not referenced by any exported entity, do not
> appear at all in the symbol file.
It would be necessary to produce a debugger "Ref" file which contains
definitions of all the types and variables in a module. I know of at
least one Oberon-2 compiler which does this.
> > There is a problem for module static variables and stack frames, because
> > although you can probably determine the names of the variables you can't
> > find their address at run-time. One way around this problem would be for
> > the compiler to allocate stack frames and static variables within records
> > which would have their own type descriptors (like heap records). The
> > definitions for the records would be in the symbol files, so it would be
> > possible to determine the addresses of variables. These records could be
> > maintained in linked lists so that they could be inspected at run-time. For
> > static variables it would be easy: the initialisation code for each module
> > would link its static variable record into a system-wide linked list. For
> > stack frames, the linking would need to be done as part of each procedure
> > prologue / epilogue.
>
> A procedure's local stack frame produced by any OOC compiler (not just
> oo2c) has little resemblance with the procedure variables declared in
> the source code. Some variables disappear in the "assembler" output,
> they only exists as intermediate results of calculations in
> registers. Also, there is no guarantee whatsoever what a variable
> (which is stored in the stack frame) contains at a given point in
> time. A post-mortem-debugger would not know if the currently stored
> value is valid. Note that these restrictions do not hold for
> variables that are not private to a procedure. Global variables and
> heap objects can be accessed without these limitations -- as long no
> one adds a fancy optimization that optimizes them away ;-)
One would need to guarantee that variables are not optimized away.
In other words, all variable optimizations would have to be disabled
and all variables stored on the stack. A debug flag should be enough
to do this. I'm not sure how much OOC depends internally on variables
being in registers.
> > There would be a slight run-time cost here, but it shouldn't require
> > more than a few pointer assignments. Remember that Oberon variables
> > have to be initialised anyway, so the extra cost may not be
> > significant.
>
> Oberon variables don't need to be initialised AFAIK.
>
> > The problem with this approach is that it requires some fairly major
> > changes to the compiler's variable allocation scheme, which in practice
> > means more work for Michael. The advantage is a great deal of flexibility.
> > I would love to see Refs implemented, because this could be used as a basis
> > for a run-time debugger.
>
> As long as `Ref' does not include stack frames, adding such
> meta-programming support to OOC (or oo2c) is possible. OOC code
> generation is too sophisticated to extend `Ref' to procedure stack
> frames in an easy way.
You could add "monitors" to each procedure which build a virtual
stack of calls which can be traversed during an error. This would
at least give a rough indication of the procedure nesting at the
time of an error. I know of one Oberon-2 debugger which also places
monitors after each line of a program and thus can implement fairly
general debugging of the source code. Single-stepping and breakpoints
are all possible with such a facility. Of course, instrumenting the
source will slow down the execution, but debugging does this anyway.
Michael G.