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
23b80d8b
Commit
23b80d8b
authored
May 16, 2014
by
Matthias Braun
Browse files
abihelper: remove now unused prolog/epilog helpers
parent
f074195d
Changes
2
Hide whitespace changes
Inline
Side-by-side
ir/be/beabihelper.c
View file @
23b80d8b
...
...
@@ -23,345 +23,6 @@
#include "irtools.h"
#include "heights.h"
/**
* An entry in the register state map.
*/
typedef
struct
reg_flag_t
{
const
arch_register_t
*
reg
;
/**< register at an input position.
may be NULL in case of memory input */
arch_register_req_type_t
flags
;
/**< requirement flags for this register. */
}
reg_flag_t
;
/**
* A register state mapping keeps track of the symbol values (=firm nodes)
* to registers. This is useful when constructing straight line code
* like the function prolog or epilog in some architectures.
*/
typedef
struct
register_state_mapping_t
{
ir_node
**
value_map
;
/**< mapping of state indices to values */
size_t
**
reg_index_map
;
/**< mapping of regclass,regnum to an index
into the value_map */
reg_flag_t
*
regs
;
/**< registers (and memory values) that form a
state */
}
register_state_mapping_t
;
/**
* The environment for all helper functions.
*/
struct
beabi_helper_env_t
{
ir_graph
*
irg
;
/**< the graph we operate on */
register_state_mapping_t
prolog
;
/**< the register state map for the prolog */
register_state_mapping_t
epilog
;
/**< the register state map for the epilog */
};
/**
* Create a new empty register state map for the given
* architecture.
*
* @param rsm the register state map to be initialized
* @param arch_env the architecture environment
*
* After this call, the register map is initialized to empty.
*/
static
void
prepare_rsm
(
register_state_mapping_t
*
rsm
,
const
arch_env_t
*
arch_env
)
{
unsigned
n_reg_classes
=
arch_env
->
n_register_classes
;
unsigned
c
;
reg_flag_t
memory
=
{
NULL
,
arch_register_req_type_none
};
rsm
->
regs
=
NEW_ARR_F
(
reg_flag_t
,
0
);
/* memory input at 0 */
ARR_APP1
(
reg_flag_t
,
rsm
->
regs
,
memory
);
rsm
->
value_map
=
NULL
;
rsm
->
reg_index_map
=
XMALLOCN
(
size_t
*
,
n_reg_classes
);
for
(
c
=
0
;
c
<
n_reg_classes
;
++
c
)
{
const
arch_register_class_t
*
cls
=
&
arch_env
->
register_classes
[
c
];
unsigned
n_regs
=
arch_register_class_n_regs
(
cls
);
unsigned
r
;
rsm
->
reg_index_map
[
c
]
=
XMALLOCN
(
size_t
,
n_regs
);
for
(
r
=
0
;
r
<
n_regs
;
++
r
)
{
rsm
->
reg_index_map
[
c
][
r
]
=
(
size_t
)
-
1
;
}
}
}
/**
* Destroy a register state map for the given
* architecture.
*
* @param rsm the register state map to be destroyed
* @param arch_env the architecture environment
*
* After this call, the register map is initialized to empty.
*/
static
void
free_rsm
(
register_state_mapping_t
*
rsm
,
const
arch_env_t
*
arch_env
)
{
unsigned
n_reg_classes
=
arch_env
->
n_register_classes
;
unsigned
c
;
for
(
c
=
0
;
c
<
n_reg_classes
;
++
c
)
{
free
(
rsm
->
reg_index_map
[
c
]);
}
free
(
rsm
->
reg_index_map
);
if
(
rsm
->
value_map
!=
NULL
)
DEL_ARR_F
(
rsm
->
value_map
);
DEL_ARR_F
(
rsm
->
regs
);
rsm
->
regs
=
NULL
;
rsm
->
reg_index_map
=
NULL
;
rsm
->
value_map
=
NULL
;
}
/**
* Remove all registers from a register state map.
*
* @param rsm the register state map to be destroyed
* @param arch_env the architecture environment
*/
static
void
rsm_clear_regs
(
register_state_mapping_t
*
rsm
,
const
arch_env_t
*
arch_env
)
{
unsigned
n_reg_classes
=
arch_env
->
n_register_classes
;
unsigned
c
;
reg_flag_t
memory
=
{
NULL
,
arch_register_req_type_none
};
for
(
c
=
0
;
c
<
n_reg_classes
;
++
c
)
{
const
arch_register_class_t
*
cls
=
&
arch_env
->
register_classes
[
c
];
unsigned
n_regs
=
arch_register_class_n_regs
(
cls
);
unsigned
r
;
for
(
r
=
0
;
r
<
n_regs
;
++
r
)
{
rsm
->
reg_index_map
[
c
][
r
]
=
(
size_t
)
-
1
;
}
}
ARR_RESIZE
(
reg_flag_t
,
rsm
->
regs
,
0
);
ARR_APP1
(
reg_flag_t
,
rsm
->
regs
,
memory
);
if
(
rsm
->
value_map
!=
NULL
)
{
DEL_ARR_F
(
rsm
->
value_map
);
rsm
->
value_map
=
NULL
;
}
}
/**
* Add a register and its constraint flags to a register state map
* and return its index inside the map.
*/
static
size_t
rsm_add_reg
(
register_state_mapping_t
*
rsm
,
const
arch_register_t
*
reg
,
arch_register_req_type_t
flags
)
{
size_t
input_idx
=
ARR_LEN
(
rsm
->
regs
);
int
cls_idx
=
reg
->
reg_class
->
index
;
int
reg_idx
=
reg
->
index
;
reg_flag_t
regflag
=
{
reg
,
flags
};
/* we must not have used get_value yet */
assert
(
rsm
->
reg_index_map
[
cls_idx
][
reg_idx
]
==
(
size_t
)
-
1
);
rsm
->
reg_index_map
[
cls_idx
][
reg_idx
]
=
input_idx
;
ARR_APP1
(
reg_flag_t
,
rsm
->
regs
,
regflag
);
if
(
rsm
->
value_map
!=
NULL
)
{
ARR_APP1
(
ir_node
*
,
rsm
->
value_map
,
NULL
);
assert
(
ARR_LEN
(
rsm
->
value_map
)
==
ARR_LEN
(
rsm
->
regs
));
}
return
input_idx
;
}
/**
* Retrieve the ir_node stored at the given index in the register state map.
*/
static
ir_node
*
rsm_get_value
(
register_state_mapping_t
*
rsm
,
size_t
index
)
{
assert
(
index
<
ARR_LEN
(
rsm
->
value_map
));
return
rsm
->
value_map
[
index
];
}
/**
* Retrieve the ir_node occupying the given register in the register state map.
*/
static
ir_node
*
rsm_get_reg_value
(
register_state_mapping_t
*
rsm
,
const
arch_register_t
*
reg
)
{
int
cls_idx
=
reg
->
reg_class
->
index
;
int
reg_idx
=
reg
->
index
;
size_t
input_idx
=
rsm
->
reg_index_map
[
cls_idx
][
reg_idx
];
return
rsm_get_value
(
rsm
,
input_idx
);
}
/**
* Enter a ir_node at the given index in the register state map.
*/
static
void
rsm_set_value
(
register_state_mapping_t
*
rsm
,
size_t
index
,
ir_node
*
value
)
{
assert
(
index
<
ARR_LEN
(
rsm
->
value_map
));
rsm
->
value_map
[
index
]
=
value
;
}
/**
* Enter a ir_node at the given register in the register state map.
*/
static
void
rsm_set_reg_value
(
register_state_mapping_t
*
rsm
,
const
arch_register_t
*
reg
,
ir_node
*
value
)
{
int
cls_idx
=
reg
->
reg_class
->
index
;
int
reg_idx
=
reg
->
index
;
size_t
input_idx
=
rsm
->
reg_index_map
[
cls_idx
][
reg_idx
];
rsm_set_value
(
rsm
,
input_idx
,
value
);
}
beabi_helper_env_t
*
be_abihelper_prepare
(
ir_graph
*
irg
)
{
const
arch_env_t
*
arch_env
=
be_get_irg_arch_env
(
irg
);
beabi_helper_env_t
*
env
=
XMALLOCZ
(
beabi_helper_env_t
);
env
->
irg
=
irg
;
prepare_rsm
(
&
env
->
prolog
,
arch_env
);
prepare_rsm
(
&
env
->
epilog
,
arch_env
);
return
env
;
}
void
be_abihelper_finish
(
beabi_helper_env_t
*
env
)
{
const
arch_env_t
*
arch_env
=
be_get_irg_arch_env
(
env
->
irg
);
free_rsm
(
&
env
->
prolog
,
arch_env
);
if
(
env
->
epilog
.
reg_index_map
!=
NULL
)
{
free_rsm
(
&
env
->
epilog
,
arch_env
);
}
free
(
env
);
}
void
be_prolog_add_reg
(
beabi_helper_env_t
*
env
,
const
arch_register_t
*
reg
,
arch_register_req_type_t
flags
)
{
rsm_add_reg
(
&
env
->
prolog
,
reg
,
flags
);
}
ir_node
*
be_prolog_create_start
(
beabi_helper_env_t
*
env
,
dbg_info
*
dbgi
,
ir_node
*
block
)
{
int
n_start_outs
=
ARR_LEN
(
env
->
prolog
.
regs
);
ir_node
*
start
=
be_new_Start
(
dbgi
,
block
,
n_start_outs
);
int
o
;
assert
(
env
->
prolog
.
value_map
==
NULL
);
env
->
prolog
.
value_map
=
NEW_ARR_F
(
ir_node
*
,
n_start_outs
);
for
(
o
=
0
;
o
<
n_start_outs
;
++
o
)
{
const
reg_flag_t
*
regflag
=
&
env
->
prolog
.
regs
[
o
];
const
arch_register_t
*
reg
=
regflag
->
reg
;
ir_node
*
proj
;
if
(
reg
==
NULL
)
{
arch_set_irn_register_req_out
(
start
,
o
,
arch_no_register_req
);
proj
=
new_r_Proj
(
start
,
mode_M
,
o
);
}
else
{
be_set_constr_single_reg_out
(
start
,
o
,
regflag
->
reg
,
regflag
->
flags
);
arch_set_irn_register_out
(
start
,
o
,
regflag
->
reg
);
proj
=
new_r_Proj
(
start
,
reg
->
reg_class
->
mode
,
o
);
}
env
->
prolog
.
value_map
[
o
]
=
proj
;
}
return
start
;
}
ir_node
*
be_prolog_get_reg_value
(
beabi_helper_env_t
*
env
,
const
arch_register_t
*
reg
)
{
return
rsm_get_reg_value
(
&
env
->
prolog
,
reg
);
}
ir_node
*
be_prolog_get_memory
(
beabi_helper_env_t
*
env
)
{
return
rsm_get_value
(
&
env
->
prolog
,
0
);
}
void
be_prolog_set_reg_value
(
beabi_helper_env_t
*
env
,
const
arch_register_t
*
reg
,
ir_node
*
value
)
{
rsm_set_reg_value
(
&
env
->
prolog
,
reg
,
value
);
}
void
be_prolog_set_memory
(
beabi_helper_env_t
*
env
,
ir_node
*
value
)
{
rsm_set_value
(
&
env
->
prolog
,
0
,
value
);
}
void
be_epilog_begin
(
beabi_helper_env_t
*
env
)
{
const
arch_env_t
*
arch_env
=
be_get_irg_arch_env
(
env
->
irg
);
rsm_clear_regs
(
&
env
->
epilog
,
arch_env
);
env
->
epilog
.
value_map
=
NEW_ARR_F
(
ir_node
*
,
1
);
env
->
epilog
.
value_map
[
0
]
=
NULL
;
}
void
be_epilog_add_reg
(
beabi_helper_env_t
*
env
,
const
arch_register_t
*
reg
,
arch_register_req_type_t
flags
,
ir_node
*
value
)
{
size_t
index
=
rsm_add_reg
(
&
env
->
epilog
,
reg
,
flags
);
rsm_set_value
(
&
env
->
epilog
,
index
,
value
);
}
void
be_epilog_set_reg_value
(
beabi_helper_env_t
*
env
,
const
arch_register_t
*
reg
,
ir_node
*
value
)
{
rsm_set_reg_value
(
&
env
->
epilog
,
reg
,
value
);
}
void
be_epilog_set_memory
(
beabi_helper_env_t
*
env
,
ir_node
*
value
)
{
rsm_set_value
(
&
env
->
epilog
,
0
,
value
);
}
ir_node
*
be_epilog_get_reg_value
(
beabi_helper_env_t
*
env
,
const
arch_register_t
*
reg
)
{
return
rsm_get_reg_value
(
&
env
->
epilog
,
reg
);
}
ir_node
*
be_epilog_get_memory
(
beabi_helper_env_t
*
env
)
{
return
rsm_get_value
(
&
env
->
epilog
,
0
);
}
ir_node
*
be_epilog_create_return
(
beabi_helper_env_t
*
env
,
dbg_info
*
dbgi
,
ir_node
*
block
)
{
size_t
n_return_in
=
ARR_LEN
(
env
->
epilog
.
regs
);
ir_node
**
in
=
env
->
epilog
.
value_map
;
int
n_res
=
1
;
/* TODO */
unsigned
pop
=
0
;
/* TODO */
size_t
i
;
assert
(
ARR_LEN
(
env
->
epilog
.
value_map
)
==
n_return_in
);
ir_node
*
const
ret
=
be_new_Return
(
dbgi
,
block
,
n_res
,
pop
,
n_return_in
,
in
);
for
(
i
=
0
;
i
<
n_return_in
;
++
i
)
{
const
reg_flag_t
*
regflag
=
&
env
->
epilog
.
regs
[
i
];
const
arch_register_t
*
reg
=
regflag
->
reg
;
if
(
reg
!=
NULL
)
{
be_set_constr_single_reg_in
(
ret
,
i
,
reg
,
arch_register_req_type_none
);
}
}
rsm_clear_regs
(
&
env
->
epilog
,
be_get_irg_arch_env
(
env
->
irg
));
return
ret
;
}
/**
* Tests whether a node has a real user and is not just kept by the End or
* Anchor node
...
...
ir/be/beabihelper.h
View file @
23b80d8b
...
...
@@ -16,83 +16,8 @@
#include "be_types.h"
#include "bearch.h"
typedef
struct
beabi_helper_env_t
beabi_helper_env_t
;
typedef
struct
be_stackorder_t
be_stackorder_t
;
/**
* Creates a helper object for the ABI constraint handling.
*/
beabi_helper_env_t
*
be_abihelper_prepare
(
ir_graph
*
irg
);
/**
* Terminates a helper object for the ABI constraint handling.
*/
void
be_abihelper_finish
(
beabi_helper_env_t
*
env
);
/**
* Mark a registers value at the beginning of the function as significant.
* This is necessary for things like:
* - Callee-Save registers (we need to restore that value at the end)
* - Parameters passed in registers
* - stack pointer, base pointer, ...
* It is possible to specify additional irn flags (useful to mark a value
* as ignore or produces_sp).
*/
void
be_prolog_add_reg
(
beabi_helper_env_t
*
env
,
const
arch_register_t
*
reg
,
arch_register_req_type_t
flags
);
/**
* Creates a start node.
* Must be called after all prolog_add_reg calls
*/
ir_node
*
be_prolog_create_start
(
beabi_helper_env_t
*
env
,
dbg_info
*
dbgi
,
ir_node
*
block
);
/**
* Get "value" of a register.
* This usually creates a Proj node for the start-node.
* Or returns the value set by a abi_helper_set_reg_value call
*/
ir_node
*
be_prolog_get_reg_value
(
beabi_helper_env_t
*
env
,
const
arch_register_t
*
reg
);
ir_node
*
be_prolog_get_memory
(
beabi_helper_env_t
*
env
);
/**
* Set current register value.
*/
void
be_prolog_set_reg_value
(
beabi_helper_env_t
*
env
,
const
arch_register_t
*
reg
,
ir_node
*
value
);
void
be_prolog_set_memory
(
beabi_helper_env_t
*
env
,
ir_node
*
value
);
/**
* Set value of register at the end of the function. Necessary for:
* - Callee-save registers
* - Return values in registers
* - stack pointer, base pointer
*/
void
be_epilog_add_reg
(
beabi_helper_env_t
*
env
,
const
arch_register_t
*
reg
,
arch_register_req_type_t
flags
,
ir_node
*
value
);
void
be_epilog_set_reg_value
(
beabi_helper_env_t
*
env
,
const
arch_register_t
*
reg
,
ir_node
*
value
);
ir_node
*
be_epilog_get_reg_value
(
beabi_helper_env_t
*
env
,
const
arch_register_t
*
reg
);
void
be_epilog_set_memory
(
beabi_helper_env_t
*
env
,
ir_node
*
value
);
ir_node
*
be_epilog_get_memory
(
beabi_helper_env_t
*
env
);
void
be_epilog_begin
(
beabi_helper_env_t
*
env
);
/**
* Create return node and finishes epilog handling
*/
ir_node
*
be_epilog_create_return
(
beabi_helper_env_t
*
env
,
dbg_info
*
dbgi
,
ir_node
*
block
);
/**
* Adds a X->Proj->Keep for each output value of X which has no Proj yet
*/
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment