DEFINITION MODULE M2DM;
(*$ LargeVars:=FALSE NameChk:=FALSE LongAlign:=FALSE *)
(* 24.1.90/bp Typ Standard um Assemble erweitert *)

FROM SYSTEM IMPORT
 ADDRESS,LONGSET;

CONST
 pc=24; (* neu von 16 auf 24 1.7.90/bp *)
 minSInt=-128; maxSInt=127; (* soll lauten: MIN(SHORTINT)... *)
 minSCard=0; maxSCard=255;
 minInt=MIN(INTEGER); maxInt=MAX(INTEGER);
 minCard=MIN(CARDINAL); maxCard=MAX(CARDINAL);
 minLInt=MIN(LONGINT); maxLInt=MAX(LONGINT);
 minLCard=MIN(LONGCARD); maxLCard=MAX(LONGCARD);
 minReal=MIN(REAL); maxReal=MAX(REAL);
 nil=0;
 pointerTypSize=4;
 procTypSize=4;
 dynArrDesSize=8; (* Descriptor size for dynamic array param. *)
 byte=0; word=1; long=2;
 (* Instruction size for simple types *)

 maxIdLen=1024;


TYPE
  ExportTypes = (exported,private,closemod,openmod,varref,iniref,charref,
  		 noHead,noDHead,main,mainclose,linkerDB);
(*
  exported = 'Module_Ident'
  private  = 'Module$nr'
  linkerDB = '_LinkerDB'
  closemod = 'Modul_END'
  openmod  = 'Modul_123456789abc' ODER 'Modul_version'
  noHead   = '_Ident' (underscore kommt IMMER davor!)
  noDHead  = '_Ident' (underscore kommt IMMER davor!)
  main     = '__main'
  mainclose= '__mainEnd'
  varref   = 'Modul_VAR'
  iniref   = 'Modul_IN'
  charref  = 'Modul_BY'
 *)

 Condition=(T,F,HI,LS,CC,CS,NE,EQ,VC,VS,PL,MI,GE,LT,GT,LE);
 WidType=[byte..long];
 RegType=(Dreg,Areg,Freg); (* 1.7.90/bp *)
 Register=[0..pc];
 RegisterSet=SET OF Register;
 ObjPtr=POINTER TO Object;
 StrPtr=POINTER TO Structure;
 ParPtr=POINTER TO Parameter;
 PDPtr=POINTER TO PDesc;
 KeyPtr=POINTER TO Key;
 ObjClass=(Header,Const,Typ,Var,Field,Proc,Code,Module,Temp);
 (* Note: for scalar types: form<=UInt *)
 (* for subrange types: RBaseTyp^.form<Range *)
 (* for structured types: form>Opaque *)
 StrForm=(
  Undef,Bool,Char,UInt,Enum,Range,FFP,Real,LReal,UReal,BPointer,Pointer,Set,
  ProcTyp,Opaque,String,Array,Record
 );
 Standard=(
  Abs,Adr,Assemble,Cap,Cast,Chr,Dec,Excl,Float,Halt,High,Inc,Incl,
  Loadregs,Max,Min,Odd,Ord,Reg,Saveregs,Setreg,Shift,Size,Tag,Tsize,Trunc,
  Val,
  Facos,Fasin,Fatan,Fcos,Fcosh,Fexp,Flog10,Flogn,Fsin,Fsinh,Fsqrt,Ftan,
  Fatanh,Fetoxm1,Flog2,Flognp1,Ftentox,Ftwotox,Fsqr,Ftanh,
  NonStand
 );

 IdRec=RECORD
   len:INTEGER; (* CARDINAL *)
   buf:ARRAY[0..maxIdLen-1] OF CHAR;
 END;
 Ident=POINTER TO IdRec;

 (*
  * Strukt für ADR(..) in Konstanten
  * Erlaubt auf:
  *    Konstanten (vcon wird automatisch in memCon umgewandelt!)
  *    Prozeduren
  *    globable Variablen (small und large)
  *    externe Vars
  *    absolute Vars
  * Verboten also nur auf lokale Vars, Module und Parameter
  *)
  CRelPtr=POINTER TO CRel;
  (*
  Was passiert bei ADR(xx[3]) oder ADR(x.feld) ?? Offset in var erhöht sich
  x^.. verboten! wird durch ip-Vergleich überprüft! vorher<->nachher
  kleines gea schreiben dafür!
  Neues ref-Format?? erweitert bei const
  *)
  CRel=RECORD (* Für Referenz-Erzeugung in M2LM *)
    next:CRelPtr;
    conOffset:INTEGER; (* off, wo innerhalb der Const entspr. pc in M2LM.ExtRef *)
    modnr:INTEGER; (* kann auch hunknr sein, nicht bei jedem RefTyp gültig *)
    (* typ ist immer ref32 oder dref32 *)
    CASE etyp:ExportTypes OF (* bei rel32,16,8 ist der Rest völlig egal *)
    | exported, noHead, noDHead:
	name:Ident;
    | private:
	procNo: LONGINT; (* gleiche SIZE wie Ident! *)
    | main, varref, iniref, charref, linkerDB, mainclose, closemod, openmod:
      (* nichts *)
    END;
    (* praktisch der eingetragene Wert im LONG-Feld, vadr oder conval.A *)
    (* ist im Feld eingetragen! *)
  END;

 ConstValue=RECORD (* Komplexer als bisher, aber sauberer! *)
  CASE inMem:BOOLEAN OF
  | FALSE: (* Wert direkt in ConstValue *)
     pad1:SHORTINT;
     pad2:INTEGER; (* auf Langwort gehen! *)
     CASE :StrForm OF
     | Undef..Range:
        conSign,
        conLI:LONGINT; (* always correctly sign extended ! *)
        conPrev:ObjPtr;
     | FFP..UReal:
        conLR:LONGREAL; (* FFP values are always stored as longreal *)
        conConvType:StrPtr; (* für CAST(xx,FFP(0.5)) *)
     | Set:
        conD:LONGINT;
        conSet:LONGSET;
     END;
  | TRUE: (* im Heap oder im ConBuffer, alle Strings,Arrays,Records und sonstige *)
     inBuff:BOOLEAN; (* schon im ConBuff alloziert? *)
     modNr:INTEGER;
     heapCon:Ident; (* Const im Heap, IMMER da! *)
     conRelocs:CRelPtr;
     conSize:INTEGER; (* Duplikat von heapCon.len! *)
     buffOffset:INTEGER; (* wenn inBuff=TRUE, dann Offset im ConBuff *)
  END;
 END;
 (*
  CASE :StrForm OF
  | Undef..UInt:
      sign,
      I:LONGINT; (* always corrctly sign extended ! *)
      prev:ObjPtr;
  | FFP..UReal:
      R:LONGREAL; (* FFP values are always stored as longreal *)
      convType:StrPtr; (* für CAST(xx,FFP(0.5)) *)
  | Set:
      d:LONGINT;
      S:LONGSET;
  (* 20.12.90/bp typisierte Const vorbereitet *)
  (* inHeap=TRUE ==> noch in Heap, noch nicht im Buffer!! A=Ident! *)
  | String,Array,Record: (* und auch memConsts Form=Range! *)
      A:LONGINT; (* offset in Buffer oder Zeiger auf IdRec! *)
      L:INTEGER; (* max 32K *)
      inHeap:BOOLEAN;
      mNo:INTEGER; (* wo deklariert *)
      relocs:CRelPtr; (* bei Bedarf, erzeugt durch ADR(..) *)
  END;
 END;
 *)
 PDesc=RECORD             (* 04.07.92/bp *)
  forward,exp,implemented,external:BOOLEAN; (* external f. ; "name" *)
  num,lev:INTEGER;
  adr,size:LONGINT;
  regs:RegisterSet;
 END;
 (* 20.12.90/bp Initialisierte Vars vorbereitet, ACHTUNG bei InRefs!!! *)
 VarModes=(normVar,absVar,regVar,farVar,extVar,smallExtVar,normIniVar,
 farIniVar);
 ModModes=(none,hasimp,library,noimp);
 Object=RECORD
  name:Ident; (* index to name buffer *)
  typ:StrPtr;
  left,right,next:ObjPtr;
  exported:BOOLEAN;
  CASE class:ObjClass OF
  | Header:
   kind:ObjClass; (* Typ, Proc, Module *)
   last,heap:ObjPtr;
  | Const: conval:ConstValue;
  | Typ: mod:ObjPtr;
  | Var:
   varpar:BOOLEAN; vmode:VarModes; vmod,vlev:INTEGER; vadr:LONGINT;
  | Field: offset:LONGINT;
     (*
      * The fields pd - cd and firstParam - firstArg have to be at the
      * same place, because Code Procedures are treated differently
      * only after the parameters have been read.
      *)
  | Proc: pd:PDPtr; firstParam:ParPtr; firstLocal:ObjPtr; pmod:INTEGER;
  | Code: cd:PDPtr; firstArg:ParPtr; std:Standard; cmod,cnum:INTEGER;
  | Module:
	key:KeyPtr; firstObj,root:ObjPtr; compmod,poolmod:INTEGER;
	mode:ModModes; mpc:INTEGER; realName:Ident;
  | Temp: baseref:INTEGER;
  END;
 END;
 Structure=RECORD
  strobj:ObjPtr; (* object (type) naming structure *)
  size:LONGINT;
  ref:INTEGER;
  CASE form:StrForm OF
  | Undef..UInt,FFP..UReal,Opaque..String: (* no field *)
  | Enum: ConstLink:ObjPtr; eMin,eMax:LONGINT; (* muß leider LONGINT! *)
  | Range: RBaseTyp:StrPtr; min,max:LONGINT; sign:BOOLEAN;
  | BPointer,Pointer: PBaseTyp:StrPtr; BaseId: Ident; (* forward refs *)
  | Set: SBaseTyp:StrPtr;
  | Array: ElemTyp,IndexTyp:StrPtr; dyn:BOOLEAN;
  | Record: firstFld:ObjPtr;
  | ProcTyp: firstPar:ParPtr; resTyp:StrPtr;
  END;
 END;
 Parameter=RECORD
  name:Ident;
  varpar:BOOLEAN;
  parMode:INTEGER; (* 0=stack, 1..16=Register 0..15 *)
  typ:StrPtr;
  next:ParPtr;
 END;
 Key=RECORD
  CASE :INTEGER OF
  |0: k0,k1,k2:INTEGER;
  |1: id: Ident; ver: INTEGER
  END
 END;

  AllTypes=RECORD (* von M2TM erstellt oder von Pool kopiert *)
    notyp,undftyp,booltyp,chartyp,uinttyp,ffptyp,realtyp,lrealtyp,urealtyp,
    bsettyp,lsettyp,ssettyp,proctyp,stringtyp,bytetyp,wordtyp,addrtyp,
    bptrtyp:StrPtr;
    numtyp:ARRAY [byte..long],[FALSE..TRUE] OF StrPtr;
  END;
VAR
 GlobVarType: VarModes;
 mainmod,sysmod:ObjPtr;
 tp:AllTypes;

(* auch von M2OM benutzt! *)
PROCEDURE Diff(i{6},j{7}: Ident): INTEGER;

(* Daten je Hunk!/bp *)
PROCEDURE AllocHunkLev(VAR a:ADDRESS; n:INTEGER);
PROCEDURE ResetHunkHeap;

(* normaler Level-Heap *)
PROCEDURE ALLOCATE(VAR a:ADDRESS; n:INTEGER);
PROCEDURE ResetHeap(adr:ADDRESS);

(* Heap für ganz globale Daten, z.B. Namen der ExtVars oder RealModule,
   und die HunkListe von M2LM
   Neu:M2RM benutzt nun diesen Heap, dadurch kann M2FM hier entfallen!
 *)
PROCEDURE AllocLev0(VAR a:ADDRESS; n:INTEGER);
PROCEDURE ResetLev0Heap; (* Dies macht M2SM in CloseScanner! *)
PROCEDURE ResetL0Heap(adr:ADDRESS);

END M2DM.
