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

-- This process translates a 'while' statement.  The current basic
-- block is terminated with a jump to a new basic block, and the test
-- clause is translated in the new BB.  An 'ifelse' exit is then
-- generated, targeted to either a new BB into which the loop body is
-- translated or another new BB which represents the loop exit.  The
-- code body BB is tied of with a jump back to the test BB, and the
-- loop exit BB is made the current BB when everything is finished.

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

cgWhile: using (interpform, cgInternal)

process (Q: cgStmtQ)

declare
  args: cgStmt;
  testBBid: BBid;
  bodyBBid: BBid;
  exitBBid: BBid;
  empty: empty;
begin
  receive args from Q;
  reveal args.stmt.qualifier.while;

  -- Generate all the BBid's we'll need
  testBBid <- BBid#unique;
  bodyBBid <- BBid#unique;
  exitBBid <- BBid#unique;

  -- Tie off the current BBid with a jump to testBBid
  unite CURBB.exit.jump from BBid#(copy of testBBid);

  -- translate the test clause into a new BB
  NEWBB(copy of testBBid);
  call FNS.cgClause(args.stmt.qualifier.while.test_clause,args.cgData);

  -- tie it off with an ifelse to the body or the loop exit, and
  -- install it
  block declare
    ie: BBIfelseExit;
    op: interpform!operation;
  begin
    new ie;
    ie.ifTarget := bodyBBid;
    ie.elseTarget := exitBBid;
    unite CURBB.exit.ifelse from ie;
    op := args.cgData.Tplt.noop;
    insert interpform!operand#(args.cgData.Proc.objAddr
	  (args.stmt.qualifier.while.result)) into op.operands;
    ADDINSTR(op);

  end block;

  -- Now translate the body clause into a new BB
  NEWBB(bodyBBid);
  call FNS.cgClause(args.stmt.qualifier.while.repeated_clause,args.cgData);

  -- tie it off with jump back to the test
  unite CURBB.exit.jump from testBBid;

  -- Now set up the loop exit BB and make it current
  NEWBB(exitBBid);

  return args;

end process
