Path: utzoo!attcan!uunet!husc6!mailrus!cornell!uw-beaver!teknowledge-vaxc!sri-unix!quintus!ok
From: ok@quintus.uucp (Richard A. O'Keefe)
Newsgroups: comp.lang.fortran
Subject: Re: Exception handling (was Fortran vs
Message-ID: <426@quintus.UUCP>
Date: 19 Sep 88 01:14:03 GMT
References: <401@quintus.UUCP> <44400022@hcx2>
Sender: news@quintus.UUCP
Reply-To: ok@quintus.UUCP (Richard A. O'Keefe)
Organization: Quintus Computer Systems, Inc.
Lines: 84

In article <44400022@hcx2> bill@hcx2.SSD.HARRIS.COM writes:
>For the record, I don't intend to respond further unless
>some other interesting point(s) is raised.  I merely want to answer
>some questions and misconceptions (I think).

{I wrote:}
>> HANDLE ('exception name, ..., exception name') IN
>> statements to be protected
>> CANNOT HANDLE
>> statements to execute if any of the exceptions cannot be trapped
>> HANDLER
>> statements to execute if any of the exceptions occurs
>> END HANDLER
>> The precise location of an exception does not matter, but any pending
>> exceptions must be signalled before control leaves the protected code.

{He replies}
>Oh, but it does.  Without a precise location, how can the generated
>code (or the runtime, or whoever) figure out whether the exception
>occurred _inside_ the HANDLE section or _outside_.  This single fact
>causes us headaches in Ada, because it is VERY expensive on our
>hardware to determine exactly where the exception occurred.  (I believe
>this is almost universally true in cases where floating-point
>operations are done by an independent co-processor.)

I didn't spell it out, but my idea was that you would not be allowed to
jump into a HANDLE block, and that jumping out of one or exiting it any
other way (such as RETURN) would dynamically end it just like falling
off the end.  

"Precise interrupts" are where the hardware goes to a lot of trouble
to *pretend* that your code was executing on a strictly sequential
machine, so that any changes which may have taken place since the
exception occurred (PC advancing, &c) which would not have taken place
in a strictly sequential implementation are backed out.  For example,
if we have
		X = X*Y
		I = I+1
in a program, on many machines the integer operation will be done while
the floating-point one is still unfinished.  By the time an overflow is
noticed, the PC be anywhere (due to jumps).

My scheme does not require precise registers, thus defined.  As for the
location of the exception, all you need to know is whether it occurs
between two *EVENTS*.  Consider the following entirely imaginary code:

	save_mask := exception_mask	# H/W register
	save_addr := exception_addr	# H/W register
	CALL EH$NEW_MASK('....', save_mask, new_mask, ierror)
	IF (ierror .ne. 0) GO TO "CANNOT HANDLE"
	exception_addr := "HANDLER"
	exception_mask := new_mask
	statements to be protected
	*wait*for*pending*exceptions*
	exception_mask := save_mask
	exception_addr := save_addr

The information we need is that the instruction which signalled the
exception started *after* the "exception_mask := new_mask" instruction
and *before* the *wait*for*pending*exceptions* instruction completed.
The wait-for-pending-exceptions code has the job of waiting until any
functional unit which *might* cause an exception has had all the time
it needs to do so.  Note that in this scheme the handler receives
*no* information about where the PC was or which instruction signalled
the exception, nor about the state of the registers when that
instruction commenced.  In fact, should several instructions be started
each of which can signal an exception (not a hard thing to do, when
there is a deep enough pipeline) it is *not* required that the first
of them be signalled, any of them may be.

Note that this scheme doesn't assume that the protected code forms a
contiguous region:  if a compiler notices that some of the code in
the protected region looks like some code elsewhere in the subprogram,
it can generate an internal subroutine.  All that matters is the TIME
of the exception:  after this event and before that?

Now, I know how to do this on the major 32-bit micros.  Generally, any
integer or addressing exceptions are synchronous anyway, so the only
problem with those machines is floating-point exceptions, and there are
things you can do which have the effect of waiting until the floating-
point unit has completed all pending operationgs.  That *is* a bottle-
neck, but it only happens when you ask for it, not after every operation.

What I >don't< know is which computers can't do something like so, or why.