# vcg_void --- evaluate side-effect expressions for code generator



# void --- evaluate expression for side effects (value not always returned)

   ipointer function void (expr, regs)
   tpointer expr
   regset regs

   include VCG_COMMON

   ipointer load, void_addaa, void_postdec, void_postinc, void_seq,
      void_preinc, void_assign, void_if, void_switch, seq, gen_generic

DB call print (ERROUT, "void:*n"s)

   if (expr == 0) {
      void = 0
      regs = 0
      return
      }

   select (Tmem (expr))
      when (ADDAA_OP)
         {
DB       call print (ERROUT, "   ADDAA_OP*n"s)
         void = void_addaa (expr, regs)
         }
      when (ASSIGN_OP)
         {
DB       call print (ERROUT, "   ASSIGN_OP*n"s)
         void = void_assign (expr, regs)
         }
      when (IF_OP)
         {
DB       call print (ERROUT, "   IF_OP*n"s)
         void = void_if (expr, regs)
         }
      when (POSTDEC_OP)
         {
DB       call print (ERROUT, "   POSTDEC_OP*n"s)
         void = void_postdec (expr, regs)
         }
      when (POSTINC_OP)
         {
DB       call print (ERROUT, "   POSTINC_OP*n"s)
         void = void_postinc (expr, regs)
         }
      when (PREINC_OP)
         {
DB       call print (ERROUT, "   PREINC_OP*n"s)
         void = void_preinc (expr, regs)
         }
      when (SEQ_OP)
         {
DB       call print (ERROUT, "   SEQ_OP*n"s)
         void = void_seq (expr, regs)
         }
      when (SWITCH_OP)
         {
DB       call print (ERROUT, "   SWITCH_OP*n"s)
         void = void_switch (expr, regs)
         }
      when (DEFINE_STAT_OP)
         {
DB       call print (ERROUT, "   DEFINE_STAT_OP*n"s)
         void = seq (gen_generic (LINK_INS),
            load (expr, regs),
            gen_generic (PROC_INS))
         }
   else
      void = load (expr, regs)      # temporary kluge

   return
   end



# void_addaa --- calculate sum, store in left operand, void result

   ipointer function void_addaa (expr, regs)
   tpointer expr
   regset regs

   include VCG_COMMON

   ipointer gen_mr, gen_generic, load, seq, reach, void_field_asg_op

   integer res, ad (ADDR_DESC_SIZE)

   if (Tmem (Tmem (expr + 2)) == FIELD_OP)
      return (void_field_asg_op (expr, regs))

   if (Tmem (expr + 1) == INT_MODE
     && Tmem (Tmem (expr + 3)) == CONST_OP
     && Tmem (Tmem (expr + 3) + 3) == 1) {
      void_addaa = reach (Tmem (expr + 2), regs, res, ad)
      if (res ~= IN_MEMORY) {
         call warning ("ADDAA left operand is not an lvalue*n"p)
         return (0)
         }
      return (seq (void_addaa, gen_mr (IRS_INS, ad),
         gen_generic (RCB_INS)))
      }

   return (load (expr, regs))
   end



# void_assign --- perform assignment, void the resulting value

   ipointer function void_assign (expr, regs)
   tpointer expr
   regset regs

   include VCG_COMMON

   integer lregs, rregs

   ipointer st_field, load, seq

   if (Tmem (Tmem (expr + 2)) == FIELD_OP) {
      select (Tmem (expr + 1))
         when (INT_MODE, UNS_MODE, LONG_INT_MODE, LONG_UNS_MODE) {
            void_assign = seq (load (Tmem (expr + 3), rregs),
               st_field (Tmem (expr + 2), lregs))
            regs = or (lregs, rregs)
            return
            }
      else {
         call warning ("*i:  bad data mode used with bit field*n"p,
            Tmem (expr + 1))
         return (0)
         }
      }

   return (load (expr, regs))
   end



# void_if --- evaluate conditional expression; side effects only

   ipointer function void_if (expr, regs)
   tpointer expr
   regset regs

   include VCG_COMMON

   ipointer void, flow, gen_generic, gen_mr, gen_label, seq

   integer else_lab, exit_lab, ad (ADDR_DESC_SIZE)
   integer mklabel

   regset cregs, tregs, eregs

   if (Tmem (expr + 4) == 0) {         # no 'else' part
      exit_lab = mklabel (1)
      void_if = flow (Tmem (expr + 2), cregs, FALSE, exit_lab)
      void_if = seq (void_if, void (Tmem (expr + 3), tregs),
         gen_label (exit_lab))
      eregs = 0
      }
   else if (Tmem (expr + 3) == 0) {    # no 'then' part
      exit_lab = mklabel (1)
      void_if = flow (Tmem (expr + 2), cregs, TRUE, exit_lab)
      void_if = seq (void_if, void (Tmem (expr + 4), eregs),
         gen_label (exit_lab))
      tregs = 0
      }
   else {                              # general case
      else_lab = mklabel (1)
      exit_lab = mklabel (1)
      AD_MODE (ad) = LABELED_AM
      AD_LABEL (ad) = exit_lab
      void_if = flow (Tmem (expr + 2), cregs, FALSE, else_lab)
      void_if = seq (void_if,
         void (Tmem (expr + 3), tregs),
         gen_mr (JMP_INS, ad), gen_generic (FIN_INS),
         gen_label (else_lab))
      void_if = seq (void_if,
         void (Tmem (expr + 4), eregs),
         gen_label (exit_lab))
      }

   regs = or (cregs, or (tregs, eregs))

   return
   end



# void_postdec --- decrement object, void the result

   ipointer function void_postdec (expr, regs)
   tpointer expr
   regset regs

   include VCG_COMMON

   regset lregs, rregs, opreg

   ipointer l, r
   ipointer seq, ld, st, gen_mr, reach, void_field_asg_op

   integer lres, rres, lad (ADDR_DESC_SIZE), rad (ADDR_DESC_SIZE),
      opins

   if (Tmem (Tmem (expr + 2)) == FIELD_OP)
      return (void_field_asg_op (expr, regs))

   select (Tmem (expr + 1))
      when (INT_MODE, UNS_MODE) {
         opreg = A_REG
         opins = SUB_INS
         }
      when (LONG_INT_MODE, LONG_UNS_MODE) {
         opreg = L_REG
         opins = SBL_INS
         }
      when (FLOAT_MODE) {
         opreg = F_REG
         opins = FSB_INS
         }
      when (LONG_FLOAT_MODE) {
         opreg = LF_REG
         opins = DFSB_INS
         }
   else {
      call warning ("*i: bad POSTDEC data mode*n"p, Tmem (expr + 1))
      regs = 0
      return (0)
      }

   l = reach (Tmem (expr + 2), lregs, lres, lad)
   r = reach (Tmem (expr + 3), rregs, rres, rad)

   if (rres == IN_ACCUMULATOR) {
      call warning ("right POSTDEC operand is not constant*n"p)
      regs = 0
      return (0)
      }
   select (AD_MODE (rad))
      when (ILIT_AM, LLIT_AM, FLIT_AM, DLIT_AM)
         ;
   else {
      call warning ("right POSTDEC operand is not constant*n"p)
      regs = 0
      return (0)
      }

   if (lres == IN_ACCUMULATOR) {
      call warning ("left POSTDEC operand is not an lvalue*n"p)
      regs = 0
      return (0)
      }

   void_postdec = seq (l,
      ld (opreg, lres, lad),
      gen_mr (opins, rad),
      st (opreg, lad))

   regs = or (opreg, lregs)
   return
   end



# void_postinc --- increment object, void result

   ipointer function void_postinc (expr, regs)
   tpointer expr
   regset regs

   include VCG_COMMON

   regset lregs, rregs, opreg

   ipointer l, r
   ipointer seq, ld, st, gen_mr, reach, gen_generic, void_field_asg_op

   integer lres, rres, lad (ADDR_DESC_SIZE), rad (ADDR_DESC_SIZE),
      opins

   if (Tmem (Tmem (expr + 2)) == FIELD_OP)
      return (void_field_asg_op (expr, regs))

   select (Tmem (expr + 1))
      when (INT_MODE, UNS_MODE) {
         opreg = A_REG
         opins = ADD_INS
         }
      when (LONG_INT_MODE, LONG_UNS_MODE) {
         opreg = L_REG
         opins = ADL_INS
         }
      when (FLOAT_MODE) {
         opreg = F_REG
         opins = FAD_INS
         }
      when (LONG_FLOAT_MODE) {
         opreg = LF_REG
         opins = DFAD_INS
         }
   else {
      call warning ("*i: bad POSTINC data mode*n"p, Tmem (expr + 1))
      regs = 0
      return (0)
      }

   l = reach (Tmem (expr + 2), lregs, lres, lad)
   r = reach (Tmem (expr + 3), rregs, rres, rad)

   if (rres == IN_ACCUMULATOR) {
      call warning ("right POSTINC operand is not constant*n"p)
      regs = 0
      return (0)
      }
   select (AD_MODE (rad))
      when (ILIT_AM, LLIT_AM, FLIT_AM, DLIT_AM)
         ;
   else {
      call warning ("right POSTINC operand is not constant*n"p)
      regs = 0
      return (0)
      }

   if (lres == IN_ACCUMULATOR) {
      call warning ("left POSTINC operand is not an lvalue*n"p)
      regs = 0
      return (0)
      }

   if (Tmem (expr + 1) == INT_MODE && AD_LIT1 (rad) == 1) {
      regs = lregs
      return (seq (l, gen_mr (IRS_INS, lad), gen_generic (RCB_INS)))
      }

   void_postinc = seq (l,
      ld (opreg, lres, lad),
      gen_mr (opins, rad),
      st (opreg, lad))

   regs = or (opreg, lregs)
   return
   end



# void_seq --- evaluate a sequence of ops for side effects only

   ipointer function void_seq (expr, regs)
   tpointer expr
   regset regs

   include VCG_COMMON

   ipointer void, seq

   regset lregs, rregs

   void_seq = void (Tmem (expr + 1), lregs)
   void_seq = seq (void_seq, void (Tmem (expr + 2), rregs))
   regs = or (lregs, rregs)

   return
   end



# void_preinc --- increment object, void the result

   ipointer function void_preinc (expr, regs)
   tpointer expr
   regset regs

   include VCG_COMMON

   ipointer load, seq, gen_generic, gen_mr, reach, void_field_asg_op

   integer res, ad (ADDR_DESC_SIZE)

   if (Tmem (Tmem (expr + 2)) == FIELD_OP)
      return (void_field_asg_op (expr, regs))

   if (Tmem (expr + 1) == INT_MODE
     && Tmem (Tmem (expr + 3)) == CONST_OP
     && Tmem (Tmem (expr + 3) + 3) == 1) {
      void_preinc = reach (Tmem (expr + 2), regs, res, ad)
      if (res ~= IN_MEMORY) {
         call warning ("PREINC left operand is not an lvalue*n"p)
         return (0)
         }
      return (seq (void_preinc, gen_mr (IRS_INS, ad),
         gen_generic (RCB_INS)))
      }

   return (load (expr, regs))
   end



# void_switch --- evaluate multiway branch

   ipointer function void_switch (expr, regs)
   tpointer expr
   regset regs

   include VCG_COMMON

   ipointer void, seq, gen_label, gen_switch

   tpointer cc

   integer cn

   unsigned clabs (MAXCASES), deflab

   regset cregs

   void_switch = gen_switch (expr, clabs, deflab, regs)

   cn = 0
   cc = Tmem (expr + 3)
   while (cc ~= 0)
      if (Tmem (cc) == CASE_OP) {
         cn += 1
         void_switch = seq (void_switch, gen_label (clabs (cn)),
            void (Tmem (cc + 2), cregs))
         regs |= cregs
         cc = Tmem (cc + 3)
         }
      else {   # Tmem (cc) == DEFAULT_OP
         void_switch = seq (void_switch, gen_label (deflab),
            void (Tmem (cc + 1), cregs))
         regs |= cregs
         cc = Tmem (cc + 2)
         }

   void_switch = seq (void_switch, gen_label (Break_stack (Break_sp)))
   Break_sp -= 1

   return
   end



