So some quick notes about where the (brand new) debug mode is going.
Here is the current help list for debug mode:
Commands:
li [s[,e|:l] List machine instructions
d [s[,e|:l] Dump memory
ds Dump storage parameters
dd [s] Dump display frames
bi a Place breakpoint at instruction
c [a] Clear breakpoint/all breakpoints
lb List active breakpoints
si [n] Step instructions
sis [n] Step instructions silently
hs Report heap space
pc a Set pc contents
sp a Set sp contents
mp a Set mp contents
np a Set np contents
cp a Set cp contents
ti Turn instruction tracing on
nti Turn instruction tracing off
tr Turn system routine tracing on
ntr Turn system routine tracing off
ts Turn source line tracing on
nts Turn source line tracing off
r Run program from current pc
ps Print current registers and instruction
q Quit interpreter
What debug mode does is behave like a SLD (Source Level Debug) such
as gdb for programs running on P6. If you look at the code, you'll
note that the source level statements are mostly stubbed out
(not implemented) but that will change rapidly.
SLD depends on two things, one fairly easy and the other harder.
Gaining access to the source is just a matter of opening the file,
which P6 does by using its own language extension routines like
assigntext(), etc. The file gets indexed, so that it can rapidly
find what source file locations correspond to which line numbers.
Then listing source, breakpointing in terms of source lines, etc,
these all flow naturally.
Harder is to be able to debug in terms of source level symbols.
This includes things like printing variables in terms of original
Pascaline source, showing all locals to current procedure/function,
watching variables, setting variables, etc. The basis
of this is both sending symbols from the front end (pcom) to the
back end (pint) via the intermediate file. In addition, it must
also send a description of the type of each object along with the
symbol.
Machine vs. source level debug
Much as gdb does, the idea is that both source level and machine
level debug is supported, with a slight preference to source
level debug, since that is the mode I believe most users will
want.
To this end there is regularity in the naming convention. For
example:
l - list source lines.
li - list machine instructions.
s - step source line.
si - step machine instructions.
b - Break at source line.
bi - Break at machine instruction.
etc.
So the idea here is that both source level debuggers and
machine level debuggers get support, and if you do both modes
at once (like me), you are also supported. For source level,
that mode gets the shorter commands.
Symbolic debugging
For symbols, the "gold standard" is to be able to print and
modify the contents of any variable, global or local, using
expressions and access syntax and semantics that are the same
or similar as the original language. Secondary to this is
the ability to place a watch on a variable (print on any
changes) and to print whole slices of structures, and to print
all variables in the set of locals.
To this end, I have established two design principles for the
symbols annotation in the intermediate:
The type description is a simple ASCII string sequence.
One string completely describes the entire type. IE., it
does not cross reference other types as the original language
does (nor indeed have any concept of a named type).
Another design princple for symbolic referencing is that
the debug is very lax as to how it treats types. For example,
s := 1;
Same as:
s := one;
for The type (zero, one, two);
And:
c := $41;
Same as:
c := 'A';
IE., it is not the debuggers job to enforce type restrictions.
In summary
Debuggers, source and machine level, can be used at both
interpreter level and target machine level. However, machine
level debuggers, while ultimately very useful in their own
right, suffer from the issue that an advanced compiler will
often modify the result code so that it bears little
relationship to the original source code. This is a result
of optimization, which moves or eliminates code blocks.
Additionally, it is often hard to integrate as many runtime
checks in a final machine compiler as are in the intermediate.
This is an important factor in P6 and P5. In fact, I will
say it again (and again): P5 and P6 are more throughly runtime
checked than any other Pascal compiler that exists or has
ever existed, and all of the possible runtime checks are not
even done yet. Read the PRT specifications. Most of those
checks are never done in compilers.
Thus, although both interpreter level and machine level
debugging are useful, I think interpreter level debug is much
better and smoother than machine level debug. This also
means that keeping the interpretive mode in P5/P6 equal to
the full compiled mode in functionality is very important.
In short, the debug mode for P6, in terms of a "bang for the
buck" analysis, is a clear win. I got the initial version
running in two days of after hours work, and the footprint
is not great.
I hope you will find it useful.
Scott Franco
Last edit: Scott Franco 2018-01-27
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Directions for debug mode
So some quick notes about where the (brand new) debug mode is going.
Here is the current help list for debug mode:
Commands:
li [s[,e|:l] List machine instructions
d [s[,e|:l] Dump memory
ds Dump storage parameters
dd [s] Dump display frames
bi a Place breakpoint at instruction
c [a] Clear breakpoint/all breakpoints
lb List active breakpoints
si [n] Step instructions
sis [n] Step instructions silently
hs Report heap space
pc a Set pc contents
sp a Set sp contents
mp a Set mp contents
np a Set np contents
cp a Set cp contents
ti Turn instruction tracing on
nti Turn instruction tracing off
tr Turn system routine tracing on
ntr Turn system routine tracing off
ts Turn source line tracing on
nts Turn source line tracing off
r Run program from current pc
ps Print current registers and instruction
q Quit interpreter
What debug mode does is behave like a SLD (Source Level Debug) such
as gdb for programs running on P6. If you look at the code, you'll
note that the source level statements are mostly stubbed out
(not implemented) but that will change rapidly.
SLD depends on two things, one fairly easy and the other harder.
Gaining access to the source is just a matter of opening the file,
which P6 does by using its own language extension routines like
assigntext(), etc. The file gets indexed, so that it can rapidly
find what source file locations correspond to which line numbers.
Then listing source, breakpointing in terms of source lines, etc,
these all flow naturally.
Harder is to be able to debug in terms of source level symbols.
This includes things like printing variables in terms of original
Pascaline source, showing all locals to current procedure/function,
watching variables, setting variables, etc. The basis
of this is both sending symbols from the front end (pcom) to the
back end (pint) via the intermediate file. In addition, it must
also send a description of the type of each object along with the
symbol.
Machine vs. source level debug
Much as gdb does, the idea is that both source level and machine
level debug is supported, with a slight preference to source
level debug, since that is the mode I believe most users will
want.
To this end there is regularity in the naming convention. For
example:
l - list source lines.
li - list machine instructions.
s - step source line.
si - step machine instructions.
b - Break at source line.
bi - Break at machine instruction.
etc.
So the idea here is that both source level debuggers and
machine level debuggers get support, and if you do both modes
at once (like me), you are also supported. For source level,
that mode gets the shorter commands.
Symbolic debugging
For symbols, the "gold standard" is to be able to print and
modify the contents of any variable, global or local, using
expressions and access syntax and semantics that are the same
or similar as the original language. Secondary to this is
the ability to place a watch on a variable (print on any
changes) and to print whole slices of structures, and to print
all variables in the set of locals.
To this end, I have established two design principles for the
symbols annotation in the intermediate:
The type description is a simple ASCII string sequence.
One string completely describes the entire type. IE., it
does not cross reference other types as the original language
does (nor indeed have any concept of a named type).
Another design princple for symbolic referencing is that
the debug is very lax as to how it treats types. For example,
s := 1;
Same as:
s := one;
for The type (zero, one, two);
And:
c := $41;
Same as:
c := 'A';
IE., it is not the debuggers job to enforce type restrictions.
In summary
Debuggers, source and machine level, can be used at both
interpreter level and target machine level. However, machine
level debuggers, while ultimately very useful in their own
right, suffer from the issue that an advanced compiler will
often modify the result code so that it bears little
relationship to the original source code. This is a result
of optimization, which moves or eliminates code blocks.
Additionally, it is often hard to integrate as many runtime
checks in a final machine compiler as are in the intermediate.
This is an important factor in P6 and P5. In fact, I will
say it again (and again): P5 and P6 are more throughly runtime
checked than any other Pascal compiler that exists or has
ever existed, and all of the possible runtime checks are not
even done yet. Read the PRT specifications. Most of those
checks are never done in compilers.
Thus, although both interpreter level and machine level
debugging are useful, I think interpreter level debug is much
better and smoother than machine level debug. This also
means that keeping the interpretive mode in P5/P6 equal to
the full compiled mode in functionality is very important.
In short, the debug mode for P6, in terms of a "bang for the
buck" analysis, is a clear win. I got the initial version
running in two days of after hours work, and the footprint
is not great.
I hope you will find it useful.
Scott Franco
Last edit: Scott Franco 2018-01-27
Almost done with debug mode. I won't bother to go over how it works again. Its really complex (perhaps overly). I'll save it for the documentation.