Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Zwinkau
libfirm
Commits
cf79ddfe
Commit
cf79ddfe
authored
Jan 11, 2008
by
Matthias Braun
Browse files
introduce new mode for initializer
[r17319]
parent
d573712d
Changes
9
Hide whitespace changes
Inline
Side-by-side
include/libfirm/firm_types.h
View file @
cf79ddfe
...
...
@@ -67,6 +67,8 @@ typedef struct ir_exec_freq ir_exec_freq, *ir_exec_freq_ptr;
typedef
struct
ir_cdep
ir_cdep
,
*
ir_cdep_ptr
;
typedef
struct
sn_entry
*
seqno_t
;
typedef
union
ir_initializer_t
ir_initializer_t
,
*
ir_initializer_ptr
;
typedef
void
irg_walk_func
(
ir_node
*
,
void
*
);
typedef
void
irg_reg_walk_func
(
ir_region
*
,
void
*
);
...
...
include/libfirm/typerep.h
View file @
cf79ddfe
...
...
@@ -454,6 +454,55 @@ ir_node *copy_const_value(dbg_info *dbg, ir_node *n);
ir_node
*
get_atomic_ent_value
(
ir_entity
*
ent
);
void
set_atomic_ent_value
(
ir_entity
*
ent
,
ir_node
*
val
);
/** the kind (type) of an initializer */
typedef
enum
ir_initializer_kind_t
{
/* initializer containing an ir_node from the const-code irg */
IR_INITIALIZER_CONST
,
/* initializer containing a tarval */
IR_INITIALIZER_TARVAL
,
/* initializes type with default values (usually 0) */
IR_INITIALIZER_NULL
,
/* list of initializers used to initializer a compound or array type */
IR_INITIALIZER_COMPOUND
}
ir_initializer_kind_t
;
/** returns kind of an initializer */
ir_initializer_kind_t
get_initializer_kind
(
const
ir_initializer_t
*
initializer
);
/**
* returns the null initializer (there's only one instance of it in a program )
*/
ir_initializer_t
*
get_initializer_null
(
void
);
/**
* creates an initializer containing a reference to a node on the const-code
* irg.
*/
ir_initializer_t
*
create_initializer_const
(
ir_node
*
value
);
/** creates an initializer containing a single tarval value */
ir_initializer_t
*
create_initializer_tarval
(
tarval
*
tv
);
/** return value contained in a const initializer */
ir_node
*
get_initializer_const_value
(
const
ir_initializer_t
*
initializer
);
/** return value contained in a tarval initializer */
tarval
*
get_initializer_tarval_value
(
const
ir_initializer_t
*
initialzier
);
/** creates a compound initializer which holds @p n_entries entries */
ir_initializer_t
*
create_initializer_compound
(
unsigned
n_entries
);
/** returns the number of entries in a compound initializer */
unsigned
get_initializer_compound_n_entries
(
const
ir_initializer_t
*
initializer
);
/** sets entry with index @p index to the initializer @p value */
void
set_initializer_compound_value
(
ir_initializer_t
*
initializer
,
unsigned
index
,
ir_initializer_t
*
value
);
/** returns the value with index @p index of a compound initializer */
ir_initializer_t
*
get_initializer_compound_value
(
const
ir_initializer_t
*
initializer
,
unsigned
index
);
/** Creates a new compound graph path of given length. */
compound_graph_path
*
new_compound_graph_path
(
ir_type
*
tp
,
int
length
);
...
...
@@ -515,6 +564,10 @@ ir_entity *get_compound_ent_value_member(ir_entity *ent, int pos);
/** Sets the path at pos 0 */
void
set_compound_ent_value
(
ir_entity
*
ent
,
ir_node
*
val
,
ir_entity
*
member
,
int
pos
);
void
set_entity_initializer
(
ir_entity
*
entity
,
ir_initializer_t
*
initializer
);
ir_initializer_t
*
get_entity_initializer
(
const
ir_entity
*
entity
);
/** Initializes the entity ent which must be of a one dimensional
array type with the values given in the values array.
The array must have a lower and an upper bound. Keeps the
...
...
ir/ana/cgana.c
View file @
cf79ddfe
...
...
@@ -58,6 +58,7 @@
#include "eset.h"
#include "pmap.h"
#include "array.h"
#include "error.h"
#include "irdump.h"
...
...
@@ -478,6 +479,39 @@ static void free_ana_walker(ir_node *node, void *env) {
set_irn_link
(
node
,
NULL
);
}
static
void
add_method_address_intitialzer
(
ir_initializer_t
*
initializer
,
eset
*
set
)
{
switch
(
initializer
->
kind
)
{
case
IR_INITIALIZER_CONST
:
{
ir_node
*
n
=
initializer
->
consti
.
value
;
/* let's check if it's the address of a function */
if
(
is_SymConst_addr_ent
(
n
))
{
ir_entity
*
ent
=
get_SymConst_entity
(
n
);
if
(
is_Method_type
(
get_entity_type
(
ent
)))
eset_insert
(
set
,
ent
);
}
return
;
}
case
IR_INITIALIZER_TARVAL
:
case
IR_INITIALIZER_NULL
:
return
;
case
IR_INITIALIZER_COMPOUND
:
{
size_t
i
;
for
(
i
=
0
;
i
<
initializer
->
compound
.
n_initializers
;
++
i
)
{
ir_initializer_t
*
sub_initializer
=
initializer
->
compound
.
initializers
[
i
];
add_method_address_intitialzer
(
sub_initializer
,
set
);
}
return
;
}
}
panic
(
"invalid initializer found"
);
}
/**
* Add all method addresses in global initializers to the set.
*
...
...
@@ -499,7 +533,9 @@ static void add_method_address(ir_entity *ent, eset *set)
if
(
get_entity_variability
(
ent
)
==
variability_uninitialized
)
return
;
if
(
is_atomic_entity
(
ent
))
{
if
(
ent
->
has_initializer
)
{
}
else
if
(
is_atomic_entity
(
ent
))
{
tp
=
get_entity_type
(
ent
);
/* ignore methods: these of course reference it's address */
...
...
ir/ana/irmemory.c
View file @
cf79ddfe
...
...
@@ -41,6 +41,7 @@
#include "irgwalk.h"
#include "irprintf.h"
#include "debug.h"
#include "error.h"
/** The debug handle. */
DEBUG_ONLY
(
static
firm_dbg_module_t
*
dbg
=
NULL
;)
...
...
@@ -952,6 +953,36 @@ static void init_taken_flag(ir_type * tp) {
}
}
/* init_taken_flag */
static
void
check_initializer_nodes
(
ir_initializer_t
*
initializer
)
{
switch
(
initializer
->
kind
)
{
case
IR_INITIALIZER_CONST
:
{
ir_node
*
n
=
initializer
->
consti
.
value
;
/* let's check if it's an address */
if
(
is_SymConst_addr_ent
(
n
))
{
ir_entity
*
ent
=
get_SymConst_entity
(
n
);
set_entity_address_taken
(
ent
,
ir_address_taken
);
}
return
;
}
case
IR_INITIALIZER_TARVAL
:
case
IR_INITIALIZER_NULL
:
return
;
case
IR_INITIALIZER_COMPOUND
:
{
size_t
i
;
for
(
i
=
0
;
i
<
initializer
->
compound
.
n_initializers
;
++
i
)
{
ir_initializer_t
*
sub_initializer
=
initializer
->
compound
.
initializers
[
i
];
check_initializer_nodes
(
sub_initializer
);
}
return
;
}
}
panic
(
"invalid initialzier found"
);
}
/**
* Mark all entities used in the initializer for the given entity as address taken
*/
...
...
@@ -968,7 +999,9 @@ static void check_initializer(ir_entity *ent) {
if
(
is_Method_type
(
get_entity_type
(
ent
)))
return
;
if
(
is_atomic_entity
(
ent
))
{
if
(
ent
->
has_initializer
)
{
check_initializer_nodes
(
ent
->
attr
.
initializer
);
}
else
if
(
is_atomic_entity
(
ent
))
{
/* let's check if it's an address */
n
=
get_atomic_ent_value
(
ent
);
if
(
is_SymConst_addr_ent
(
n
))
{
...
...
ir/be/begnuas.c
View file @
cf79ddfe
...
...
@@ -40,6 +40,7 @@
#include "irnode.h"
#include "irprog.h"
#include "pdeq.h"
#include "entity_t.h"
#include "error.h"
#include "be_t.h"
...
...
@@ -353,7 +354,7 @@ static void do_dump_atomic_init(be_gas_decl_env_t *env, obstack_t *obst,
* @param obst an obstack the output is written to
* @param size the size in bytes
*/
static
void
dump_size_type
(
obstack_t
*
obst
,
in
t
size
)
{
static
void
dump_size_type
(
obstack_t
*
obst
,
size_
t
size
)
{
switch
(
size
)
{
case
1
:
...
...
@@ -409,6 +410,40 @@ static void dump_atomic_init(be_gas_decl_env_t *env, obstack_t *obst,
/* Routines to dump global variables */
/************************************************************************/
static
int
initializer_is_string_const
(
const
ir_initializer_t
*
initializer
)
{
size_t
i
,
len
;
if
(
initializer
->
kind
!=
IR_INITIALIZER_COMPOUND
)
return
0
;
len
=
initializer
->
compound
.
n_initializers
;
for
(
i
=
0
;
i
<
len
;
++
i
)
{
int
c
;
tarval
*
tv
;
ir_mode
*
mode
;
ir_initializer_t
*
sub_initializer
=
initializer
->
compound
.
initializers
[
i
];
if
(
sub_initializer
->
kind
!=
IR_INITIALIZER_TARVAL
)
return
0
;
tv
=
sub_initializer
->
tarval
.
value
;
mode
=
get_tarval_mode
(
tv
);
if
(
!
mode_is_int
(
mode
)
||
get_mode_size_bits
(
mode
)
!=
get_mode_size_bits
(
mode_Bs
))
return
0
;
c
=
get_tarval_long
(
tv
);
if
((
i
<
len
-
1
&&
!
(
isgraph
(
c
)
||
isspace
(
c
)))
||
(
i
>=
len
-
1
&&
c
!=
0
))
return
0
;
}
return
1
;
}
/**
* Determine if an entity is a string constant
* @param ent The entity
...
...
@@ -439,18 +474,23 @@ static int ent_is_string_const(ir_entity *ent)
||
get_mode_size_bits
(
mode
)
!=
get_mode_size_bits
(
mode_Bs
))
return
0
;
/* if it contains only printable chars and a 0 at the end */
n
=
get_compound_ent_n_values
(
ent
);
for
(
i
=
0
;
i
<
n
;
++
i
)
{
ir_node
*
irn
=
get_compound_ent_value
(
ent
,
i
);
if
(
!
is_Const
(
irn
))
return
0
;
c
=
(
int
)
get_tarval_long
(
get_Const_tarval
(
irn
));
if
((
i
<
n
-
1
&&
!
(
isgraph
(
c
)
||
isspace
(
c
)))
||
(
i
==
n
-
1
&&
c
!=
'\0'
))
return
0
;
if
(
ent
->
has_initializer
)
{
/* TODO */
return
0
;
}
else
{
/* if it contains only printable chars and a 0 at the end */
n
=
get_compound_ent_n_values
(
ent
);
for
(
i
=
0
;
i
<
n
;
++
i
)
{
ir_node
*
irn
=
get_compound_ent_value
(
ent
,
i
);
if
(
!
is_Const
(
irn
))
return
0
;
c
=
(
int
)
get_tarval_long
(
get_Const_tarval
(
irn
));
if
((
i
<
n
-
1
&&
!
(
isgraph
(
c
)
||
isspace
(
c
)))
||
(
i
==
n
-
1
&&
c
!=
'\0'
))
return
0
;
}
}
/* then we can emit it as a string constant */
...
...
@@ -506,19 +546,299 @@ static void dump_string_cst(obstack_t *obst, ir_entity *ent)
}
}
static
void
dump_string_initializer
(
obstack_t
*
obst
,
const
ir_initializer_t
*
initializer
)
{
size_t
i
,
len
;
obstack_printf
(
obst
,
"
\t
.string
\"
"
);
len
=
initializer
->
compound
.
n_initializers
;
for
(
i
=
0
;
i
<
len
;
++
i
)
{
const
ir_initializer_t
*
sub_initializer
=
get_initializer_compound_value
(
initializer
,
i
);
tarval
*
tv
=
get_initializer_tarval_value
(
sub_initializer
);
int
c
=
get_tarval_long
(
tv
);
switch
(
c
)
{
case
'"'
:
obstack_printf
(
obst
,
"
\\\"
"
);
break
;
case
'\n'
:
obstack_printf
(
obst
,
"
\\
n"
);
break
;
case
'\r'
:
obstack_printf
(
obst
,
"
\\
r"
);
break
;
case
'\t'
:
obstack_printf
(
obst
,
"
\\
t"
);
break
;
case
'\\'
:
obstack_printf
(
obst
,
"
\\\\
"
);
break
;
default
:
if
(
isprint
(
c
))
obstack_printf
(
obst
,
"%c"
,
c
);
else
obstack_printf
(
obst
,
"
\\
%o"
,
c
);
break
;
}
}
obstack_printf
(
obst
,
"
\"\n
"
);
}
enum
normal_or_bitfield_kind
{
NORMAL
=
0
,
TARVAL
,
BITFIELD
};
typedef
struct
{
enum
normal_or_bitfield_kind
kind
;
union
{
ir_node
*
value
;
unsigned
char
bf_val
;
ir_node
*
value
;
tarval
*
tarval
;
unsigned
char
bf_val
;
}
v
;
}
normal_or_bitfield
;
static
int
is_type_variable_size
(
ir_type
*
type
)
{
(
void
)
type
;
/* TODO */
return
0
;
}
static
size_t
get_initializer_size
(
const
ir_initializer_t
*
initializer
,
ir_type
*
type
)
{
switch
(
get_initializer_kind
(
initializer
))
{
case
IR_INITIALIZER_TARVAL
:
{
tarval
*
tv
=
get_initializer_tarval_value
(
initializer
);
assert
(
get_tarval_mode
(
tv
)
==
get_type_mode
(
type
));
return
get_type_size_bytes
(
type
);
}
case
IR_INITIALIZER_CONST
:
case
IR_INITIALIZER_NULL
:
return
get_type_size_bytes
(
type
);
case
IR_INITIALIZER_COMPOUND
:
{
if
(
!
is_type_variable_size
(
type
))
{
return
get_type_size_bytes
(
type
);
}
else
{
unsigned
n_entries
=
get_initializer_compound_n_entries
(
initializer
);
unsigned
i
;
unsigned
initializer_size
=
get_type_size_bytes
(
type
);
for
(
i
=
0
;
i
<
n_entries
;
++
i
)
{
ir_entity
*
entity
=
get_compound_member
(
type
,
i
);
ir_type
*
type
=
get_entity_type
(
entity
);
const
ir_initializer_t
*
sub_initializer
=
get_initializer_compound_value
(
initializer
,
i
);
unsigned
offset
=
get_entity_offset
(
entity
);
unsigned
size
=
get_initializer_size
(
sub_initializer
,
type
);
if
(
offset
+
size
>
initializer_size
)
{
initializer_size
=
offset
+
size
;
}
}
return
initializer_size
;
}
}
}
panic
(
"found invalid initializer"
);
}
#ifndef NDEBUG
static
normal_or_bitfield
*
glob_vals
;
static
size_t
max_vals
;
#endif
static
void
dump_ir_initializer
(
normal_or_bitfield
*
vals
,
const
ir_initializer_t
*
initializer
,
ir_type
*
type
)
{
assert
((
size_t
)
(
vals
-
glob_vals
)
<
max_vals
);
switch
(
get_initializer_kind
(
initializer
))
{
case
IR_INITIALIZER_NULL
:
return
;
case
IR_INITIALIZER_TARVAL
:
{
size_t
i
;
assert
(
vals
->
kind
!=
BITFIELD
);
vals
->
kind
=
TARVAL
;
vals
->
v
.
tarval
=
get_initializer_tarval_value
(
initializer
);
assert
(
get_type_mode
(
type
)
==
get_tarval_mode
(
vals
->
v
.
tarval
));
for
(
i
=
1
;
i
<
get_type_size_bytes
(
type
);
++
i
)
{
vals
[
i
].
kind
=
NORMAL
;
vals
[
i
].
v
.
value
=
NULL
;
}
return
;
}
case
IR_INITIALIZER_CONST
:
{
size_t
i
;
assert
(
vals
->
kind
!=
BITFIELD
);
vals
->
kind
=
NORMAL
;
vals
->
v
.
value
=
get_initializer_const_value
(
initializer
);
for
(
i
=
1
;
i
<
get_type_size_bytes
(
type
);
++
i
)
{
vals
[
i
].
kind
=
NORMAL
;
vals
[
i
].
v
.
value
=
NULL
;
}
return
;
}
case
IR_INITIALIZER_COMPOUND
:
{
size_t
i
=
0
;
size_t
n
=
get_initializer_compound_n_entries
(
initializer
);
if
(
is_Array_type
(
type
))
{
ir_type
*
element_type
=
get_array_element_type
(
type
);
size_t
skip
=
get_type_size_bytes
(
element_type
);
size_t
alignment
=
get_type_alignment_bytes
(
element_type
);
size_t
misalign
=
skip
%
alignment
;
if
(
misalign
!=
0
)
{
skip
+=
alignment
-
misalign
;
}
for
(
i
=
0
;
i
<
n
;
++
i
)
{
ir_initializer_t
*
sub_initializer
=
get_initializer_compound_value
(
initializer
,
i
);
dump_ir_initializer
(
vals
,
sub_initializer
,
element_type
);
vals
+=
skip
;
}
}
else
{
assert
(
is_compound_type
(
type
));
size_t
n_members
=
get_compound_n_members
(
type
);
size_t
i
;
for
(
i
=
0
;
i
<
n_members
;
++
i
)
{
ir_entity
*
member
=
get_compound_member
(
type
,
i
);
size_t
offset
=
get_entity_offset
(
member
);
ir_type
*
subtype
=
get_entity_type
(
member
);
ir_initializer_t
*
sub_initializer
;
assert
(
i
<
get_initializer_compound_n_entries
(
initializer
));
sub_initializer
=
get_initializer_compound_value
(
initializer
,
i
);
dump_ir_initializer
(
&
vals
[
offset
],
sub_initializer
,
subtype
);
}
}
return
;
}
}
#if 0
/* collect the values and store them at the offsets */
for (i = 0; i < n; ++i) {
unsigned offset = get_compound_ent_value_offset_bytes(ent, i);
int offset_bits = get_compound_ent_value_offset_bit_remainder(ent, i);
ir_node *value = get_compound_ent_value(ent, i);
int value_len = get_mode_size_bits(get_irn_mode(value));
assert(offset_bits >= 0);
if (offset_bits != 0 ||
(value_len != 8 && value_len != 16 && value_len != 32 && value_len != 64)) {
tarval *tv = get_atomic_init_tv(value);
unsigned char curr_bits, last_bits = 0;
if (tv == NULL) {
panic("Couldn't get numeric value for bitfield initializer '%s'\n",
get_entity_ld_name(ent));
}
/* normalize offset */
offset += offset_bits >> 3;
offset_bits &= 7;
for (j = 0; value_len + offset_bits > 0; ++j) {
assert(offset + j < last_ofs);
assert(vals[offset + j].kind == BITFIELD || vals[offset + j].v.value == NULL);
vals[offset + j].kind = BITFIELD;
curr_bits = get_tarval_sub_bits(tv, j);
vals[offset + j].v.bf_val |= (last_bits >> (8 - offset_bits)) | (curr_bits << offset_bits);
value_len -= 8;
last_bits = curr_bits;
}
} else {
int i;
assert(offset < last_ofs);
assert(vals[offset].kind == NORMAL);
for (i = 1; i < value_len / 8; ++i) {
assert(vals[offset + i].v.value == NULL);
}
vals[offset].v.value = value;
}
}
#endif
}
static
void
dump_initializer
(
be_gas_decl_env_t
*
env
,
obstack_t
*
obst
,
ir_entity
*
entity
)
{
const
ir_initializer_t
*
initializer
=
entity
->
attr
.
initializer
;
ir_type
*
type
;
normal_or_bitfield
*
vals
;
size_t
size
;
size_t
k
;
if
(
initializer_is_string_const
(
initializer
))
{
dump_string_initializer
(
obst
,
initializer
);
return
;
}
type
=
get_entity_type
(
entity
);
size
=
get_initializer_size
(
initializer
,
type
);
/*
* In the worst case, every initializer allocates one byte.
* Moreover, initializer might be big, do not allocate on stack.
*/
vals
=
xcalloc
(
size
,
sizeof
(
vals
[
0
]));
#ifndef NDEBUG
glob_vals
=
vals
;
max_vals
=
size
;
#endif
dump_ir_initializer
(
vals
,
initializer
,
type
);
/* now write values sorted */
for
(
k
=
0
;
k
<
size
;
)
{
int
space
=
0
,
skip
=
0
;
if
(
vals
[
k
].
kind
==
NORMAL
)
{
if
(
vals
[
k
].
v
.
value
!=
NULL
)
{
dump_atomic_init
(
env
,
obst
,
vals
[
k
].
v
.
value
);
skip
=
get_mode_size_bytes
(
get_irn_mode
(
vals
[
k
].
v
.
value
))
-
1
;
}
else
{
space
=
1
;
}
}
else
if
(
vals
[
k
].
kind
==
TARVAL
)
{
tarval
*
tv
=
vals
[
k
].
v
.
tarval
;
size_t
size
=
get_mode_size_bytes
(
get_tarval_mode
(
tv
));
assert
(
tv
!=
NULL
);
skip
=
size
-
1
;
dump_size_type
(
obst
,
size
);
dump_arith_tarval
(
obst
,
tv
,
size
);
obstack_1grow
(
obst
,
'\n'
);
}
else
{
assert
(
vals
[
k
].
kind
==
BITFIELD
);
obstack_printf
(
obst
,
"
\t
.byte
\t
%d
\n
"
,
vals
[
k
].
v
.
bf_val
);
}
++
k
;
while
(
k
<
size
&&
vals
[
k
].
kind
==
NORMAL
&&
vals
[
k
].
v
.
value
==
NULL
)
{
++
space
;
++
k
;
}
space
-=
skip
;
assert
(
space
>=
0
);
/* a gap */
if
(
space
>
0
)
obstack_printf
(
obst
,
"
\t
.skip
\t
%d
\n
"
,
space
);
}
xfree
(
vals
);
}
/**
* Dump an initializer for a compound entity.
*/
...
...
@@ -526,9 +846,16 @@ static void dump_compound_init(be_gas_decl_env_t *env, obstack_t *obst,
ir_entity
*
ent
)
{
normal_or_bitfield
*
vals
;
int
i
,
j
,
n
=
get_compound_ent_n_values
(
ent
)
;
int
i
,
j
,
n
;
unsigned
k
,
last_ofs
;
if
(
ent
->
has_initializer
)
{
dump_initializer
(
env
,
obst
,
ent
);
return
;
}
n
=
get_compound_ent_n_values
(
ent
);
/* Find the initializer size. Sorrily gcc support a nasty feature:
The last field of a compound may be a flexible array. This allows
initializers bigger than the type size. */
...
...
@@ -695,6 +1022,8 @@ static void dump_global(be_gas_decl_env_t *env, ir_entity *ent, int emit_commons
obstack_printf
(
obst
,
"
\t
.comm %s,%u # %u
\n
"
,
ld_name
,
get_type_size_bytes
(
type
),
align
);
break
;
case
GAS_FLAVOUR_MAX
:
panic
(
"invalid gas flavour selected"
);
}
}
else
{
obstack_printf
(
obst
,
"
\t
.zero %u
\n
"
,
get_type_size_bytes
(
type
));
...
...
ir/tr/entity.c
View file @
cf79ddfe
...
...
@@ -40,13 +40,13 @@
#include "irhooks.h"
#include "irprintf.h"
/* All this is needed to build the constant node for methods: */
#include "irprog_t.h"
#include "ircons.h"
#include "tv_t.h"
#include "irdump.h"
/* for output if errors occur. */
#include "irdump.h"
#include "irgraph_t.h"
#include "callgraph.h"
/* for dumping debug output */
#include "callgraph.h"
/**