a few more warnings
[suif.git] / src / basesuif / cbsplit / main.cc
blob7c3facc2b011db683c42fb6930a2196ee7387f0b
1 /* file "main.cc" of the cbsplit program for SUIF */
3 /* Copyright (c) 1994 Stanford University
5 All rights reserved.
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
18 #include <suif1.h>
19 #include <useful.h>
20 #include <string.h>
22 RCS_BASE(
23 "$Id: main.cc,v 1.1.1.1 1998/06/16 15:17:10 brm Exp $")
25 INCLUDE_SUIF_COPYRIGHT
27 /*----------------------------------------------------------------------*
28 Begin Documentation
29 *----------------------------------------------------------------------*
31 Summary
32 -------
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.
51 Options
52 -------
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
65 weren't used.
68 *----------------------------------------------------------------------*
69 End Documentation
70 *----------------------------------------------------------------------*/
71 /*----------------------------------------------------------------------*
72 Begin Private Type Definitions
73 *----------------------------------------------------------------------*/
75 class chunk_data
77 public:
78 int offset;
79 int size;
80 boolean is_unit;
81 var_sym *replacement;
82 chunk_data *next;
84 chunk_data(int new_offset, int new_size, chunk_data *new_next)
86 offset = new_offset;
87 size = new_size;
88 is_unit = FALSE;
89 replacement = NULL;
90 next = 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))
160 usage();
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();
168 while (TRUE)
170 file_set_entry *fse = fileset->next_file();
171 if (fse == NULL)
172 break;
173 split_blocks(fse->symtab());
174 fse->reset_proc_iter();
175 while (TRUE)
177 proc_sym *this_proc_sym = fse->next_proc();
178 if (this_proc_sym == NULL)
179 break;
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();
187 exit_suif();
188 return 0;
191 /*----------------------------------------------------------------------*
192 End Public Function Implementations
193 *----------------------------------------------------------------------*/
194 /*----------------------------------------------------------------------*
195 Begin Private Function Implementations
196 *----------------------------------------------------------------------*/
198 static void usage(void)
200 fprintf(stderr,
201 "usage: %s { -assume-no-reshape-communication } "
202 "<infile> <outfile> { <infile> <outfile> }*\n",
203 _suif_prog_base_name);
204 exit(1);
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())
215 continue;
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'",
235 the_common->name());
237 var_def *old_def = the_common->definition();
238 if (old_def == NULL)
240 error_line(1, NULL, "no definition for common block `%s'",
241 the_common->name());
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()));
255 return;
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);
265 return;
269 * If the split would just give back one chunk of the same size,
270 * don't do anything.
272 if ((the_data->next == NULL) &&
273 (the_data->size == the_common->type()->size()) &&
274 (common_group->num_fields() != 1))
276 delete the_data;
277 deallocate_init_data(initializers);
278 return;
281 int initializer_offset = 0;
283 chunk_data *follow_chunk = the_data;
284 while (follow_chunk != NULL)
286 type_node *new_type;
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,
293 &unit_name);
294 assert(new_type != NULL);
296 if (unit_type != NULL)
298 assert(new_type->parent() == NULL);
299 delete new_type;
300 new_type = unit_type;
302 follow_chunk->is_unit = TRUE;
304 unsigned num_children = the_common->num_children();
305 unsigned child_num;
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))
312 break;
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;
339 else
341 follow_chunk->replacement =
342 the_common->parent()->new_var(new_type, new_var_name);
344 delete[] new_var_name;
346 else
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,
359 new immed_list);
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)))
369 int new_offset =
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,
375 new_offset);
376 --num_children;
378 else
380 ++child_num;
385 var_def *chunk_def =
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;
391 boolean init_fit =
392 split_init_data(initializers,
393 follow_chunk->offset - initializer_offset,
394 &first_init, &second_init);
395 if (!init_fit)
397 error_line(1, NULL,
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);
405 if (!init_fit)
407 error_line(1, NULL,
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);
450 else
452 if ((*next_place)->offset >= this_offset + this_size)
454 *next_place =
455 new chunk_data(this_offset, this_size, *next_place);
457 else
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)
466 break;
467 (*next_place)->size =
468 (next_block->offset + next_block->size) -
469 (*next_place)->offset;
470 (*next_place)->next = next_block->next;
471 delete next_block;
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);
493 int this_offset = 0;
494 while (!init_iter.is_empty())
496 base_init_struct *this_init = init_iter.step();
497 int this_size;
498 int repetitions = 0;
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;
509 else
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 <=
520 this_offset))
522 next_place = &((*next_place)->next);
525 if (*next_place == NULL)
527 *next_place = new chunk_data(this_offset, this_size, NULL);
529 else
531 if ((*next_place)->offset >= this_offset + this_size)
533 *next_place =
534 new chunk_data(this_offset, this_size,
535 *next_place);
537 else
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)
546 break;
547 (*next_place)->size =
548 (next_block->offset + next_block->size) -
549 (*next_place)->offset;
550 (*next_place)->next = next_block->next;
551 delete next_block;
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;
565 --repetitions;
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);
582 delete[] new_name;
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);
598 if ((*is_unit))
600 if (this_offset != offset)
602 *is_unit = FALSE;
603 *unit_type = NULL;
605 else
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)
614 *is_unit = FALSE;
615 *unit_type = NULL;
622 return new_struct;
625 static void split_on_proc(tree_proc *)
629 /*----------------------------------------------------------------------*
630 End Private Function Implementations
631 *----------------------------------------------------------------------*/