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

-- This process generates code for a POSITION OF <selector> operation.
-- The code is based on an 'exactlyOne' loop skeleton produced by
-- cgSelector.  In the body of the loop, a matching table element is
-- used in a 'position' instruction to extract its position

-- A 'scan' style loop ends up looking like this:
--
-- 	initget 	r,t
-- loop:get_or_err 	r,t
--	[additional tests, result in 'test']
--	bfalse 		test {loop}
--      position	dst,r
--	endget		r,t
--

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

cgPosition: using (cgInternal, interpform)

process (Q: cgStmtQ)

declare
  args: cgStmt;
  tbl: objectname;		-- source table
  tblAddr: interpform!operand;	-- its LI address
  lk: lookupInfo;		-- describes lookup method used in loop
  endLoop: cgSelectorContinueFn; -- call this to tie off the loop
  empty: empty;

begin
  receive args from Q;
  reveal args.stmt.qualifier.selector;

  -- Get source table LI address
  tbl <- objectname#(AREF(tmp,args.stmt.operands,ONE));
  tblAddr <- interpform!operand#(args.cgData.Proc.objAddr(tbl));

  -- Now generate the top part of the loop skeleton
  endLoop <- cgSelectorContinueFn#(FNS.cgSelector(
      args.stmt.qualifier.selector, args.cgData,
      typename#(args.cgData.Proc.objType(tbl)),
      selectorLoopType#'exactlyOne', lk, tblAddr));

  -- Now the 'position' operation in the loop body
  block declare
     op: interpform!operation;
  begin
    new op;
    new op.operands;
    insert interpform!operand#(args.cgData.Proc.objAddr(
	objectname#(AREF(tmp,args.stmt.operands,ZERO)))) into op.operands;
    insert interpform!operand#(args.cgData.Proc.rootAddr(
	    args.stmt.qualifier.selector.element,
	    args.stmt.qualifier.selector.scope))
	into op.operands;
    -- If we did a scan-style loop, use a 'position' instruction.
    -- Otherwise use 'scan_position' and supply the table address.
    if B(lookupType#(case of lk) = lookupType#'scan') then
      op.opcode <- interpform!opcode#'position';
    else
      op.opcode <- interpform!opcode#'scan_position';
      insert tblAddr into op.operands;
    end if;
    unite op.qualifier.empty from empty;

    ADDINSTR(op);

  end block;

  -- Now finish up the loop skeleton
  call endLoop(args.cgData);

  return args;

end process
