add $(EXEEXT) to executable targets during installation for MinGW
[suif.git] / src / basesuif / useful / positioning.cc
blob6ad9352b6e7601dd02fc89d714ed9a5994ea35a1
1 /* file "positioning.cc" */
3 /* Copyright (c) 1995 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 is the implementation of variable positioning routines for the
14 * SUIF library of miscellaneous useful routines.
17 #define _MODULE_ "libuseful.a"
19 #pragma implementation "basic.h"
21 #define RCS_BASE_FILE positioning_cc
23 #include "useful_internal.h"
24 #include <string.h>
26 RCS_BASE(
27 "$Id: positioning.cc,v 1.1.1.1 1998/06/16 15:15:36 brm Exp $")
30 #define COMBO_NAME_PREFIX "__suif_combo_"
33 static char *generate_combination_name(void);
36 extern boolean set_relative_positions(var_sym *var1, var_sym *var2,
37 i_integer offset,
38 offset_kind which_offset)
40 base_symtab *parent = var1->parent();
41 if (parent != var2->parent())
42 return FALSE;
43 if (var1->is_param() || var2->is_param())
44 return FALSE;
45 if (var1->is_auto() != var2->is_auto())
46 return FALSE;
47 if (var1->is_reg() != var2->is_reg())
48 return FALSE;
49 var_sym *root1 = var1->root_ancestor();
50 var_sym *root2 = var2->root_ancestor();
51 if (parent->kind() == SYMTAB_GLOBAL)
53 if ((!root1->has_var_def()) || (!root2->has_var_def()))
54 return FALSE;
56 i_integer start_to_start_offset;
57 switch (which_offset)
59 case OFFSET_START_TO_START:
60 start_to_start_offset = offset;
61 break;
62 case OFFSET_START_TO_END:
63 start_to_start_offset = offset - var2->type()->size();
64 break;
65 case OFFSET_END_TO_START:
66 start_to_start_offset = offset + var1->type()->size();
67 break;
68 case OFFSET_END_TO_END:
69 start_to_start_offset =
70 (offset + var1->type()->size()) - var2->type()->size();
71 break;
72 default:
73 assert(FALSE);
75 start_to_start_offset =
76 (start_to_start_offset + var1->root_offset()) -
77 var2->root_offset();
78 if (root1 == root2)
79 return (start_to_start_offset == 0);
80 if (start_to_start_offset < 0)
82 start_to_start_offset = -start_to_start_offset;
83 var_sym *temp_root = root1;
84 root1 = root2;
85 root2 = temp_root;
87 base_init_struct_list *initialization = NULL;
88 if (root1->has_var_def())
90 assert(root2->has_var_def());
91 var_def *def1 = root1->definition();
92 var_def *def2 = root2->definition();
93 assert((def1 != NULL) && (def2 != NULL));
94 base_init_struct_list *init1 = read_init_data(def1);
95 base_init_struct_list *init2 = read_init_data(def2);
96 base_init_struct_list *leftovers;
97 boolean split_ok =
98 split_init_data(init1, start_to_start_offset.c_int(),
99 &initialization, &leftovers);
100 if (!split_ok)
102 deallocate_init_data(init1);
103 deallocate_init_data(init2);
104 return FALSE;
106 if (!leftovers->is_empty())
108 deallocate_init_data(initialization);
109 deallocate_init_data(leftovers);
110 deallocate_init_data(init2);
111 return FALSE;
113 deallocate_init_data(leftovers);
114 i_integer skip_total = 0;
115 base_init_struct_list_iter init_iter(initialization);
116 while (!init_iter.is_empty())
118 base_init_struct *this_init_struct = init_iter.step();
119 skip_total += this_init_struct->total_size();
121 assert(skip_total <= start_to_start_offset);
122 if (skip_total < start_to_start_offset)
124 int fill_size = (start_to_start_offset - skip_total).c_int();
125 initialization->append(new fill_init_struct(fill_size, 0));
127 initialization->append(init2);
128 delete init2;
130 i_integer alignment1 = get_alignment(root1->type());
131 i_integer alignment2 = get_alignment(root2->type());
132 i_integer coeff_n;
133 i_integer coeff_m;
134 i_integer gcd = ii_gcd(alignment1, alignment2, &coeff_n, &coeff_m);
135 i_integer lcm = (alignment1 / gcd) * alignment2;
136 if ((start_to_start_offset % gcd) != 0)
138 error_line(1, NULL,
139 "set_relative_positions(): requested relative offset "
140 "violates alignment restrictions");
142 i_integer first_offset =
143 (- alignment1 * coeff_n * (start_to_start_offset / gcd)) % lcm;
144 if (first_offset < 0)
145 first_offset += lcm;
146 i_integer second_offset = first_offset + start_to_start_offset;
147 assert(first_offset >= 0);
148 assert(second_offset >= 0);
149 i_integer end1 = first_offset + root1->type()->size();
150 i_integer end2 = second_offset + root2->type()->size();
151 i_integer total_size;
152 if (end1 >= end2)
153 total_size = end1;
154 else
155 total_size = end2;
156 assert(total_size >= 0);
157 if (!total_size.is_c_int())
159 error_line(1, NULL,
160 "set_relative_positions(): overflow in total size of "
161 "requested combined entity");
163 assert(first_offset.is_c_int());
164 assert(second_offset.is_c_int());
165 char *new_name = generate_combination_name();
166 struct_type *new_type =
167 new struct_type(TYPE_GROUP, total_size.c_int(), new_name, 2);
168 new_type->set_field_name(0, root1->name());
169 new_type->set_field_type(0, root1->type());
170 new_type->set_offset(0, first_offset.c_int());
171 new_type->set_field_name(1, root2->name());
172 new_type->set_field_type(1, root2->type());
173 new_type->set_offset(1, second_offset.c_int());
174 new_type = (struct_type *)(parent->install_type(new_type));
176 var_sym *combined_var = parent->new_var(new_type, new_name);
178 if (root1->has_var_def())
180 assert(root2->has_var_def());
181 var_def *def1 = root1->definition();
182 var_def *def2 = root2->definition();
183 assert((def1 != NULL) && (def2 != NULL));
184 if (!lcm.is_c_int())
186 error_line(1, NULL,
187 "set_relative_positions(): overflow in alignment of "
188 "requested combined entity");
190 var_def *new_def =
191 def1->parent()->define_var(combined_var, lcm.c_int());
192 def1->parent()->remove_def(def1);
193 def2->parent()->remove_def(def2);
194 delete def1;
195 delete def2;
196 if (initialization != NULL)
198 if (first_offset > 0)
200 int fill_size = first_offset.c_int();
201 initialization->push(new fill_init_struct(fill_size, 0));
203 write_init_data(new_def, initialization);
204 deallocate_init_data(initialization);
208 if (root1->is_addr_taken() || root2->is_addr_taken())
209 combined_var->set_addr_taken();
210 else
211 combined_var->reset_addr_taken();
212 combined_var->add_child(root1, first_offset.c_int());
213 combined_var->add_child(root2, second_offset.c_int());
214 return TRUE;
218 static char *generate_combination_name(void)
220 static i_integer *counter = NULL;
221 static char *buffer = NULL;
222 static unsigned long buffer_size = 0;
224 if (buffer == NULL)
226 buffer_size = (strlen(COMBO_NAME_PREFIX) + 20);
227 buffer = new char[buffer_size];
228 strcpy(buffer, COMBO_NAME_PREFIX);
230 if (counter == NULL)
231 counter = new i_integer(0);
232 if (counter->written_length() + (unsigned int)(strlen(COMBO_NAME_PREFIX) + 1) >
233 buffer_size)
235 buffer_size *= 2;
236 delete[] buffer;
237 buffer = new char[buffer_size];
238 strcpy(buffer, COMBO_NAME_PREFIX);
240 counter->write(&(buffer[strlen(COMBO_NAME_PREFIX)]));
241 ++(*counter);
242 return buffer;