-- (C) Copyright International Business Machines Corporation 23 January 
-- 1990.  All Rights Reserved. 
--  
-- See the file USERAGREEMENT distributed with this software for full 
-- terms and conditions of use. 
-- File: cgproglit.pp
-- Author: Andy Lowry
-- SCCS Info: @(#)cgproglit.pp	1.7 3/13/90

-- This process translates a 'program_literal' statement into a
-- 'prog_lit' instruction.  The process indicated in the statement
-- qualifier is codegened, and the resulting LI code is wrapped up in
-- a fake program object for the LI instruction qualifier.  The
-- program object is actually mostly uninit, contradicting the
-- typestate declarations, but we'll live with it for the present...

-- In the case that the processid listed in the statement qualifier
-- doesn't correspond to one of the processes in the absprog, we
-- instead codegen a 'link' instruction whose qualifier gives an
-- index into the LI prog's link table to retrieve a statically linked
-- external program.

#include "typemark.h"
#include "codegen.h"

cgProgLit: using (cgInternal, interpform)

process (Q: cgStmtQ)
  
declare
  args: cgStmt;
  LIProg: interpform!prog;
  program: predefined!program;
  procData: cgProcData;
  op: interpform!operation;
begin
  receive args from Q;
  reveal args.stmt.qualifier.program_literal;
  
  if B(exists of proc in ABSPROG.programs
	  [args.stmt.qualifier.program_literal]) then
    -- This is a real program literal, and must be codegened

    -- Save away current proc-related data so we can restore it after
    -- we've codegened the proglit process
    procData := args.cgData.Proc;

    -- codegen the indicated process
    LIProg <- interpform!prog#(
      FNS.cgProcess(args.stmt.qualifier.program_literal,args.cgData));

    -- Now create a fake absprog and stuff the LI code into it.
    -- *** WARNING: other absprog fields are stuffed with bogus values
    -- *** to avoid typestate errors... they are unusable!
    new program;
    new program.definitions_modules;
    program.main_program <- processid#unique;
    new program.programs;
    call FNS.LIStuff(program,LIProg);

    -- Now restore prior proc-related data and install the 'prog_lit'
    -- instruction
    args.cgData.Proc <- procData;
    new op;
    op.opcode <- interpform!opcode#'prog_lit';
    new op.operands;
    insert interpform!operand#(args.cgData.Proc.objAddr(
	objectname#(AREF(tmp,args.stmt.operands,ZERO)))) into op.operands;
    unite op.qualifier.program from program;-- *** TYPESTATE ERROR ***
    ADDINSTR(op);

  else
    -- Indicated program does not exist in absprog... this must refer
    -- to a statically linked external program.  Find the process id
    -- in this process' link table, or add it if it's not already
    -- there
    block declare
      linkno: integer;
    begin
      block begin
	linkno <- I(position of pid in args.cgData.Proc.linkedPids where
	      (B(pid = args.stmt.qualifier.program_literal)));
      on (NotFound)
	linkno <- I(size of args.cgData.Proc.linkedPids);
	insert processid#(copy of args.stmt.qualifier.program_literal) 
	    into args.cgData.Proc.linkedPids;
      end block;
      -- Now generate a 'link' instruction with the correct link number
      new op;
      op.opcode <- interpform!opcode#'link';
      new op.operands;
      insert interpform!operand#(args.cgData.Proc.objAddr(
	  objectname#(AREF(tmp,args.stmt.operands,ZERO)))) into op.operands;
      unite op.qualifier.integer from linkno;
      ADDINSTR(op);
    end block;
  end if;

  return args;
  
end process
