-- CGenDebugCC.mesa  Edited by Sweet,  October 14, 1980  4:58 PM

DIRECTORY
  AllocDebugDefs USING [TableBase],
  CGenDebugDefs USING [],
  CodeDefs USING [CCIndex, CCInfoType, CCItem, CCNull, JumpType],
  DebugUsefulDefs USING [ShortCopyREAD],
  IODefs USING [SP],
  OpTableDefs USING [instlength],
  P5 USING [NumberOfParams],
  RESOut USING [
    PChar, PCr, PDecimal, PNext, PNextNull, PNextUnsigned, PNull, POctal, 
    PString, PUnsigned],
  STDebugDefs USING [showLinks, WriteMOpName, WriteOpName],
  Table USING [Base, Limit];

CGenDebugCC: PROGRAM 
  IMPORTS 
    AllocDebugDefs, STDebugDefs, DebugUsefulDefs, OpTableDefs, P5, RESOut
  EXPORTS CGenDebugDefs =
  BEGIN OPEN CodeDefs, CGenDebugDefs, AllocDebugDefs, RESOut;

  PutAsFopcode: PUBLIC PROCEDURE [n: CARDINAL] =
    BEGIN
    PCr[];
    PDecimal[n];
    PString[" = q"L];
    STDebugDefs.WriteOpName[n, fopcodes];
    RETURN
    END;

  WriteFOpName: PUBLIC PROCEDURE [n: CARDINAL] =
    BEGIN
    PChar['q];
    STDebugDefs.WriteOpName[n, fopcodes];
    RETURN
    END;

  FCPtr: TYPE = POINTER TO FreeChunk;
  FreeChunk: TYPE = MACHINE DEPENDENT RECORD [ -- copied from Allocator.Chunk
    free: BOOLEAN,               f1: [0..1],
    size: [0..Table.Limit),      f2: [0..3],
    flink: CodeDefs.CCIndex,     f3: [0..3],
    blink: CodeDefs.CCIndex];

  FullCCSize: CARDINAL = MAX[
    SIZE[FreeChunk], SIZE[CCItem], SIZE[code CCItem]+3];
  FullCC: TYPE = ARRAY [0..FullCCSize) OF UNSPECIFIED;

  ccInfo: PUBLIC CodeDefs.CCInfoType ← generating;

  current: CodeDefs.CCIndex ← CodeDefs.CCNull;

  PutNextCC: PUBLIC PROCEDURE =
    BEGIN
    fc: FullCC;
    cbc: POINTER TO CodeDefs.CCItem = LOOPHOLE[@fc];
    cb: Table.Base = TableBase[];
    next: CodeDefs.CCIndex;

    IF current = CodeDefs.CCNull THEN RETURN;
    DebugUsefulDefs.ShortCopyREAD[
      to: @fc,
      from: @cb[current],
      nwords: FullCCSize];
    IF cbc.free THEN next ← LOOPHOLE[cbc, FCPtr].flink
    ELSE next ← cbc.flink;
    IF next # CodeDefs.CCNull THEN
      PutAsCC[next];
    END;

  PutPrevCC: PUBLIC PROCEDURE =
    BEGIN
    fc: FullCC;
    cbc: POINTER TO CodeDefs.CCItem = LOOPHOLE[@fc];
    cb: Table.Base = TableBase[];
    prev: CodeDefs.CCIndex;

    IF current = CodeDefs.CCNull THEN RETURN;
    DebugUsefulDefs.ShortCopyREAD[
      to: @fc,
      from: @cb[current],
      nwords: FullCCSize];
    IF cbc.free THEN prev ← LOOPHOLE[cbc, FCPtr].blink
    ELSE prev ← cbc.blink;
    IF prev # CodeDefs.CCNull THEN
      PutAsCC[prev];
    END;

  GoFwd: PUBLIC PROCEDURE [n: INTEGER] =
    BEGIN
    fc: FullCC;
    cbc: POINTER TO CodeDefs.CCItem = LOOPHOLE[@fc];
    cb: Table.Base = TableBase[];
    next: CodeDefs.CCIndex;

    IF current = CodeDefs.CCNull THEN RETURN;
    THROUGH [0..n) DO
      DebugUsefulDefs.ShortCopyREAD[
        to: @fc,
        from: @cb[current],
        nwords: FullCCSize];
      IF cbc.free THEN next ← LOOPHOLE[cbc, FCPtr].flink
      ELSE next ← cbc.flink;
      IF next = CodeDefs.CCNull THEN EXIT;
      PutAsCC[next];
      ENDLOOP;
    END;

  PutRecentCC: PUBLIC PROCEDURE [n: INTEGER] =
    BEGIN
    fc: FullCC;
    cbc: POINTER TO CodeDefs.CCItem = LOOPHOLE[@fc];
    cb: Table.Base = TableBase[];
    c: CCIndex ← current;
    k: CARDINAL ← 0;
    prev: CodeDefs.CCIndex;

    IF n = 0 OR c = CodeDefs.CCNull THEN RETURN;
    THROUGH (0..n) DO
      DebugUsefulDefs.ShortCopyREAD[
        to: @fc,
        from: @cb[c],
        nwords: FullCCSize];
      IF cbc.free THEN prev ← LOOPHOLE[cbc, FCPtr].blink
      ELSE prev ← cbc.blink;
      IF prev = CodeDefs.CCNull THEN EXIT;
      k ← k+1;
      c ← prev;
      ENDLOOP;
    PutAsCC[c];
    IF k # 0 THEN GoFwd[k];
    END;

  PutAsCC: PUBLIC PROCEDURE [index: CodeDefs.CCIndex] =
    BEGIN
    fc: FullCC;
    cbc: POINTER TO CodeDefs.CCItem = LOOPHOLE[@fc];
    cb: Table.Base ← TableBase[];

    DebugUsefulDefs.ShortCopyREAD[
      to: @fc,
      from: @cb[index],
      nwords: FullCCSize];
    current ← index;
    PCr[];
    PDecimal[LOOPHOLE[index]];
    IF cbc.pad # 0 THEN PChar['*];
    PString[":	"L];
    IF cbc.free THEN
      BEGIN
      PString["FREE - size: "L];
      PUnsigned[LOOPHOLE[cbc, FCPtr].size];
      END
    ELSE WITH cc:cbc SELECT FROM
      label =>
        BEGIN
        PString["Lbl - "L];
        WITH cc SELECT ccInfo FROM 
          generating => 
            BEGIN
	    PString["jlist: "L];
	    PNull[jumplist, CCNull];
	    END;
          binding =>
            BEGIN
            PString["minPC: "L]; PUnsigned[minPC];
            PNextUnsigned["maxPC"L, maxPC, 10];
            END;
          coding =>
            BEGIN
            PString["pc: "L]; PUnsigned[pc];
            END;
          ENDCASE;
	IF cc.labelseen THEN PNext["seen"L,,10];
        END;
      jump =>
        BEGIN
        WriteJumpName[cc.jtype];
	PChar[IODefs.SP]; 
        PNull[cc.destlabel, CCNull];
	IF cc.forward THEN PNext["fwd"L,,10];
	IF cc.fixedup THEN PNext["fixed"L,,10];
	IF cc.completed THEN PNext["complete"L,,10];
	PNextUnsigned["jsize"L, cc.jsize, 10]; 
	PNextUnsigned["param"L, cc.jparam, 10]; 
        WITH cc SELECT ccInfo FROM 
          generating => PNextNull["thread"L, thread, CCNull, 10];
          binding =>
            BEGIN
            PNextUnsigned["minPC"L, minPC, 10];
            PNextUnsigned["maxPC"L, maxPC, 10];
            END;
          coding => PNextUnsigned["pc"L, pc, 10];
          ENDCASE;
        END;
      code =>
        BEGIN
        np: CARDINAL = IF ~cc.realinst THEN P5.NumberOfParams[cc.inst] 
	               ELSE MAX[(IF cc.isize # 0 THEN cc.isize
			 ELSE OpTableDefs.instlength[cc.inst]), 1]-1;
        i: CARDINAL;
        IF cc.realinst THEN STDebugDefs.WriteMOpName[cc.inst] 
        ELSE WriteFOpName[cc.inst];
        IF np # 0 THEN
	  BEGIN
	  PChar[IODefs.SP];
          FOR i IN [1..np] DO
            IF i # 1 THEN PString[", "L];
            POctal[cc.parameters[i]];
            ENDLOOP;
	  END;
        IF cc.isize # 0 THEN
	  BEGIN
	  PNextUnsigned["size"L, cc.isize, 10];
	  POctal[cc.isize];
	  END;
	IF cc.aligned THEN PNext["aligned"L,,10];
	IF cc.minimalStack THEN PNext["minStk"L,,10];
        END;
      other => WITH cc SELECT FROM
        table => 
	  BEGIN
	  PString["Table - offset: "L];
	  POctal[taboffset];
	  IF btab THEN PNext["btab"L,,10];
	  PNextUnsigned["bytes"L, tablecodebytes, 10];
	  END;
        startbody, endbody =>
          BEGIN
          PString[IF cc.otag = startbody THEN "Start"L ELSE "End"L];
          PString["Body, bti: "L];
          PUnsigned[LOOPHOLE[index]];
          END;
        source => 
	  BEGIN
	  PString["Source: "L];
	  POctal[index];
	  END;
        ENDCASE;
      ENDCASE;
    IF STDebugDefs.showLinks THEN
      BEGIN
      PNextNull[
	"blink"L, 
	IF cbc.free THEN LOOPHOLE[cbc, FCPtr].blink ELSE cbc.blink, 
	CCNull, 
	10];
      PNextNull[
	"flink"L, 
	IF cbc.free THEN LOOPHOLE[cbc, FCPtr].flink ELSE cbc.flink, 
	CCNull, 
	10];
      END;
    END;

  WriteJumpName: PROCEDURE[n: CodeDefs.JumpType] =
    BEGIN OPEN CodeDefs;
    JumpName: ARRAY JumpType OF STRING =
	["JumpE"L, "JumpN"L, "JumpL"L, "JumpGE"L, "JumpG"L, "JumpLE"L,
	 "UJumpL"L, "UJumpGE"L, "UJumpG"L, "UJumpLE"L, "ZJumpE"L, "ZJumpN"L, 
	 "Jump"L, "JumpA"L, "JumpC"L, "JumpCA"L, "JumpRet"L,
	 "NILJumpE"L, "NILJumpN"L,
	 "PAIRJumpL"L, "PAIRJumpG"L, "BYTEJumpE"L, "BYTEJumpN"L, "BITJumpE"L, "BITJumpN"L];

    IF n > LAST[JumpType] THEN
      BEGIN PChar['j]; PDecimal[LOOPHOLE[n]] END
    ELSE PString[JumpName[n]];  RETURN
    END;

  END.