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

-- This process translates an 'if' statement.  The test clause is
-- generated into the current BB.  The 'then' and 'else' clauses are
-- generated into new BB's, and their exits point to another new BB,
-- which is the current BB on exit.  The exit structure following the
-- test clause points to the 'then' and 'else' clause entry BB's.  If
-- there is no 'else' clause, then the exit after the test clause
-- points to the 'then' clause entry BB and to the merge point BB.

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

cgIf: using (interpform, cgInternal)

process (Q: cgStmtQ)

declare
  args: cgStmt;
  thenBBid: BBid;
  elseBBid: BBid;
  mergeBBid: BBid;
  empty: empty;
begin
  receive args from Q;
  reveal args.stmt.qualifier.if;


  -- codegen the test clause in the current BB
  call FNS.cgClause(args.stmt.qualifier.if.test_clause,args.cgData);

  -- Generate unique ID's for the BB's we'll be generating.. if no
  -- 'else' clause, redirect the else branch to the merge point
  thenBBid <- BBId#unique;
  mergeBBid <- BBid#unique;
  if B(option#(case of args.stmt.qualifier.if.opt_else_clause) = PRESENT) then
    elseBBid <- BBid#unique;
  else
    elseBBid := mergeBBid;
  end if;

  -- Build the exit structure for the test clause BBid
  block declare
    ie: BBIfelseExit;
  begin
    new ie;
    ie.ifTarget := thenBBid;
    ie.elseTarget := elseBBid;
    unite CURBB.exit.ifelse from ie;
  end block;
  -- Add a final instruction to accompany that exit structure
  block declare
    op: interpform!operation;
  begin
    op := args.cgData.Tplt.noop;
    insert interpform!operand#(args.cgData.Proc.objAddr
	  (args.stmt.qualifier.if.test_result)) into op.operands;
    ADDINSTR(op);
  end block;
  
  -- Generate the 'then' clause into a new BB and install an exit to
  -- the merge BB
  NEWBB(thenBBid);
  call FNS.cgClause(args.stmt.qualifier.if.then_clause,args.cgData);
  unite CURBB.exit.jump from BBid#(copy of mergeBBid);    

  -- If there's an 'else' clause, generate it in a new BB and install
  -- a jump to the merge point
  if B(option#(case of args.stmt.qualifier.if.opt_else_clause) = PRESENT) then
    reveal args.stmt.qualifier.if.opt_else_clause.clauseid;
    NEWBB(elseBBid);
    call FNS.cgClause(args.stmt.qualifier.if.opt_else_clause.clauseid,
		      args.cgData);
    unite CURBB.exit.jump from BBid#(copy of mergeBBid);
  end if;

  -- Now create the merge-pont basic block and make it current
  NEWBB(mergeBBid);

  return args;

end process
