diff options
author | John van Groningen | 2003-07-11 13:47:24 +0000 |
---|---|---|
committer | John van Groningen | 2003-07-11 13:47:24 +0000 |
commit | 2255def3b1d52edce2b87c30ddff0a206abda7cd (patch) | |
tree | 406f668067c28094b4a64a59d6549554bcb54f51 /cgstack.c | |
parent | fix bug in floating point subtract and divide (diff) |
add .c and .h files
Diffstat (limited to 'cgstack.c')
-rw-r--r-- | cgstack.c | 4320 |
1 files changed, 4320 insertions, 0 deletions
diff --git a/cgstack.c b/cgstack.c new file mode 100644 index 0000000..73163e5 --- /dev/null +++ b/cgstack.c @@ -0,0 +1,4320 @@ +/* + File: cgstack.c + Author: John van Groningen + At: University of Nijmegen +*/ + +#include <stdio.h> +#include "cgport.h" +#include "cgconst.h" +#include "cgrconst.h" +#include "cgtypes.h" + +#include "cgstack.h" + +#include "cg.h" +#include "cglin.h" +#include "cgcalc.h" +#include "cgopt.h" +#include "cgcode.h" + +#define for_l(v,l,n) for(v=(l);v!=NULL;v=v->n) + +#define g_fhighlow(gh,gl,gf) \ + (gh)=g_instruction_2 (GFHIGH,(gf),NULL); \ + (gl)=g_instruction_2 (GFLOW,(gf),(gh)); \ + (gh)->instruction_parameters[1].p=(gl) + +#define ELEMENT_MAY_BE_REMOVED 1 +#define ELEMENT_USED_BEFORE_JSR 2 +#define ELEMENT_MUST_BE_REMOVED 4 +#define BEGIN_ELEMENT_MUST_BE_REMOVED 8 + +struct stack { + struct stack * stack_next; + WORD stack_offset; + WORD stack_flags; + INSTRUCTION_GRAPH stack_graph; + INSTRUCTION_GRAPH stack_load_graph; +}; + +struct a_stack { + struct a_stack * a_stack_next; + WORD a_stack_offset; + WORD a_stack_flags; + INSTRUCTION_GRAPH a_stack_graph; + INSTRUCTION_GRAPH a_stack_load_graph; +}; + +struct b_stack { + struct b_stack * b_stack_next; + WORD b_stack_offset; + WORD b_stack_flags; + INSTRUCTION_GRAPH b_stack_graph; + INSTRUCTION_GRAPH b_stack_load_graph; +}; + +/* from cgcode */ + +struct block_graph global_block; + +extern struct basic_block *last_block; +extern struct instruction *last_instruction; + +/* from cgopt.c */ +extern unsigned int end_a_registers,end_d_registers,end_f_registers; + +/* from cglin.c */ +extern int local_data_offset; + +#pragma segment Code4 + +#define allocate_struct_from_heap(a) (struct a*)allocate_memory_from_heap(sizeof (struct a)) + +INSTRUCTION_GRAPH s_get_a (int offset) +{ + register struct a_stack **element_h,*element_p,*new_element; + register int required_offset; + INSTRUCTION_GRAPH graph; + + required_offset=global_block.block_graph_a_stack_top_offset+offset; + + element_h=&global_block.block_graph_a_stack; + while ((element_p=*element_h)!=NULL){ + register int element_offset=element_p->a_stack_offset; + + if (element_offset==required_offset) + return element_p->a_stack_graph; + + if (element_offset>required_offset) + break; + + element_h=&element_p->a_stack_next; + } + + graph=g_load + (-((required_offset+global_block.block_graph_a_stack_begin_displacement+1)<<2),A_STACK_POINTER); + + new_element=allocate_struct_from_heap (a_stack); + new_element->a_stack_offset=required_offset; + new_element->a_stack_flags=0; + new_element->a_stack_graph=graph; + new_element->a_stack_load_graph=graph; + + new_element->a_stack_next=*element_h; + *element_h=new_element; + + return graph; +} + +static void s_put_a_l (int offset,INSTRUCTION_GRAPH graph,INSTRUCTION_GRAPH new_load_graph) +{ + register struct a_stack *element_p,**element_h,*new_element; + register int required_offset; + + required_offset=global_block.block_graph_a_stack_top_offset+offset; + + element_h=&global_block.block_graph_a_stack; + while ((element_p=*element_h)!=NULL){ + int element_offset=element_p->a_stack_offset; + + if (element_offset==required_offset){ + element_p->a_stack_graph=graph; + return; + } + + if (element_offset>required_offset) + break; + + element_h=&element_p->a_stack_next; + } + + new_element=allocate_struct_from_heap (a_stack); + new_element->a_stack_offset=required_offset; + new_element->a_stack_flags=0; + new_element->a_stack_graph=graph; + new_element->a_stack_load_graph=new_load_graph; + + new_element->a_stack_next=*element_h; + *element_h=new_element; +} + +void s_put_a (int offset,INSTRUCTION_GRAPH graph) +{ + s_put_a_l (offset,graph,NULL); +} + +void s_push_a (INSTRUCTION_GRAPH graph) +{ + --global_block.block_graph_a_stack_top_offset; + s_put_a (0,graph); +} + +INSTRUCTION_GRAPH s_pop_a (VOID) +{ + INSTRUCTION_GRAPH graph; + + graph=s_get_a (0); + ++global_block.block_graph_a_stack_top_offset; + + return graph; +} + +void s_remove_a (VOID) +{ + ++global_block.block_graph_a_stack_top_offset; +} + +void release_a_stack (VOID) +{ + register int n; + + global_block.block_graph_a_stack=NULL; + for (n=0; n<N_ADDRESS_PARAMETER_REGISTERS; ++n) + global_block.block_graph_a_register_parameter_node[n]=NULL; + + global_block.block_graph_begin_a_stack_size=0; + global_block.block_graph_a_stack_top_offset=0; + global_block.block_graph_a_stack_begin_displacement=0; + global_block.block_graph_a_stack_end_displacement=0; +} + +INSTRUCTION_GRAPH s_get_b (int offset) +{ + register struct b_stack **element_h,*element_p,*new_element; + register int required_offset; + INSTRUCTION_GRAPH graph; + + required_offset=global_block.block_graph_b_stack_top_offset+offset; + + element_h=&global_block.block_graph_b_stack; + while ((element_p=*element_h)!=NULL){ + int element_offset=element_p->b_stack_offset; + + if (element_offset==required_offset) + return element_p->b_stack_graph; + + if (element_offset>required_offset) + break; + + element_h=&element_p->b_stack_next; + } + + graph=g_load + ((required_offset+global_block.block_graph_b_stack_begin_displacement)<<2,B_STACK_POINTER); + + new_element=allocate_struct_from_heap (b_stack); + new_element->b_stack_offset=required_offset; + new_element->b_stack_flags=0; + new_element->b_stack_graph=graph; + new_element->b_stack_load_graph=graph; + + new_element->b_stack_next=*element_h; + *element_h=new_element; + + return graph; +} + +static void s_put_b_l (int offset,INSTRUCTION_GRAPH graph,INSTRUCTION_GRAPH new_load_graph) +{ + register struct b_stack **element_h,*element_p,*new_element; + register int required_offset; + + required_offset=global_block.block_graph_b_stack_top_offset+offset; + + element_h=&global_block.block_graph_b_stack; + while ((element_p=*element_h)!=NULL){ + int element_offset=element_p->b_stack_offset; + + if (element_offset==required_offset){ + element_p->b_stack_graph=graph; + return; + } + + if (element_offset>required_offset) + break; + + element_h=&element_p->b_stack_next; + } + + new_element=allocate_struct_from_heap ( b_stack); + new_element->b_stack_offset=required_offset; + new_element->b_stack_flags=0; + new_element->b_stack_graph=graph; + new_element->b_stack_load_graph=new_load_graph; + + new_element->b_stack_next=*element_h; + *element_h=new_element; +} + +void s_put_b (int offset,INSTRUCTION_GRAPH graph) +{ + s_put_b_l (offset,graph,NULL); +} + +void s_push_b (INSTRUCTION_GRAPH graph) +{ + --global_block.block_graph_b_stack_top_offset; + s_put_b (0,graph); +} + +INSTRUCTION_GRAPH s_pop_b (VOID) +{ + INSTRUCTION_GRAPH graph; + + graph=s_get_b (0); + ++global_block.block_graph_b_stack_top_offset; + + return graph; +} + +void s_remove_b (VOID) +{ + ++global_block.block_graph_b_stack_top_offset; +} + +void release_b_stack (VOID) +{ + register int n; + + global_block.block_graph_b_stack=NULL; + + for (n=0; n<N_DATA_PARAMETER_REGISTERS +#ifdef MORE_PARAMETER_REGISTERS + + N_ADDRESS_PARAMETER_REGISTERS +#endif + ; ++n) + global_block.block_graph_d_register_parameter_node[n]=NULL; + + for (n=0; n<N_FLOAT_PARAMETER_REGISTERS; ++n) + global_block.block_graph_f_register_parameter_node[n]=NULL; + + global_block.block_graph_begin_b_stack_size=0; + global_block.block_graph_b_stack_top_offset=0; + global_block.block_graph_b_stack_begin_displacement=0; + global_block.block_graph_b_stack_end_displacement=0; +} + +void init_a_stack (int a_stack_size) +{ + int n; + + global_block.block_graph_begin_a_stack_size=a_stack_size; + + if (a_stack_size>N_ADDRESS_PARAMETER_REGISTERS) + a_stack_size=N_ADDRESS_PARAMETER_REGISTERS; + + last_block->block_n_begin_a_parameter_registers=a_stack_size; + global_block.block_graph_a_stack_begin_displacement=-a_stack_size; + + for (n=0; n<a_stack_size; ++n){ + INSTRUCTION_GRAPH register_graph; + int a_register; + + a_register=num_to_a_reg (a_stack_size-1-n); + + register_graph=g_register (a_register); + s_put_a_l (n,register_graph,register_graph); + } +} + +void init_b_stack (int b_stack_size,ULONG vector[]) +{ + int offset,stack_displacement,n,all_parameters_in_registers; + int number_of_data_register_parameters,number_of_float_register_parameters; + int data_offsets[N_DATA_PARAMETER_REGISTERS +#ifdef MORE_PARAMETER_REGISTERS + + N_ADDRESS_PARAMETER_REGISTERS +#endif + ],float_offsets[N_FLOAT_PARAMETER_REGISTERS]; + + global_block.block_graph_begin_b_stack_size=b_stack_size; + + number_of_data_register_parameters=0; + number_of_float_register_parameters=0; + + offset=0; + stack_displacement=0; + all_parameters_in_registers=1; + + for (offset=0; offset<b_stack_size;){ + if (test_bit (vector,offset)){ + if (mc68881_flag){ + if (number_of_float_register_parameters<N_FLOAT_PARAMETER_REGISTERS){ + float_offsets [number_of_float_register_parameters++]=offset; + + if (all_parameters_in_registers) + stack_displacement-=2; + } else { + INSTRUCTION_GRAPH f_graph,h_graph,l_graph; + + f_graph=g_fload ((offset+stack_displacement)<<2,B_STACK_POINTER); +#ifdef g_fhighlow + g_fhighlow (h_graph,l_graph,f_graph); +#else + h_graph=g_fhigh (f_graph); + l_graph=g_flow (f_graph); +#endif + s_put_b_l (offset+1,l_graph,l_graph); + s_put_b_l (offset,h_graph,h_graph); + + all_parameters_in_registers=0; + } + } else + all_parameters_in_registers=0; + offset+=2; + } else { + if (number_of_data_register_parameters < (parallel_flag ? N_DATA_PARAMETER_REGISTERS-1 : N_DATA_PARAMETER_REGISTERS)){ + data_offsets [number_of_data_register_parameters++]=offset; + + if (all_parameters_in_registers) + --stack_displacement; + } else + all_parameters_in_registers=0; + offset+=1; + } + } + + for (n=0; n<number_of_data_register_parameters; ++n){ + INSTRUCTION_GRAPH register_graph; + + register_graph=g_register (num_to_d_reg (number_of_data_register_parameters-1-n)); + s_put_b_l (data_offsets[n],register_graph,register_graph); + } + + for (n=0; n<number_of_float_register_parameters; ++n){ + INSTRUCTION_GRAPH register_graph,h_graph,l_graph; + register int offset; + + register_graph=g_fregister (number_of_float_register_parameters-1-n); + +#ifdef g_fhighlow + g_fhighlow (h_graph,l_graph,register_graph); +#else + h_graph=g_fhigh (register_graph); + l_graph=g_flow (register_graph); +#endif + offset=float_offsets[n]; + + s_put_b_l (offset+1,l_graph,l_graph); + s_put_b_l (offset,h_graph,h_graph); + } + + last_block->block_n_begin_d_parameter_registers=number_of_data_register_parameters; + + global_block.block_graph_b_stack_begin_displacement=stack_displacement; +} + +#ifdef MORE_PARAMETER_REGISTERS +void init_ab_stack (int a_stack_size,int b_stack_size,ULONG vector[]) +{ + int offset,stack_displacement,n,all_parameters_in_registers; + int number_of_data_register_parameters,number_of_float_register_parameters; + int data_offsets[N_DATA_PARAMETER_REGISTERS+N_ADDRESS_PARAMETER_REGISTERS],float_offsets[N_FLOAT_PARAMETER_REGISTERS]; + int n_data_parameter_registers,n_extra_data_parameter_registers; + + init_a_stack (a_stack_size); + + n_data_parameter_registers=N_DATA_PARAMETER_REGISTERS; + n_extra_data_parameter_registers=N_ADDRESS_PARAMETER_REGISTERS-a_stack_size; + if (n_extra_data_parameter_registers<0) + n_extra_data_parameter_registers=0; + + global_block.block_graph_begin_b_stack_size=b_stack_size; + + number_of_data_register_parameters=0; + number_of_float_register_parameters=0; + + offset=0; + stack_displacement=0; + all_parameters_in_registers=1; + + for (offset=0; offset<b_stack_size;){ + if (test_bit (vector,offset)){ + if (mc68881_flag){ + if (number_of_float_register_parameters<N_FLOAT_PARAMETER_REGISTERS){ + float_offsets [number_of_float_register_parameters++]=offset; + + if (all_parameters_in_registers) + stack_displacement-=2; + } else { + INSTRUCTION_GRAPH f_graph,h_graph,l_graph; + + f_graph=g_fload ((offset+stack_displacement)<<2,B_STACK_POINTER); +#ifdef g_fhighlow + g_fhighlow (h_graph,l_graph,f_graph); +#else + h_graph=g_fhigh (f_graph); + l_graph=g_flow (f_graph); +#endif + s_put_b_l (offset+1,l_graph,l_graph); + s_put_b_l (offset,h_graph,h_graph); + + all_parameters_in_registers=0; + } + } else + all_parameters_in_registers=0; + offset+=2; + } else { + if (number_of_data_register_parameters < + (parallel_flag ? n_data_parameter_registers-1 : n_data_parameter_registers) + n_extra_data_parameter_registers) + { + data_offsets [number_of_data_register_parameters++]=offset; + + if (all_parameters_in_registers) + --stack_displacement; + } else + all_parameters_in_registers=0; + offset+=1; + } + } + + n_extra_data_parameter_registers=number_of_data_register_parameters-n_data_parameter_registers; + if (n_extra_data_parameter_registers<0) + n_extra_data_parameter_registers=0; + + for (n=0; n<number_of_data_register_parameters; ++n){ + INSTRUCTION_GRAPH register_graph; + int d_n; + + d_n=(number_of_data_register_parameters-1-n)-n_extra_data_parameter_registers; + + if (d_n>=0) + register_graph=g_register (num_to_d_reg (d_n)); + else + register_graph=g_register (num_to_a_reg (N_ADDRESS_PARAMETER_REGISTERS+d_n)); + s_put_b_l (data_offsets[n],register_graph,register_graph); + } + + for (n=0; n<number_of_float_register_parameters; ++n){ + INSTRUCTION_GRAPH register_graph,h_graph,l_graph; + register int offset; + + register_graph=g_fregister (number_of_float_register_parameters-1-n); + +#ifdef g_fhighlow + g_fhighlow (h_graph,l_graph,register_graph); +#else + h_graph=g_fhigh (register_graph); + l_graph=g_flow (register_graph); +#endif + offset=float_offsets[n]; + + s_put_b_l (offset+1,l_graph,l_graph); + s_put_b_l (offset,h_graph,h_graph); + } + + last_block->block_n_begin_d_parameter_registers=number_of_data_register_parameters; + + global_block.block_graph_b_stack_begin_displacement=stack_displacement; +} +#endif + +void insert_graph_in_b_stack (INSTRUCTION_GRAPH graph,int b_stack_size,ULONG *vector) +{ + register int offset,required_offset; + register struct b_stack **element_p,*new_element; + INSTRUCTION_GRAPH *graph_p; + + required_offset=global_block.block_graph_b_stack_top_offset; + + element_p=&global_block.block_graph_b_stack; + while (*element_p!=NULL && (*element_p)->b_stack_offset<required_offset) + element_p=&(*element_p)->b_stack_next; + + for (offset=0; offset<b_stack_size; ++offset,++required_offset){ + if (test_bit (vector,offset)){ + if ((*element_p==NULL || (*element_p)->b_stack_offset>required_offset+1) && mc68881_flag){ + INSTRUCTION_GRAPH f_graph,l_graph,h_graph; + + f_graph=g_fload + ((required_offset+global_block.block_graph_b_stack_begin_displacement)<<2,B_STACK_POINTER); +#ifdef g_fhighlow + g_fhighlow (h_graph,l_graph,f_graph); +#else + h_graph=g_fhigh (f_graph); + l_graph=g_flow (f_graph); +#endif + new_element=allocate_struct_from_heap (b_stack); + new_element->b_stack_offset=required_offset; + new_element->b_stack_flags=0; + new_element->b_stack_graph=h_graph; + new_element->b_stack_load_graph=h_graph; + + new_element->b_stack_next=*element_p; + *element_p=new_element; + + element_p=&new_element->b_stack_next; + ++offset; + ++required_offset; + + new_element=allocate_struct_from_heap (b_stack); + new_element->b_stack_offset=required_offset; + new_element->b_stack_flags=0; + new_element->b_stack_graph=l_graph; + new_element->b_stack_load_graph=l_graph; + + new_element->b_stack_next=*element_p; + *element_p=new_element; + + element_p=&new_element->b_stack_next; + continue; + } else { + if (*element_p==NULL || (*element_p)->b_stack_offset!=required_offset){ + INSTRUCTION_GRAPH load_graph; + + load_graph=g_load + ((required_offset+global_block.block_graph_b_stack_begin_displacement)<<2,B_STACK_POINTER); + + new_element=allocate_struct_from_heap (b_stack); + new_element->b_stack_offset=required_offset; + new_element->b_stack_flags=0; + new_element->b_stack_graph=load_graph; + new_element->b_stack_load_graph=load_graph; + + new_element->b_stack_next=*element_p; + *element_p=new_element; + } + element_p=&(*element_p)->b_stack_next; + + ++offset; + ++required_offset; + } + } + + if (*element_p==NULL || (*element_p)->b_stack_offset!=required_offset){ + INSTRUCTION_GRAPH load_graph; + + load_graph=g_load + ((required_offset+global_block.block_graph_b_stack_begin_displacement)<<2,B_STACK_POINTER); + + new_element=allocate_struct_from_heap (b_stack); + new_element->b_stack_offset=required_offset; + new_element->b_stack_flags=0; + new_element->b_stack_graph=load_graph; + new_element->b_stack_load_graph=load_graph; + + new_element->b_stack_next=*element_p; + *element_p=new_element; + } + element_p=&(*element_p)->b_stack_next; + } + + required_offset=global_block.block_graph_b_stack_top_offset-1; + + element_p=&global_block.block_graph_b_stack; + while (*element_p!=NULL && (*element_p)->b_stack_offset<required_offset){ + (*element_p)->b_stack_graph=NULL; + element_p=&(*element_p)->b_stack_next; + } + + if (*element_p==NULL || (*element_p)->b_stack_offset!=required_offset){ + new_element=allocate_struct_from_heap (b_stack); + new_element->b_stack_offset=required_offset; + new_element->b_stack_flags=0; + new_element->b_stack_load_graph=NULL; + + new_element->b_stack_next=*element_p; + *element_p=new_element; + } + + graph_p=&(*element_p)->b_stack_graph; + ++required_offset; + element_p=&(*element_p)->b_stack_next; + + for (offset=0; offset<b_stack_size; ++offset){ + *graph_p=(*element_p)->b_stack_graph; + graph_p=&(*element_p)->b_stack_graph; + element_p=&(*element_p)->b_stack_next; + } + + *graph_p=graph; + + --global_block.block_graph_b_stack_top_offset; +} + +static int count_a_stack_size (struct a_stack *a_element,register int a_stack_top_offset) +{ + int a_stack_size,offset; + + a_stack_size=0; + + while (a_element!=NULL && a_element->a_stack_offset<a_stack_top_offset) + a_element=a_element->a_stack_next; + + offset=a_stack_top_offset; + + while (a_element!=NULL && a_element->a_stack_offset==offset + && !(a_element->a_stack_flags & ELEMENT_MAY_BE_REMOVED && a_element->a_stack_graph==NULL)) + { + ++a_stack_size; + a_element=a_element->a_stack_next; + ++offset; + } + + return a_stack_size; +} + +int get_a_stack_size (VOID) +{ + return count_a_stack_size (global_block.block_graph_a_stack,global_block.block_graph_a_stack_top_offset); +} + +static int count_b_stack_size (ULONG *vector_p[],struct b_stack *b_stack,int b_stack_top_offset) +{ + register struct b_stack *first_b_element,*b_element; + register int b_stack_size,offset,i; + ULONG *vector; + + b_stack_size=0; + first_b_element=b_stack; + + while (first_b_element!=NULL && first_b_element->b_stack_offset<b_stack_top_offset) + first_b_element=first_b_element->b_stack_next; + + offset=b_stack_top_offset; + b_element=first_b_element; + + while (b_element!=NULL && b_element->b_stack_offset==offset + && !(b_element->b_stack_flags & ELEMENT_MAY_BE_REMOVED && b_element->b_stack_graph==NULL)) + { + ++b_stack_size; + b_element=b_element->b_stack_next; + ++offset; + } + + if (b_stack_size<=VECTOR_ELEMENT_SIZE) + vector=*vector_p; + else { + vector=(ULONG*)fast_memory_allocate + (((b_stack_size+VECTOR_ELEMENT_SIZE-1)*sizeof (ULONG))>>LOG_VECTOR_ELEMENT_SIZE); + *vector_p=vector; + } + + b_element=first_b_element; + + for (i=0; i<b_stack_size; ){ + register struct b_stack *next_b_element; + INSTRUCTION_GRAPH graph,next_graph; + + if (i<b_stack_size-1 + && (graph=b_element->b_stack_graph)->instruction_code==GFHIGH + && (next_graph=(next_b_element=b_element->b_stack_next)->b_stack_graph)!=NULL + && next_graph->instruction_code==GFLOW + && next_graph->instruction_parameters[0].p==graph->instruction_parameters[0].p) + { + set_bit (vector,i); + ++i; + set_bit (vector,i); + ++i; + b_element=next_b_element->b_stack_next; + } else { + clear_bit (vector,i); + ++i; + b_element=b_element->b_stack_next; + } + } + + return b_stack_size; +} + +static int count_b_stack_size_2 (ULONG *vector_p[],struct b_stack *b_stack,int b_stack_top_offset) +{ + register struct b_stack *first_b_element,*b_element; + register int b_stack_size,offset,i; + ULONG *vector; + + b_stack_size=0; + first_b_element=b_stack; + + while (first_b_element!=NULL && first_b_element->b_stack_offset<b_stack_top_offset) + first_b_element=first_b_element->b_stack_next; + + offset=b_stack_top_offset; + b_element=first_b_element; + + while (b_element!=NULL && b_element->b_stack_offset==offset + && b_element->b_stack_graph!=NULL + && b_element->b_stack_flags & ELEMENT_USED_BEFORE_JSR + /*(b_element->b_stack_graph->node_mark==2 + || ((b_element->b_stack_graph->instruction_code==GFHIGH + || b_element->b_stack_graph->instruction_code==GFLOW) + && b_element->b_stack_graph->instruction_parameters[0].p->node_mark==2)) */ + && !((b_element->b_stack_flags & ELEMENT_MAY_BE_REMOVED) + && b_element->b_stack_graph==NULL)) + { + ++b_stack_size; + b_element=b_element->b_stack_next; + ++offset; + } + + if (b_stack_size<=VECTOR_ELEMENT_SIZE) + vector=*vector_p; + else { + vector=(ULONG*)fast_memory_allocate + (((b_stack_size+VECTOR_ELEMENT_SIZE-1)*sizeof (ULONG))>>LOG_VECTOR_ELEMENT_SIZE); + *vector_p=vector; + } + + b_element=first_b_element; + + for (i=0; i<b_stack_size; ){ + register struct b_stack *next_b_element; + INSTRUCTION_GRAPH graph,next_graph; + + if (i<b_stack_size-1 + && (graph=b_element->b_stack_graph)!=NULL + && graph->instruction_code==GFHIGH + && (next_graph=(next_b_element=b_element->b_stack_next)->b_stack_graph)!=NULL + && next_graph->instruction_code==GFLOW + && next_graph->instruction_parameters[0].p==graph->instruction_parameters[0].p) + { + set_bit (vector,i); + ++i; + set_bit (vector,i); + ++i; + b_element=next_b_element->b_stack_next; + } else { + clear_bit (vector,i); + ++i; + b_element=b_element->b_stack_next; + } + } + + return b_stack_size; +} + +int get_b_stack_size (ULONG *vector_p[]) +{ + return count_b_stack_size (vector_p,global_block.block_graph_b_stack,global_block.block_graph_b_stack_top_offset); +} + +static void a_stack_load_register_values (int n_parameters,int n_address_parameter_registers) +{ + register struct a_stack **element_p; + register int parameter_n; + + if (n_parameters>n_address_parameter_registers) + n_parameters=n_address_parameter_registers; + + element_p=&global_block.block_graph_a_stack; + for (parameter_n=0; parameter_n<n_parameters; ++parameter_n){ + struct a_stack *new_element; + int required_offset; + INSTRUCTION_GRAPH graph; + + required_offset=global_block.block_graph_a_stack_top_offset+parameter_n; + + while (*element_p!=NULL && (*element_p)->a_stack_offset<required_offset) + element_p=&(*element_p)->a_stack_next; + + if (*element_p!=NULL && (*element_p)->a_stack_offset==required_offset){ + struct a_stack *element; + + element=*element_p; + if (element->a_stack_flags & ELEMENT_MAY_BE_REMOVED && element->a_stack_graph==NULL){ + graph=g_load + ((-(1+required_offset+global_block.block_graph_a_stack_begin_displacement))<<2,A_STACK_POINTER); + element->a_stack_graph=graph; + element->a_stack_load_graph=graph; + } + element_p=&(*element_p)->a_stack_next; + } else { + graph=g_load + ((-(1+required_offset+global_block.block_graph_a_stack_begin_displacement))<<2,A_STACK_POINTER); + + new_element=allocate_struct_from_heap (a_stack); + new_element->a_stack_offset=required_offset; + new_element->a_stack_flags=0; + new_element->a_stack_graph=graph; + new_element->a_stack_load_graph=graph; + + new_element->a_stack_next=*element_p; + *element_p=new_element; + element_p=&new_element->a_stack_next; + } + } +} + +static void a_stack_stores (int n_parameters,int n_address_parameter_registers) +{ + register struct a_stack *a_element; + + end_a_registers=0; + + if (n_parameters>n_address_parameter_registers) + n_parameters=n_address_parameter_registers; + + global_block.block_graph_a_stack_end_displacement=n_parameters; + + for_l (a_element,global_block.block_graph_a_stack,a_stack_next) + if (a_element->a_stack_graph!=NULL){ + if (a_element->a_stack_offset<global_block.block_graph_a_stack_top_offset) + a_element->a_stack_graph=NULL; + else { + if (a_element->a_stack_offset-global_block.block_graph_a_stack_top_offset<n_parameters){ + register int register_number; + + register_number=n_parameters-1-(a_element->a_stack_offset-global_block.block_graph_a_stack_top_offset); + + a_element->a_stack_graph= + g_store_r (num_to_a_reg (register_number),a_element->a_stack_graph); + + end_a_registers |= ((unsigned)1<<register_number); + } else { + if (a_element->a_stack_graph==a_element->a_stack_load_graph + && a_element->a_stack_load_graph->instruction_code!=GREGISTER + ) + a_element->a_stack_graph=NULL; + else { + INSTRUCTION_GRAPH l_graph; + + l_graph=a_element->a_stack_graph; + + while (l_graph->instruction_code==GFILL) + l_graph=l_graph->instruction_parameters[0].p; + + if (l_graph!=a_element->a_stack_load_graph + || a_element->a_stack_load_graph->instruction_code==GREGISTER + ) + a_element->a_stack_graph=g_store ( + (-(1+a_element->a_stack_offset+global_block.block_graph_a_stack_begin_displacement))<<2, + A_STACK_POINTER,a_element->a_stack_graph, + a_element->a_stack_load_graph + ); + } + } + } + } +} + +static int set_basic_block_begin_a_registers + (struct a_stack **element_p,int n_a_registers,INSTRUCTION_GRAPH a_register_parameter_node[]) +{ + int offset; + + while (*element_p!=NULL && (*element_p)->a_stack_offset<0) + element_p=&(*element_p)->a_stack_next; + + for (offset=0; offset<n_a_registers; ++offset){ + INSTRUCTION_GRAPH graph; + + if (*element_p!=NULL && (*element_p)->a_stack_offset==offset){ + struct a_stack *element; + + element=*element_p; + + if (element->a_stack_flags & ELEMENT_MAY_BE_REMOVED && element->a_stack_graph==NULL){ + graph=g_new_node (GREGISTER,0,sizeof (union instruction_parameter)); + graph->instruction_parameters[0].i=num_to_a_reg (n_a_registers-1-offset); + + a_register_parameter_node[n_a_registers-1-offset]=graph; + + element->a_stack_graph=graph; + element->a_stack_load_graph=graph; + } else { + graph=element->a_stack_load_graph; + if (graph!=NULL){ + graph->instruction_code=GREGISTER; + graph->inode_arity=0; + graph->instruction_parameters[0].i=num_to_a_reg (n_a_registers-1-offset); + + a_register_parameter_node[n_a_registers-1-offset]=graph; + } else + a_register_parameter_node[n_a_registers-1-offset]=NULL; + } + + element_p=&(*element_p)->a_stack_next; + } else { + struct a_stack *new_element; + + graph=g_new_node (GREGISTER,0,sizeof (union instruction_parameter)); + graph->instruction_parameters[0].i=num_to_a_reg (n_a_registers-1-offset); + + a_register_parameter_node[n_a_registers-1-offset]=graph; + + new_element=allocate_struct_from_heap (a_stack); + new_element->a_stack_offset=offset; + new_element->a_stack_flags=0; + new_element->a_stack_graph=graph; + new_element->a_stack_load_graph=graph; + + new_element->a_stack_next=*element_p; + *element_p=new_element; + element_p=&new_element->a_stack_next; + } + } + + return -n_a_registers; +} + +static void compute_a_load_offsets (register struct a_stack *a_element,int offset) +{ + for (; a_element!=NULL; a_element=a_element->a_stack_next){ + register INSTRUCTION_GRAPH load_graph; + + load_graph=a_element->a_stack_load_graph; + if (load_graph!=NULL) + switch (load_graph->instruction_code){ + case GLOAD: + load_graph->instruction_parameters[0].i= -((1+a_element->a_stack_offset)<<2)-offset; + break; + case GREGISTER: + break; + default: + internal_error_in_function ("compute_a_load_offsets"); + } + } +} + +static void b_stack_load_register_values (int n_parameters,ULONG vector[],int n_data_parameter_registers +#ifdef MORE_PARAMETER_REGISTERS + ,int n_extra_data_parameter_registers +#endif + ) +{ + register struct b_stack **element_p; + register int parameter_n; + int number_of_d_register_parameters,number_of_f_register_parameters_m_2; + +#ifdef MORE_PARAMETER_REGISTERS + if (n_extra_data_parameter_registers<0) + n_extra_data_parameter_registers=0; +#endif + + number_of_d_register_parameters=0; + number_of_f_register_parameters_m_2=0; + + element_p=&global_block.block_graph_b_stack; + for (parameter_n=0; parameter_n<n_parameters; ++parameter_n){ + struct b_stack *new_element; + int required_offset; + INSTRUCTION_GRAPH graph; + + required_offset=global_block.block_graph_b_stack_top_offset+parameter_n; + + while (*element_p!=NULL && (*element_p)->b_stack_offset<required_offset) + element_p=&(*element_p)->b_stack_next; + + if (!test_bit (vector,parameter_n) + ? number_of_d_register_parameters++ < n_data_parameter_registers +#ifdef MORE_PARAMETER_REGISTERS + + n_extra_data_parameter_registers +#endif + : (mc68881_flag && number_of_f_register_parameters_m_2++<(N_FLOAT_PARAMETER_REGISTERS<<1))) + { + if (*element_p!=NULL && (*element_p)->b_stack_offset==required_offset){ + register struct b_stack *element; + + element=*element_p; + if (element->b_stack_flags & ELEMENT_MAY_BE_REMOVED && element->b_stack_graph==NULL){ + graph=g_load ((required_offset+global_block.block_graph_b_stack_begin_displacement)<<2,B_STACK_POINTER); + element->b_stack_graph=graph; + element->b_stack_load_graph=graph; + } + element_p=&(*element_p)->b_stack_next; + } else{ + graph=g_load ((required_offset+global_block.block_graph_b_stack_begin_displacement)<<2,B_STACK_POINTER); + + new_element=allocate_struct_from_heap (b_stack); + new_element->b_stack_offset=required_offset; + new_element->b_stack_flags=0; + new_element->b_stack_graph=graph; + new_element->b_stack_load_graph=graph; + + new_element->b_stack_next=*element_p; + *element_p=new_element; + element_p=&new_element->b_stack_next; + } + } + } +} + +static void b_stack_stores (int n_parameters,ULONG vector[],int n_data_parameter_registers +#ifdef MORE_PARAMETER_REGISTERS + ,int n_extra_data_parameter_registers, + INSTRUCTION_GRAPH a_register_parameter_nodes[],INSTRUCTION_GRAPH d_register_parameter_nodes[] +#endif + ) +{ + struct b_stack *b_element; + int n,displacement,parameter_n; + int number_of_d_register_parameters,number_of_f_register_parameters; +#ifdef MORE_PARAMETER_REGISTERS + INSTRUCTION_GRAPH *d_graphs_p[N_DATA_PARAMETER_REGISTERS+N_ADDRESS_PARAMETER_REGISTERS], + d_graphs[N_DATA_PARAMETER_REGISTERS+N_ADDRESS_PARAMETER_REGISTERS]; +#else + INSTRUCTION_GRAPH *d_graphs_p[N_DATA_PARAMETER_REGISTERS],d_graphs[N_DATA_PARAMETER_REGISTERS]; +#endif + INSTRUCTION_GRAPH *f_graphs_p[N_FLOAT_PARAMETER_REGISTERS],f_graphs[N_FLOAT_PARAMETER_REGISTERS<<1]; + +#ifdef MORE_PARAMETER_REGISTERS + if (n_extra_data_parameter_registers<0) + n_extra_data_parameter_registers=0; +#endif + + end_d_registers=0; + end_f_registers=0; + + number_of_d_register_parameters=0; + number_of_f_register_parameters=0; + + for_l (b_element,global_block.block_graph_b_stack,b_stack_next){ + INSTRUCTION_GRAPH graph; + + if (b_element->b_stack_offset<global_block.block_graph_b_stack_top_offset){ + b_element->b_stack_graph=NULL; + continue; + } + + graph=b_element->b_stack_graph; + + parameter_n=b_element->b_stack_offset-global_block.block_graph_b_stack_top_offset; + if ((unsigned)parameter_n<(unsigned)n_parameters) + if (test_bit (vector,parameter_n)){ + if (number_of_f_register_parameters<N_FLOAT_PARAMETER_REGISTERS && mc68881_flag){ + struct b_stack *next_b_element; + + next_b_element=b_element->b_stack_next; + + if (graph==NULL || next_b_element==NULL || next_b_element->b_stack_graph==NULL) + internal_error_in_function ("b_stack_stores"); + + f_graphs[number_of_f_register_parameters]=g_fjoin (graph,next_b_element->b_stack_graph); + f_graphs_p[number_of_f_register_parameters]=&b_element->b_stack_graph; + + next_b_element->b_stack_graph=NULL; + ++number_of_f_register_parameters; + + b_element=next_b_element; + + continue; + } + } else { + if (number_of_d_register_parameters<n_data_parameter_registers +#ifdef MORE_PARAMETER_REGISTERS + + n_extra_data_parameter_registers +#endif + ){ + d_graphs[number_of_d_register_parameters]=graph; + d_graphs_p[number_of_d_register_parameters]=&b_element->b_stack_graph; + ++number_of_d_register_parameters; + + continue; + } + } + + if (graph!=NULL){ + struct b_stack *next_b_element; + INSTRUCTION_GRAPH next_graph; + + if (graph->instruction_code==GFHIGH + && (next_b_element=b_element->b_stack_next)!=NULL + && (next_graph=next_b_element->b_stack_graph)!=NULL + && next_graph->instruction_code==GFLOW + && next_b_element->b_stack_offset==b_element->b_stack_offset+1 + && next_graph->instruction_parameters[0].p==graph->instruction_parameters[0].p + ){ + if (graph==b_element->b_stack_load_graph && + next_graph==next_b_element->b_stack_load_graph && + graph->instruction_parameters[0].p->instruction_code!=GFREGISTER) + { + b_element->b_stack_graph=NULL; + next_b_element->b_stack_graph=NULL; + } else { + b_element->b_stack_graph=g_fstore ( + (b_element->b_stack_offset+global_block.block_graph_b_stack_begin_displacement)<<2, + B_STACK_POINTER,graph->instruction_parameters[0].p, + b_element->b_stack_load_graph,next_b_element->b_stack_load_graph + ); + next_b_element->b_stack_graph=NULL; + } + b_element=next_b_element; + continue; + } + + if (graph==b_element->b_stack_load_graph && graph->instruction_code!=GREGISTER) + b_element->b_stack_graph=NULL; + else + b_element->b_stack_graph=g_store ( + (b_element->b_stack_offset+global_block.block_graph_b_stack_begin_displacement)<<2, + B_STACK_POINTER,graph,b_element->b_stack_load_graph + ); + } + } + +#ifdef MORE_PARAMETER_REGISTERS + n_extra_data_parameter_registers=number_of_d_register_parameters-n_data_parameter_registers; + if (n_extra_data_parameter_registers<0) + n_extra_data_parameter_registers=0; +#endif + + for (n=0; n<number_of_d_register_parameters; ++n) + if (d_graphs[n]!=NULL){ + register int d_reg_n; + +#ifdef MORE_PARAMETER_REGISTERS + d_reg_n=(number_of_d_register_parameters-1-n)-n_extra_data_parameter_registers; + + if (d_reg_n>=0){ + end_d_registers |= ((unsigned)1<<d_reg_n); + + *d_graphs_p[n]=g_store_r (num_to_d_reg (d_reg_n),d_graphs[n]); + } else { +# if 1 + int extra_d_reg_n; + + extra_d_reg_n=n_data_parameter_registers-1-d_reg_n; + + end_d_registers |= ((unsigned)1<<extra_d_reg_n); + + *d_graphs_p[n]=g_store_r (num_to_d_reg (extra_d_reg_n),d_graphs[n]); + + if (a_register_parameter_nodes[N_ADDRESS_PARAMETER_REGISTERS+d_reg_n]!=NULL){ + INSTRUCTION_GRAPH register_node; + + register_node=a_register_parameter_nodes[N_ADDRESS_PARAMETER_REGISTERS+d_reg_n]; + register_node->instruction_parameters[0].i=num_to_d_reg (extra_d_reg_n); + d_register_parameter_nodes[extra_d_reg_n]=register_node; + a_register_parameter_nodes[N_ADDRESS_PARAMETER_REGISTERS+d_reg_n]=NULL; + global_block.block_graph_d_register_parameter_node[extra_d_reg_n]=register_node; + global_block.block_graph_a_register_parameter_node[N_ADDRESS_PARAMETER_REGISTERS+d_reg_n]=NULL; + } +# else + end_a_registers |= ((unsigned)1<<N_ADDRESS_PARAMETER_REGISTERS+d_reg_n); + + *d_graphs_p[n]=g_store_r (num_to_a_reg (N_ADDRESS_PARAMETER_REGISTERS+d_reg_n),d_graphs[n]); +# endif + } +#else + d_reg_n=number_of_d_register_parameters-1-n; + + end_d_registers |= ((unsigned)1<<d_reg_n); + + *d_graphs_p[n]=g_store_r (num_to_d_reg (d_reg_n),d_graphs[n]); +#endif + } + + for (n=0; n<number_of_f_register_parameters; ++n) + if (f_graphs[n]!=NULL){ + register int f_reg_n; + + f_reg_n=number_of_f_register_parameters-1-n; + + end_f_registers |= ((unsigned)1<<f_reg_n); + + *f_graphs_p[n]=g_fstore_r (f_reg_n,f_graphs[n]); + } + + displacement=0; + number_of_d_register_parameters=0; + number_of_f_register_parameters=0; + + for (parameter_n=0; parameter_n<n_parameters; ++parameter_n) + if (test_bit (vector,parameter_n)){ + if (number_of_f_register_parameters<N_FLOAT_PARAMETER_REGISTERS + && mc68881_flag) + { + ++number_of_f_register_parameters; + displacement+=2; + ++parameter_n; + } else + break; + } else { + if (number_of_d_register_parameters<n_data_parameter_registers +#ifdef MORE_PARAMETER_REGISTERS + + n_extra_data_parameter_registers +#endif + ){ + ++number_of_d_register_parameters; + ++displacement; + } else + break; + } + + global_block.block_graph_b_stack_end_displacement=displacement; +} + +static int set_basic_block_begin_d_registers + (struct b_stack **element_p,int b_stack_size,ULONG vector[], + INSTRUCTION_GRAPH d_register_parameter_node[],INSTRUCTION_GRAPH f_register_parameter_node[] +#ifdef MORE_PARAMETER_REGISTERS + ,int n_extra_data_parameter_registers,INSTRUCTION_GRAPH a_register_parameter_node[] +#endif + ) +{ + register int offset,stack_displacement; + register int n_d_registers,n_f_registers,all_parameters_in_registers; + register int n_data_parameter_registers; + + n_data_parameter_registers = + (parallel_flag ? N_DATA_PARAMETER_REGISTERS-1 : N_DATA_PARAMETER_REGISTERS) +#ifdef MORE_PARAMETER_REGISTERS + + n_extra_data_parameter_registers +#endif + ; + + n_d_registers=0; + n_f_registers=0; + + for (offset=0; offset<b_stack_size; ++offset) + if (!test_bit (vector,offset)){ +#ifdef I486 + if (n_d_registers<n_data_parameter_registers) +#else + if (n_d_registers<n_data_parameter_registers-1) +#endif + ++n_d_registers; + } else { + if (n_f_registers<N_FLOAT_PARAMETER_REGISTERS && mc68881_flag) + ++n_f_registers; + ++offset; + } + + stack_displacement=0; + all_parameters_in_registers=1; + + for (offset=0; offset<b_stack_size; ++offset){ + register INSTRUCTION_GRAPH graph; + + if (!test_bit (vector,offset)){ + if (n_d_registers<=0) + all_parameters_in_registers=0; + else { + --n_d_registers; + + if (all_parameters_in_registers) + --stack_displacement; + + while (*element_p!=NULL && (*element_p)->b_stack_offset<offset) + element_p=&(*element_p)->b_stack_next; + + if (*element_p!=NULL && (*element_p)->b_stack_offset==offset){ + register struct b_stack *element; + + element=*element_p; + + if (element->b_stack_flags & ELEMENT_MAY_BE_REMOVED && element->b_stack_graph==NULL){ + graph=g_new_node (GREGISTER,0,sizeof (union instruction_parameter)); +#ifdef MORE_PARAMETER_REGISTERS + { + int d_reg_n; + + d_reg_n=n_d_registers - n_extra_data_parameter_registers; + + if (d_reg_n>=0){ + graph->instruction_parameters[0].i=num_to_d_reg (d_reg_n); + d_register_parameter_node [d_reg_n]=graph; + } else { + graph->instruction_parameters[0].i=num_to_a_reg (N_ADDRESS_PARAMETER_REGISTERS+d_reg_n); + a_register_parameter_node [N_ADDRESS_PARAMETER_REGISTERS+d_reg_n]=graph; + } + } +#else + graph->instruction_parameters[0].i=num_to_d_reg (n_d_registers); + d_register_parameter_node [n_d_registers]=graph; +#endif + element->b_stack_graph=NULL; + element->b_stack_load_graph=NULL; + } else { + graph=element->b_stack_load_graph; + if (graph!=NULL){ + if (graph->instruction_code==GFHIGH && + graph->instruction_parameters[0].p->instruction_code==GFLOAD) + { + struct b_stack *next_element; + INSTRUCTION_GRAPH fload_graph,low_graph; + + fload_graph=graph->instruction_parameters[0].p; + + next_element=element->b_stack_next; + if (next_element==NULL || next_element->b_stack_offset!=offset+1) + internal_error_in_function ("compute_b_load_offsets"); + + low_graph=next_element->b_stack_load_graph; + if (low_graph==NULL || low_graph->instruction_code!=GFLOW + || low_graph->instruction_parameters[0].p!=fload_graph) + internal_error_in_function ("compute_b_load_offsets"); + + /* added 25-10-2001 */ + low_graph->instruction_code=GLOAD; + low_graph->instruction_parameters[0].i=fload_graph->instruction_parameters[0].i+4; + low_graph->instruction_parameters[1].i=fload_graph->instruction_parameters[1].i; + /* */ + + fload_graph->instruction_code=GFJOIN; + fload_graph->instruction_parameters[0].p=graph; + fload_graph->instruction_parameters[1].p=low_graph; + } + + graph->instruction_code=GREGISTER; + graph->inode_arity=0; +#ifdef MORE_PARAMETER_REGISTERS + { + int d_reg_n; + + d_reg_n=n_d_registers - n_extra_data_parameter_registers; + + if (d_reg_n>=0){ + graph->instruction_parameters[0].i=num_to_d_reg (d_reg_n); + d_register_parameter_node[d_reg_n]=graph; + } else { + graph->instruction_parameters[0].i=num_to_a_reg (N_ADDRESS_PARAMETER_REGISTERS+d_reg_n); + a_register_parameter_node[N_ADDRESS_PARAMETER_REGISTERS+d_reg_n]=graph; + } + } +#else + graph->instruction_parameters[0].i=num_to_d_reg (n_d_registers); + d_register_parameter_node[n_d_registers]=graph; +#endif + } else +#ifdef MORE_PARAMETER_REGISTERS + { + int d_reg_n; + + d_reg_n=n_d_registers - n_extra_data_parameter_registers; + + if (d_reg_n>=0) + d_register_parameter_node[d_reg_n]=NULL; + else + a_register_parameter_node[N_ADDRESS_PARAMETER_REGISTERS+d_reg_n]=NULL; + } +#else + d_register_parameter_node[n_d_registers]=NULL; +#endif + } + + element_p=&(*element_p)->b_stack_next; + } else { + register struct b_stack *new_element; + + graph=g_new_node (GREGISTER,0,sizeof (union instruction_parameter)); +#ifdef MORE_PARAMETER_REGISTERS + { + int d_reg_n; + + d_reg_n=n_d_registers - n_extra_data_parameter_registers; + + if (d_reg_n>=0){ + graph->instruction_parameters[0].i=num_to_d_reg (d_reg_n); + d_register_parameter_node[d_reg_n]=graph; + } else { + graph->instruction_parameters[0].i=num_to_a_reg (N_ADDRESS_PARAMETER_REGISTERS+d_reg_n); + a_register_parameter_node[N_ADDRESS_PARAMETER_REGISTERS+d_reg_n]=graph; + } + } +#else + graph->instruction_parameters[0].i=num_to_d_reg (n_d_registers); + d_register_parameter_node[n_d_registers]=graph; +#endif + new_element=allocate_struct_from_heap (b_stack); + new_element->b_stack_offset=offset; + new_element->b_stack_flags=0; + new_element->b_stack_graph=graph; + new_element->b_stack_load_graph=graph; + + new_element->b_stack_next=*element_p; + *element_p=new_element; + element_p=&new_element->b_stack_next; + } + } + } else { + if (n_f_registers<=0) + all_parameters_in_registers=0; + else { + INSTRUCTION_GRAPH r_graph; + int f_register_not_used_flag; + register struct b_stack *element; + + --n_f_registers; + + if (all_parameters_in_registers) + --stack_displacement; + + while (*element_p!=NULL && (*element_p)->b_stack_offset<offset) + element_p=&(*element_p)->b_stack_next; + + r_graph=NULL; + + if ((element=*element_p)!=NULL){ + if (element->b_stack_offset==offset){ + if ((graph=element->b_stack_load_graph)!=NULL && + graph->instruction_code==GFHIGH) + { + r_graph=graph->instruction_parameters[0].p; + r_graph->instruction_code=GFREGISTER; + r_graph->inode_arity=0; + r_graph->instruction_parameters[0].i=n_f_registers; + } + element=element->b_stack_next; + } + if (element!=NULL && element->b_stack_offset==offset+1 && + (graph=element->b_stack_load_graph)!=NULL && + graph->instruction_code==GFLOW) + { + r_graph=graph->instruction_parameters[0].p; + r_graph->instruction_code=GFREGISTER; + r_graph->inode_arity=0; + r_graph->instruction_parameters[0].i=n_f_registers; + } + } + + if (r_graph==NULL){ + r_graph=g_new_node (GFREGISTER,0,sizeof (union instruction_parameter)); + r_graph->instruction_parameters[0].i=n_f_registers; + } + + f_register_not_used_flag=0; + + if ((element=*element_p)!=NULL && element->b_stack_offset==offset){ + if (element->b_stack_flags & ELEMENT_MAY_BE_REMOVED && element->b_stack_graph==NULL){ +#ifdef g_fhighlow + graph=g_new_node (GFHIGH,0,2*sizeof (union instruction_parameter)); + graph->instruction_parameters[1].p=NULL; +#else + graph=g_new_node (GFHIGH,0,sizeof (union instruction_parameter)); +#endif + graph->instruction_parameters[0].p=r_graph; + + element->b_stack_graph=NULL; + element->b_stack_load_graph=NULL; + } else { + graph=element->b_stack_load_graph; + if (graph!=NULL){ + graph->instruction_code=GFHIGH; + graph->inode_arity=0; + graph->instruction_parameters[0].p=r_graph; +#ifdef g_fhighlow + graph->instruction_parameters[1].p=NULL; +#endif + } else + ++f_register_not_used_flag; + } + + element_p=&(*element_p)->b_stack_next; + } else { + register struct b_stack *new_element; + +#ifdef g_fhighlow + graph=g_new_node (GFHIGH,0,2*sizeof (union instruction_parameter)); + graph->instruction_parameters[1].p=NULL; +#else + graph=g_new_node (GFHIGH,0,sizeof (union instruction_parameter)); +#endif + graph->instruction_parameters[0].p=r_graph; + + new_element=allocate_struct_from_heap (b_stack); + new_element->b_stack_offset=offset; + new_element->b_stack_flags=0; + new_element->b_stack_graph=graph; + new_element->b_stack_load_graph=graph; + + new_element->b_stack_next=*element_p; + *element_p=new_element; + element_p=&new_element->b_stack_next; + } + + ++offset; + + if (all_parameters_in_registers) + --stack_displacement; + + if (*element_p!=NULL && (*element_p)->b_stack_offset==offset){ + register struct b_stack *element; + + element=*element_p; + if (element->b_stack_flags & ELEMENT_MAY_BE_REMOVED && element->b_stack_graph==NULL){ +#ifdef g_fhighlow + graph=g_new_node (GFLOW,0,2*sizeof (union instruction_parameter)); + graph->instruction_parameters[1].p=NULL; +#else + graph=g_new_node (GFLOW,0,sizeof (union instruction_parameter)); +#endif + graph->instruction_parameters[0].p=r_graph; + + element->b_stack_graph=NULL; + element->b_stack_load_graph=NULL; + } else { + graph=element->b_stack_load_graph; + if (graph!=NULL){ + graph->instruction_code=GFLOW; + graph->inode_arity=0; + graph->instruction_parameters[0].p=r_graph; +#ifdef g_fhighlow + graph->instruction_parameters[1].p=NULL; +#endif + } else + ++f_register_not_used_flag; + } + + element_p=&(*element_p)->b_stack_next; + } else { + register struct b_stack *new_element; + +#ifdef g_fhighlow + graph=g_new_node (GFLOW,0,2*sizeof (union instruction_parameter)); + graph->instruction_parameters[1].p=NULL; +#else + graph=g_new_node (GFLOW,0,sizeof (union instruction_parameter)); +#endif + graph->instruction_parameters[0].p=r_graph; + + new_element=allocate_struct_from_heap (b_stack); + new_element->b_stack_offset=offset; + new_element->b_stack_flags=0; + new_element->b_stack_graph=graph; + new_element->b_stack_load_graph=graph; + + new_element->b_stack_next=*element_p; + *element_p=new_element; + element_p=&new_element->b_stack_next; + } + + f_register_parameter_node[n_f_registers]= + f_register_not_used_flag!=2 ? r_graph : NULL; + } + } + } + + return stack_displacement; +} + +static void compute_b_load_offsets (register struct b_stack *b_element,int offset) +{ + for (; b_element!=NULL; b_element=b_element->b_stack_next){ + register INSTRUCTION_GRAPH load_graph; + + load_graph=b_element->b_stack_load_graph; + + if (load_graph!=NULL) + switch (load_graph->instruction_code){ + case GLOAD: + load_graph->instruction_parameters[0].i= + (b_element->b_stack_offset<<2)+offset; + break; + case GREGISTER: + case GFREGISTER: + break; + case GFHIGH: + { + INSTRUCTION_GRAPH graph_1; + + graph_1=load_graph->instruction_parameters[0].p; + if (graph_1->instruction_code==GFLOAD) + graph_1->instruction_parameters[0].i = (b_element->b_stack_offset<<2)+offset; + else if (graph_1->instruction_code!=GFREGISTER) + internal_error_in_function ("compute_b_load_offsets"); + + break; + } + case GFLOW: + { + INSTRUCTION_GRAPH graph_1; + + graph_1=load_graph->instruction_parameters[0].p; + if (graph_1->instruction_code==GFLOAD) + graph_1->instruction_parameters[0].i = ((b_element->b_stack_offset-1)<<2)+offset; + else if (graph_1->instruction_code!=GFREGISTER) + internal_error_in_function ("compute_b_load_offsets"); + + break; + } + default: + internal_error_in_function ("compute_b_load_offsets"); + } + } +} + +static void remove_stack_element (struct stack **element_p) +{ + struct stack *element; + + element=(*element_p)->stack_next; + *element_p=element; + + while (element!=NULL){ + --element->stack_offset; + element=element->stack_next; + } +} + +static void remove_end_stack_element + (struct stack **element_p,int remove_offset,int stack_begin_displacement,int stack_top_offset,int b_stack_flag) +{ + struct stack *element; + INSTRUCTION_GRAPH graph_1; + int offset,flags_1,begin_offset; + + element=*element_p; + + graph_1=NULL; + flags_1=0; + + begin_offset= stack_top_offset<=0 ? stack_top_offset : 0; + + while (element!=NULL && element->stack_offset<begin_offset){ + element_p=&element->stack_next; + element=*element_p; + } + + for (offset=begin_offset; offset<remove_offset; ++offset){ + INSTRUCTION_GRAPH graph_2; + int flags_2; + + if (element==NULL || element->stack_offset!=offset){ + struct stack *new_element; + INSTRUCTION_GRAPH graph; + + if (!b_stack_flag) + graph=g_load (-(offset+stack_begin_displacement+1)<<2,A_STACK_POINTER); + else + graph=g_load ((offset+stack_begin_displacement)<<2,B_STACK_POINTER); + + graph->node_mark=offset<stack_top_offset ? 0 : 2; + + new_element=allocate_struct_from_heap (stack); + new_element->stack_offset=offset; + new_element->stack_flags=0; + new_element->stack_graph=graph; + new_element->stack_load_graph=graph; + + new_element->stack_next=element; + *element_p=new_element; + element=new_element; + } + + graph_2=graph_1; + flags_2=flags_1; + + graph_1=element->stack_graph; + flags_1=element->stack_flags; + + element->stack_graph=graph_2; + element->stack_flags= (element->stack_flags & ~ELEMENT_USED_BEFORE_JSR) | (flags_2 & ELEMENT_USED_BEFORE_JSR); + + element_p=&element->stack_next; + element=*element_p; + } + + element->stack_graph=graph_1; + element->stack_flags= (element->stack_flags & ~ELEMENT_USED_BEFORE_JSR) | (flags_1 & ELEMENT_USED_BEFORE_JSR); +} + +static void remove_begin_stack_element + (struct stack **element_p,int remove_offset,int stack_begin_displacement, + int stack_top_offset,int b_stack_flag) +{ + struct stack *element,*previous_element; + int offset,begin_offset; + + begin_offset= stack_top_offset<=0 ? stack_top_offset : 0; + + previous_element=NULL; + element=*element_p; + + while (element!=NULL && element->stack_offset<begin_offset){ + previous_element=element; + element_p=&element->stack_next; + element=*element_p; + } + + for (offset=begin_offset; offset<=remove_offset; ++offset){ + if (element==NULL || element->stack_offset!=offset){ + struct stack *new_element; + INSTRUCTION_GRAPH graph; + + if (!b_stack_flag) + graph=g_load (-(offset+stack_begin_displacement+1)<<2,A_STACK_POINTER); + else + graph=g_load ((offset+stack_begin_displacement)<<2,B_STACK_POINTER); + + graph->node_mark= offset<stack_top_offset ? 0 : 2; + + new_element=allocate_struct_from_heap (stack); + new_element->stack_offset=offset; + new_element->stack_flags=0; + new_element->stack_load_graph=graph; + new_element->stack_graph=graph; + + new_element->stack_next=element; + *element_p=new_element; + element=new_element; + } + + if (previous_element==NULL || previous_element->stack_offset!=offset-1){ + struct stack *new_element; + + new_element=allocate_struct_from_heap (stack); + new_element->stack_offset=offset-1; + new_element->stack_flags=0; + new_element->stack_load_graph=NULL; + new_element->stack_graph=NULL; + + new_element->stack_next=element; + *element_p=new_element; + element_p=&new_element->stack_next; + previous_element=new_element; + } + + previous_element->stack_graph=element->stack_graph; + previous_element->stack_flags= (previous_element->stack_flags & ~ELEMENT_USED_BEFORE_JSR) + | (element->stack_flags & ELEMENT_USED_BEFORE_JSR); + + element->stack_graph=NULL; + element->stack_flags &= ~ELEMENT_USED_BEFORE_JSR; + + if (offset<remove_offset){ + previous_element=element; + element_p=&element->stack_next; + element=*element_p; + } + } + + if (element!=NULL) + *element_p=element->stack_next; + + for (element=*element_p; element!=NULL; element=element->stack_next) + --element->stack_offset; +} + +#define INSERT_LOAD_GRAPHS + +#ifdef INSERT_LOAD_GRAPHS + static struct stack ** insert_load_graphs + (struct stack **element_p,int remove_offset,int stack_begin_displacement,int stack_top_offset,int b_stack_flag) + { + struct stack *element; + int offset,begin_offset; + + begin_offset= stack_top_offset<=0 ? stack_top_offset : 0; + + element=*element_p; + + while (element!=NULL && element->stack_offset<begin_offset){ + element_p=&element->stack_next; + element=*element_p; + } + + for (offset=begin_offset; offset<remove_offset; ++offset){ + if (element==NULL || element->stack_offset!=offset){ + struct stack *new_element; + INSTRUCTION_GRAPH graph; + + if (!b_stack_flag) + graph=g_load (-(offset+stack_begin_displacement+1)<<2,A_STACK_POINTER); + else + graph=g_load ((offset+stack_begin_displacement)<<2,B_STACK_POINTER); + + graph->node_mark= offset<stack_top_offset ? 0 : 2; + + new_element=allocate_struct_from_heap (stack); + new_element->stack_offset=offset; + new_element->stack_flags=0; + new_element->stack_load_graph=graph; + new_element->stack_graph=graph; + + new_element->stack_next=element; + *element_p=new_element; + element=new_element; + } + + element_p=&element->stack_next; + element=*element_p; + } + + return element_p; + } +#endif + +static void remove_not_used_a_stack_elements (struct block_graph *block_graph,struct block_graph *next_block_graph) +{ + struct a_stack *a_element_1,**a_element_1_p; + struct a_stack *a_element_2,**a_element_2_p; + int stack_offset_1_min_2,first_non_parameter_offset,offset; + +#ifdef DEBUG + printf ("%d %d %d %d\n",block_graph->block_graph_a_stack_top_offset, + block_graph->block_graph_end_a_stack_size, + -next_block_graph->block_graph_begin_a_stack_size, + block_graph->block_graph_used_a_stack_elements); +#endif + + a_element_1_p=&block_graph->block_graph_a_stack; + a_element_1=*a_element_1_p; + + while (a_element_1!=NULL && a_element_1->a_stack_offset<block_graph->block_graph_a_stack_top_offset){ + if (a_element_1->a_stack_flags & (ELEMENT_MUST_BE_REMOVED | BEGIN_ELEMENT_MUST_BE_REMOVED)){ + if (a_element_1->a_stack_flags & ELEMENT_MUST_BE_REMOVED) + internal_error_in_function ("remove_not_used_a_stack_elements"); + + remove_begin_stack_element + ((struct stack **)&block_graph->block_graph_a_stack, + a_element_1->a_stack_offset,block_graph->block_graph_a_stack_begin_displacement, + block_graph->block_graph_a_stack_top_offset,0); + a_element_1=*a_element_1_p; + + --block_graph->block_graph_a_stack_top_offset; + } else { + a_element_1_p=&a_element_1->a_stack_next; + a_element_1=*a_element_1_p; + } + } + + offset=block_graph->block_graph_a_stack_top_offset; + first_non_parameter_offset= block_graph->block_graph_used_a_stack_elements + +block_graph->block_graph_a_stack_top_offset; + + while (offset<first_non_parameter_offset && a_element_1!=NULL && a_element_1->a_stack_offset==offset){ + if (a_element_1->a_stack_flags & (ELEMENT_MUST_BE_REMOVED | BEGIN_ELEMENT_MUST_BE_REMOVED)){ + if (a_element_1->a_stack_flags & ELEMENT_MUST_BE_REMOVED) + internal_error_in_function ("remove_not_used_a_stack_elements"); + + remove_begin_stack_element + ((struct stack **)&block_graph->block_graph_a_stack, + offset,block_graph->block_graph_a_stack_begin_displacement, + block_graph->block_graph_a_stack_top_offset,0); + a_element_1=*a_element_1_p; + + --block_graph->block_graph_a_stack_top_offset; + --first_non_parameter_offset; + } else { + a_element_1_p=&a_element_1->a_stack_next; + a_element_1=*a_element_1_p; + ++offset; + } + } + + stack_offset_1_min_2= block_graph->block_graph_a_stack_top_offset + +block_graph->block_graph_end_a_stack_size + -next_block_graph->block_graph_begin_a_stack_size; + + a_element_2_p=&next_block_graph->block_graph_a_stack; + a_element_2=*a_element_2_p; + + if (offset>=first_non_parameter_offset) + while (a_element_1!=NULL && a_element_1->a_stack_offset==offset){ + int offset_2; + + offset_2=offset-stack_offset_1_min_2; + + while (a_element_2!=NULL && a_element_2->a_stack_offset<offset_2){ + a_element_2_p=&a_element_2->a_stack_next; + a_element_2=*a_element_2_p; + } + + if (a_element_1->a_stack_flags & ELEMENT_MUST_BE_REMOVED + || (a_element_1->a_stack_flags & BEGIN_ELEMENT_MUST_BE_REMOVED && + ( (a_element_2!=NULL && a_element_2->a_stack_offset==offset_2) + ? (a_element_2->a_stack_load_graph==NULL || !a_element_2->a_stack_load_graph->node_mark) + : offset_2<next_block_graph->block_graph_a_stack_top_offset ))) + { + remove_stack_element ((struct stack **)a_element_1_p); + a_element_1=*a_element_1_p; + --stack_offset_1_min_2; + + if (a_element_2!=NULL && a_element_2->a_stack_offset==offset_2){ + if (a_element_2->a_stack_flags & ELEMENT_MAY_BE_REMOVED) + a_element_2->a_stack_flags |= ELEMENT_MUST_BE_REMOVED; + else { + a_element_2->a_stack_flags |= BEGIN_ELEMENT_MUST_BE_REMOVED; +#ifdef INSERT_LOAD_GRAPHS + a_element_2_p=(struct a_stack**)insert_load_graphs + ((struct stack **)&next_block_graph->block_graph_a_stack,offset_2, + next_block_graph->block_graph_a_stack_begin_displacement, + next_block_graph->block_graph_a_stack_top_offset,0); +#endif + } + } else { + struct a_stack *new_element; + + new_element=allocate_struct_from_heap (a_stack); + new_element->a_stack_offset=offset_2; + new_element->a_stack_flags=BEGIN_ELEMENT_MUST_BE_REMOVED; + new_element->a_stack_graph=NULL; + new_element->a_stack_load_graph=NULL; + + new_element->a_stack_next=a_element_2; + *a_element_2_p=new_element; + a_element_2=new_element; +#ifdef INSERT_LOAD_GRAPHS + a_element_2_p=(struct a_stack**)insert_load_graphs + ((struct stack **)&next_block_graph->block_graph_a_stack,offset_2, + next_block_graph->block_graph_a_stack_begin_displacement, + next_block_graph->block_graph_a_stack_top_offset,0); +#endif + } + } else if (a_element_1->a_stack_flags & BEGIN_ELEMENT_MUST_BE_REMOVED){ + remove_begin_stack_element + ((struct stack **)&block_graph->block_graph_a_stack, + offset,block_graph->block_graph_a_stack_begin_displacement, + block_graph->block_graph_a_stack_top_offset,0); + a_element_1=*a_element_1_p; + + --block_graph->block_graph_a_stack_top_offset; + --stack_offset_1_min_2; + } else { + if ( (a_element_2!=NULL && a_element_2->a_stack_offset==offset_2) + ? (a_element_2->a_stack_load_graph==NULL || !a_element_2->a_stack_load_graph->node_mark) + : offset_2<next_block_graph->block_graph_a_stack_top_offset ) + { + remove_end_stack_element + ((struct stack **)&block_graph->block_graph_a_stack,offset, + block_graph->block_graph_a_stack_begin_displacement, + block_graph->block_graph_a_stack_top_offset,0); + a_element_1=*a_element_1_p; + + ++block_graph->block_graph_a_stack_top_offset; + + if (a_element_2!=NULL && a_element_2->a_stack_offset==offset_2){ + if (a_element_2->a_stack_flags & ELEMENT_MAY_BE_REMOVED) + a_element_2->a_stack_flags |= ELEMENT_MUST_BE_REMOVED; + else { + a_element_2->a_stack_flags |= BEGIN_ELEMENT_MUST_BE_REMOVED; +#ifdef INSERT_LOAD_GRAPHS + a_element_2_p=(struct a_stack**)insert_load_graphs + ((struct stack **)&next_block_graph->block_graph_a_stack,offset_2, + next_block_graph->block_graph_a_stack_begin_displacement, + next_block_graph->block_graph_a_stack_top_offset,0); +#endif + } + } else { + struct a_stack *new_element; + + new_element=allocate_struct_from_heap (a_stack); + new_element->a_stack_offset=offset_2; + new_element->a_stack_flags=BEGIN_ELEMENT_MUST_BE_REMOVED; + new_element->a_stack_graph=NULL; + new_element->a_stack_load_graph=NULL; + + new_element->a_stack_next=a_element_2; + *a_element_2_p=new_element; + a_element_2=new_element; +#ifdef INSERT_LOAD_GRAPHS + a_element_2_p=(struct a_stack**)insert_load_graphs + ((struct stack **)&next_block_graph->block_graph_a_stack,offset_2, + next_block_graph->block_graph_a_stack_begin_displacement, + next_block_graph->block_graph_a_stack_top_offset,0); +#endif + } + } + + ++offset; + a_element_1_p=&a_element_1->a_stack_next; + a_element_1=*a_element_1_p; + } + } + + while (a_element_1!=NULL){ + if (a_element_1->a_stack_flags & ELEMENT_MUST_BE_REMOVED){ + int offset_2; + + offset=a_element_1->a_stack_offset; + offset_2=offset-stack_offset_1_min_2; + + while (a_element_2!=NULL && a_element_2->a_stack_offset<offset_2){ + a_element_2_p=&a_element_2->a_stack_next; + a_element_2=*a_element_2_p; + } + + remove_stack_element ((struct stack **)a_element_1_p); + a_element_1=*a_element_1_p; + + --stack_offset_1_min_2; + + if (a_element_2!=NULL && a_element_2->a_stack_offset==offset_2){ + if (a_element_2->a_stack_flags & ELEMENT_MAY_BE_REMOVED) + a_element_2->a_stack_flags |= ELEMENT_MUST_BE_REMOVED; + else { + a_element_2->a_stack_flags |= BEGIN_ELEMENT_MUST_BE_REMOVED; +#ifdef INSERT_LOAD_GRAPHS + a_element_2_p=(struct a_stack**)insert_load_graphs + ((struct stack **)&next_block_graph->block_graph_a_stack,offset_2, + next_block_graph->block_graph_a_stack_begin_displacement, + next_block_graph->block_graph_a_stack_top_offset,0); +#endif + } + } else { + struct a_stack *new_element; + + new_element=allocate_struct_from_heap (a_stack); + new_element->a_stack_offset=offset_2; + new_element->a_stack_flags=BEGIN_ELEMENT_MUST_BE_REMOVED; + new_element->a_stack_graph=NULL; + new_element->a_stack_load_graph=NULL; + + new_element->a_stack_next=a_element_2; + *a_element_2_p=new_element; + a_element_2=new_element; +#ifdef INSERT_LOAD_GRAPHS + a_element_2_p=(struct a_stack**)insert_load_graphs + ((struct stack **)&next_block_graph->block_graph_a_stack,offset_2, + next_block_graph->block_graph_a_stack_begin_displacement, + next_block_graph->block_graph_a_stack_top_offset,0); +#endif + } + } else if (a_element_1->a_stack_flags & BEGIN_ELEMENT_MUST_BE_REMOVED){ + remove_begin_stack_element + ((struct stack **)&block_graph->block_graph_a_stack, + a_element_1->a_stack_offset,block_graph->block_graph_a_stack_begin_displacement, + block_graph->block_graph_a_stack_top_offset,0); + a_element_1=*a_element_1_p; + + --block_graph->block_graph_a_stack_top_offset; + --stack_offset_1_min_2; + } else { + a_element_1_p=&a_element_1->a_stack_next; + a_element_1=*a_element_1_p; + } + } +} +#undef DEBUG + +static void remove_not_used_b_stack_elements (struct block_graph *block_graph,struct block_graph *next_block_graph) +{ + struct b_stack *b_element_1,**b_element_1_p; + struct b_stack *b_element_2,**b_element_2_p; + int stack_offset_1_min_2,first_non_parameter_offset_1,offset_1; + +#ifdef DEBUG + printf ("%d %d %d %d\n",block_graph->block_graph_b_stack_top_offset, + block_graph->block_graph_end_b_stack_size, + -next_block_graph->block_graph_begin_b_stack_size, + block_graph->block_graph_used_b_stack_elements); +#endif + + b_element_1_p=&block_graph->block_graph_b_stack; + b_element_1=*b_element_1_p; + + while (b_element_1!=NULL && b_element_1->b_stack_offset<block_graph->block_graph_b_stack_top_offset){ + if (b_element_1->b_stack_flags & (ELEMENT_MUST_BE_REMOVED | BEGIN_ELEMENT_MUST_BE_REMOVED)){ + if (b_element_1->b_stack_flags & ELEMENT_MUST_BE_REMOVED) + internal_error_in_function ("remove_not_used_b_stack_elements"); + + remove_begin_stack_element + ((struct stack **)&block_graph->block_graph_b_stack, + b_element_1->b_stack_offset,block_graph->block_graph_b_stack_begin_displacement, + block_graph->block_graph_b_stack_top_offset,1); + b_element_1=*b_element_1_p; + + --block_graph->block_graph_b_stack_top_offset; + } else { + b_element_1_p=&b_element_1->b_stack_next; + b_element_1=*b_element_1_p; + } + } + + offset_1=block_graph->block_graph_b_stack_top_offset; + first_non_parameter_offset_1= + block_graph->block_graph_used_b_stack_elements + +block_graph->block_graph_b_stack_top_offset; + + while (offset_1<first_non_parameter_offset_1 && b_element_1!=NULL && b_element_1->b_stack_offset==offset_1){ + if (b_element_1->b_stack_flags & (ELEMENT_MUST_BE_REMOVED | BEGIN_ELEMENT_MUST_BE_REMOVED)){ + if (b_element_1->b_stack_flags & ELEMENT_MUST_BE_REMOVED) + internal_error_in_function ("remove_not_used_b_stack_elements"); + + remove_begin_stack_element + ((struct stack **)&block_graph->block_graph_b_stack, + offset_1,block_graph->block_graph_b_stack_begin_displacement, + block_graph->block_graph_b_stack_top_offset,1); + b_element_1=*b_element_1_p; + + --block_graph->block_graph_b_stack_top_offset; + --first_non_parameter_offset_1; + } else { + b_element_1_p=&b_element_1->b_stack_next; + b_element_1=*b_element_1_p; + ++offset_1; + } + } + + stack_offset_1_min_2= + block_graph->block_graph_b_stack_top_offset + +block_graph->block_graph_end_b_stack_size + -next_block_graph->block_graph_begin_b_stack_size; + + b_element_2_p=&next_block_graph->block_graph_b_stack; + b_element_2=*b_element_2_p; + + if (offset_1>=first_non_parameter_offset_1) + while (b_element_1!=NULL && b_element_1->b_stack_offset==offset_1){ + INSTRUCTION_GRAPH load_graph; + int offset_2; + + offset_2=offset_1-stack_offset_1_min_2; + + while (b_element_2!=NULL && b_element_2->b_stack_offset<offset_2){ + b_element_2_p=&b_element_2->b_stack_next; + b_element_2=*b_element_2_p; + } + + if (b_element_1->b_stack_flags & ELEMENT_MUST_BE_REMOVED || + (b_element_1->b_stack_flags & BEGIN_ELEMENT_MUST_BE_REMOVED && + ( (b_element_2!=NULL && b_element_2->b_stack_offset==offset_2) + ? ((load_graph=b_element_2->b_stack_load_graph)==NULL || + (!load_graph->node_mark && + !((load_graph->instruction_code==GFHIGH || + load_graph->instruction_code==GFLOW) + && load_graph->instruction_parameters[0].p->node_mark))) + : offset_2<next_block_graph->block_graph_b_stack_top_offset))) + { + remove_stack_element ((struct stack **)b_element_1_p); + b_element_1=*b_element_1_p; + --stack_offset_1_min_2; + + if (b_element_2!=NULL && b_element_2->b_stack_offset==offset_2){ + if (b_element_2->b_stack_flags & ELEMENT_MAY_BE_REMOVED) + b_element_2->b_stack_flags |= ELEMENT_MUST_BE_REMOVED; + else { + b_element_2->b_stack_flags |= BEGIN_ELEMENT_MUST_BE_REMOVED; +#ifdef INSERT_LOAD_GRAPHS + b_element_2_p=(struct b_stack**)insert_load_graphs + ((struct stack **)&next_block_graph->block_graph_b_stack,offset_2, + next_block_graph->block_graph_b_stack_begin_displacement, + next_block_graph->block_graph_b_stack_top_offset,1); +#endif + } + } else { + struct b_stack *new_element; + + new_element=allocate_struct_from_heap (b_stack); + new_element->b_stack_offset=offset_2; + new_element->b_stack_flags=BEGIN_ELEMENT_MUST_BE_REMOVED; + new_element->b_stack_graph=NULL; + new_element->b_stack_load_graph=NULL; + + new_element->b_stack_next=b_element_2; + *b_element_2_p=new_element; + b_element_2=new_element; +#ifdef INSERT_LOAD_GRAPHS + b_element_2_p=(struct b_stack**)insert_load_graphs + ((struct stack **)&next_block_graph->block_graph_b_stack,offset_2, + next_block_graph->block_graph_b_stack_begin_displacement, + next_block_graph->block_graph_b_stack_top_offset,1); +#endif + } + } else if (b_element_1->b_stack_flags & BEGIN_ELEMENT_MUST_BE_REMOVED){ + remove_begin_stack_element + ((struct stack **)&block_graph->block_graph_b_stack, + offset_1,block_graph->block_graph_b_stack_begin_displacement, + block_graph->block_graph_b_stack_top_offset,1); + b_element_1=*b_element_1_p; + + --block_graph->block_graph_b_stack_top_offset; + --stack_offset_1_min_2; + } else { + if ((b_element_2!=NULL && b_element_2->b_stack_offset==offset_2) + ? ((load_graph=b_element_2->b_stack_load_graph)==NULL || + (!load_graph->node_mark && + !((load_graph->instruction_code==GFHIGH || + load_graph->instruction_code==GFLOW) + && load_graph->instruction_parameters[0].p->node_mark))) + : offset_2<next_block_graph->block_graph_b_stack_top_offset) + { + remove_end_stack_element + ((struct stack **)&block_graph->block_graph_b_stack,offset_1, + block_graph->block_graph_b_stack_begin_displacement, + block_graph->block_graph_b_stack_top_offset,1); + b_element_1=*b_element_1_p; + + ++block_graph->block_graph_b_stack_top_offset; + + if (b_element_2!=NULL && b_element_2->b_stack_offset==offset_2){ + if (b_element_2->b_stack_flags & ELEMENT_MAY_BE_REMOVED) + b_element_2->b_stack_flags |= ELEMENT_MUST_BE_REMOVED; + else { + b_element_2->b_stack_flags |= BEGIN_ELEMENT_MUST_BE_REMOVED; +#ifdef INSERT_LOAD_GRAPHS + b_element_2_p=(struct b_stack**)insert_load_graphs + ((struct stack **)&next_block_graph->block_graph_b_stack,offset_2, + next_block_graph->block_graph_b_stack_begin_displacement, + next_block_graph->block_graph_b_stack_top_offset,1); +#endif + } + } else { + struct b_stack *new_element; + + new_element=allocate_struct_from_heap (b_stack); + new_element->b_stack_offset=offset_2; + new_element->b_stack_flags=BEGIN_ELEMENT_MUST_BE_REMOVED; + new_element->b_stack_graph=NULL; + new_element->b_stack_load_graph=NULL; + + new_element->b_stack_next=b_element_2; + *b_element_2_p=new_element; + b_element_2=new_element; +#ifdef INSERT_LOAD_GRAPHS + b_element_2_p=(struct b_stack**)insert_load_graphs + ((struct stack **)&next_block_graph->block_graph_b_stack,offset_2, + next_block_graph->block_graph_b_stack_begin_displacement, + next_block_graph->block_graph_b_stack_top_offset,1); +#endif + } + } + + ++offset_1; + b_element_1_p=&b_element_1->b_stack_next; + b_element_1=*b_element_1_p; + } + } + + while (b_element_1!=NULL){ + if (b_element_1->b_stack_flags & ELEMENT_MUST_BE_REMOVED){ + int offset_2; + + offset_1=b_element_1->b_stack_offset; + offset_2=offset_1-stack_offset_1_min_2; + + while (b_element_2!=NULL && b_element_2->b_stack_offset<offset_2){ + b_element_2_p=&b_element_2->b_stack_next; + b_element_2=*b_element_2_p; + } + + remove_stack_element ((struct stack **)b_element_1_p); + b_element_1=*b_element_1_p; + --stack_offset_1_min_2; + + if (b_element_2!=NULL && b_element_2->b_stack_offset==offset_2){ + if (b_element_2->b_stack_flags & ELEMENT_MAY_BE_REMOVED) + b_element_2->b_stack_flags |= ELEMENT_MUST_BE_REMOVED; + else { + b_element_2->b_stack_flags |= BEGIN_ELEMENT_MUST_BE_REMOVED; +#ifdef INSERT_LOAD_GRAPHS + b_element_2_p=(struct b_stack**)insert_load_graphs + ((struct stack **)&next_block_graph->block_graph_b_stack,offset_2, + next_block_graph->block_graph_b_stack_begin_displacement, + next_block_graph->block_graph_b_stack_top_offset,1); +#endif + } + } else { + struct b_stack *new_element; + + new_element=allocate_struct_from_heap (b_stack); + new_element->b_stack_offset=offset_2; + new_element->b_stack_flags=BEGIN_ELEMENT_MUST_BE_REMOVED; + new_element->b_stack_graph=NULL; + new_element->b_stack_load_graph=NULL; + + new_element->b_stack_next=b_element_2; + *b_element_2_p=new_element; + b_element_2=new_element; +#ifdef INSERT_LOAD_GRAPHS + b_element_2_p=(struct b_stack**)insert_load_graphs + ((struct stack **)&next_block_graph->block_graph_b_stack,offset_2, + next_block_graph->block_graph_b_stack_begin_displacement, + next_block_graph->block_graph_b_stack_top_offset,1); +#endif + } + } else if (b_element_1->b_stack_flags & BEGIN_ELEMENT_MUST_BE_REMOVED){ + remove_begin_stack_element + ((struct stack **)&block_graph->block_graph_b_stack, + b_element_1->b_stack_offset,block_graph->block_graph_b_stack_begin_displacement, + block_graph->block_graph_b_stack_top_offset,1); + b_element_1=*b_element_1_p; + + --block_graph->block_graph_b_stack_top_offset; + --stack_offset_1_min_2; + } else { + b_element_1_p=&b_element_1->b_stack_next; + b_element_1=*b_element_1_p; + } + } + +} + +static void remove_not_used_stack_elements_from_last_block (struct block_graph *block_graph) +{ + struct a_stack *a_element_1,**a_element_1_p; + struct b_stack *b_element_1,**b_element_1_p; + + a_element_1_p=&block_graph->block_graph_a_stack; + a_element_1=*a_element_1_p; + + while (a_element_1!=NULL){ + if (a_element_1->a_stack_flags & BEGIN_ELEMENT_MUST_BE_REMOVED){ + remove_begin_stack_element + ((struct stack **)&block_graph->block_graph_a_stack, + a_element_1->a_stack_offset,block_graph->block_graph_a_stack_begin_displacement, + block_graph->block_graph_a_stack_top_offset,0); + a_element_1=*a_element_1_p; + + --block_graph->block_graph_a_stack_top_offset; + } else { + if (a_element_1->a_stack_flags & ELEMENT_MUST_BE_REMOVED){ + internal_error_in_function ("remove_not_used_stack_elements_from_last_block"); + } else + a_element_1_p=&a_element_1->a_stack_next; + a_element_1=*a_element_1_p; + } + } + + b_element_1_p=&block_graph->block_graph_b_stack; + b_element_1=*b_element_1_p; + + while (b_element_1!=NULL){ + if (b_element_1->b_stack_flags & BEGIN_ELEMENT_MUST_BE_REMOVED){ + remove_begin_stack_element + ((struct stack **)&block_graph->block_graph_b_stack, + b_element_1->b_stack_offset,block_graph->block_graph_b_stack_begin_displacement, + block_graph->block_graph_b_stack_top_offset,1); + b_element_1=*b_element_1_p; + + --block_graph->block_graph_b_stack_top_offset; + } else { + if (b_element_1->b_stack_flags & ELEMENT_MUST_BE_REMOVED){ + internal_error_in_function ("remove_not_used_stack_elements_from_last_block"); + } else + b_element_1_p=&b_element_1->b_stack_next; + b_element_1=*b_element_1_p; + } + } +} + +static struct block_graph *first_block_graph,*last_block_graph; + +static void insert_dummy_graphs_for_unused_a_stack_elements + (struct block_graph *block_graph,struct block_graph *next_block_graph) +{ + struct a_stack *a_element_1,**a_element_1_p; + struct a_stack *a_element_2; + int stack_offset_difference,offset,n; + int first_non_parameter_offset_1,first_non_parameter_offset_2; + +#ifdef DEBUG + printf ("%d %d %d %d\n",block_graph->block_graph_a_stack_top_offset, + block_graph->block_graph_end_a_stack_size, + -next_block_graph->block_graph_begin_a_stack_size, + block_graph->block_graph_used_a_stack_elements); +#endif + + stack_offset_difference= block_graph->block_graph_a_stack_top_offset + +block_graph->block_graph_end_a_stack_size + -next_block_graph->block_graph_begin_a_stack_size; + first_non_parameter_offset_1= block_graph->block_graph_used_a_stack_elements + +block_graph->block_graph_a_stack_top_offset; + + a_element_1_p=&block_graph->block_graph_a_stack; + a_element_1=*a_element_1_p; + + a_element_2=next_block_graph->block_graph_a_stack; + + first_non_parameter_offset_2=first_non_parameter_offset_1-stack_offset_difference; + while (a_element_2!=NULL && a_element_2->a_stack_offset<first_non_parameter_offset_2) + a_element_2=a_element_2->a_stack_next; + + for (; a_element_2!=NULL; a_element_2=a_element_2->a_stack_next){ + INSTRUCTION_GRAPH load_graph; + + if (a_element_2->a_stack_flags & ELEMENT_MAY_BE_REMOVED + || (load_graph=a_element_2->a_stack_load_graph)==NULL + || !load_graph->node_mark) + { + offset=a_element_2->a_stack_offset+stack_offset_difference; + + while (a_element_1!=NULL && a_element_1->a_stack_offset<offset){ + a_element_1_p=&a_element_1->a_stack_next; + a_element_1=*a_element_1_p; + } + + if (a_element_1==NULL || a_element_1->a_stack_offset!=offset){ + struct a_stack *new_element; +#ifdef DEBUG + printf ("%d ",offset); +#endif + new_element=allocate_struct_from_heap (a_stack); + new_element->a_stack_offset=offset; + new_element->a_stack_flags=ELEMENT_MAY_BE_REMOVED; + new_element->a_stack_graph=NULL; + new_element->a_stack_load_graph=NULL; + + new_element->a_stack_next=a_element_1; + *a_element_1_p=new_element; + a_element_1_p=&new_element->a_stack_next; + } + } + } + +#ifdef DEBUG + printf ("| "); +#endif + + a_element_1_p=&block_graph->block_graph_a_stack; + a_element_1=*a_element_1_p; + + a_element_2=next_block_graph->block_graph_a_stack; + + n=first_non_parameter_offset_1-stack_offset_difference; + if (n<0) + n=0; + + for (; n<next_block_graph->block_graph_a_stack_top_offset; ++n){ + while (a_element_2!=NULL && a_element_2->a_stack_offset<n) + a_element_2=a_element_2->a_stack_next; + if (a_element_2==NULL || a_element_2->a_stack_offset!=n){ + + while (a_element_1!=NULL && a_element_1->a_stack_offset<n+stack_offset_difference){ + a_element_1_p=&a_element_1->a_stack_next; + a_element_1=*a_element_1_p; + } + if (a_element_1==NULL || a_element_1->a_stack_offset!=n+stack_offset_difference){ + struct a_stack *new_element; +#ifdef DEBUG + printf ("%d ",n+stack_offset_difference); +#endif + new_element=allocate_struct_from_heap (a_stack); + new_element->a_stack_offset=n+stack_offset_difference; + new_element->a_stack_flags=ELEMENT_MAY_BE_REMOVED; + new_element->a_stack_graph=NULL; + new_element->a_stack_load_graph=NULL; + + new_element->a_stack_next=a_element_1; + *a_element_1_p=new_element; + a_element_1_p=&new_element->a_stack_next; + } + } + } + +#ifdef DEBUG + printf ("\n"); +#endif +} + +static void insert_dummy_graphs_for_unused_b_stack_elements + (register struct block_graph *block_graph,struct block_graph *next_block_graph) +{ + struct b_stack *b_element_1,**b_element_1_p,*b_element_2; + int stack_offset_1_min_2,offset_1,offset_2; + int first_non_parameter_offset_1,first_non_parameter_offset_2; + + /* + printf ("%d %d %d %d\n",block_graph->block_graph_b_stack_top_offset, + block_graph->block_graph_end_b_stack_size, + -next_block_graph->block_graph_begin_b_stack_size, + block_graph->block_graph_used_b_stack_elements); + */ + + stack_offset_1_min_2= + block_graph->block_graph_b_stack_top_offset + +block_graph->block_graph_end_b_stack_size + -next_block_graph->block_graph_begin_b_stack_size; + first_non_parameter_offset_1= + block_graph->block_graph_used_b_stack_elements + +block_graph->block_graph_b_stack_top_offset; + + /* + insert dummy graphs in the current block for elements for which a node + has been made in the next block, but will not be used any more + */ + + b_element_1_p=&block_graph->block_graph_b_stack; + b_element_1=*b_element_1_p; + + b_element_2=next_block_graph->block_graph_b_stack; + + first_non_parameter_offset_2=first_non_parameter_offset_1-stack_offset_1_min_2; + while (b_element_2!=NULL && b_element_2->b_stack_offset<first_non_parameter_offset_2) + b_element_2=b_element_2->b_stack_next; + + for (; b_element_2!=NULL; b_element_2=b_element_2->b_stack_next){ + INSTRUCTION_GRAPH load_graph; + + if (b_element_2->b_stack_flags & ELEMENT_MAY_BE_REMOVED || + ((load_graph=b_element_2->b_stack_load_graph)==NULL || + (!load_graph->node_mark && + !((load_graph->instruction_code==GFHIGH || + load_graph->instruction_code==GFLOW) && + load_graph->instruction_parameters[0].p->node_mark)))) + { + offset_1=b_element_2->b_stack_offset+stack_offset_1_min_2; + + while (b_element_1!=NULL && b_element_1->b_stack_offset<offset_1){ + b_element_1_p=&b_element_1->b_stack_next; + b_element_1=*b_element_1_p; + } + + if (b_element_1==NULL || b_element_1->b_stack_offset!=offset_1){ + register struct b_stack *new_element; + + /* printf ("%d ",offset_1); */ + + new_element=allocate_struct_from_heap (b_stack); + new_element->b_stack_offset=offset_1; + new_element->b_stack_flags=ELEMENT_MAY_BE_REMOVED; + new_element->b_stack_graph=NULL; + new_element->b_stack_load_graph=NULL; + + new_element->b_stack_next=b_element_1; + *b_element_1_p=new_element; + b_element_1_p=&new_element->b_stack_next; + } + } + } + + /* printf ("| "); */ + + /* + insert dummy graphs in the current block for elements for which are popped + from the stack in the next block + */ + + b_element_1_p=&block_graph->block_graph_b_stack; + b_element_1=*b_element_1_p; + + b_element_2=next_block_graph->block_graph_b_stack; + + offset_2=first_non_parameter_offset_2; + if (offset_2<0) + offset_2=0; + + for (; offset_2<next_block_graph->block_graph_b_stack_top_offset; ++offset_2){ + while (b_element_2!=NULL && b_element_2->b_stack_offset<offset_2) + b_element_2=b_element_2->b_stack_next; + if (b_element_2==NULL || b_element_2->b_stack_offset!=offset_2){ + offset_1=offset_2+stack_offset_1_min_2; + while (b_element_1!=NULL && b_element_1->b_stack_offset<offset_1){ + b_element_1_p=&b_element_1->b_stack_next; + b_element_1=*b_element_1_p; + } + if (b_element_1==NULL || b_element_1->b_stack_offset!=offset_1){ + register struct b_stack *new_element; + + /* printf ("%d ",offset_1); */ + + new_element=allocate_struct_from_heap (b_stack); + new_element->b_stack_offset=offset_1; + new_element->b_stack_flags=ELEMENT_MAY_BE_REMOVED; + new_element->b_stack_graph=NULL; + new_element->b_stack_load_graph=NULL; + + new_element->b_stack_next=b_element_1; + *b_element_1_p=new_element; + b_element_1_p=&new_element->b_stack_next; + } + } + } + + /* printf ("\n"); */ +} + +static void mark_stack_graphs_1 + (struct block_graph *block_graph,struct block_graph *next_block_graph,int jmp_jsr_or_rtn_flag) +{ + int stack_offset_difference,first_non_parameter_offset,offset; + struct b_stack *b_element_1,*b_element_2,**b_element_1_p; + struct a_stack *a_element; + int a_stack_top_offset,b_stack_top_offset; + + a_stack_top_offset=block_graph->block_graph_a_stack_top_offset; + a_element=block_graph->block_graph_a_stack; + + while (a_element!=NULL && a_element->a_stack_offset<a_stack_top_offset) + a_element=a_element->a_stack_next; + + for (; a_element!=NULL; a_element=a_element->a_stack_next) + if (a_element->a_stack_graph!=NULL) + mark_graph_2 (a_element->a_stack_graph); + + stack_offset_difference=block_graph->block_graph_b_stack_top_offset + +block_graph->block_graph_end_b_stack_size + -next_block_graph->block_graph_begin_b_stack_size; + first_non_parameter_offset=block_graph->block_graph_used_b_stack_elements + +block_graph->block_graph_b_stack_top_offset; + + /* + printf ("%d %d %d %d\n", + block_graph->block_graph_used_b_stack_elements, + block_graph->block_graph_b_stack_top_offset, + stack_offset_difference,first_non_parameter_offset); + */ + + b_element_2=next_block_graph->block_graph_b_stack; + + b_stack_top_offset=block_graph->block_graph_b_stack_top_offset; + b_element_1=block_graph->block_graph_b_stack; + + while (b_element_1!=NULL && b_element_1->b_stack_offset<b_stack_top_offset) + b_element_1=b_element_1->b_stack_next; + + for (; b_element_1!=NULL; b_element_1=b_element_1->b_stack_next) + if (b_element_1->b_stack_graph!=NULL){ + /* printf ("%d",b_element_1->b_stack_offset); */ + + if (b_element_1->b_stack_offset<first_non_parameter_offset){ + b_element_1->b_stack_flags|=ELEMENT_USED_BEFORE_JSR; + mark_graph_2 (b_element_1->b_stack_graph); + } else { + int required_offset; + + required_offset=b_element_1->b_stack_offset-stack_offset_difference; + + while (b_element_2!=NULL && b_element_2->b_stack_offset<required_offset) + b_element_2=b_element_2->b_stack_next; + + if (!jmp_jsr_or_rtn_flag || + block_graph->block_graph_kind!=JSR_EVAL_BLOCK || + (b_element_2!=NULL && b_element_2->b_stack_offset==required_offset + && b_element_2->b_stack_load_graph!=NULL + && (b_element_2->b_stack_load_graph->node_mark==2 || + ((b_element_2->b_stack_load_graph->instruction_code==GFHIGH + || b_element_2->b_stack_load_graph->instruction_code==GFLOW) + && b_element_2->b_stack_load_graph->instruction_parameters[0].p->node_mark==2)))) + { + b_element_1->b_stack_flags|=ELEMENT_USED_BEFORE_JSR; + mark_graph_2 (b_element_1->b_stack_graph); + } else { + mark_graph_1 (b_element_1->b_stack_graph); + /* printf ("*"); */ + } + } + /* printf (" "); */ + } + + if (block_graph->block_graph_kind==JSR_EVAL_BLOCK){ + b_element_1_p=&block_graph->block_graph_b_stack; + b_element_1=*b_element_1_p; + + for (b_element_2=next_block_graph->block_graph_b_stack; + b_element_2!=NULL; b_element_2=b_element_2->b_stack_next) + { + INSTRUCTION_GRAPH load_graph,next_load_graph,graph_1,next_graph_1; + struct b_stack *next_b_element_2,*next_b_element_1; + + load_graph=b_element_2->b_stack_load_graph; + if (load_graph!=NULL && + (load_graph->node_mark==2 || + ((load_graph->instruction_code==GFHIGH || load_graph->instruction_code==GFLOW) + && load_graph->instruction_parameters[0].p->node_mark==2)) && + (offset=b_element_2->b_stack_offset+stack_offset_difference)>=first_non_parameter_offset) + { + while (b_element_1!=NULL && b_element_1->b_stack_offset<offset){ + b_element_1_p=&b_element_1->b_stack_next; + b_element_1=*b_element_1_p; + } + + if (load_graph->instruction_code==GFHIGH && + (next_b_element_2=b_element_2->b_stack_next)!=NULL && + next_b_element_2->b_stack_offset==b_element_2->b_stack_offset+1 && + (next_load_graph=next_b_element_2->b_stack_load_graph)!=NULL && + next_load_graph->instruction_code==GFLOW && + next_load_graph->instruction_parameters[0].p==load_graph->instruction_parameters[0].p && + b_element_1!=NULL && b_element_1->b_stack_offset==offset && + (graph_1=b_element_1->b_stack_graph)!=NULL && + graph_1->instruction_code==GLOAD && + (next_b_element_1=b_element_1->b_stack_next)!=NULL && + next_b_element_1->b_stack_offset==offset+1 && + (next_graph_1=next_b_element_1->b_stack_graph)!=NULL && + next_graph_1->instruction_code==GLOAD && + graph_1->instruction_parameters[0].i+4==next_graph_1->instruction_parameters[0].i && + graph_1->instruction_parameters[1].i==next_graph_1->instruction_parameters[1].i) + { + INSTRUCTION_GRAPH f_graph; + + /* printf ("%d## ",offset); */ + + f_graph=g_fload + (graph_1->instruction_parameters[0].i,graph_1->instruction_parameters[1].i); + f_graph->node_mark=2; + + graph_1->instruction_code=GFHIGH; + graph_1->instruction_parameters[0].p=f_graph; +#ifdef g_fhighlow + graph_1->instruction_parameters[1].p=next_graph_1; +#endif + graph_1->node_mark=2; + + next_graph_1->instruction_code=GFLOW; + next_graph_1->instruction_parameters[0].p=f_graph; +#ifdef g_fhighlow + next_graph_1->instruction_parameters[1].p=graph_1; +#endif + next_graph_1->node_mark=2; + } else + if (b_element_1==NULL || b_element_1->b_stack_offset!=offset){ + if (load_graph->instruction_code==GFHIGH && + (next_b_element_2=b_element_2->b_stack_next)!=NULL && + next_b_element_2->b_stack_offset==b_element_2->b_stack_offset+1 && + (next_load_graph=next_b_element_2->b_stack_load_graph)!=NULL && + next_load_graph->instruction_code==GFLOW && + next_load_graph->instruction_parameters[0].p==load_graph->instruction_parameters[0].p && + (b_element_1==NULL || b_element_1->b_stack_offset!=offset+1)) + { + register struct b_stack *new_element; + INSTRUCTION_GRAPH f_graph,l_graph,h_graph; + + /* printf ("%d# ",offset); */ + + f_graph=g_fload + ((offset+block_graph->block_graph_b_stack_begin_displacement)<<2,B_STACK_POINTER); + f_graph->node_mark=2; + +#ifdef g_fhighlow + g_fhighlow (h_graph,l_graph,f_graph); +#else + h_graph=g_fhigh (f_graph); + l_graph=g_flow (f_graph); +#endif + h_graph->node_mark=2; + l_graph->node_mark=2; + + new_element=allocate_struct_from_heap (b_stack); + new_element->b_stack_offset=offset; + new_element->b_stack_flags=ELEMENT_USED_BEFORE_JSR; + new_element->b_stack_graph=h_graph; + new_element->b_stack_load_graph=h_graph; + + new_element->b_stack_next=b_element_1; + *b_element_1_p=new_element; + b_element_1_p=&new_element->b_stack_next; + + new_element=allocate_struct_from_heap (b_stack); + new_element->b_stack_offset=offset+1; + new_element->b_stack_flags=ELEMENT_USED_BEFORE_JSR; + new_element->b_stack_graph=l_graph; + new_element->b_stack_load_graph=l_graph; + + new_element->b_stack_next=b_element_1; + *b_element_1_p=new_element; + b_element_1_p=&new_element->b_stack_next; + + b_element_2=next_b_element_2; + } else { + register struct b_stack *new_element; + INSTRUCTION_GRAPH graph; + + /* printf ("%d ",offset); */ + + graph=g_load + ((offset+block_graph->block_graph_b_stack_begin_displacement)<<2,B_STACK_POINTER); + graph->node_mark=2; + + new_element=allocate_struct_from_heap (b_stack); + new_element->b_stack_offset=offset; + new_element->b_stack_flags=ELEMENT_USED_BEFORE_JSR; + new_element->b_stack_graph=graph; + new_element->b_stack_load_graph=graph; + + new_element->b_stack_next=b_element_1; + *b_element_1_p=new_element; + b_element_1_p=&new_element->b_stack_next; + } + } + } + } + } + + b_element_1_p=&block_graph->block_graph_b_stack; + b_element_1=*b_element_1_p; + + for (offset=block_graph->block_graph_b_stack_top_offset; offset<first_non_parameter_offset; ++offset){ + while (b_element_1!=NULL && b_element_1->b_stack_offset<offset){ + b_element_1_p=&b_element_1->b_stack_next; + b_element_1=*b_element_1_p; + } + + if (b_element_1==NULL || b_element_1->b_stack_offset!=offset){ + int n; + + n=offset-block_graph->block_graph_b_stack_top_offset; + + if ((unsigned)n < (unsigned)block_graph->block_graph_end_b_stack_size + && test_bit (block_graph->block_graph_end_stack_vector,n) + && (b_element_1==NULL || b_element_1->b_stack_offset!=offset+1) + && mc68881_flag) + { + register struct b_stack *new_element; + INSTRUCTION_GRAPH f_graph,l_graph,h_graph; + + /* printf ("%d$# ",offset); */ + + f_graph=g_fload + ((offset+block_graph->block_graph_b_stack_begin_displacement)<<2,B_STACK_POINTER); + f_graph->node_mark=2; +#ifdef g_fhighlow + g_fhighlow (h_graph,l_graph,f_graph); +#else + h_graph=g_fhigh (f_graph); + l_graph=g_flow (f_graph); +#endif + h_graph->node_mark=2; + l_graph->node_mark=2; + + new_element=allocate_struct_from_heap (b_stack); + new_element->b_stack_offset=offset; + new_element->b_stack_flags=ELEMENT_USED_BEFORE_JSR; + new_element->b_stack_graph=h_graph; + new_element->b_stack_load_graph=h_graph; + + new_element->b_stack_next=b_element_1; + *b_element_1_p=new_element; + b_element_1_p=&new_element->b_stack_next; + + new_element=allocate_struct_from_heap (b_stack); + new_element->b_stack_offset=offset+1; + new_element->b_stack_flags=ELEMENT_USED_BEFORE_JSR; + new_element->b_stack_graph=l_graph; + new_element->b_stack_load_graph=l_graph; + + new_element->b_stack_next=b_element_1; + *b_element_1_p=new_element; + b_element_1_p=&new_element->b_stack_next; + + ++offset; + } else { + register struct b_stack *new_element; + INSTRUCTION_GRAPH graph; + + /* printf ("%d$ ",offset); */ + + graph=g_load + ((offset+block_graph->block_graph_b_stack_begin_displacement)<<2,B_STACK_POINTER); + graph->node_mark=2; + + new_element=allocate_struct_from_heap (b_stack); + new_element->b_stack_offset=offset; + new_element->b_stack_flags=ELEMENT_USED_BEFORE_JSR; + new_element->b_stack_graph=graph; + new_element->b_stack_load_graph=graph; + + new_element->b_stack_next=b_element_1; + *b_element_1_p=new_element; + b_element_1_p=&new_element->b_stack_next; + } + } + } + + /* printf ("\n"); */ +} + +static void mark_stack_graphs_2 (struct block_graph *block_graph) +{ + struct a_stack *a_element; + struct b_stack *b_element; + int a_stack_top_offset,b_stack_top_offset; + + a_stack_top_offset=block_graph->block_graph_a_stack_top_offset; + + a_element=block_graph->block_graph_a_stack; + + while (a_element!=NULL && a_element->a_stack_offset<a_stack_top_offset) + a_element=a_element->a_stack_next; + + for (; a_element!=NULL; a_element=a_element->a_stack_next) + if (a_element->a_stack_graph!=NULL) + mark_graph_2 (a_element->a_stack_graph); + + b_stack_top_offset=block_graph->block_graph_b_stack_top_offset; + + b_element=block_graph->block_graph_b_stack; + while (b_element!=NULL && b_element->b_stack_offset<b_stack_top_offset) + b_element=b_element->b_stack_next; + + for (; b_element!=NULL; b_element=b_element->b_stack_next) + if (b_element->b_stack_graph!=NULL){ + b_element->b_stack_flags|=ELEMENT_USED_BEFORE_JSR; + mark_graph_2 (b_element->b_stack_graph); + } +} + +#ifndef M68000 +extern LONG offset_from_heap_register; +#endif +#ifdef G_POWER +extern LONG heap_pointer_offset_in_basic_block; +#endif + +static void allocate_registers (void) +{ + int n; + + free_all_aregisters(); + free_all_dregisters(); + free_all_fregisters(); + + for (n=0; n<N_ADDRESS_PARAMETER_REGISTERS; ++n){ + INSTRUCTION_GRAPH register_graph; + + register_graph=global_block.block_graph_a_register_parameter_node[n]; + if (register_graph!=NULL && register_graph->node_count>0) + allocate_aregister (register_graph->instruction_parameters[0].i); + } + + for (n=0; n<N_DATA_PARAMETER_REGISTERS +#ifdef MORE_PARAMETER_REGISTERS + + N_ADDRESS_PARAMETER_REGISTERS +#endif + ; ++n){ + INSTRUCTION_GRAPH register_graph; + + register_graph=global_block.block_graph_d_register_parameter_node[n]; + + if (register_graph!=NULL && register_graph->node_count>0) + allocate_dregister (register_graph->instruction_parameters[0].i); + } + + if (mc68881_flag) + for (n=0; n<N_FLOAT_PARAMETER_REGISTERS; ++n){ + INSTRUCTION_GRAPH register_graph; + + register_graph=global_block.block_graph_f_register_parameter_node[n]; + + if (register_graph!=NULL && register_graph->node_count>0) + allocate_fregister (register_graph->instruction_parameters[0].i); + } +} + +static void calculate_and_linearize_graphs (int n_elements,INSTRUCTION_GRAPH graphs[]) +{ + int n; + + local_data_offset= + (global_block.block_graph_b_stack_top_offset+ + global_block.block_graph_b_stack_begin_displacement+ + global_block.block_graph_b_stack_end_displacement)<<2; + if (local_data_offset>0) + local_data_offset=0; + + for (n=0; n<n_elements; ++n){ + INSTRUCTION_GRAPH a_graph; + + a_graph=graphs[n]; + + if (a_graph->instruction_code!=GFILL) + count_graph (a_graph); + else { + int n; + + for (n=0; n<a_graph->inode_arity; ++n) + if (a_graph->instruction_parameters[n].p!=NULL) + count_graph (a_graph->instruction_parameters[n].p); + } + } + + allocate_registers(); + + for (n=0; n<n_elements; ++n) + calculate_graph_register_uses (graphs[n]); + +#ifndef M68000 + offset_from_heap_register=0; +#endif +#ifdef G_POWER + heap_pointer_offset_in_basic_block=0; +#endif + + evaluate_arguments_and_free_addresses ((union instruction_parameter*)graphs,n_elements); + +#ifndef M68000 + if (offset_from_heap_register!=0) +# ifdef G_POWER + optimize_heap_pointer_increment (last_block,offset_from_heap_register); +# else + i_add_i_r (offset_from_heap_register,HEAP_POINTER); +# endif +#endif +} + +static int allocate_and_fill_graph_array (INSTRUCTION_GRAPH **graphs_p) +{ + int element_n,n_a_elements,n_b_elements; + struct a_stack *a_element; + struct b_stack *b_element; + INSTRUCTION_GRAPH *graphs; + + n_a_elements=0; + for_l (a_element,global_block.block_graph_a_stack,a_stack_next) + if (a_element->a_stack_graph!=NULL) + ++n_a_elements; + + n_b_elements=0; + for_l (b_element,global_block.block_graph_b_stack,b_stack_next) + if (b_element->b_stack_graph!=NULL) + ++n_b_elements; + + if (n_a_elements+n_b_elements==0){ + *graphs_p=NULL; + return 0; + } + + graphs=(INSTRUCTION_GRAPH*)memory_allocate (sizeof (INSTRUCTION_GRAPH) * (n_a_elements+n_b_elements)); + *graphs_p=graphs; + + if (global_block.block_graph_a_stack_top_offset+ + global_block.block_graph_a_stack_begin_displacement+ + global_block.block_graph_a_stack_end_displacement<=0) + { + element_n=n_a_elements+n_b_elements; + for_l (a_element,global_block.block_graph_a_stack,a_stack_next) + if (a_element->a_stack_graph!=NULL) + graphs[--element_n]=a_element->a_stack_graph; + } else { + element_n=n_b_elements; + for_l (a_element,global_block.block_graph_a_stack,a_stack_next) + if (a_element->a_stack_graph!=NULL) + graphs[element_n++]=a_element->a_stack_graph; + } + + if (global_block.block_graph_b_stack_top_offset+ + global_block.block_graph_b_stack_begin_displacement+ + global_block.block_graph_b_stack_end_displacement<=0) + { + element_n=n_b_elements; + for_l (b_element,global_block.block_graph_b_stack,b_stack_next) + if (b_element->b_stack_graph!=NULL) + graphs[--element_n]=b_element->b_stack_graph; + } else { + element_n=0; + for_l (b_element,global_block.block_graph_b_stack,b_stack_next) + if (b_element->b_stack_graph!=NULL) + graphs[element_n++]=b_element->b_stack_graph; + } + + return n_a_elements+n_b_elements; +} + +void linearize_stack_graphs (VOID) +{ + int n_elements; + INSTRUCTION_GRAPH *graphs; + + n_elements=allocate_and_fill_graph_array (&graphs); + + if (graphs!=NULL){ + calculate_and_linearize_graphs (n_elements,graphs); + + memory_free (graphs); + } else + allocate_registers(); +} + +void linearize_stack_graphs_with_overflow_test (INSTRUCTION_GRAPH test_overflow_graph,INSTRUCTION_GRAPH store_calculate_with_overflow_graph) +{ + int n_elements; + INSTRUCTION_GRAPH *graphs; + + count_graph (store_calculate_with_overflow_graph); + + n_elements=allocate_and_fill_graph_array (&graphs); + + if (graphs!=NULL){ + int n; + + local_data_offset= (global_block.block_graph_b_stack_top_offset+ + global_block.block_graph_b_stack_begin_displacement+ + global_block.block_graph_b_stack_end_displacement)<<2; + if (local_data_offset>0) + local_data_offset=0; + + for (n=0; n<n_elements; ++n){ + INSTRUCTION_GRAPH a_graph; + + a_graph=graphs[n]; + + if (a_graph->instruction_code!=GFILL) + count_graph (a_graph); + else { + int n; + + for (n=0; n<a_graph->inode_arity; ++n) + if (a_graph->instruction_parameters[n].p!=NULL) + count_graph (a_graph->instruction_parameters[n].p); + } + } + } + + if (test_overflow_graph->node_count==1 && store_calculate_with_overflow_graph->node_count==1 + && (store_calculate_with_overflow_graph->instruction_code==GSTORE_R + ? store_calculate_with_overflow_graph->instruction_parameters[1].p->node_count==2 + : store_calculate_with_overflow_graph->instruction_parameters[2].p->node_count==2)) + { + test_overflow_graph->node_count=0; + if (store_calculate_with_overflow_graph->instruction_code==GSTORE_R) + store_calculate_with_overflow_graph->instruction_parameters[1].p->node_count=1; + else + store_calculate_with_overflow_graph->instruction_parameters[2].p->node_count=1; + } + + allocate_registers(); + + if (graphs!=NULL){ + int n; + + for (n=0; n<n_elements; ++n) + calculate_graph_register_uses (graphs[n]); + +#ifndef M68000 + offset_from_heap_register=0; +#endif +#ifdef G_POWER + heap_pointer_offset_in_basic_block=0; +#endif + + evaluate_arguments_and_free_addresses ((union instruction_parameter*)graphs,n_elements); + +#ifndef M68000 + if (offset_from_heap_register!=0) +# ifdef G_POWER + optimize_heap_pointer_increment (last_block,offset_from_heap_register); +# else + i_add_i_r (offset_from_heap_register,HEAP_POINTER); +# endif +#endif + + memory_free (graphs); + } + + calculate_and_linearize_graph (store_calculate_with_overflow_graph); +} + +INSTRUCTION_GRAPH search_and_remove_graph_from_b_stack (INSTRUCTION_GRAPH calculate_with_overflow_graph) +{ + struct b_stack *b_element; + + for_l (b_element,global_block.block_graph_b_stack,b_stack_next){ + INSTRUCTION_GRAPH stack_graph; + + stack_graph=b_element->b_stack_graph; + if (stack_graph!=NULL && + ((stack_graph->instruction_code==GSTORE_R && stack_graph->instruction_parameters[1].p==calculate_with_overflow_graph) + || (stack_graph->instruction_code==GSTORE && stack_graph->instruction_parameters[2].p==calculate_with_overflow_graph))) + { + b_element->b_stack_graph=NULL; + return stack_graph; + } + } + + return NULL; +} + +static int block_check; +#ifdef SEPARATE_A_AND_B_STACK_OVERFLOW_CHECKS +int block_a_stack_displacement,block_b_stack_displacement; +static WORD *a_check_size_p,*b_check_size_p; +#else +int block_stack_displacement; +static WORD *check_size_p; +#endif + +static int stack_access_and_adjust_a_stack_pointer (int extra_b_offset) +{ + int a_offset,b_offset,minimum_b_offset; + + a_offset=-( global_block.block_graph_a_stack_top_offset+ + global_block.block_graph_a_stack_begin_displacement+ + global_block.block_graph_a_stack_end_displacement)<<2; + b_offset=( global_block.block_graph_b_stack_top_offset+ + global_block.block_graph_b_stack_begin_displacement+ + global_block.block_graph_b_stack_end_displacement)<<2; + + minimum_b_offset= local_data_offset<b_offset ? local_data_offset : b_offset; + + if (block_check){ +#ifdef SEPARATE_A_AND_B_STACK_OVERFLOW_CHECKS + int a_check_size,b_check_size; + + if (last_block_graph!=NULL){ + last_block_graph->block_graph_a_stack_displacement=a_offset; + last_block_graph->block_graph_b_stack_displacement=b_offset; + } + + if (a_check_size_p==NULL){ + a_check_size=a_offset>0 ? a_offset : 0; + b_check_size=minimum_b_offset<0 ? -b_offset : 0; + + a_check_size_p=&last_block->block_a_stack_check_size; + b_check_size_p=&last_block->block_b_stack_check_size; + *a_check_size_p=a_check_size; + *b_check_size_p=b_check_size; + block_a_stack_displacement=a_offset; + block_b_stack_displacement=-b_offset; + } else { + a_check_size=block_a_stack_displacement+(a_offset>0 ? a_offset : 0); + b_check_size=block_b_stack_displacement+(minimum_b_offset<0 ? -b_offset : 0); + if (a_check_size>*a_check_size_p) + *a_check_size_p=a_check_size; + if (b_check_size>*b_check_size_p) + *b_check_size_p=b_check_size; + block_a_stack_displacement+=a_offset; + block_b_stack_displacement-=b_offset; + } + } else { + last_block->block_a_stack_check_size=a_offset>0 ? a_offset : 0; + last_block->block_b_stack_check_size=minimum_b_offset<0 ? -b_offset : 0; + } +#else + int check_size; + + if (last_block_graph!=NULL) + last_block_graph->block_graph_stack_displacement=a_offset+b_offset; + + if (check_size_p==NULL){ + check_size=(minimum_b_offset<0 ? -b_offset : 0) + (a_offset>0 ? a_offset : 0); + + check_size_p=&last_block->block_stack_check_size; + *check_size_p=check_size; + block_stack_displacement=a_offset-b_offset; + } else { + check_size=block_stack_displacement+(minimum_b_offset<0 ? -b_offset : 0) + (a_offset>0 ? a_offset : 0); + if (check_size>*check_size_p) + *check_size_p=check_size; + block_stack_displacement+=a_offset-b_offset; + } + } else + last_block->block_stack_check_size=(minimum_b_offset<0 ? -b_offset : 0) + (a_offset>0 ? a_offset : 0); +#endif + + b_offset+=extra_b_offset; + +#if defined (M68000) || defined (I486) || defined (G_POWER) + optimize_stack_access (last_block,&a_offset,&b_offset); +#endif + + if (a_offset!=0) +#ifdef I486 + i_lea_id_r (a_offset,A_STACK_POINTER,A_STACK_POINTER); +#else + if (a_offset>0) + i_add_i_r (a_offset,A_STACK_POINTER); + else + i_sub_i_r (-a_offset,A_STACK_POINTER); +#endif + + return b_offset; +} + +static void stack_access (void) +{ + register int b_offset; + + b_offset=stack_access_and_adjust_a_stack_pointer (0); + + if (b_offset!=0) +#ifdef I486 + i_lea_id_r (b_offset,B_STACK_POINTER,B_STACK_POINTER); +#else + if (b_offset>0) + i_add_i_r (b_offset,B_STACK_POINTER); + else + i_sub_i_r (-b_offset,B_STACK_POINTER); +#endif +} + +static int local_register_allocation_and_adjust_a_stack_pointer (int extra_b_offset) +{ + int n_virtual_a_regs,n_virtual_d_regs,n_virtual_f_regs; + + get_n_virtual_registers (&n_virtual_a_regs,&n_virtual_d_regs,&n_virtual_f_regs); + do_register_allocation (last_instruction,last_block,n_virtual_a_regs,n_virtual_d_regs,n_virtual_f_regs,0,0); + return stack_access_and_adjust_a_stack_pointer (extra_b_offset); +} + +void adjust_stack_pointers (void) +{ + int n_virtual_a_regs,n_virtual_d_regs,n_virtual_f_regs; + + get_n_virtual_registers (&n_virtual_a_regs,&n_virtual_d_regs,&n_virtual_f_regs); + do_register_allocation (last_instruction,last_block,n_virtual_a_regs,n_virtual_d_regs,n_virtual_f_regs,0,0); + stack_access(); +} + +int adjust_stack_pointers_without_altering_condition_codes (int float_condition,int condition) +{ + int n_virtual_a_regs,n_virtual_d_regs,n_virtual_f_regs,condition_on_stack; + + get_n_virtual_registers (&n_virtual_a_regs,&n_virtual_d_regs,&n_virtual_f_regs); + condition_on_stack=do_register_allocation (last_instruction,last_block,n_virtual_a_regs,n_virtual_d_regs,n_virtual_f_regs,1+float_condition,condition); + stack_access(); + return condition_on_stack; +} + +struct basic_block *allocate_empty_basic_block (VOID) +{ + register struct basic_block *block; + + block=(struct basic_block*)fast_memory_allocate (sizeof (struct basic_block)); + block->block_next=NULL; + block->block_instructions=NULL; + block->block_last_instruction=NULL; + block->block_labels=NULL; + block->block_n_new_heap_cells=0; + block->block_n_begin_a_parameter_registers=0; + block->block_n_begin_d_parameter_registers=0; + block->block_n_node_arguments=-100; +#ifdef SEPARATE_A_AND_B_STACK_OVERFLOW_CHECKS + block->block_a_stack_check_size=0; + block->block_b_stack_check_size=0; +#else + block->block_stack_check_size=0; +#endif + block->block_begin_module=0; + block->block_profile=0; +#ifdef G_POWER + block->block_gc_kind=0; +#endif + + return block; +} + +#ifdef G_POWER +# define SMALLER_EVAL +#endif + +#ifdef M68000 +static int +#else +static void +#endif +generate_code_for_jsr_eval (int n_a_registers,int n_d_registers,int n_f_registers,int offset) +{ + int n,node_a_register; + struct basic_block *new_block; +#ifdef M68000 + int code_size; +#endif + +#if defined (sparc) || defined (I486) || defined (G_POWER) + int a_offset,b_offset; +#else + static int d_registers[]={ + REGISTER_D0,REGISTER_D1,REGISTER_D2,REGISTER_D3,REGISTER_D4, + REGISTER_D5,REGISTER_D6 + }; +#endif + + node_a_register=n_a_registers-offset-1; + + last_instruction=NULL; + + new_block=allocate_empty_basic_block(); + + new_block->block_n_begin_a_parameter_registers=n_a_registers; + new_block->block_n_begin_d_parameter_registers=n_d_registers+1; +#ifdef SEPARATE_A_AND_B_STACK_OVERFLOW_CHECKS + new_block->block_a_stack_check_size=(n_a_registers)<<2; + new_block->block_b_stack_check_size=(n_d_registers<<2) + (n_f_registers<<3); +#else + new_block->block_stack_check_size=((n_a_registers+n_d_registers)<<2) + (n_f_registers<<3); +#endif + + new_block->block_next=last_block->block_next; + last_block->block_next=new_block; + last_block=new_block; + +#ifdef M68000 + code_size=0; + for (n=n_a_registers-1; n>=0; --n) + if (n!=node_a_register){ + i_move_r_pi (num_to_a_reg (n),A_STACK_POINTER); + code_size+=2; + } +#else + a_offset=0; +# ifdef SMALLER_EVAL + if (n_a_registers>1) + i_mtctr (num_to_d_reg (n_d_registers)); +# else + for (n=n_a_registers-1; n>=0; --n) + if (n!=node_a_register){ + i_move_r_id (num_to_a_reg (n),a_offset,A_STACK_POINTER); + a_offset+=4; + } + if (a_offset>0) + i_add_i_r (a_offset,A_STACK_POINTER); +# endif +#endif + +#ifndef SMALLER_EVAL + if (node_a_register!=0){ + i_move_r_r (num_to_a_reg (node_a_register),REGISTER_A0); +# ifdef M68000 + code_size+=2; +# endif + } +#endif + +#ifdef M68000 + if (n_d_registers>=4){ + i_movem_pd (B_STACK_POINTER,n_d_registers,d_registers); + code_size+=4; + } else + for (n=0; n<n_d_registers; ++n){ + i_move_r_pd (num_to_d_reg (n),B_STACK_POINTER); + code_size+=2; + } +#else + b_offset=0; +# ifdef I486 + for (n=0; n<n_d_registers; ++n) + i_move_r_pd (num_to_d_reg (n),B_STACK_POINTER); +# else + for (n=0; n<n_d_registers; ++n){ + b_offset+=4; + i_move_r_id (num_to_d_reg (n),-b_offset,B_STACK_POINTER); + } +# endif +#endif + +#ifdef M68000 + for (n=0; n<n_f_registers; ++n){ + i_fmove_fr_pd (n,B_STACK_POINTER); + code_size+=4; + } +#else + for (n=0; n<n_f_registers; ++n){ + b_offset+=8; + i_fmove_fr_id (n,-b_offset,B_STACK_POINTER); + } +# ifdef I486 + if (b_offset) + i_sub_i_r (b_offset,B_STACK_POINTER); +# else +# if !defined (G_POWER) + i_sub_i_r (b_offset+4,B_STACK_POINTER); +# endif +# endif +#endif + +#ifdef M68000 + i_move_r_r (num_to_d_reg (n_d_registers),REGISTER_A1); + i_jsr_id (0,REGISTER_A1,256); + code_size+=4; +#else +# if defined (I486) + i_jsr_id (0,num_to_a_reg (node_a_register),0); +# else +# if defined (G_POWER) +# ifdef SMALLER_EVAL + if (n_a_registers>1){ + struct label *eval_label; + + if (n_a_registers==2) + eval_label = node_a_register==0 ? eval_01_label : eval_11_label; + else + eval_label = node_a_register==0 ? eval_02_label : node_a_register==1 ? eval_12_label : eval_22_label; + + i_jsr_l_idu (eval_label,-(b_offset+4)); + } else +# endif + i_jsr_id_idu (0,num_to_d_reg (n_d_registers),-(b_offset+4)); +# else + i_jsr_id_id (0,num_to_d_reg (n_d_registers),0); +# endif +# endif +#endif + +#ifdef M68000 + for (n=n_f_registers-1; n>=0; --n){ + i_fmove_pi_fr (B_STACK_POINTER,n); + code_size+=4; + } +#else + offset=0; + for (n=n_f_registers-1; n>=0; --n){ + i_fmove_id_fr (-offset,B_STACK_POINTER,n); + offset-=8; + } +#endif + +#ifdef M68000 + if (n_d_registers>=4){ + i_movem_pi (B_STACK_POINTER,n_d_registers,d_registers); + code_size+=4; + } else + for (n=n_d_registers-1; n>=0; --n){ + i_move_pi_r (B_STACK_POINTER,num_to_d_reg (n)); + code_size+=2; + } +#else +# ifdef I486 + if (b_offset>0) + i_add_i_r (b_offset,B_STACK_POINTER); + for (n=n_d_registers-1; n>=0; --n) + i_move_pi_r (B_STACK_POINTER,num_to_d_reg (n)); +# else + for (n=n_d_registers-1; n>=0; --n){ + i_move_id_r (-offset,B_STACK_POINTER,num_to_d_reg (n)); + offset-=4; + } + if (b_offset>0) + i_add_i_r (b_offset,B_STACK_POINTER); +# endif +#endif + + if (node_a_register!=0){ + i_move_r_r (REGISTER_A0,num_to_a_reg (node_a_register)); +#ifdef M68000 + code_size+=2; +#endif + } + +#ifdef M68000 + for (n=0; n<n_a_registers; ++n) + if (n!=node_a_register){ + i_move_pd_r (A_STACK_POINTER,num_to_a_reg (n)); + code_size+=2; + } +#else + offset=0; +# ifdef G_POWER + { + int last_a_register; + + last_a_register=n_a_registers-1; + if (last_a_register==node_a_register) + --last_a_register; + + for (n=0; n<n_a_registers; ++n) + if (n!=node_a_register){ + offset-=4; + if (n==last_a_register) + i_move_idu_r (offset,A_STACK_POINTER,num_to_a_reg (n)); + else + i_move_id_r (offset,A_STACK_POINTER,num_to_a_reg (n)); + } + } +# else + for (n=0; n<n_a_registers; ++n) + if (n!=node_a_register){ + offset-=4; + i_move_id_r (offset,A_STACK_POINTER,num_to_a_reg (n)); + } + if (a_offset>0) + i_sub_i_r (a_offset,A_STACK_POINTER); +#endif +#endif + +#ifdef M68000 + return code_size; +#endif +} + +static void generate_code_for_basic_block (struct block_graph *next_block_graph) +{ + register struct block_graph *block_graph; + struct basic_block *old_last_block; + struct instruction *block_instructions,*block_last_instruction; + int n_allocated_d_regs,n_allocated_f_regs,n_data_parameter_registers; + int end_b_stack_size; + ULONG *vector; +#ifdef M68000 + LONG *branch_offset_p; +#endif + + old_last_block=last_block; + + block_graph=last_block_graph; + /* + last_block_graph=block_graph->block_graph_previous; + if (last_block_graph!=NULL) + last_block_graph->block_graph_next=NULL; + else + first_block_graph=NULL; + */ + + last_block=block_graph->block_graph_block; + + block_instructions=last_block->block_instructions; + block_last_instruction=last_block->block_last_instruction; + + last_block->block_instructions=NULL; + last_block->block_last_instruction=NULL; + last_instruction=NULL; + + global_block=*block_graph; + if (global_block.block_graph_end_b_stack_size<=VECTOR_ELEMENT_SIZE){ + global_block.block_graph_small_end_stack_vector = *global_block.block_graph_end_stack_vector; + global_block.block_graph_end_stack_vector = &global_block.block_graph_small_end_stack_vector; + } + + n_data_parameter_registers = +#ifndef I486 + block_graph->block_graph_kind==JSR_EVAL_BLOCK ? N_DATA_PARAMETER_REGISTERS-1 : +#endif + N_DATA_PARAMETER_REGISTERS; + + if (parallel_flag) + --n_data_parameter_registers; + + end_b_stack_size=block_graph->block_graph_end_b_stack_size; + if (block_graph->block_graph_kind==JSR_BLOCK +#ifdef G_POWER + || block_graph->block_graph_kind==JSR_BLOCK_WITH_INSTRUCTIONS +#endif + ) + --end_b_stack_size; + + a_stack_load_register_values (block_graph->block_graph_end_a_stack_size,N_ADDRESS_PARAMETER_REGISTERS); + b_stack_load_register_values (end_b_stack_size,block_graph->block_graph_end_stack_vector,n_data_parameter_registers +#ifdef MORE_PARAMETER_REGISTERS + ,N_ADDRESS_PARAMETER_REGISTERS-block_graph->block_graph_end_a_stack_size +#endif + ); + + a_stack_stores (block_graph->block_graph_end_a_stack_size,N_ADDRESS_PARAMETER_REGISTERS); + b_stack_stores (end_b_stack_size,block_graph->block_graph_end_stack_vector,n_data_parameter_registers +#ifdef MORE_PARAMETER_REGISTERS + ,N_ADDRESS_PARAMETER_REGISTERS-block_graph->block_graph_end_a_stack_size, + block_graph->block_graph_a_register_parameter_node,block_graph->block_graph_d_register_parameter_node +#endif + ); + + linearize_stack_graphs(); + + switch (block_graph->block_graph_kind){ + case JSR_EVAL_BLOCK: + { + register int n,b_stack_size,n_data_parameter_registers; + + n_data_parameter_registers = parallel_flag ? N_DATA_PARAMETER_REGISTERS-1 : N_DATA_PARAMETER_REGISTERS; + + adjust_stack_pointers(); + + vector=block_graph->block_graph_end_stack_vector; + b_stack_size=block_graph->block_graph_end_b_stack_size; + + n_allocated_d_regs=0; + n_allocated_f_regs=0; + + for (n=0; n<b_stack_size; ++n) + if (!test_bit (vector,n)){ +#ifdef I486 + if (n_allocated_d_regs<n_data_parameter_registers) +#else + if (n_allocated_d_regs<n_data_parameter_registers-1) +#endif + ++n_allocated_d_regs; + } else { + if (n_allocated_f_regs<N_FLOAT_PARAMETER_REGISTERS && mc68881_flag) + ++n_allocated_f_regs; + ++n; + } +#ifdef I486 + i_btst_i_id (2,0,num_to_a_reg (block_graph->block_graph_end_a_stack_size + -block_graph->block_graph_jsr_eval_offset-1)); + i_bne_l (block_graph->block_graph_last_instruction_label); +#else + i_move_id_r (0-NODE_POINTER_OFFSET,num_to_a_reg (block_graph->block_graph_end_a_stack_size + -block_graph->block_graph_jsr_eval_offset-1), + num_to_d_reg (n_allocated_d_regs)); +# ifdef M68000 + if (check_stack || parallel_flag) + i_bmi_l (block_graph->block_graph_last_instruction_label); + else + branch_offset_p=i_bmi_i(); +# else + i_btst_i_r (2,num_to_d_reg (n_allocated_d_regs)); +# ifdef G_POWER + i_bnep_l (block_graph->block_graph_last_instruction_label); +# else + i_bne_l (block_graph->block_graph_last_instruction_label); +# endif +# endif +#endif + break; + } +#ifdef G_POWER + case JSR_BLOCK_WITH_INSTRUCTIONS: + if (block_last_instruction!=NULL){ + if (last_block->block_instructions!=NULL) + last_instruction->instruction_next=block_instructions; + else + last_block->block_instructions=block_instructions; + + last_block->block_last_instruction=block_last_instruction; + last_instruction=block_last_instruction; + block_last_instruction=NULL; + } + /* no break */ +#endif + case JSR_BLOCK: + { + register int b_offset; + +#if ! (defined (sparc) || defined (G_POWER)) + b_offset=local_register_allocation_and_adjust_a_stack_pointer + (end_b_stack_size==global_block.block_graph_b_stack_end_displacement ? 4 : 0); +#else + b_offset=local_register_allocation_and_adjust_a_stack_pointer (0); +#endif + +#ifdef G_POWER + { + int return_offset; + + return_offset = (end_b_stack_size-global_block.block_graph_b_stack_end_displacement)<<2; + + if (return_offset==0 && b_offset!=0) + i_jsr_l_idu (block_graph->block_graph_last_instruction_label,b_offset); + else { + if (b_offset!=0) + if (b_offset<0) + i_sub_i_r (-b_offset,B_STACK_POINTER); + else + i_add_i_r (b_offset,B_STACK_POINTER); + i_jsr_l_id (block_graph->block_graph_last_instruction_label,return_offset); + } + } +#else + if (b_offset!=0) +# ifdef I486 + i_lea_id_r (b_offset,B_STACK_POINTER,B_STACK_POINTER); +# else + if (b_offset<0) + i_sub_i_r (-b_offset,B_STACK_POINTER); + else + i_add_i_r (b_offset,B_STACK_POINTER); +# endif + +# if ! defined (sparc) + { + int n_a_and_f_registers,n_a_registers; + + n_a_and_f_registers=0; + + if (mc68881_flag){ + int parameter_n; + ULONG *vector; + + vector=block_graph->block_graph_end_stack_vector; + + for (parameter_n=0; parameter_n<end_b_stack_size; ++parameter_n) + if (test_bit (vector,parameter_n)) + if (n_a_and_f_registers<N_FLOAT_PARAMETER_REGISTERS){ + ++n_a_and_f_registers; + ++parameter_n; + } else + break; + } + + n_a_registers=block_graph->block_graph_end_a_stack_size; + if (n_a_registers>N_ADDRESS_PARAMETER_REGISTERS) + n_a_registers=N_ADDRESS_PARAMETER_REGISTERS; + n_a_and_f_registers+=n_a_registers<<4; + + if (end_b_stack_size!=global_block.block_graph_b_stack_end_displacement) + i_jmp_l (block_graph->block_graph_last_instruction_label,n_a_and_f_registers); + else + i_jsr_l (block_graph->block_graph_last_instruction_label,n_a_and_f_registers); + } +# else + i_jsr_l_id (block_graph->block_graph_last_instruction_label, + (end_b_stack_size-global_block.block_graph_b_stack_end_displacement)<<2); +# endif +#endif + if (block_check){ +#ifdef SEPARATE_A_AND_B_STACK_OVERFLOW_CHECKS + int a_stack_change,b_stack_change; + + a_stack_change= + (next_block_graph->block_graph_begin_a_stack_size+ + next_block_graph->block_graph_a_stack_begin_displacement)- + (block_graph->block_graph_end_a_stack_size- + block_graph->block_graph_a_stack_end_displacement); + b_stack_change= + (next_block_graph->block_graph_begin_b_stack_size+ + next_block_graph->block_graph_b_stack_begin_displacement)- + (block_graph->block_graph_end_b_stack_size- + block_graph->block_graph_b_stack_end_displacement); + block_a_stack_displacement+=a_stack_change<<2; + block_b_stack_displacement+=b_stack_change<<2; + block_graph->block_graph_a_stack_displacement+=a_stack_change<<2; + block_graph->block_graph_b_stack_displacement+=b_stack_change<<2; +#else + int stack_change; + + stack_change= + (next_block_graph->block_graph_begin_a_stack_size+ + next_block_graph->block_graph_a_stack_begin_displacement)- + (block_graph->block_graph_end_a_stack_size- + block_graph->block_graph_a_stack_end_displacement)+ + (next_block_graph->block_graph_begin_b_stack_size+ + next_block_graph->block_graph_b_stack_begin_displacement)- + (block_graph->block_graph_end_b_stack_size- + block_graph->block_graph_b_stack_end_displacement); + block_stack_displacement+=stack_change<<2; + block_graph->block_graph_stack_displacement+=stack_change<<2; +#endif + } + + break; + } + case APPLY_BLOCK: + { + register int b_offset; + +#if defined (sparc) || defined (G_POWER) + b_offset=local_register_allocation_and_adjust_a_stack_pointer (-4); +#else + b_offset=local_register_allocation_and_adjust_a_stack_pointer (0); +#endif + + if (b_offset!=0) + if (b_offset<0) + i_sub_i_r (-b_offset,B_STACK_POINTER); + else + i_add_i_r (b_offset,B_STACK_POINTER); + +#if defined (I486) + i_move_id_r (0,REGISTER_A1,REGISTER_A2); + i_jsr_id (4-2,REGISTER_A2,0); +#else +# ifdef M68000 +# if !defined (SUN) + i_add_r_r (GLOBAL_DATA_REGISTER,REGISTER_A2); +# endif + i_jsr_id (0,REGISTER_A2,2<<4); +# else + i_jsr_id_id (0,REGISTER_A2,0); +# endif +#endif + break; + } + default: + internal_error_in_function ("generate_code_for_basic_block"); + } + + if (block_last_instruction!=NULL){ + if (last_block->block_instructions!=NULL){ + last_instruction->instruction_next=block_instructions; + last_block->block_last_instruction=block_last_instruction; + } else { + last_block->block_instructions=block_instructions; + last_block->block_last_instruction=block_last_instruction; + } + } else + last_block->block_last_instruction=last_instruction; + + if (block_graph->block_graph_kind==JSR_EVAL_BLOCK) +#ifdef M68000 + if (!check_stack && !parallel_flag){ + *branch_offset_p + = generate_code_for_jsr_eval (block_graph->block_graph_end_a_stack_size,n_allocated_d_regs, + n_allocated_f_regs,block_graph->block_graph_jsr_eval_offset); + } else +#endif + generate_code_for_jsr_eval + (block_graph->block_graph_end_a_stack_size,n_allocated_d_regs, + n_allocated_f_regs,block_graph->block_graph_jsr_eval_offset); + + last_block=old_last_block; +} + +static int optimize_jsr_eval (struct block_graph *block_graph,int a_stack_size,struct block_graph *next_block_graph) +{ + struct a_stack *a_element,*a_element_0; + struct a_stack *begin_a_element; + int offset,n; + INSTRUCTION_GRAPH graph; + + offset=block_graph->block_graph_a_stack_top_offset; + + a_element=block_graph->block_graph_a_stack; + while (a_element!=NULL && a_element->a_stack_offset<offset) + a_element=a_element->a_stack_next; + + if (a_element==NULL || a_element->a_stack_offset!=offset) + return a_stack_size; + + a_element_0=a_element; + graph=a_element->a_stack_graph; + + begin_a_element=next_block_graph->block_graph_a_stack; + while (begin_a_element!=NULL && begin_a_element->a_stack_offset<0) + begin_a_element=begin_a_element->a_stack_next; + + if ((begin_a_element!=NULL && begin_a_element->a_stack_offset==0) + ? (begin_a_element->a_stack_load_graph!=NULL + && begin_a_element->a_stack_load_graph->node_mark) + : 0>=next_block_graph->block_graph_a_stack_top_offset + ) + return a_stack_size; + + for (n=1; n<a_stack_size; ++n){ + a_element=a_element->a_stack_next; + if (a_element==NULL || a_element->a_stack_offset!=offset+n) + return a_stack_size; + if (a_element->a_stack_graph==graph) + break; + } + + if (n>=a_stack_size) + return a_stack_size; + + remove_end_stack_element + ((struct stack **)&block_graph->block_graph_a_stack,offset, + block_graph->block_graph_a_stack_begin_displacement, + block_graph->block_graph_a_stack_top_offset,0); + /* + a_element_0->a_stack_graph=NULL; + a_element_0->a_stack_flags &= ~ELEMENT_USED_BEFORE_JSR;; + */ + ++block_graph->block_graph_a_stack_top_offset; + block_graph->block_graph_jsr_eval_offset=n-1; + + remove_begin_stack_element + ((struct stack **)&next_block_graph->block_graph_a_stack,0,next_block_graph->block_graph_a_stack_begin_displacement, + next_block_graph->block_graph_a_stack_top_offset,0); + --next_block_graph->block_graph_a_stack_top_offset; + + return a_stack_size-1; +} + +void generate_code_for_previous_blocks (int jmp_jsr_or_rtn_flag) +{ + if (check_stack){ +#ifdef SEPARATE_A_AND_B_STACK_OVERFLOW_CHECKS + a_check_size_p=NULL; + b_check_size_p=NULL; +#else + check_size_p=NULL; +#endif + block_check=1; + } + + if (last_block_graph!=NULL){ + struct block_graph *block_graph,*next_block_graph; + struct block_graph end_block_graph; + + last_block->block_last_instruction=last_instruction; + + end_block_graph=global_block; + + end_block_graph.block_graph_end_a_stack_size=0; + end_block_graph.block_graph_end_b_stack_size=0; + end_block_graph.block_graph_end_stack_vector=NULL; + + mark_stack_graphs_2 (&global_block); + + next_block_graph=&end_block_graph; + for_l (block_graph,last_block_graph,block_graph_previous){ + insert_dummy_graphs_for_unused_a_stack_elements (block_graph,next_block_graph); + insert_dummy_graphs_for_unused_b_stack_elements (block_graph,next_block_graph); + + mark_stack_graphs_1 (block_graph,next_block_graph,jmp_jsr_or_rtn_flag); + if (block_graph->block_graph_kind!=JSR_EVAL_BLOCK) + jmp_jsr_or_rtn_flag=1; + + next_block_graph=block_graph; + } + + for_l (block_graph,first_block_graph,block_graph_next){ + next_block_graph=block_graph->block_graph_next; + + if (next_block_graph==NULL) + next_block_graph=&end_block_graph; + + remove_not_used_a_stack_elements (block_graph,next_block_graph); + remove_not_used_b_stack_elements (block_graph,next_block_graph); + } + remove_not_used_stack_elements_from_last_block (&end_block_graph); + + for_l (block_graph,first_block_graph,block_graph_next){ + next_block_graph=block_graph->block_graph_next; + if (next_block_graph==NULL) + next_block_graph=&end_block_graph; + + if (block_graph->block_graph_kind!=JSR_EVAL_BLOCK){ + compute_a_load_offsets (next_block_graph->block_graph_a_stack, + next_block_graph->block_graph_a_stack_begin_displacement<<2); + compute_b_load_offsets (next_block_graph->block_graph_b_stack, + next_block_graph->block_graph_b_stack_begin_displacement<<2); + } else { + int a_stack_size,b_stack_size; + ULONG *vector; + + a_stack_size=count_a_stack_size (block_graph->block_graph_a_stack, + block_graph->block_graph_a_stack_top_offset); + if (a_stack_size<1) + a_stack_size=1; + else + if (a_stack_size>N_ADDRESS_PARAMETER_REGISTERS+1) + a_stack_size=N_ADDRESS_PARAMETER_REGISTERS+1; + + block_graph->block_graph_end_stack_vector= + &block_graph->block_graph_small_end_stack_vector; + b_stack_size=count_b_stack_size_2 + (&block_graph->block_graph_end_stack_vector, + block_graph->block_graph_b_stack, + block_graph->block_graph_b_stack_top_offset); + + vector=block_graph->block_graph_end_stack_vector; + + a_stack_size=optimize_jsr_eval (block_graph,a_stack_size,next_block_graph); + + if (a_stack_size>N_ADDRESS_PARAMETER_REGISTERS) + a_stack_size=N_ADDRESS_PARAMETER_REGISTERS; + block_graph->block_graph_end_a_stack_size=a_stack_size; + block_graph->block_graph_end_b_stack_size=b_stack_size; + + if (block_graph->block_graph_next!=NULL) + next_block_graph->block_graph_block->block_n_begin_a_parameter_registers=a_stack_size; + else + last_block->block_n_begin_a_parameter_registers=a_stack_size; + + next_block_graph->block_graph_a_stack_begin_displacement= + set_basic_block_begin_a_registers + (&next_block_graph->block_graph_a_stack,a_stack_size, + next_block_graph->block_graph_a_register_parameter_node); + compute_a_load_offsets (next_block_graph->block_graph_a_stack, + next_block_graph->block_graph_a_stack_begin_displacement<<2); + + next_block_graph->block_graph_b_stack_begin_displacement= + set_basic_block_begin_d_registers + (&next_block_graph->block_graph_b_stack,b_stack_size, + block_graph->block_graph_end_stack_vector, + next_block_graph->block_graph_d_register_parameter_node, + next_block_graph->block_graph_f_register_parameter_node +#ifdef MORE_PARAMETER_REGISTERS + ,N_ADDRESS_PARAMETER_REGISTERS - a_stack_size, + next_block_graph->block_graph_a_register_parameter_node +#endif + ); + compute_b_load_offsets (next_block_graph->block_graph_b_stack, + next_block_graph->block_graph_b_stack_begin_displacement<<2); + } + } + + for_l (block_graph,first_block_graph,block_graph_next){ + struct block_graph *next_block_graph; + + last_block_graph=block_graph; + next_block_graph=block_graph->block_graph_next; + if (next_block_graph==NULL) + next_block_graph=&end_block_graph; + generate_code_for_basic_block (next_block_graph); + } + + if (check_stack){ +#ifdef SEPARATE_A_AND_B_STACK_OVERFLOW_CHECKS + if (a_check_size_p!=NULL){ + struct block_graph *block_graph; + int a_stack_displacement,b_stack_displacement; + + a_stack_displacement=0; + b_stack_displacement=0; + for_l (block_graph,first_block_graph,block_graph_next){ + a_stack_displacement+=block_graph->block_graph_a_stack_displacement; + b_stack_displacement+=block_graph->block_graph_b_stack_displacement; + + if (block_graph->block_graph_kind==JSR_EVAL_BLOCK){ + struct basic_block *block; + int a_check_size,b_check_size; + + if (block_graph->block_graph_block==NULL || block_graph->block_graph_block->block_next==NULL) + internal_error_in_function ("generate_code_for_previous_blocks"); + + block=block_graph->block_graph_block->block_next; + a_check_size=block->block_a_stack_check_size; + b_check_size=block->block_b_stack_check_size; + + if (a_check_size>0 && a_stack_displacement+a_check_size<=*a_check_size_p) + block->block_a_stack_check_size=0; + if (b_check_size>0 && b_stack_displacement+b_check_size<=*b_check_size_p) + block->block_b_stack_check_size=0; + } + } + } +#else + if (check_size_p!=NULL){ + struct block_graph *block_graph; + int stack_displacement; + + stack_displacement=0; + for_l (block_graph,first_block_graph,block_graph_next){ + stack_displacement+=block_graph->block_graph_stack_displacement; + + if (block_graph->block_graph_kind==JSR_EVAL_BLOCK){ + struct basic_block *block; + int check_size; + + if (block_graph->block_graph_block==NULL || block_graph->block_graph_block->block_next==NULL) + internal_error_in_function ("generate_code_for_previous_blocks"); + + block=block_graph->block_graph_block->block_next; + check_size=block->block_stack_check_size; + + if (check_size>0 && stack_displacement+check_size<=*check_size_p) + block->block_stack_check_size=0; + } + } + } +#endif + block_check=0; + } + + first_block_graph=last_block_graph=NULL; + + global_block=end_block_graph; + + global_block.block_graph_end_a_stack_size=0; + global_block.block_graph_end_b_stack_size=0; + global_block.block_graph_end_stack_vector=NULL; + + last_instruction=last_block->block_last_instruction; + } +} + +int end_basic_block_with_registers_and_return_b_stack_offset (int n_a_parameters,int n_b_parameters,ULONG vector[],int n_address_parameter_registers) +{ + int b_stack_offset; + + a_stack_load_register_values (n_a_parameters,n_address_parameter_registers); + b_stack_load_register_values (n_b_parameters,vector,parallel_flag ? N_DATA_PARAMETER_REGISTERS-1: N_DATA_PARAMETER_REGISTERS +#ifdef MORE_PARAMETER_REGISTERS + ,n_address_parameter_registers-n_a_parameters +#endif + ); + + generate_code_for_previous_blocks (1); + + a_stack_stores (n_a_parameters,n_address_parameter_registers); + b_stack_stores (n_b_parameters,vector,parallel_flag ? N_DATA_PARAMETER_REGISTERS-1 : N_DATA_PARAMETER_REGISTERS +#ifdef MORE_PARAMETER_REGISTERS + ,n_address_parameter_registers-n_a_parameters, + global_block.block_graph_a_register_parameter_node,global_block.block_graph_d_register_parameter_node +#endif + ); + + linearize_stack_graphs(); + b_stack_offset=local_register_allocation_and_adjust_a_stack_pointer (0); + + return b_stack_offset; +} + +void end_basic_block_with_registers (int n_a_parameters,int n_b_parameters,ULONG vector[]) +{ + int b_offset; + + b_offset=end_basic_block_with_registers_and_return_b_stack_offset (n_a_parameters,n_b_parameters,vector,N_ADDRESS_PARAMETER_REGISTERS); + + if (b_offset!=0) +#ifdef I486 + i_lea_id_r (b_offset,B_STACK_POINTER,B_STACK_POINTER); +#else + if (b_offset>0) + i_add_i_r (b_offset,B_STACK_POINTER); + else + i_sub_i_r (-b_offset,B_STACK_POINTER); +#endif +} + +void end_stack_elements (int n_a_parameters,int n_b_parameters,ULONG vector[]) +{ + int n_data_parameter_registers; + + n_data_parameter_registers = parallel_flag ? N_DATA_PARAMETER_REGISTERS-1 : N_DATA_PARAMETER_REGISTERS; + + a_stack_load_register_values (n_a_parameters,N_ADDRESS_PARAMETER_REGISTERS); + b_stack_load_register_values (n_b_parameters,vector,n_data_parameter_registers +#ifdef MORE_PARAMETER_REGISTERS + ,N_ADDRESS_PARAMETER_REGISTERS-n_a_parameters +#endif + ); + + a_stack_stores (n_a_parameters,N_ADDRESS_PARAMETER_REGISTERS); + b_stack_stores (n_b_parameters,vector,n_data_parameter_registers +#ifdef MORE_PARAMETER_REGISTERS + ,N_ADDRESS_PARAMETER_REGISTERS-n_a_parameters, + global_block.block_graph_a_register_parameter_node,global_block.block_graph_d_register_parameter_node +#endif + ); +} + +void begin_new_basic_block (VOID) +{ + last_block->block_last_instruction=last_instruction; + + last_instruction=NULL; + + last_block->block_next=allocate_empty_basic_block(); + last_block=last_block->block_next; + + release_a_stack(); + release_b_stack(); + + release_heap(); + + load_indexed_list=NULL; +} + +void insert_basic_block (int block_graph_kind,int a_stack_size,int b_stack_size,ULONG *vector_p,LABEL *label) +{ + struct block_graph *new_block; + + last_block->block_last_instruction=last_instruction; + + new_block=allocate_struct_from_heap (block_graph); + + *new_block=global_block; + + new_block->block_graph_kind=block_graph_kind; + new_block->block_graph_block=last_block; + + new_block->block_graph_used_a_stack_elements=block_graph_kind==JSR_EVAL_BLOCK ? 1 : a_stack_size; + new_block->block_graph_used_b_stack_elements=b_stack_size; + + new_block->block_graph_end_a_stack_size=a_stack_size; + new_block->block_graph_end_b_stack_size=b_stack_size; + + if (b_stack_size<=VECTOR_ELEMENT_SIZE){ + new_block->block_graph_small_end_stack_vector=*vector_p; + new_block->block_graph_end_stack_vector=&new_block->block_graph_small_end_stack_vector; + } else { + int vector_size; + ULONG *vector,*old_vector; + + vector_size=(b_stack_size+VECTOR_ELEMENT_SIZE-1)>>LOG_VECTOR_ELEMENT_SIZE; + vector=(ULONG*)fast_memory_allocate (vector_size * sizeof (ULONG)); + label->label_vector=vector; + new_block->block_graph_end_stack_vector=vector; + + old_vector=vector_p; + while (vector_size>0){ + *vector++=*old_vector++; + --vector_size; + } + } + + new_block->block_graph_jsr_eval_offset=0; + new_block->block_graph_last_instruction_label=label; + + if (last_block_graph==NULL) + first_block_graph=new_block; + else + last_block_graph->block_graph_next=new_block; + new_block->block_graph_previous=last_block_graph; + new_block->block_graph_next=NULL; + last_block_graph=new_block; + + last_instruction=NULL; + + last_block->block_next=allocate_empty_basic_block(); + last_block=last_block->block_next; + + release_a_stack(); + release_b_stack(); + + load_indexed_list=NULL; +} + +void insert_basic_block_with_extra_parameters_on_stack (int block_graph_kind,int a_stack_size,int b_stack_size,ULONG *vector_p, + int extra_a_stack_size,int extra_b_stack_size,LABEL *label) +{ + insert_basic_block (block_graph_kind,a_stack_size,b_stack_size,vector_p,label); + + last_block_graph->block_graph_used_a_stack_elements+=extra_a_stack_size; + last_block_graph->block_graph_used_b_stack_elements+=extra_b_stack_size; +} + +void initialize_stacks (VOID) +{ + release_a_stack(); + + release_b_stack(); + + last_block_graph=NULL; + first_block_graph=NULL; + + block_check=0; + + load_indexed_list=NULL; +} |