Patch title: Release 87 bulk changes
Abstract:
File: /pliant/language/compiler/function/function.c
Key:
    Removed line
    Added line
   
// Copyright  Hubert Tonneau  hubert.tonneau@pliant.cx
//
// This program is free software; you can redistribute it an
// modify it under the terms of the GNU General Public Licen
// as published by the Free Software Foundation.
// 
// This program is distributed in the hope that it will be u
// but WITHOUT ANY WARRANTY; without even the implied warran
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public
// version 2 along with this program; if not, write to the F
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA


FUNCTION Void Function_terminate_arguments_prototypes(struct
  struct Function *proto;
  struct CompilingRules *rules;
  Int available_call_registers[nb_8_register_sets],available
  Int push_count;
  Int ii,i,start,mode,flag,reg; struct FunctionPrototype *p;
  Int j,pcg;
  if(f->flags&Function_flag_prototype_terminated) return;
  f->flags|=extra_flags;
  check(f->nb_arg>=0 && f->nb_argres>=f->nb_arg && f->nb_arg
  for(i=0; i<f->nb_argres; i++)
    if(f->arguments[i].type==null) {
      error_notifyn(error_id_compile,Z,"There is a parameter
  if(f->flags&Function_flag_generic) {
    check(f->nb_arg>0);
    f->generic_index=generic_allocate_method(f->arguments[0]
  proto=Function_watch_generic(f);
  if(proto!=null && proto->nb_argres!=f->nb_argres) {
    error_notifyn(error_id_compile,Z,"The result is inconsis
    proto=null; }
  #ifdef _BYTECODE_
    rules=&compiler_rules;
  #else
// Copyright  Hubert Tonneau  hubert.tonneau@pliant.cx
//
// This program is free software; you can redistribute it an
// modify it under the terms of the GNU General Public Licen
// as published by the Free Software Foundation.
// 
// This program is distributed in the hope that it will be u
// but WITHOUT ANY WARRANTY; without even the implied warran
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public
// version 2 along with this program; if not, write to the F
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA


FUNCTION Void Function_terminate_arguments_prototypes(struct
  struct Function *proto;
  struct CompilingRules *rules;
  Int available_call_registers[nb_8_register_sets],available
  Int push_count;
  Int ii,i,start,mode,flag,reg; struct FunctionPrototype *p;
  Int j,pcg;
  if(f->flags&Function_flag_prototype_terminated) return;
  f->flags|=extra_flags;
  check(f->nb_arg>=0 && f->nb_argres>=f->nb_arg && f->nb_arg
  for(i=0; i<f->nb_argres; i++)
    if(f->arguments[i].type==null) {
      error_notifyn(error_id_compile,Z,"There is a parameter
  if(f->flags&Function_flag_generic) {
    check(f->nb_arg>0);
    f->generic_index=generic_allocate_method(f->arguments[0]
  proto=Function_watch_generic(f);
  if(proto!=null && proto->nb_argres!=f->nb_argres) {
    error_notifyn(error_id_compile,Z,"The result is inconsis
    proto=null; }
  #ifdef _BYTECODE_
    rules=&compiler_rules;
  #else
    rules=(f->flags&Function_flag_external ? &external_rules
    rules=(f->flags&Function_flag_varargs ? &varargs_rules : (f->flags&Function_flag_kernel ? &kernel_rules : (f->flags&Function_flag_external ? &external_rules : &compiler_rules)));
  #endif
  f->flags|=rules->flags;
  start=0;
  for(ii=0; ii<f->nb_argres; ii++) {
    i=(ii+f->nb_arg)%f->nb_argres;
    p=f->arguments+i; mode=p->access&(Access_read|Access_wri
    check(i<f->nb_arg || mode==Aw);
    if(p->type->flags&Type_flag_atomic) {
      if(p->access&(Access_mapped|Access_object|Access_force
        flag=0;
      orif(i==0 && (f->flags&Function_flag_generic))
        flag=0;
      orif(i>=f->nb_arg)
        flag=Function_flag_result_byvalue;
      orif(mode==Ar)
        flag=Function_flag_ro_byvalue;
      orif(mode==Aw)
        flag=Function_flag_wo_byvalue;
      other
        flag=Function_flag_rw_byvalue; }
      if(f->flags&flag)
        p->access|=Access_byvalue; }
    if(i==0 && (f->flags&Function_flag_generic))
      p->access|=Access_object;
    if(proto!=null && proto!=f) {
      if((p->access&~(Access_byvalue|Access_was_byvalue|Acce
        error_notifyn(error_id_compile,Z,"The parameters acc
      p->access=proto->arguments[i].access; }
    if(i>=f->nb_arg)
      if(p->access&Access_byvalue) {
        if(f->flags&Function_flag_byvalue_result_first)
          start=i;
      orif(p->access&Access_mapped)
        if(f->flags&Function_flag_mapped_result_first)
          start=i;
      other
        if(f->flags&Function_flag_byaddress_result_first)
          start=i; } }
  memory_clear(available_call_registers,bit_size(nb_register
  for(i=0; i<rules->nb_call_registers; i++)
    bit_set(available_call_registers,rules->call_registers[i
  memory_clear(available_return_registers,bit_size(nb_regist
  for(i=0; i<rules->nb_return_registers; i++)
    bit_set(available_return_registers,rules->return_registe
  push_count=0;
  for(ii=0; ii<f->nb_argres; ii++) {
    i=(ii+start)%f->nb_argres;
    p=f->arguments+i; mode=p->access&(Access_read|Access_wri
    reg=int_bad;
    if(mode==Ar || mode==Arw || !(p->access&(Access_byvalue|
      for(j=0; j<rules->nb_call_registers; j++)
        if(bit_test(available_call_registers,rules->call_reg
          reg=rules->call_registers[j]; break; }
    other
      check(mode==Aw && (p->access&(Access_byvalue|Access_ma
      for(j=0; j<rules->nb_return_registers; j++)
        if(bit_test(available_return_registers,rules->return
          reg=rules->return_registers[j]; break; } }
    if(reg!=int_bad) {
      p->cpu_register=reg;
      if(mode==Ar || !(p->access&(Access_byvalue|Access_mapp
        if(f->flags&Function_flag_modify_call_registers)
          bit_set(f->modify_registers,reg);
        bit_clear(available_call_registers,reg);
      orif(mode==Aw)
        bit_set(f->modify_registers,reg);
        bit_clear(available_return_registers,reg);
      other
        check(mode==Arw);
        bit_set(f->modify_registers,reg);
        bit_clear(available_call_registers,reg);
        bit_clear(available_return_registers,reg); }
    other
      check(!(p->access&Access_mapped));
      if(p->access&Access_write)
        p->access=(p->access&~Access_byvalue)|Access_was_byv
      p->cpu_register=-(++push_count);
      if(f->flags&Function_flag_not_popped) f->stack_grow+=s
  if(!(f->flags&Function_flag_push_reversed))
    for(i=0; i<f->nb_argres; i++) {
      p=f->arguments+i;
      if(p->cpu_register<0)
        p->cpu_register=-(push_count+1)-p->cpu_register; }
  pcg=f->flags&Function_flag_pliant_code_generator;
  for(i=0; i<(pcg ? rules->nb_can_modify_registers : rules->
    bit_set(f->modify_registers,pcg ? rules->can_modify_regi
  f->flags|=Function_flag_prototype_terminated; }



  #endif
  f->flags|=rules->flags;
  start=0;
  for(ii=0; ii<f->nb_argres; ii++) {
    i=(ii+f->nb_arg)%f->nb_argres;
    p=f->arguments+i; mode=p->access&(Access_read|Access_wri
    check(i<f->nb_arg || mode==Aw);
    if(p->type->flags&Type_flag_atomic) {
      if(p->access&(Access_mapped|Access_object|Access_force
        flag=0;
      orif(i==0 && (f->flags&Function_flag_generic))
        flag=0;
      orif(i>=f->nb_arg)
        flag=Function_flag_result_byvalue;
      orif(mode==Ar)
        flag=Function_flag_ro_byvalue;
      orif(mode==Aw)
        flag=Function_flag_wo_byvalue;
      other
        flag=Function_flag_rw_byvalue; }
      if(f->flags&flag)
        p->access|=Access_byvalue; }
    if(i==0 && (f->flags&Function_flag_generic))
      p->access|=Access_object;
    if(proto!=null && proto!=f) {
      if((p->access&~(Access_byvalue|Access_was_byvalue|Acce
        error_notifyn(error_id_compile,Z,"The parameters acc
      p->access=proto->arguments[i].access; }
    if(i>=f->nb_arg)
      if(p->access&Access_byvalue) {
        if(f->flags&Function_flag_byvalue_result_first)
          start=i;
      orif(p->access&Access_mapped)
        if(f->flags&Function_flag_mapped_result_first)
          start=i;
      other
        if(f->flags&Function_flag_byaddress_result_first)
          start=i; } }
  memory_clear(available_call_registers,bit_size(nb_register
  for(i=0; i<rules->nb_call_registers; i++)
    bit_set(available_call_registers,rules->call_registers[i
  memory_clear(available_return_registers,bit_size(nb_regist
  for(i=0; i<rules->nb_return_registers; i++)
    bit_set(available_return_registers,rules->return_registe
  push_count=0;
  for(ii=0; ii<f->nb_argres; ii++) {
    i=(ii+start)%f->nb_argres;
    p=f->arguments+i; mode=p->access&(Access_read|Access_wri
    reg=int_bad;
    if(mode==Ar || mode==Arw || !(p->access&(Access_byvalue|
      for(j=0; j<rules->nb_call_registers; j++)
        if(bit_test(available_call_registers,rules->call_reg
          reg=rules->call_registers[j]; break; }
    other
      check(mode==Aw && (p->access&(Access_byvalue|Access_ma
      for(j=0; j<rules->nb_return_registers; j++)
        if(bit_test(available_return_registers,rules->return
          reg=rules->return_registers[j]; break; } }
    if(reg!=int_bad) {
      p->cpu_register=reg;
      if(mode==Ar || !(p->access&(Access_byvalue|Access_mapp
        if(f->flags&Function_flag_modify_call_registers)
          bit_set(f->modify_registers,reg);
        bit_clear(available_call_registers,reg);
      orif(mode==Aw)
        bit_set(f->modify_registers,reg);
        bit_clear(available_return_registers,reg);
      other
        check(mode==Arw);
        bit_set(f->modify_registers,reg);
        bit_clear(available_call_registers,reg);
        bit_clear(available_return_registers,reg); }
    other
      check(!(p->access&Access_mapped));
      if(p->access&Access_write)
        p->access=(p->access&~Access_byvalue)|Access_was_byv
      p->cpu_register=-(++push_count);
      if(f->flags&Function_flag_not_popped) f->stack_grow+=s
  if(!(f->flags&Function_flag_push_reversed))
    for(i=0; i<f->nb_argres; i++) {
      p=f->arguments+i;
      if(p->cpu_register<0)
        p->cpu_register=-(push_count+1)-p->cpu_register; }
  pcg=f->flags&Function_flag_pliant_code_generator;
  for(i=0; i<(pcg ? rules->nb_can_modify_registers : rules->
    bit_set(f->modify_registers,pcg ? rules->can_modify_regi
  f->flags|=Function_flag_prototype_terminated; }