-- (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: compoffsets.pp
-- Author: Andy Lowry
-- SCCS Info: @(#)compoffsets.pp	1.8 3/13/90

-- This process maps components of record and variant types to offsets
-- suitable for LI addresses.  The process acts as a server and is
-- initialized with the program data portion of the standard cgData
-- record.  A service capability and a shutdown capability are
-- returned from the init call.

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

compOffsets: using (cgInternal, cginit, compOffsets, common, interpform)

process (initQ: compOffsetsInitQ)
  
declare
  initArgs: compOffsetsInit;
  Q: compOffsetsQ;
  shutQ: signalQ;
  defMods: definitions_modules;
  typeDef: typeDefFn;
  compMap: componentMap;
begin
  receive initArgs from initQ;

  -- grab the definitions modules for this program
  defMods := initArgs.progData.absprog.definitions_modules;
  -- copy the typeDef capa, which we'll need later
  typeDef := initArgs.typeDef;
  -- set up our queues and establish connections
  new Q; connect initArgs.compOffsets to Q;
  new shutQ; connect initArgs.shutdown to shutQ;
  return initArgs;
  
  -- start with an empty component map
  new compMap;

  -- Now serve the public cheerfully
  while TRUE repeat
    select
    event shutQ
      exit done;
      
    event Q
      -- handle a service request
      block declare
	args: compOffsets;
      begin
	receive args from Q;
	
	-- start with an empty offsets list
	new args.offsets;
	-- loop over all the component ID's, maintaining current type
	-- name as we go, and gather offsets
	for comp in args.components[] inspect
	  block begin
	    inspect entry in compMap[args.type,comp] begin
	      -- component was in map... extract its type and offset
	      args.type := entry.compType;
	      insert I(copy of entry.offset) into args.offsets;
	    end inspect;
	  on (NotFound)
	    -- component was not in map... find the definition for
	    -- this type and add map all its components
	    block declare
	      tdef: type_definition;
	      entry: componentMapEntry;
	    begin
	      tdef <- type_definition#(typeDef(args.type));
	      if B(primitive_types#(case of tdef.specification) =
		      primitive_types#'varianttype') then
		-- for a variant, all components are mapped to offset zero
		for vcomp in tdef.component_declarations[] inspect
		  new entry;
		  entry.type := args.type;
		  entry.comp := vcomp.id;
		  entry.offset <- ZERO;
		  entry.compType := vcomp.type;
		  insert entry into compMap;
		end for;
		-- all offsets are zero, including the one we were
		-- looking for
		insert ZERO into args.offsets;
	      else
		-- must be a record or callmessage type... components
		-- get successive offsets starting at zero
		block declare
		  counter: integer;
		begin
		  counter <- ZERO;
		  for rcomp in tdef.component_declarations[] inspect
		    new entry;
		    entry.type := args.type;
		    entry.comp := rcomp.id;
		    entry.offset := counter;
		    entry.compType := rcomp.type;
		    insert entry into compMap;
		    if B(comp = rcomp.id) then
		      -- extract offset we need when we find it
		      insert I(copy of counter) into args.offsets;
		    end if;
		    -- bump counter for next component
		    counter <- I(counter + ONE);
		  end for;
		end block;
	      end if;
	      -- extract type of our component
	      inspect component in tdef.component_declarations
		    where (B(component.id = comp)) begin
		args.type := component.type;
	      end inspect;
	    end block;
	  end block;
	end for;

	-- Got all the offsets, and args.type is typename of last
	-- component... this one's finished
	return args;

      end block;
	  
    otherwise
      exit cantHappen;
    end select;
  end while;
  
on exit(done)
  -- Here when we're finished
on exit(cantHappen)
  print S("CantHappen exit taken in compoffsets");
end process
