DragonRuntimeSupport: CEDAR DEFINITIONS = BEGIN ProcAny: TYPE = PROC ANY RETURNS ANY; ProcPtr: TYPE = LONG POINTER TO ProcAny; Comparison: TYPE = MACHINE DEPENDENT {less(0), equal(1), greater(2)}; PTR: TYPE = LONG POINTER TO Word; Word: TYPE = PACKED ARRAY [0..bitsPerWord) OF BOOL; bitsPerWord: NAT = 32; RefPtr: TYPE = LONG POINTER TO REF; Type: TYPE = MACHINE DEPENDENT { nullType (0), lastType (177777B) }; RegArrayPtr: TYPE = LONG POINTER TO RegArray; RegArray: TYPE = ARRAY [0..15] OF Word; ExceptAny: TYPE = SIGNAL ANY RETURNS ANY; LockPtr: TYPE = LONG POINTER TO LockRep; LockRep: TYPE; -- for MONITORLOCK CondPtr: TYPE = LONG POINTER TO CondRep; CondRep: TYPE; -- for CONDITION Process: TYPE = LONG POINTER TO ProcessRep; -- for PROCESS ProcessRep: TYPE; MixedMul: PROC [x: CARD, y: INT] RETURNS [INT]; IntMul: PROC [x, y: INT] RETURNS [INT]; IntDiv: PROC [x, y: INT] RETURNS [INT]; IntMod: PROC [x,y: INT] RETURNS [INT]; CardMul: PROC [x, y: CARD] RETURNS [CARD]; CardDiv: PROC [x, y: CARD] RETURNS [CARD]; CardMod: PROC [x, y: CARD] RETURNS [CARD]; RealCompare: PROC [x, y: REAL] RETURNS [Comparison]; RealAdd: PROC [x, y: REAL] RETURNS [REAL]; RealSub: PROC [x, y: REAL] RETURNS [REAL]; RealMul: PROC [x, y: REAL] RETURNS [REAL]; RealDiv: PROC [x, y: REAL] RETURNS [REAL]; RealMod: PROC [x, y: REAL] RETURNS [REAL]; RealScale: PROC [r: REAL, scale: INTEGER] RETURNS [REAL]; Float: PROC [int: INT] RETURNS [REAL]; Fix: PROC [r: REAL, mode: RoundingMode _ rn] RETURNS [INT]; RoundingMode: TYPE = MACHINE DEPENDENT {rn, rz, rm, rp}; ArithmeticOverflow: ERROR; ZeroDivisor: ERROR; BoundsFault: ERROR; MoveWords: PROC [src: PTR, dst: PTR, nWords: INT]; MoveWordsDisjoint: PROC [src: PTR, dst: PTR, nWords: INT]; FillWords: PROC [src: Word, dst: PTR, nWords: INT]; FillMultiWords: PROC [src: PTR, srcSize: INT, dst: PTR, nTimes: INT]; EqualWords: PROC [x: PTR, y: PTR, nWords: INT] RETURNS [BOOL]; ExtractField: PROC [base: PTR, offset: INT, bits: [0..bitsPerWord]] RETURNS [Word]; DepositField: PROC [base: PTR, offset: INT, bits: [0..bitsPerWord], word: Word]; MoveFields: PROC [ src: PTR, srcOffset: INT, dst: PTR, dstOffset: PTR, bits: [0..bitsPerWord], times: INT]; FillFields: PROC [dst: PTR, dstOffset: PTR, bits: [0..bitsPerWord], times: INT, value: Word]; Fork: PROC [proc: ProcAny, args: PTR] RETURNS [Process]; Join: PROC [process: Process] RETURNS [rets: PTR]; Wait: PROC [cond: CondPtr, lock: LockPtr]; Notify: PROC [cond: CondPtr, lock: LockPtr]; Broadcast: PROC [cond: CondPtr, lock: LockPtr]; MonitorEntry: PROC [lock: LockPtr]; MonitorExit: PROC [lock: LockPtr]; ExtensionAlloc: PROC [nWords: INT] RETURNS [PTR]; ExtensionFree: PROC [ptr: PTR] RETURNS [PTR _ NIL]; CopyModule: PROC; StartModule: PROC [module: PTR, args: PTR]; RestartModule: PROC [module: PTR, args: PTR]; StopModule: PROC; HandlerAction: TYPE = {reject, resume, exit}; BytePC: TYPE = WORD; HandlerType: TYPE = PROC [regsPtr: RegArrayPtr, except: ExceptAny, rtnPtr: PTR, argPtr: PTR] RETURNS[action: HandlerAction, pc: BytePC, levels: NAT]; RaiseSignal: PROC [which: ExceptAny, rtns: PTR, args: PTR]; RaiseError: PROC [which: ExceptAny, args: PTR]; ExceptionBody: PROC; AbortedError: ERROR; UnwindError: ERROR; UnnamedError: ERROR; UnnamedSignal: SIGNAL; UncaughtError: ERROR; AssignRef: PROC [dstPtr: RefPtr, src: REF]; AssignNil: PROC [dstPtr: RefPtr]; AssignRefComposite: PROC [dst: PTR, src: PTR, type: Type]; AssignRefCompositeFault: ERROR; IncRC: PROC [ref: REF]; DecRC: PROC [ref: REF]; GetReferentType: PROC [ref: REF] RETURNS [Type]; Narrow: PROC [ref: REF, type: Type] RETURNS [REF]; NarrowFault: ERROR [ref: REF, type: Type]; AssignProc: PROC [dstPtr: ProcPtr, src: ProcAny]; CheckProc: PROC [proc: ProcAny]; NestedProcError: ERROR [proc: ProcAny]; NewObject: PROC [nWords: INT, type: Type] RETURNS [REF]; END. *@///Users/CHauser.pa/Dragonware/DragonRuntimeSupport.mesa Copyright c 1985, 1986 by Xerox Corporation. All rights reserved. Russ Atkinson (RRA) January 27, 1987 7:30:51 pm PST Carl Hauser, April 17, 1987 11:32:59 am PDT This definitions file describes the runtime support assumed by the compiler. There is a Dragon flavor right now, but we will slowly get this stuff to be machine independent. Types Basic definitions For safe storage This definition is likely to be changed somewhat. For signalling These definitions are partial. For more details, see DragonProcesses.mesa. Denotes any SIGNAL or ERROR For locks & processes These definitions are partial. For details, see DragonProcesses.mesa. The compiler DOES NOT know the details of CONDITION, MONITORLOCK, except for their size and initial values. Arithmetic Signed numbers (INT) returns x * y raises ArithmeticOverflow if the result is not expressible as an INT note especially efficient when x is small how about optional efficient special cases for various machines? returns x * y raises ArithmeticOverflow if the result is not expressible as an INT returns x / y raises ZeroDivisor if y = 0 ArithmeticOverflow if the result is not expressible as an INT returns x MOD y (always IN [0..ABS[y]) ) raises ZeroDivisor if y = 0 ArithmeticOverflow if the result is not expressible as an INT (i.e. FIRST[INT]/-1) Signed division note: let q = IntDiv[x, y], r = IntMod[x, y], with no exceptions then x = IntMul[q, y] + r, and 0 < r < ABS[y] Unsigned numbers (CARD) returns x * y note no overflow checking returns x / y raises ZeroDivisor if y = 0 note no overflow checking returns x MOD y raises ZeroDivisor if y = 0 note no overflow checking Unigned division note: let q = CardDiv[x, y], r = CardMod[x, y], with no exceptions then x = CardMul[q, y] + r, and 0 < r < y Real numbers (32-bit IEEE) compares x and y raises RealException as specified by the IEEE standard returns x + y raises RealException as specified by the IEEE standard returns x - y raises RealException as specified by the IEEE standard returns x * y raises RealException as specified by the IEEE standard returns x / y raises RealException as specified by the IEEE standard returns x MOD y == x - Trunc[x/y]*y raises RealException as specified by the IEEE standard returns r*(2**scale) raises RealException as specified by the IEEE standard returns the real number most closely corresponding to int raises RealException as specified by the IEEE standard returns the integer closest to r determined by the mode raises RealException as specified by the IEEE standard rn: Round to nearest (unbiased). rz: Round to zero (truncate). rp: Round to plus infinity (round up). rm: Round to minus infinity (round down). Arithmetic Exceptions raised on arithmetic overflow; the compiler may raise this explictly when an arithmetic overflow is detected via a comparison rather than an arithmetic instruction. raised when dividing by 0; the compiler may raise this explictly when a division by zero is detected via a comparison rather than a call to divide. raised when a bounds check instruction fails; the compiler may raise this explictly when a bounds fault is detected via a comparison rather than via a bounds check instruction. RealException: ERROR ...; -- is defined in the Real interface. (The compiler does not know the details, and does not use this error explictly). Vectors Moving Multi-word variables are transferred via these built-in routines. Moves words from the source to the destination. No words are moved if nWords < 0. Increasing addresses are used. If the variables overlap, words are transferred singly, otherwise MoveWords is the same as MoveWordsDisjoint. Moves words from the source to the destination. No words are moved if nWords < 0. Increasing addresses are used. For efficiency, no check is made for overlapping variables, but the caller assures disjointness. Filling The ALL construct allows for filling of arrays. Assignment of some kinds of constant multi-word variables can be handled similarly. For sub-word arrays, the compiler promotes the filling to word or field assignment. Initializes words in the destination to the src word. No words are moved if nWords < 0. Increasing dst addresses are used. Useful for ALL[foo]. Initializes words in the destination to the src words (starting at src for srcSize words). No words are moved if nTimes < 0. Increasing addresses are used. Useful for ALL[foo]. Equality Multi-word variables need multi-word equality testing. Tests the two multi-word variables for equality. Fields When the compiler encounters really difficult cases it emits calls to these routines. Extracts the field from any base pointer at any reasonable bit offset. The word returned is the field right-justified with zero bits on the left. Deposits the field to any base pointer at any reasonable bit offset. The word given has the bits right-justified. Moves fields that are bits wide from the src address (plus srcOffset bits) to the dst address (plus dstOffset bits) for times number of fields. Increasing addresses will be used. If the source and destination overlap then single-field transfers will be used. Fills fields that are bits wide in the dst address (plus dstOffset bits) for times number of fields. Increasing addresses will be used. The fill value will be right-justified in value. Monitors & Processes Takes a procedure and pointer to the arguments and forks a new process to execute the procedure. Takes a process, waits for it to finish, and returns a pointer to the return record. Waits for a condition variable to be notified (the condition variable is protected by the given monitor lock). Notifies the "best" process waiting for the given condition variable (the condition variable is protected by the given monitor lock). If lock # NIL, Notify places the process on the monitor lock's queue, otherwise just allows that process to run. Notifies all processes waiting on the given condition variable (the condition variable is protected by the given monitor lock). If lock # NIL, Broadcast places those processes on the monitor lock's queue, otherwise just allows those processes to run. Attempts to enter the monitor protected by the given monitor lock. The executing process will wait until it has possession of the lock. Releases the monitor lock, allowing the "best" process waiting for the monitor lock to proceed. Frame Extensions Although frames are normally in registers, there are various cases where frame extensions must be placed in actual storage. The compiler uses these routines to allocate and free the parts of local frames that must be in memory. Allocates a frame extension large enough to hold nWords worth of data. Frees a frame extension obtained by ExtensionAlloc. Ignores ptr = NIL. Always returns NIL for convenience of assigning back to the link. Global Frame Modules can be started, stopped, restarted, and copied through the current language. Although there is some question as to how much of this support should be continued, here are the hooks to support the current semantics. Used to implement NEW prog. Starts a module (with given arguments). Used to implement START prog. Starts a module (with given arguments). Used to implement RESTART prog. Used to implement STOP of the current module. Signaller The signaller finds the appropriate handler by looking in tables passed from the compiler to the runtime system via the loader. These tables provide a PC to handler map, where the handler is given as a PC. For signals and errors, argument and return records are always passed by reference, rather than sometimes by value (as in current PrincOps). We think that the added uniformity is worth the slight additional runtime cost. This is the type of the handler procedure. The regsPtr passed in gives the saved registers for the frame containing the handler. The signal denotes which exception is being raised, and the args give the argument record for the signal. The return values generated by RESUME are assigned to rtns^. pc and levels are significant only if action=exit, corresponding to the source constructs GO TO, RETRY, and CONTINUE from within catch phrases. pc denotes the program counter to be used by the frame containing the target of the GOTO out of the catch phrase, and levels deenotes the number of levels of nested catch phrases to be unwound. In the simplest possible situation p[args ! err => CONTINUE] levels should be 1. Raises the named signal with the given argument record. Used for result _ SIGNAL which[args]. rtns^ is assigned the return record supplied by RESUME. Raises the named error with the given argument record. Used for ERROR which[args]. Used for foo: ERROR = CODE or foo: SIGNAL = CODE. Should never be called. Corresponds to ABORTED. Corresponds to UNWIND. Corresponds to unnamed ERROR. Corresponds to unnamed SIGNAL. Corresponds to RuntimeError.UNCAUGHT, which may be built-in some day. SafeStorage Safe Storage support for Cedar extensions to Mesa performs reference-counting to determine when to automtically reclaim storage. Atomically assigns a reference to a reference-containing cell. Atomically assigns NIL to a reference-containing cell. Performs dst^ _ src^, treating the copied variable as being of the specified type. Reference-counted fields are treated properly. This operation is definitely not atomic. AssignRefCompositeFault will be raised if an an improper assignment is attempted (i.e. assignment to a variant record). Here for completeness. Not actually used by the compiler. Increments the RC of a given reference. Useful when initializing a newly allocated object. Decrements the RC of a given reference. Useful?? Gets the referent type of an object from a reference to that object. Returns nullType for ref = NIL. Useful for WITH ref SELECT FROM ... Checks to determine that the type of the object is equal to the given type, then returns the original reference. When ref = NIL, NIL is returned and no checking is performed. Raises NarrowFault if the types are different. Useful for NARROW. This error is raised by Narrow when the type of the reference is not equal to the expected type. Assigns the procedure to the given cell, checking for scope violations (only NIL or outer-level procedures can be assigned). Performs reference-counting if src or dstPtr^ is a valid REF. Raises NestedProcError if assigning a nested procedure. Checks the procedure for being assignable. Raises NestedProcError if the proc is nested. Raised if the procedure described by proc is a nested procedure. Allocates a new object of the given type from the default zone, using at least nWords of storage, and initializing the type appropriately. Ê M˜codešœ8™8Kšœ Ïmœ7™BK™3K™+—K˜K™®IheadšœÏkœž œž˜/™™Kš œ žœžœžœžœžœ˜%Kš œ žœžœžœžœ ˜(Kšœ žœžœž œ!˜EKš žœžœžœžœžœ˜!š œžœžœžœžœžœ˜3Kšœ žœ˜——™Kš œžœžœžœžœžœ˜#šœžœžœž œ˜ Kšœ1™1Kšœ ˜ Kšœ˜Kšœ˜——™KšœK™KK™Kš œ žœžœžœžœ ˜-Jšœ žœžœ žœ˜'š œ žœžœžœžœžœ˜)Kšœ žœž™——™Kšœrž œž œ+™³K™š œ žœžœžœžœ ˜(Kšœ žœÏcÐck ˜"K˜—š œ žœžœžœžœ ˜(Kšœ žœŸ  ˜ K˜—š œ žœžœžœžœŸ ˜;Kšœ žœ˜———™ šœžœ™š Ïnœžœžœžœžœžœ˜/Kšœ ™ šœ™Kšœ=™=—™K™$K™@K™——š ¡œžœžœžœžœ˜'Kšœ ™ šœ™Kšœ=™=K™——š ¡œžœžœžœžœ˜'Kšœ ™ šœ™Kšœ™Kšœ=™=—K™—š ¡œžœžœžœžœ˜&Kšœ žœ žœžœ™(šœ™Kšœ™šœ=™=Kšœžœžœ™K™——™Kšœ:™:Kšœ!œžœ™-———šœžœ™š ¡œžœžœžœžœ˜*Kšœ ™ ™K™K™——š ¡œžœžœžœžœ˜*Kšœ ™ šœ™Kšœ™—™K™K™——š ¡œžœžœžœžœ˜*Kšœ™šœ™Kšœ™—™K™—K™™Kšœ<™KšœŸDœ Ÿ™P———™™KšœA™AK™š ¡ œžœžœžœ žœ˜2KšœNœ’™áK™—š ¡œžœžœžœ žœ˜:KšœNœ…™Ô——™KšœÙ™ÙK™š¡ œžœžœ žœ˜3KšœTœ=™’K˜—š ¡œžœžœ žœžœ žœ˜EKšœyœ9™³——™Kšœ6™6K™š¡ œžœžœžœ žœžœžœ˜>Kšœ0™0———™KšœU™UK™š ¡ œžœžœ žœžœ˜SKšœ’™’K™—š¡ œžœžœ žœ&˜PKšœr™rK™—š¡ œžœžœ žœžœ žœ!žœ˜kKš œÏzœ£œ£ œ£œ£ œ £œ‡™„K™—š ¡ œžœžœ žœ!žœ˜]Kš œ£œ £œ£ œ £œb£œ™º——™š¡œžœžœžœ ˜8Kšœ`™`K˜—š¡œžœžœžœ˜2KšœT™TK˜—š¡œžœ ˜*Kšœn™nK˜—š¡œžœ ˜,Kšœ‘žœc™÷K˜—š¡ œžœ ˜/Kšœ‹žœm™ûK˜—š¡ œžœ˜#Kšœˆ™ˆK˜—š¡ œžœ˜"Kšœ_™_——™Kšœä™äK™š ¡œžœ žœžœžœ˜1KšœF™FK˜—š ¡ œžœžœžœžœžœ˜3KšœCžœžœ/™Š——™ KšœÞ™ÞK™š¡ œžœ˜Kšœžœ™K™—š¡ œžœ žœžœ˜+Kšœ;žœ™FK˜—š¡ œžœ žœžœ˜-Kšœ;žœ™HK˜—š¡ œžœ˜Kšœžœ™-——™ KšœÎ™ÎK™K™ÝK™Kšœžœ˜-Kšœžœžœ˜K˜š¢ œžœžœ3žœ žœžœ,žœ˜•Kšœ0£œP£œ2£œ+™îKšœžœ£œ™>š£œ£œ£œ.žœžœžœžœ£œt£œi™õKšœ™—Kšœ™K™—š¡ œžœžœžœ˜;KšœKžœ?žœ™—K™—š¡ œžœžœ˜/KšœAžœ ™SK™—š¡ œžœ˜Kš œžœžœ žœžœ™JK™—š¡ œžœ˜Kšœžœ™K˜—š¡ œžœ˜Kšœžœ™K˜—š¡ œžœ˜Kšœžœ™K˜—š¡ œžœ˜Kšœžœ™K˜—š¡ œžœ˜Kšœžœ!™E——šœ ™ šœ€™€K™—š¡ œžœžœ˜+Kšœ>™>K˜—š¡ œžœ˜!Kšœžœ ™6K˜—š¡œžœžœžœ˜:Kšœ¥™¥K˜—š¡œžœ˜K™:K˜—š¡œžœžœ˜KšœžœJ™[K˜—š¡œžœžœ˜Kšœžœ ™1—K˜š¡œžœžœžœ˜0Kš œažœžœžœžœ™Š—K˜š ¡œžœžœžœžœ˜2Kšœ}žœžœgžœ™óK™—š¡ œžœžœ˜*Kšœ`™`K™—š¡ œžœ!˜1KšœMžœgžœ:™ôK™—š¡ œžœ˜ KšœY™YK™—š¡œžœ˜'Kšœ@™@K™—š ¡ œžœ žœžœžœ˜8KšœŠ™ŠK™—K˜—Jšžœ˜J˜—…—F‘