2 * dumper for initialized and uninitialized global data. based on cggg's implementation.
3 * @author Hannes Jakschitsch
16 #include "beasm_dump_globals.h"
21 * returns the highest bit value
23 static unsigned highest_bit(unsigned v)
27 if (v >= (1U << 16U)) {
31 if (v >= (1U << 8U)) {
35 if (v >= (1U << 4U)) {
39 if (v >= (1U << 2U)) {
43 if (v >= (1U << 1U)) {
55 * Determine if an entity is a string constant
56 * @param ent The entity
57 * @return 1 if it is a string constant, 0 otherwise
59 static int ent_is_string_const(entity *ent)
64 ty = get_entity_type(ent);
66 /* if it's an array */
67 if (is_Array_type(ty)) {
68 type *elm_ty = get_array_element_type(ty);
70 /* and the array's alement type is primitive */
71 if (is_Primitive_type(elm_ty)) {
72 ir_mode *mode = get_type_mode(elm_ty);
75 * and the mode of the element type is an int of
76 * the same size as the byte mode
79 && get_mode_size_bits(mode) == get_mode_size_bits(mode_Bs))
83 n = get_compound_ent_n_values(ent);
84 for (i = 0; i < n; ++i) {
85 ir_node *irn = get_compound_ent_value(ent, i);
86 if(get_irn_opcode(irn) != iro_Const)
89 c = (int) get_tarval_long(get_Const_tarval(irn));
91 if((i < n - 1 && !(isgraph(c) || isspace(c)))
92 || (i == n - 1 && c != '\0'))
105 * dump an atomic value
107 static void dump_atomic_value( assembler_t *assembler,
108 asm_segment_t target_segment, ir_node *init)
110 ir_mode *mode = get_irn_mode(init);
111 int bytes = get_mode_size_bytes(mode);
114 switch (get_irn_opcode(init)) {
117 dump_atomic_value(assembler, target_segment, get_Cast_op(init));
121 dump_atomic_value(assembler, target_segment, get_Conv_op(init));
125 tv = get_Const_tarval(init);
127 /* beware of old stuff */
128 assert(! mode_is_reference(mode));
130 /* it's a arithmetic value */
131 assembler->dump_arith_tarval(assembler->private_data, target_segment, tv, bytes);
135 assembler->dump_symconst(assembler->private_data, target_segment, init);
137 switch (get_SymConst_kind(init)) {
138 case symconst_addr_name:
139 assembler->dump_addr_name(assembler->private_data, target_segment, get_id_str(get_SymConst_name(init)));
142 case symconst_addr_ent:
143 assembler->dump_addr_ent(assembler->private_data, target_segment, get_entity_ld_name(get_SymConst_entity(init)));
147 assembler->dump_size(assembler->private_data, target_segment, get_type_size_bytes(get_SymConst_type(init)));
151 assert(0 && "dump_atomic_init(): don't know how to init from this SymConst");
156 dump_atomic_value(assembler, target_segment, get_Add_left(init));
157 assembler->dump_arith_op(assembler->private_data, target_segment, ASM_ARITH_OPERATION_ADD);
158 dump_atomic_value(assembler, target_segment, get_Add_right(init));
162 dump_atomic_value(assembler, target_segment, get_Sub_left(init));
163 assembler->dump_arith_op(assembler, target_segment, ASM_ARITH_OPERATION_SUB);
164 dump_atomic_value(assembler, target_segment, get_Sub_right(init));
168 dump_atomic_value(assembler, target_segment, get_Mul_left(init));
169 assembler->dump_arith_op(assembler, target_segment, ASM_ARITH_OPERATION_MUL);
170 dump_atomic_value(assembler, target_segment, get_Mul_right(init));
174 assert(0 && "dump_atomic_init(): unknown IR-node");
180 * dump an atomic value
182 static void dump_atomic_init(assembler_t* assembler,
183 asm_segment_t target_segment, ir_node *init)
186 ir_mode *mode = get_irn_mode(init);
187 int bytes = get_mode_size_bytes(mode);
189 assembler->dump_atomic_decl(assembler->private_data, target_segment, bytes);
190 dump_atomic_value(assembler, target_segment, init);
191 assembler->dump_newline(assembler->private_data, target_segment);
205 * Dumps the initialization of global variables that are not
208 static void asm_dump_global ( assembler_t *assembler, entity *ent)
210 type *ty = get_entity_type(ent);
211 const char *ld_name = get_entity_ld_name(ent);
212 int align, is_constant, h;
215 asm_segment_t target_segment = ASM_SEGMENT_DATA_INIT;
218 * FIXME: did NOT work for partly constant values
221 /* ignore methods, they are emitted later */
222 if(is_Method_type(ty))
225 /* get the properties of the entity */
226 ent_variability variability = get_entity_variability(ent);
227 ent_visibility visibility = get_entity_visibility(ent);
229 if (variability == variability_constant) {
230 /* a constant entity, put it into the const segment */
231 target_segment = ASM_SEGMENT_CONST;
234 /* check, wether it is initialized, if yes create data */
235 if (variability != variability_uninitialized ) {
237 /* if (visibility == visibility_external_visible) {
238 assembler->dump_external_declaration(assembler->private_data, target_segment, ld_name);
239 // obstack_printf(obst, ".globl\t%s\n", ld_name);
241 align = get_type_alignment_bytes(ty);
243 // obstack_printf(obst, "\t.type\t%s,@object\n", ld_name);
244 // obstack_printf(obst, "\t.size\t%s,%d\n", ld_name, (get_type_size_bits(ty) + 7) >> 3);
245 assembler->dump_declare_object_symbol(assembler->private_data, target_segment, ld_name, (get_type_size_bits(ty) + 7) >> 3);
247 align = get_type_alignment_bytes(ty);
248 assembler->dump_align(assembler->private_data, target_segment, align );
249 assembler->dump_object_symbol_init_decl(assembler->private_data, target_segment, ld_name);
251 align = get_type_alignment_bytes(ty);
252 assembler->dump_declare_initialized_symbol ( assembler->private_data, target_segment, ld_name, (get_type_size_bits(ty)+7)>>3, align, visibility );
257 /* dumps of the different entity type initializiations */
260 if (is_atomic_type(ty)) {
261 if (get_entity_visibility(ent) != visibility_external_allocated)
262 dump_atomic_init(assembler, target_segment, get_atomic_ent_value(ent));
264 else if(ent_is_string_const(ent)) {
265 assembler->dump_string(assembler->private_data, target_segment, ent);
267 else if(is_Array_type(ty)) {
271 /* potential spare values should be already included! */
272 for (i = 0; i < get_compound_ent_n_values(ent); ++i) {
273 entity *step = get_compound_ent_value_member(ent, i);
274 type *stype = get_entity_type(step);
276 if (get_type_mode(stype)) {
278 int align = (get_type_alignment_bits(stype) + 7) >> 3;
279 int n = size % align;
282 assembler->dump_zero_padding(assembler->private_data, target_segment, align-n);
286 dump_atomic_init(assembler, target_segment, get_compound_ent_value(ent, i));
287 size += get_type_size_bytes(stype);
290 filler = get_type_size_bytes(ty) - size;
293 assembler->dump_zero_padding(assembler->private_data, target_segment, filler);
295 else if (is_compound_type(ty)) {
300 /* Compound entities are NOT sorted.
301 * The sorting strategy used doesn't work for `value' compound fields nor
302 * for partially_constant entities.
306 * in the worst case, every entity allocates one byte, so the type
307 * size should be equal or bigger the number of fields
310 type_size = get_type_size_bytes(ty);
311 vals = xcalloc(type_size, sizeof(*vals));
313 /* collect the values and store them at the offsets */
314 for(i = 0; i < get_compound_ent_n_values(ent); ++i) {
315 int graph_length, aipos, offset, stepsize;
319 entity *member = get_compound_ent_value_member(ent, i);
320 compound_graph_path *path = get_compound_ent_value_path(ent, i);
321 entity *node = get_compound_graph_path_node(path, 0);
322 type *node_type = get_entity_type(node);
324 /* get the access path to the costant value */
325 graph_length = get_compound_graph_path_length(path);
326 ai = xcalloc(graph_length, sizeof(struct arr_info));
328 /* We wanna know how many arrays are on the path to the entity. We also have to know how
329 * many elements each array holds to calculate the offset for the entity. */
330 for (j = 0; j < graph_length; j++) {
331 entity *step = get_compound_graph_path_node(path, j);
332 type *step_type = get_entity_type(step);
333 int ty_size = (get_type_size_bits(step_type) + 7) >> 3;
337 if (is_Array_type(step_type))
338 for (k = 0; k < get_array_n_dimensions(step_type); k++)
339 n += get_tarval_long(get_Const_tarval(get_array_upper_bound(step_type, k)));
341 ai[j].n_elems = n ? all_n + 1 : 0;
343 ai[j].size = ty_size;
346 aipos = graph_length - 1;
349 for (offset = j = 0; j < graph_length; j++) {
350 entity *step = get_compound_graph_path_node(path, j);
351 type *step_type = get_entity_type(step);
352 int ent_ofs = get_entity_offset_bytes(step);
355 /* add all positive offsets (= offsets in structs) */
356 if (ent_ofs >= 0) offset += ent_ofs;
358 if (j == graph_length - 1) {
359 stepsize = (get_type_size_bits(step_type) + 7) >> 3;
361 /* Search the next free position in vals depending on the information from above (ai). */
362 while (vals[offset]) {
363 if (ai[aipos].visit_cnt < ai[aipos].n_elems) {
365 ai[aipos].visit_cnt++;
368 while (aipos >= 0 && ai[aipos].visit_cnt == ai[aipos].n_elems) {
369 stepsize = ai[aipos--].size;
374 assert(aipos >= 0 && "couldn't store entity");
375 vals[offset] = get_compound_ent_value(ent, i);
382 /* now write them sorted */
383 for(i = 0; i < type_size; ) {
385 dump_atomic_init(assembler, target_segment, vals[i]);
386 i += (get_mode_size_bytes(get_irn_mode(vals[i])));
390 //obstack_printf(obst, "\t.byte\t0\n");
391 assembler->dump_zero_padding(assembler->private_data, target_segment, 1);
398 assert(0 && "unsupported type");
400 assembler->dump_newline(assembler->private_data, target_segment);
403 /* uninitialized, but allocated here */
406 /* if (visibility != visibility_external_allocated) {
408 if (visibility == visibility_local) {
409 assembler->dump_local_declaration(assembler->private_data, ASM_SEGMENT_COMMON , ld_name);
412 /* calculate the alignment */
414 target_segment = ASM_SEGMENT_DATA_UNINIT;
416 align = get_type_alignment_bytes(ty);
417 h = highest_bit(align);
419 if ((1 << h) < align)
425 // declare the symbol.
426 assembler->dump_declare_uninitialized_symbol(assembler->private_data, target_segment , ld_name, (get_type_size_bits(ty)+7)>>3, align, visibility);
434 * dump the global symbols
437 void asm_dump_globals ( assembler_t *assembler ) {
439 type *gt = get_glob_type();
440 int i, n = get_class_n_members(gt);
442 for (i = 0; i < n; i++)
443 asm_dump_global( assembler, get_class_member(gt, i) );