MODULE PCBT;
IMPORT
SYSTEM, PCM, PCT;
CONST
MaxConstSize = 2147483647;
DefaultNofSysCalls* = 12;
newrec* = 0; newarr* = 1; newsys* = 2; casetable* = 3; procaddr* = 4;
lock* = 5; unlock* = 6; start* = 7; passivate* = 8; interfacelookup* = 9;
registerinterface* = 10; getprocedure* = 11;
FixupSentinel* = LONGINT(0FFFFFFFFH);
UndefEntryNo* = -1;
OberonCC* = 1; OberonPassivateCC* = 2; WinAPICC* = 3; CLangCC*= 4;
VAR
init: BOOLEAN;
TYPE
ConstArray* = POINTER TO ARRAY OF CHAR;
Size* = OBJECT (PCM.Attribute)
VAR
size*: LONGINT;
align*: LONGINT;
type*: SHORTINT;
signed*: BOOLEAN;
containPtrs*: BOOLEAN;
needsrecursion*: BOOLEAN;
END Size;
RecSize* = OBJECT (Size)
VAR
td*: GlobalVariable;
level*: LONGINT;
nofMethods*, nofLocalMethods*: LONGINT;
END RecSize;
Fixup* = POINTER TO RECORD
offset-: LONGINT;
next-: Fixup
END;
Variable* = OBJECT (PCM.Attribute)
VAR
offset*: LONGINT
END Variable;
GlobalVariable* = OBJECT (Variable)
VAR
owner-: Module;
entryNo*: INTEGER;
link-: Fixup;
next-: GlobalVariable;
PROCEDURE AddFixup(offset: LONGINT);
VAR l: Fixup;
BEGIN
NEW(l); l.offset := offset; l.next := link; link := l
END AddFixup;
PROCEDURE & Init*(owner: Module);
BEGIN
SELF.owner := owner;
entryNo := UndefEntryNo;
ASSERT((owner # NIL) OR (SELF = sentinel) OR (sentinel = NIL));
END Init;
END GlobalVariable;
Attribute* = OBJECT(PCM.Attribute)
VAR
codeoffset-: LONGINT;
beginOffset- : LONGINT;
endOffset- : LONGINT;
PROCEDURE SetBeginOffset*(offset : LONGINT);
BEGIN
beginOffset := offset
END SetBeginOffset;
PROCEDURE SetEndOffset*(offset : LONGINT);
BEGIN
endOffset := offset
END SetEndOffset;
END Attribute;
Procedure* = OBJECT (Attribute)
VAR
owner-: Module;
public-: BOOLEAN;
locsize*: LONGINT;
parsize*: LONGINT;
entryNr*, fixlist*: LONGINT;
next-: Procedure;
link-: Fixup;
finallyOff*: LONGINT;
PROCEDURE AddFixup(offset: LONGINT);
VAR l: Fixup;
BEGIN
NEW(l); l.offset := offset; l.next := link; link := l
END AddFixup;
PROCEDURE & Init*(owner: Module; public: BOOLEAN);
BEGIN
ASSERT((owner # NIL) OR init);
SELF.owner := owner;
SELF.public := public;
fixlist := FixupSentinel;
finallyOff := -1;
END Init;
END Procedure;
Method* = OBJECT (Procedure)
VAR
mthNo*: LONGINT
END Method;
Module* = OBJECT (Attribute)
VAR
locsize*: LONGINT;
constsize*: INTEGER;
casetablesize*: INTEGER;
nr*: INTEGER;
const*: ConstArray;
OwnProcs-: Procedure;
ExtProcs-: Procedure;
OwnVars-: GlobalVariable;
ExtVars-: GlobalVariable;
syscalls-: POINTER TO ARRAY OF Fixup;
finallyOff*: LONGINT;
PROCEDURE & Init*;
BEGIN
NEW(syscalls, NofSysCalls);
NEW(const, 128);
ResetLists;
constsize := 0;
nr := 0;
finallyOff := -1;
END Init;
PROCEDURE ResetLists*;
VAR i: LONGINT;
PROCEDURE KillPList(VAR root: Procedure);
VAR p, q: Procedure;
BEGIN
p := root; root := psentinel;
WHILE p # NIL DO
q := p;
p := p.next;
q.link := NIL;
q.next := NIL
END;
END KillPList;
PROCEDURE KillVList(VAR root: GlobalVariable);
VAR p, q: GlobalVariable;
BEGIN
p := root; root := sentinel;
WHILE p # NIL DO
q := p;
p := p.next;
q.entryNo := UndefEntryNo;
q.link := NIL;
q.next := NIL;
END;
END KillVList;
BEGIN
KillPList(OwnProcs); KillPList(ExtProcs);
KillVList(OwnVars); KillVList(ExtVars);
FOR i := 0 TO NofSysCalls-1 DO syscalls[i] := NIL END;
END ResetLists;
PROCEDURE AddCasetable*(tablesize: LONGINT): LONGINT;
VAR size,base: LONGINT; c: ConstArray;
BEGIN{EXCLUSIVE}
size := constsize+tablesize*4;
ASSERT(size < MaxConstSize);
IF size >= LEN(const^) THEN
INC(size,(-size) MOD 256);
NEW(c, size);
SYSTEM.MOVE(SYSTEM.ADR(const[0]), SYSTEM.ADR(c[0]), LEN(const));
const := c
END;
size := constsize;
INC(constsize,SHORT(tablesize*4));
INC(casetablesize,SHORT(tablesize));
RETURN size;
END AddCasetable;
PROCEDURE NewConst*(VAR a: ARRAY OF SYSTEM.BYTE; len: LONGINT): LONGINT;
VAR base: LONGINT; c: ConstArray;
BEGIN {EXCLUSIVE}
ASSERT(len <= LEN(a));
base := constsize;
ASSERT(base+len < MaxConstSize);
IF base+len >= LEN(const^) THEN
NEW(c, LEN(const) + 256);
SYSTEM.MOVE(SYSTEM.ADR(const[0]), SYSTEM.ADR(c[0]), LEN(const));
const := c
END;
IF PCM.bigEndian THEN
IF len = 8 THEN
PCM.SwapBytes(a, 0, 4); PCM.SwapBytes(a, 4, 4);
ELSE
PCM.SwapBytes(a, 0, len);
END;
END;
SYSTEM.MOVE(SYSTEM.ADR(a[0]), SYSTEM.ADR(const[base]), len);
INC(constsize, SHORT(len + (-len) MOD 4));
RETURN base
END NewConst;
PROCEDURE NewStringConst*(VAR a: ARRAY OF SYSTEM.BYTE; len: LONGINT): LONGINT;
VAR base: LONGINT; c: ConstArray;
BEGIN {EXCLUSIVE}
ASSERT(len <= LEN(a));
base := constsize;
ASSERT(base+len < MaxConstSize);
IF base+len >= LEN(const^) THEN
NEW(c, LEN(const) + 256);
SYSTEM.MOVE(SYSTEM.ADR(const[0]), SYSTEM.ADR(c[0]), LEN(const));
const := c
END;
SYSTEM.MOVE(SYSTEM.ADR(a[0]), SYSTEM.ADR(const[base]), len);
INC(constsize, SHORT(len + (-len) MOD 4));
RETURN base
END NewStringConst;
PROCEDURE NewArrayConst*( VAR a: ARRAY OF CHAR; VAR len: ARRAY OF LONGINT; blen: LONGINT ): LONGINT;
VAR base: LONGINT; c: ConstArray; tlen, tdim: LONGINT; clen, alen, tbase: LONGINT; dim: LONGINT;
BEGIN {EXCLUSIVE}
base := constsize; dim := LEN( len ); tlen := blen; tdim := 0;
WHILE (tdim < dim) DO tlen := tlen * len[tdim]; INC( tdim ); END;
ASSERT ( tlen <= LEN( a ) );
alen := tlen;
ASSERT ( base + alen < MaxConstSize );
clen := LEN( const^ );
IF base + alen >= clen THEN
NEW( c, clen + 256 + 256 * (base + alen - clen) DIV 256 );
SYSTEM.MOVE( SYSTEM.ADR( const[0] ), SYSTEM.ADR( c[0] ), clen ); const := c;
END;
tbase := base;
SYSTEM.MOVE( SYSTEM.ADR( a[0] ), SYSTEM.ADR( const[tbase] ), tlen );
INC( constsize, SHORT( alen + (-alen) MOD 4 ) );
RETURN base;
END NewArrayConst;
PROCEDURE UseVariable*(v: GlobalVariable; offset: LONGINT);
BEGIN
v.AddFixup(offset);
IF v.next = NIL THEN
IF v.owner = SELF THEN
v.next := OwnVars; OwnVars := v
ELSE
v.next := ExtVars; ExtVars := v
END
END
END UseVariable;
PROCEDURE AddOwnProc*(p: Procedure; codeOffset: LONGINT);
BEGIN
ASSERT(p.owner = context, 500);
ASSERT((p.next = NIL), 501);
p.next := OwnProcs; OwnProcs := p;
p.codeoffset := codeOffset
END AddOwnProc;
PROCEDURE UseProcedure*(p: Procedure; offset: LONGINT);
BEGIN
p.AddFixup(offset);
IF (p.owner # SELF) & (p.next = NIL) THEN
BEGIN {EXCLUSIVE}
p.next := ExtProcs; ExtProcs := p
END
END
END UseProcedure;
PROCEDURE UseSyscall*(syscall, offset: LONGINT);
VAR l: Fixup;
BEGIN
NEW(l); l.offset := offset;
BEGIN {EXCLUSIVE}
l.next := syscalls[syscall]; syscalls[syscall] := l
END;
END UseSyscall;
END Module;
ObjFGeneratorProc* = PROCEDURE (VAR R: PCM.Rider; scope: PCT.ModScope; VAR codeSize: LONGINT);
VAR
NofSysCalls-: LONGINT;
sentinel-: GlobalVariable;
psentinel-: Procedure;
context*: Module;
generate*: ObjFGeneratorProc;
PROCEDURE SetNumberOfSyscalls*(nofsyscalls: LONGINT);
BEGIN
ASSERT(nofsyscalls >= DefaultNofSysCalls, 100);
NofSysCalls := nofsyscalls
END SetNumberOfSyscalls;
PROCEDURE AllocateTD*(size: RecSize);
VAR zero: HUGEINT; ga: GlobalVariable;
BEGIN {EXCLUSIVE}
IF size.td = NIL THEN
zero := 0;
NEW(ga, context);
ga.offset := context.NewConst(zero, PCT.AddressSize);
size.td := ga;
END
END AllocateTD;
BEGIN
init := TRUE;
sentinel := NIL;
NEW(sentinel, NIL);
NEW(psentinel, NIL , FALSE);
NofSysCalls := DefaultNofSysCalls;
init := FALSE;
END PCBT.
(*
15.11.06 ug FixupSentinel extended to 32 bits, MaxConstSize adapted, additional information in type Procedure for GC
18.03.02 prk PCBT code cleanup and redesign
11.08.01 prk Fixup and use lists for procedures in PCBT cleaned up
10.08.01 prk PCBT.Procedure: imported: BOOLEAN replaced by owner: Module
10.08.01 prk PCBT.Module.imported removed
09.08.01 prk Symbol Table Loader Plugin
06.08.01 prk make code generator and object file generator indipendent
29.05.01 be syscall structures moved to backend (PCLIR & code generators)
07.05.01 prk Installable code generators moved to PCLIR; debug function added
03.05.01 be Installable code generators
26.04.01 prk separation of RECORD and OBJECT in the parser
*)
(**
PCBT use:
1. Procedure Entry Points
When a procedure implemented in the compilation unit is emitted, it must register itself as an entry point using
PCBT.context.AddOwnProc(procaddr, codeoffset)
procaddr is added to the entries list, procaddr.codeoffset is set.
Invariants:
mod.entries:
- all entries have owner = mod
- list terminated by PCBT.psentinel
mod.ExtProcs:
- all procs have owner # mod
- list terminated by PCBT.psentinel
*)