1 /* file "main.cc" of the cbsplit program for SUIF */
3 /* Copyright (c) 1994 Stanford University
7 This software is provided under the terms described in
8 the "suif_copyright.h" include file. */
10 #include <suif_copyright.h>
13 * This file contains the main program for cbsplit.
16 #define RCS_BASE_FILE main_cc
23 "$Id: main.cc,v 1.1.1.1 1998/06/16 15:17:10 brm Exp $")
25 INCLUDE_SUIF_COPYRIGHT
27 /*----------------------------------------------------------------------*
29 *----------------------------------------------------------------------*
34 The cbsplit program splits up Fortran common blocks into
35 pieces that are as small as possible, given the reshaping in
36 the program. This can in many cases lead to common blocks
37 which consist of only one field, in which case a single global
38 variable of the appropriate type can be used. The idea is
39 that some interprocedural analysis that deals only with
40 var_syms and can't handle the offsets and overlapping of a
41 common block will be able to do more because more things will
42 be in their own var_syms.
44 Note that to be correct, this pass must know how all the
45 functions in the entire program use their common blocks before
46 it can split anything. Hence if the program is in multiple
47 files, the files must be linked before this pass is run and
48 this pass should be run on all simultaneously.
54 -assume-no-reshape-communication
55 Assume that if there is any reshaping of common
56 blocks, either through equivalences or different
57 shapes in different procedures, that there is no
58 communication from one shape to another. That is,
59 assume it is safe to make different shapes not overlap
60 one another at all. With this assumption, every field
61 of every common block is made into its own independent
62 global variable unless there is some initialization
63 data for the common block. If the common block has
64 initialization data, it is handled as if this flag
68 *----------------------------------------------------------------------*
70 *----------------------------------------------------------------------*/
71 /*----------------------------------------------------------------------*
72 Begin Private Type Definitions
73 *----------------------------------------------------------------------*/
84 chunk_data(int new_offset
, int new_size
, chunk_data
*new_next
)
94 /*----------------------------------------------------------------------*
95 End Private Type Definitions
96 *----------------------------------------------------------------------*/
97 /*----------------------------------------------------------------------*
98 Begin Public Global Variables
99 *----------------------------------------------------------------------*/
101 /*----------------------------------------------------------------------*
102 End Public Global Variables
103 *----------------------------------------------------------------------*/
104 /*----------------------------------------------------------------------*
105 Begin Private Global Variables
106 *----------------------------------------------------------------------*/
108 static char *k_cbsplit_data
= "cbsplit data";
109 boolean assume_no_reshape_communication
= FALSE
;
111 /*----------------------------------------------------------------------*
112 End Private Global Variables
113 *----------------------------------------------------------------------*/
114 /*----------------------------------------------------------------------*
115 Begin Public Function Declarations
116 *----------------------------------------------------------------------*/
118 extern int main(int argc
, char *argv
[]);
120 /*----------------------------------------------------------------------*
121 End Public Function Declarations
122 *----------------------------------------------------------------------*/
123 /*----------------------------------------------------------------------*
124 Begin Private Function Declarations
125 *----------------------------------------------------------------------*/
127 static void usage(void);
128 static void split_blocks(global_symtab
*the_symtab
);
129 static void split_common_block(var_sym
*the_common
);
130 static chunk_data
*group_split_common(struct_type
*the_struct
);
131 static chunk_data
*fix_partition_for_initialization(chunk_data
*partition
,
132 base_init_struct_list
*initializers
);
133 static struct_type
*struct_section(struct_type
*original_struct
, int offset
,
134 int size
, boolean
*is_unit
,
135 type_node
**unit_type
,
136 const char **unit_name
);
137 static void split_on_proc(tree_proc
*);
139 /*----------------------------------------------------------------------*
140 End Private Function Declarations
141 *----------------------------------------------------------------------*/
142 /*----------------------------------------------------------------------*
143 Begin Public Function Implementations
144 *----------------------------------------------------------------------*/
146 extern int main(int argc
, char *argv
[])
148 static cmd_line_option option_table
[] =
150 {CLO_NOARG
, "-assume-no-reshape-communication", NULL
,
151 &assume_no_reshape_communication
}
154 start_suif(argc
, argv
);
156 parse_cmd_line(argc
, argv
, option_table
,
157 sizeof(option_table
) / sizeof(cmd_line_option
));
159 if ((argc
< 3) || (argc
% 2 != 1))
162 for (int arg_num
= 1; arg_num
< argc
; arg_num
+= 2)
163 fileset
->add_file(argv
[arg_num
], argv
[arg_num
+ 1]);
165 split_blocks(fileset
->globals());
167 fileset
->reset_iter();
170 file_set_entry
*fse
= fileset
->next_file();
173 split_blocks(fse
->symtab());
174 fse
->reset_proc_iter();
177 proc_sym
*this_proc_sym
= fse
->next_proc();
178 if (this_proc_sym
== NULL
)
180 this_proc_sym
->read_proc(TRUE
, TRUE
);
181 split_on_proc(this_proc_sym
->block());
182 this_proc_sym
->write_proc(fse
);
183 this_proc_sym
->flush_proc();
191 /*----------------------------------------------------------------------*
192 End Public Function Implementations
193 *----------------------------------------------------------------------*/
194 /*----------------------------------------------------------------------*
195 Begin Private Function Implementations
196 *----------------------------------------------------------------------*/
198 static void usage(void)
201 "usage: %s { -assume-no-reshape-communication } "
202 "<infile> <outfile> { <infile> <outfile> }*\n",
203 _suif_prog_base_name
);
207 static void split_blocks(global_symtab
*the_symtab
)
209 sym_node_list_iter
sym_iter(the_symtab
->symbols());
210 while (!sym_iter
.is_empty())
212 sym_node
*this_symbol
= sym_iter
.step();
214 if (!this_symbol
->is_var())
216 var_sym
*this_var
= (var_sym
*)this_symbol
;
218 if (this_var
->peek_annote(k_common_block
) != NULL
)
219 split_common_block(this_var
);
222 the_symtab
->number_globals();
225 static void split_common_block(var_sym
*the_common
)
227 type_node
*common_type
= the_common
->type();
228 if (common_type
->op() != TYPE_GROUP
)
229 error_line(1, the_common
, "common block does not have group type");
230 struct_type
*common_group
= (struct_type
*)common_type
;
232 if (!the_common
->has_var_def())
234 error_line(1, NULL
, "no definition for common block `%s'",
237 var_def
*old_def
= the_common
->definition();
240 error_line(1, NULL
, "no definition for common block `%s'",
244 base_init_struct_list
*initializers
= read_init_data(old_def
);
246 if (assume_no_reshape_communication
&& initializers
->is_empty())
248 while (the_common
->num_children() > 0)
250 var_sym
*this_child
= the_common
->child_var(0);
251 the_common
->remove_child(this_child
);
252 old_def
->parent()->define_var(this_child
,
253 get_alignment(this_child
->type()));
258 chunk_data
*the_data
= group_split_common(common_group
);
260 the_data
= fix_partition_for_initialization(the_data
, initializers
);
262 if (the_data
== NULL
)
264 deallocate_init_data(initializers
);
269 * If the split would just give back one chunk of the same size,
272 if ((the_data
->next
== NULL
) &&
273 (the_data
->size
== the_common
->type()->size()) &&
274 (common_group
->num_fields() != 1))
277 deallocate_init_data(initializers
);
281 int initializer_offset
= 0;
283 chunk_data
*follow_chunk
= the_data
;
284 while (follow_chunk
!= NULL
)
287 boolean is_unit
= TRUE
;
288 type_node
*unit_type
= NULL
;
289 const char *unit_name
= NULL
;
291 new_type
= struct_section(common_group
, follow_chunk
->offset
,
292 follow_chunk
->size
, &is_unit
, &unit_type
,
294 assert(new_type
!= NULL
);
296 if (unit_type
!= NULL
)
298 assert(new_type
->parent() == NULL
);
300 new_type
= unit_type
;
302 follow_chunk
->is_unit
= TRUE
;
304 unsigned num_children
= the_common
->num_children();
306 for (child_num
= 0; child_num
< num_children
; ++child_num
)
308 if ((the_common
->child_var(child_num
)->offset() ==
309 follow_chunk
->offset
) &&
310 (the_common
->child_var(child_num
)->type() == unit_type
))
317 * Add an underscore after the name to avoid name
318 * conflicts, because we are adding external linkage. For
319 * example, a field named ``time'' would conflict with the
320 * C library ``time()'' function if we didn't add the
321 * underscore. Since sf2c just adds a single underscore
322 * to all function names, we can assume that a trailing
323 * underscore is enough to avoid conflict with library
324 * symbols, and since we require all non-library source
325 * files for this pass, we can assume that the SUIF
326 * library will take care of any name conflicts in the
327 * SUIF global symbol table.
329 char *new_var_name
= new char[strlen(unit_name
) + 2];
330 sprintf(new_var_name
, "%s_", unit_name
);
332 if (child_num
< num_children
)
334 var_sym
*child_var
= the_common
->child_var(child_num
);
335 the_common
->remove_child(child_var
);
336 child_var
->set_name(new_var_name
);
337 follow_chunk
->replacement
= child_var
;
341 follow_chunk
->replacement
=
342 the_common
->parent()->new_var(new_type
, new_var_name
);
344 delete[] new_var_name
;
348 new_type
= common_group
->parent()->install_type(new_type
);
350 char *new_var_name
= new char[strlen(the_common
->name()) + 40];
351 sprintf(new_var_name
, "%s_%d_%d", the_common
->name(),
352 follow_chunk
->offset
, follow_chunk
->size
);
353 follow_chunk
->replacement
=
354 the_common
->parent()->new_var(new_type
, new_var_name
);
355 follow_chunk
->replacement
->reset_addr_taken();
356 delete[] new_var_name
;
358 follow_chunk
->replacement
->append_annote(k_common_block
,
361 unsigned num_children
= the_common
->num_children();
362 for (unsigned child_num
= 0; child_num
< num_children
;)
364 var_sym
*child_var
= the_common
->child_var(child_num
);
365 if ((child_var
->offset() >= follow_chunk
->offset
) &&
366 ((child_var
->offset() + child_var
->type()->size()) <=
367 (follow_chunk
->offset
+ follow_chunk
->size
)))
370 child_var
->offset() - follow_chunk
->offset
;
371 the_common
->remove_child(child_var
);
372 if (child_var
->is_addr_taken())
373 follow_chunk
->replacement
->set_addr_taken();
374 follow_chunk
->replacement
->add_child(child_var
,
386 old_def
->parent()->define_var(follow_chunk
->replacement
,
387 get_alignment(new_type
));
389 base_init_struct_list
*first_init
;
390 base_init_struct_list
*second_init
;
392 split_init_data(initializers
,
393 follow_chunk
->offset
- initializer_offset
,
394 &first_init
, &second_init
);
398 "misalignment of initialization data on common block "
399 "`%s'", the_common
->name());
401 deallocate_init_data(first_init
);
403 init_fit
= split_init_data(second_init
, follow_chunk
->size
,
404 &first_init
, &initializers
);
408 "misalignment of initialization data on common block "
409 "`%s'", the_common
->name());
411 write_init_data(chunk_def
, first_init
);
412 deallocate_init_data(first_init
);
414 initializer_offset
= follow_chunk
->offset
+ follow_chunk
->size
;
416 follow_chunk
= follow_chunk
->next
;
419 assert(the_common
->num_children() == 0);
421 deallocate_init_data(initializers
);
423 the_common
->append_annote(k_cbsplit_data
, the_data
);
426 static chunk_data
*group_split_common(struct_type
*the_struct
)
428 assert(the_struct
->op() == TYPE_GROUP
);
430 chunk_data
*new_partition
= NULL
;
432 unsigned num_fields
= the_struct
->num_fields();
433 for (unsigned field_num
= 0; field_num
< num_fields
; ++field_num
)
435 int this_offset
= the_struct
->offset(field_num
);
436 int this_size
= the_struct
->field_type(field_num
)->size();
438 chunk_data
**next_place
= &new_partition
;
440 while ((*next_place
!= NULL
) &&
441 ((*next_place
)->offset
+ (*next_place
)->size
<= this_offset
))
443 next_place
= &((*next_place
)->next
);
446 if (*next_place
== NULL
)
448 *next_place
= new chunk_data(this_offset
, this_size
, NULL
);
452 if ((*next_place
)->offset
>= this_offset
+ this_size
)
455 new chunk_data(this_offset
, this_size
, *next_place
);
459 if ((*next_place
)->offset
> this_offset
)
460 (*next_place
)->offset
= this_offset
;
462 while ((*next_place
)->next
!= NULL
)
464 chunk_data
*next_block
= (*next_place
)->next
;
465 if (next_block
->offset
>= this_offset
+ this_size
)
467 (*next_place
)->size
=
468 (next_block
->offset
+ next_block
->size
) -
469 (*next_place
)->offset
;
470 (*next_place
)->next
= next_block
->next
;
474 if (((*next_place
)->offset
+ (*next_place
)->size
) <
475 (this_offset
+ this_size
))
477 (*next_place
)->size
=
478 (this_offset
+ this_size
) - (*next_place
)->offset
;
484 return new_partition
;
487 static chunk_data
*fix_partition_for_initialization(chunk_data
*partition
,
488 base_init_struct_list
*initializers
)
490 chunk_data
*new_partition
= partition
;
492 base_init_struct_list_iter
init_iter(initializers
);
494 while (!init_iter
.is_empty())
496 base_init_struct
*this_init
= init_iter
.step();
499 if (this_init
->the_multi_init() != NULL
)
501 this_size
= this_init
->the_multi_init()->size
;
502 repetitions
= this_init
->the_multi_init()->data
->count();
504 else if (this_init
->the_repeat_init() != NULL
)
506 this_size
= this_init
->the_repeat_init()->size
;
507 repetitions
= this_init
->the_repeat_init()->repetitions
;
511 this_offset
+= this_init
->total_size();
514 while (repetitions
> 0)
516 chunk_data
**next_place
= &new_partition
;
518 while ((*next_place
!= NULL
) &&
519 ((*next_place
)->offset
+ (*next_place
)->size
<=
522 next_place
= &((*next_place
)->next
);
525 if (*next_place
== NULL
)
527 *next_place
= new chunk_data(this_offset
, this_size
, NULL
);
531 if ((*next_place
)->offset
>= this_offset
+ this_size
)
534 new chunk_data(this_offset
, this_size
,
539 if ((*next_place
)->offset
> this_offset
)
540 (*next_place
)->offset
= this_offset
;
542 while ((*next_place
)->next
!= NULL
)
544 chunk_data
*next_block
= (*next_place
)->next
;
545 if (next_block
->offset
>= this_offset
+ this_size
)
547 (*next_place
)->size
=
548 (next_block
->offset
+ next_block
->size
) -
549 (*next_place
)->offset
;
550 (*next_place
)->next
= next_block
->next
;
554 if (((*next_place
)->offset
+ (*next_place
)->size
) <
555 (this_offset
+ this_size
))
557 (*next_place
)->size
=
558 (this_offset
+ this_size
) -
559 (*next_place
)->offset
;
564 this_offset
+= this_size
;
569 return new_partition
;
572 static struct_type
*struct_section(struct_type
*original_struct
, int offset
,
573 int size
, boolean
*is_unit
,
574 type_node
**unit_type
,
575 const char **unit_name
)
577 assert(original_struct
->is_struct());
579 char *new_name
= new char[strlen(original_struct
->name()) + 40];
580 sprintf(new_name
, "%s_%d_%d", original_struct
->name(), offset
, size
);
581 struct_type
*new_struct
= new struct_type(TYPE_GROUP
, size
, new_name
, 0);
584 unsigned num_fields
= original_struct
->num_fields();
585 for (unsigned field_num
= 0; field_num
< num_fields
; ++field_num
)
587 int this_offset
= original_struct
->offset(field_num
);
588 if ((this_offset
>= offset
) && (this_offset
< offset
+ size
))
590 unsigned new_field_num
= new_struct
->num_fields();
591 type_node
*new_field_type
= original_struct
->field_type(field_num
);
592 const char *new_field_name
= original_struct
->field_name(field_num
);
593 new_struct
->set_num_fields(new_field_num
+ 1);
594 new_struct
->set_field_name(new_field_num
, new_field_name
);
595 new_struct
->set_field_type(new_field_num
, new_field_type
);
596 new_struct
->set_offset(new_field_num
, this_offset
- offset
);
600 if (this_offset
!= offset
)
607 if (*unit_type
== NULL
)
609 *unit_type
= new_field_type
;
610 *unit_name
= new_field_name
;
612 else if (*unit_type
!= new_field_type
)
625 static void split_on_proc(tree_proc
*)
629 /*----------------------------------------------------------------------*
630 End Private Function Implementations
631 *----------------------------------------------------------------------*/