Cédric Valensi

Sync

Showing 156 changed files with 1222 additions and 644 deletions
......@@ -318,7 +318,7 @@ find_path(RPMBUILD_PATH NAMES rpmbuild) # look for rpmbuild
find_path(DPKG_DEB_PATH NAMES dpkg-deb) # look for dpkg-deb
SET(CPACK_PACKAGE_VERSION_MAJOR "2")
SET(CPACK_PACKAGE_VERSION_MINOR "11")
SET(CPACK_PACKAGE_VERSION_MINOR "12")
SET(CPACK_PACKAGE_VERSION_PATCH "0")
# ---- Check if at least one package generator has been found
......
.\" File generated using by MAQAO.
.TH MAQAO-ANALYZE "1" "2020/07/23" "MAQAO-ANALYZE 2.11.0" "User Commands"
.TH MAQAO-ANALYZE "1" "2020/12/03" "MAQAO-ANALYZE 2.12.0" "User Commands"
.SH NAME
maqao-analyze \- manual page for maqao analyze module.
.SH SYNOPSIS
......
.\" File generated using by MAQAO.
.TH MAQAO-MADRAS "1" "2020/07/23" "MAQAO-MADRAS 2.11.0" "User Commands"
.TH MAQAO-MADRAS "1" "2020/12/03" "MAQAO-MADRAS 2.12.0" "User Commands"
.SH NAME
maqao-madras \- manual page for maqao madras module.
.SH SYNOPSIS
......
.\" File generated using by MAQAO.
.TH MAQAO "1" "2020/07/23" "MAQAO 2.11.0" "User Commands"
.TH MAQAO "1" "2020/12/03" "MAQAO 2.12.0" "User Commands"
.SH NAME
maqao \- manual page for maqao module.
.SH SYNOPSIS
......
......@@ -202,31 +202,54 @@ IF (NOT is_WINDOWS)
ENDIF (NOT is_WINDOWS)
# List dynamic sources #
SET(maqao_sources-dyn $<TARGET_OBJECTS:mmaqao-obj-dyn>
$<TARGET_OBJECTS:mcommon-obj-dyn>
$<TARGET_OBJECTS:masm-obj-dyn>
$<TARGET_OBJECTS:mdisass-obj-dyn>
$<TARGET_OBJECTS:manalyze-obj-dyn>
$<TARGET_OBJECTS:madras-obj-dyn>
$<TARGET_OBJECTS:mtroll-obj-dyn>
$<TARGET_OBJECTS:mpatch-obj-dyn>
$<TARGET_OBJECTS:masmbl-obj-dyn>
${arch_objs-dyn}
$<TARGET_OBJECTS:perf-obj-dyn>
$<TARGET_OBJECTS:dwarf-obj-dyn>
$<TARGET_OBJECTS:elf-obj-dyn>
$<TARGET_OBJECTS:dwarfreader-obj-dyn>
$<TARGET_OBJECTS:mdbg-obj-dyn>
${error_files}
$<TARGET_OBJECTS:madras_lua-obj-dyn>
$<TARGET_OBJECTS:abstract_objects_c_lua-obj-dyn>
$<TARGET_OBJECTS:classes_c_lua-obj-dyn>
)
IF (is_WINDOWS)
SET(maqao_sources-dyn $<TARGET_OBJECTS:mmaqao-obj-dyn>
$<TARGET_OBJECTS:mcommon-obj-dyn>
$<TARGET_OBJECTS:masm-obj-dyn>
$<TARGET_OBJECTS:mdisass-obj-dyn>
$<TARGET_OBJECTS:manalyze-obj-dyn>
$<TARGET_OBJECTS:madras-obj-dyn>
$<TARGET_OBJECTS:mtroll-obj-dyn>
$<TARGET_OBJECTS:mpatch-obj-dyn>
$<TARGET_OBJECTS:masmbl-obj-dyn>
${arch_objs-dyn}
$<TARGET_OBJECTS:perf-obj-dyn>
$<TARGET_OBJECTS:dwarf-obj-dyn>
$<TARGET_OBJECTS:elf-obj-dyn>
$<TARGET_OBJECTS:dwarfreader-obj-dyn>
$<TARGET_OBJECTS:mdbg-obj-dyn>
${error_files}
$<TARGET_OBJECTS:madras_lua-obj-dyn>
$<TARGET_OBJECTS:abstract_objects_c_lua-obj-dyn>
$<TARGET_OBJECTS:classes_c_lua-obj-dyn>
)
ELSE(is_WINDOWS)
SET(maqao_sources-dyn $<TARGET_OBJECTS:mmaqao-obj-static>
$<TARGET_OBJECTS:mcommon-obj-static>
$<TARGET_OBJECTS:masm-obj-static>
$<TARGET_OBJECTS:mdisass-obj-static>
$<TARGET_OBJECTS:manalyze-obj-static>
$<TARGET_OBJECTS:madras-obj-static>
$<TARGET_OBJECTS:mtroll-obj-static>
$<TARGET_OBJECTS:mpatch-obj-static>
$<TARGET_OBJECTS:masmbl-obj-static>
${arch_objs-dyn}
$<TARGET_OBJECTS:perf-obj-static>
$<TARGET_OBJECTS:dwarf-obj-static>
$<TARGET_OBJECTS:elf-obj-static>
$<TARGET_OBJECTS:dwarfreader-obj-static>
$<TARGET_OBJECTS:mdbg-obj-static>
${error_files}
$<TARGET_OBJECTS:madras_lua-obj-static>
$<TARGET_OBJECTS:abstract_objects_c_lua-obj-static>
$<TARGET_OBJECTS:classes_c_lua-obj-static>
)
ENDIF(is_WINDOWS)
IF (NOT is_WINDOWS)
SET(maqao_sources-dyn ${maqao_sources-dyn}
$<TARGET_OBJECTS:fcgi-obj-dyn>
$<TARGET_OBJECTS:fcgx_lua-obj-dyn>
$<TARGET_OBJECTS:madras-module-dyn>)
$<TARGET_OBJECTS:fcgi-obj-static>
$<TARGET_OBJECTS:fcgx_lua-obj-static>
$<TARGET_OBJECTS:madras-module-static>)
ENDIF (NOT is_WINDOWS)
......
......@@ -42,9 +42,12 @@ FILE(GLOB
ADD_LIBRARY(manalyze-obj-static OBJECT ${core_files} ${core_arch_files})
SET_TARGET_PROPERTIES(manalyze-obj-static PROPERTIES COMPILE_FLAGS "${C_STATIC_FLAGS}")
# Create the manalyze object for DYNAMIC libraries/binaries #
ADD_LIBRARY(manalyze-obj-dyn OBJECT ${core_files} ${core_arch_files})
SET_TARGET_PROPERTIES(manalyze-obj-dyn PROPERTIES COMPILE_FLAGS "${C_DYNAMIC_FLAGS}")
IF (is_WINDOWS)
# Create the manalyze object for DYNAMIC libraries/binaries #
ADD_LIBRARY(manalyze-obj-dyn OBJECT ${core_files} ${core_arch_files})
SET_TARGET_PROPERTIES(manalyze-obj-dyn PROPERTIES COMPILE_FLAGS "${C_DYNAMIC_FLAGS}")
SET_TARGET_PROPERTIES (manalyze-obj-dyn PROPERTIES COMPILE_DEFINITIONS "${COMPILE_DEF}")
ENDIF(is_WINDOWS)
# Add definitions flags #
SET(COMPILE_DEF "")
......@@ -52,7 +55,6 @@ foreach(ARCH ${ARCHS})
SET(COMPILE_DEF "${COMPILE_DEF};_ARCHDEF_${ARCH}")
endforeach(ARCH)
SET_TARGET_PROPERTIES (manalyze-obj-static PROPERTIES COMPILE_DEFINITIONS "${COMPILE_DEF}")
SET_TARGET_PROPERTIES (manalyze-obj-dyn PROPERTIES COMPILE_DEFINITIONS "${COMPILE_DEF}")
......
......@@ -107,14 +107,17 @@ list_t *lcore_collect_init_heads(fct_t *f)
DBGMSG("Collecting connected components head in function %s\n", fct_get_name(f));
int i;
list_t* initheads = NULL;
int *cinfos = (int *) lc_malloc(sizeof(int) * f->blocks->length);
const int nb_blocks = fct_get_nb_blocks(f);
if (nb_blocks == 0) return initheads;
for (i = 0; (unsigned int) i < f->blocks->length; i++)
int *cinfos = (int *) lc_malloc(sizeof(int) * nb_blocks);
for (i = 0; i < nb_blocks; i++)
cinfos[i] = 0;
//Process until stability
FOREACH_INQUEUE(f->blocks, blockiter) {
block_t *b1 = GET_DATA_T(block_t*, blockiter);
FOREACH_INARRAY(fct_get_blocks(f), blockiter) {
block_t *b1 = ARRAY_GET_DATA_T(block_t*, blockiter);
if (b1->begin_sequence != NULL) {
if (cinfos[b1->id] == 0) {
if (b1->cfg_node->in == NULL)
......@@ -288,44 +291,45 @@ void lcore_analyze_connected_components(asmfile_t *asmfile)
hashtable_t* marks = hashtable_new(&direct_hash, &direct_equal);
// Iterate over asmfile functions
FOREACH_INQUEUE(asmfile->functions, it_func) {
fct_t* func = GET_DATA_T(fct_t*, it_func);
FOREACH_INARRAY(asmfile_get_fcts (asmfile), it_func) {
fct_t* func = ARRAY_GET_DATA_T(fct_t*, it_func);
if (func->components != NULL)
break;
insn_t* finsn = fct_get_first_insn(func);
block_t* entryblock = insn_get_block(finsn);
func->components = queue_new();
queue_t *tmp_components = queue_new();
fct_upd_blocks_id(func);
// List CC heads for current function -----------------------------------
FOREACH_INQUEUE(func->blocks, it_b) {
block_t* b = GET_DATA_T(block_t*, it_b);
array_t *blocks = fct_get_blocks (func);
assert (blocks != NULL);
FOREACH_INARRAY(blocks, it_b) {
block_t* b = ARRAY_GET_DATA_T(block_t*, it_b);
if (_block_is_CC_entry(b) || b->global_id == entryblock->global_id) {
queue_t* cc = queue_new();
queue_add_tail(cc, b);
if (b->global_id == entryblock->global_id)
queue_add_head(func->components, cc);
queue_add_head(tmp_components, cc);
else
queue_add_tail(func->components, cc);
queue_add_tail(tmp_components, cc);
}
}
// Look for CC with multiple entries ------------------------------------
if (queue_length(func->components) > 1) {
if (queue_length(tmp_components) > 1) {
int pos = 0;
cntxt_t cntxt;
cntxt.f = func;
cntxt.current_CC = NULL;
cntxt.current_CC_ht = NULL;
cntxt.bflags = lc_malloc0(
queue_length(func->blocks) * sizeof(queue_t*));
cntxt.bflags_ht = lc_malloc0(
queue_length(func->blocks) * sizeof(hashtable_t*));
const int nb_blocks = fct_get_nb_blocks (func);
cntxt.bflags = lc_malloc0(nb_blocks * sizeof(queue_t*));
cntxt.bflags_ht = lc_malloc0(nb_blocks * sizeof(hashtable_t*));
cntxt.CC_to_remove = queue_new();
queue_t *CC_ht_to_remove = queue_new();
FOREACH_INQUEUE(func->components, it_cc) {
FOREACH_INQUEUE(tmp_components, it_cc) {
queue_t* cc = GET_DATA_T(queue_t*, it_cc);
block_t* b = queue_peek_head(cc);
cntxt.current_CC = cc;
......@@ -350,7 +354,7 @@ void lcore_analyze_connected_components(asmfile_t *asmfile)
// Remove merged CC from function CCs --------------------------------
FOREACH_INQUEUE(cntxt.CC_to_remove, it_cc1) {
queue_t* cc = GET_DATA_T(queue_t*, it_cc1);
queue_remove(func->components, cc, NULL);
queue_remove(tmp_components, cc, NULL);
queue_free(cc, NULL);
}
queue_free(cntxt.CC_to_remove, NULL);
......@@ -364,6 +368,13 @@ void lcore_analyze_connected_components(asmfile_t *asmfile)
lc_free(cntxt.bflags);
lc_free(cntxt.bflags_ht);
}
func->components = array_new();
FOREACH_INQUEUE (tmp_components, tmp_cc_it) {
queue_t *blocks = GET_DATA_T (queue_t *, tmp_cc_it);
array_add (func->components, blocks);
}
queue_free (tmp_components, NULL);
}
// recycled structures
......
......@@ -599,23 +599,21 @@ adfa_val_t* ADFA_analyze_insn(ssa_insn_t* ssain, adfa_cntxt_t* cntxt)
hashtable_insert(cntxt->Rvals, ssain->output[0], val);
}
}
// Instruction is XOR
else if (family == FM_XOR) {
//Special case : same register => 0
if (oprnd_is_reg(insn_get_oprnd(in, 0)) == TRUE
&& oprnd_is_reg(insn_get_oprnd(in, 1)) == TRUE
&& oprnd_get_reg(insn_get_oprnd(in, 0))
== oprnd_get_reg(insn_get_oprnd(in, 1))) {
val = lc_malloc(sizeof(adfa_val_t));
queue_add_tail(cntxt->Avals, val);
val->is_mem = FALSE;
val->op = ADFA_OP_NULL;
val->type = ADFA_TYPE_IMM;
val->data.imm = 0;
// Instruction is XOR => Special case : same register => 0
else if (family == FM_XOR
&& (oprnd_is_reg(insn_get_oprnd(in, 0)) == TRUE
&& oprnd_is_reg(insn_get_oprnd(in, 1)) == TRUE
&& oprnd_get_reg(insn_get_oprnd(in, 0))
== oprnd_get_reg(insn_get_oprnd(in, 1)))) {
val = lc_malloc(sizeof(adfa_val_t));
queue_add_tail(cntxt->Avals, val);
val->is_mem = FALSE;
val->op = ADFA_OP_NULL;
val->type = ADFA_TYPE_IMM;
val->data.imm = 0;
if (ssain->output != NULL && ssain->output[0] != NULL && hashtable_lookup(cntxt->Rvals, ssain->output[0]) == NULL)
hashtable_insert(cntxt->Rvals, ssain->output[0], val);
}
if (ssain->output != NULL && ssain->output[0] != NULL && hashtable_lookup(cntxt->Rvals, ssain->output[0]) == NULL)
hashtable_insert(cntxt->Rvals, ssain->output[0], val);
}
// Instruction is LEA
else if (family == FM_LEA) {
......@@ -788,8 +786,11 @@ static void __DFA_BFS_is_computable(graph_node_t* node, void* context)
static int _check_traversed_blocks(adfa_cntxt_t* cntxt)
{
FOREACH_INQUEUE(cntxt->f->blocks, it_b) {
block_t* b = GET_DATA_T(block_t*, it_b);
array_t *blocks = fct_get_blocks (cntxt->f);
if (blocks == NULL) return TRUE;
FOREACH_INARRAY(blocks, it_b) {
block_t* b = ARRAY_GET_DATA_T(block_t*, it_b);
if (!block_is_padding(b) && cntxt->_traversed[b->id] == 0)
return (FALSE);
}
......@@ -799,14 +800,17 @@ static int _check_traversed_blocks(adfa_cntxt_t* cntxt)
static void _backup_strat(adfa_cntxt_t* cntxt)
{
array_t *blocks = fct_get_blocks (cntxt->f);
if (blocks == NULL) return;
// Iterate over analyzed blocks to add one not analyzed successor
// in the "todo" list
// This should "unlock" the traverse algorithm and allow to analyze
// all blocks.
FOREACH_INQUEUE(cntxt->f->blocks, it_b)
FOREACH_INARRAY(blocks, it_b)
{
int stop = FALSE;
block_t* b = GET_DATA_T(block_t*, it_b);
block_t* b = ARRAY_GET_DATA_T(block_t*, it_b);
if (!block_is_padding(b) && cntxt->_traversed[b->id] == 1) {
FOREACH_INLIST(b->cfg_node->out, it_next)
......@@ -875,7 +879,7 @@ adfa_cntxt_t* ADFA_analyze_function(fct_t* f, adfa_driver_t* driver)
cntxt->arch = f->asmfile->arch;
cntxt->ssa = lcore_compute_ssa(f);
cntxt->graph = FCT_ENTRY(f)->cfg_node;
cntxt->_traversed = lc_malloc0(queue_length(f->blocks) * sizeof(char));
cntxt->_traversed = lc_malloc0(fct_get_nb_blocks(f) * sizeof(char));
cntxt->f = f;
cntxt->driver = driver;
......
......@@ -154,7 +154,7 @@ static void fill_DDG_data(ddg_context_t *ctxt, array_t *insns)
/* For each instruction */
FOREACH_INARRAY(insns, insns_iter)
{
insn_t *insn = ARRAY_GET_DATA(insn, insns_iter);
insn_t *insn = ARRAY_GET_DATA_T(insn_t *, insns_iter);
/* Save instruction rank */
hashtable_insert(ctxt->insn_rank, insn, (void *) rank++);
......@@ -278,7 +278,7 @@ static void insert_RAW_or_WAW(ddg_context_t ctxt, insn_t *dst_insn,
/* Looking for the nearest instruction in the same loop iteration */
/* For each instruction writing <reg_key>, from the last to the first executed */
FOREACH_INARRAY_REVERSE(src_insns, src_insns_iter) {
insn_t *src_insn = ARRAY_GET_DATA(src_insn, src_insns_iter);
insn_t *src_insn = ARRAY_GET_DATA_T(insn_t *, src_insns_iter);
/* skips previous iteration */
long src_insn_rank = (long) hashtable_lookup(ctxt.insn_rank, src_insn);
......@@ -316,7 +316,7 @@ static void insert_WAR(ddg_context_t ctxt, insn_t *dst_insn, void *reg_key)
/* Looking for all matching instructions */
FOREACH_INARRAY_REVERSE(src_insns, src_insns_iter)
{
insn_t *src_insn = ARRAY_GET_DATA(src_insn, src_insns_iter);
insn_t *src_insn = ARRAY_GET_DATA_T(insn_t *, src_insns_iter);
long src_insn_rank = (long) hashtable_lookup(ctxt.insn_rank, src_insn);
if (src_insn_rank >= dst_insn_rank) /* previous iteration */
......@@ -374,7 +374,7 @@ static void build_DDG(array_t *insns, graph_t *ddg, array_t *edges, int only_RAW
FOREACH_INARRAY(insns, insns_rdreg_iter)
{
insn_t *insn = ARRAY_GET_DATA(insn, insns_rdreg_iter);
insn_t *insn = ARRAY_GET_DATA_T(insn_t *, insns_rdreg_iter);
insert_RAW(ctxt, insn, reg_key);
}
......@@ -389,7 +389,7 @@ static void build_DDG(array_t *insns, graph_t *ddg, array_t *edges, int only_RAW
FOREACH_INARRAY(insns, insns_wrreg_iter)
{
insn_t *insn = ARRAY_GET_DATA(insn, insns_wrreg_iter);
insn_t *insn = ARRAY_GET_DATA_T(insn_t *, insns_wrreg_iter);
insert_WAR(ctxt, insn, reg_key);
insert_WAW(ctxt, insn, reg_key);
......@@ -412,7 +412,7 @@ static array_t *get_path_insns (array_t *path)
/* Get number of instructions */
int nb_insns = 0;
FOREACH_INARRAY(path, path_iter1) {
block_t *block = ARRAY_GET_DATA(block, path_iter1);
block_t *block = ARRAY_GET_DATA_T(block_t *, path_iter1);
nb_insns += block_get_size (block);
}
......@@ -420,7 +420,7 @@ static array_t *get_path_insns (array_t *path)
/* Insert instructions from path to insns */
FOREACH_INARRAY(path, path_iter2) {
block_t *block = ARRAY_GET_DATA(block, path_iter2);
block_t *block = ARRAY_GET_DATA_T(block_t *, path_iter2);
FOREACH_INSN_INBLOCK(block, block_iter) {
insn_t *insn = GET_DATA_T(insn_t*, block_iter);
......@@ -489,11 +489,11 @@ static graph_t *get_path_DDG(array_t *path, int only_RAW)
* Gets function/loop paths. If not previously built (by another MAQAO function), build them
* and informs the caller about that via the 'already_built' parameter
* */
static queue_t *get_obj_paths(void *obj, int *already_built,
queue_t* (*get_paths)(void *),
static array_t *get_obj_paths(void *obj, int *already_built,
array_t* (*get_paths)(void *),
void (*build_paths)(void *))
{
queue_t *paths = get_paths(obj);
array_t *paths = get_paths(obj);
if (paths == NULL) {
*already_built = FALSE;
......@@ -507,18 +507,20 @@ static queue_t *get_obj_paths(void *obj, int *already_built,
/* CF lcore_fctpath_getddg and build_DDG */
static queue_t *objpath_getddg(void *obj, int only_RAW,
queue_t* (*get_paths)(void *),
array_t* (*get_paths)(void *),
void (*build_paths)(void *),
void (*free_paths)(void *),
arch_t *arch)
{
int paths_already_built;
queue_t *paths = get_obj_paths(obj, &paths_already_built, get_paths, build_paths);
array_t *paths = get_obj_paths(obj, &paths_already_built, get_paths, build_paths);
if (paths == NULL) return NULL;
queue_t *ddg_allpaths = queue_new();
/* For each path */
FOREACH_INQUEUE(paths, paths_iter) {
array_t *path = GET_DATA_T(array_t*, paths_iter);
FOREACH_INARRAY(paths, paths_iter) {
array_t *path = ARRAY_GET_DATA_T(array_t*, paths_iter);
graph_t *ddg = get_path_DDG(path, only_RAW);
lcore_set_ddg_latency (ddg, get_default_latency (arch));
queue_add_tail(ddg_allpaths, ddg);
......@@ -533,18 +535,20 @@ static queue_t *objpath_getddg(void *obj, int only_RAW,
/* CF lcore_fct_getddg and build_DDG */
static graph_t *obj_getddg(void *obj, int only_RAW,
queue_t* (*get_paths)(void *),
array_t* (*get_paths)(void *),
void (*build_paths)(void *),
void (*free_paths)(void *),
arch_t *arch)
{
graph_t *obj_ddg = graph_new();
int paths_already_built;
queue_t *paths = get_obj_paths(obj, &paths_already_built, get_paths, build_paths);
array_t *paths = get_obj_paths(obj, &paths_already_built, get_paths, build_paths);
if (paths == NULL) return NULL;
graph_t *obj_ddg = graph_new();
/* If only one path, directly build+get DDG */
if (queue_length(paths) == 1) {
array_t *path = list_getdata(queue_iterator(paths)); /* first path */
if (array_length(paths) == 1) {
array_t *path = array_get_first_elt(paths); /* first path */
array_t *insns = get_path_insns (path);
build_DDG(insns, obj_ddg, NULL, only_RAW);
array_free (insns, NULL);
......@@ -555,8 +559,8 @@ static graph_t *obj_getddg(void *obj, int only_RAW,
array_t *ddg_edges = array_new();
/* Get DDG edges for each path */
FOREACH_INQUEUE(paths, paths_iter) {
array_t *path = GET_DATA_T(array_t*, paths_iter);
FOREACH_INARRAY(paths, paths_iter) {
array_t *path = ARRAY_GET_DATA_T(array_t*, paths_iter);
array_t *insns = get_path_insns (path);
build_DDG(insns, NULL, ddg_edges, only_RAW);
array_free (insns, NULL);
......@@ -569,7 +573,7 @@ static graph_t *obj_getddg(void *obj, int only_RAW,
/* Insert DDG edges in obj_ddg */
FOREACH_INARRAY(ddg_edges, ddg_edges_iter) {
ddg_edge_t *ddg_edge = ARRAY_GET_DATA(ddg_edge, ddg_edges_iter);
ddg_edge_t *ddg_edge = ARRAY_GET_DATA_T(ddg_edge_t *, ddg_edges_iter);
insert_in_DDG(ctxt, ddg_edge->src, ddg_edge->dst, ddg_edge->kind,
ddg_edge->distance);
}
......@@ -592,7 +596,7 @@ static graph_t *obj_getddg(void *obj, int only_RAW,
* Specific to functions *
***************************************************************************************************/
static queue_t *_fct_get_paths (void *f) { return fct_get_paths (f); }
static array_t *_fct_get_paths (void *f) { return fct_get_paths (f); }
static void fct_build_paths (void *f) {
enum lcore_nb_paths_status status;
(void) lcore_fct_getnpaths (f, 0, &status);
......@@ -650,7 +654,7 @@ graph_t *lcore_fct_getddg_ext(fct_t *fct)
* Specific to loops *
***************************************************************************************************/
static queue_t *_loop_get_paths (void *l) { return loop_get_paths (l); }
static array_t *_loop_get_paths (void *l) { return loop_get_paths (l); }
static void loop_build_paths (void *l) {
enum lcore_nb_paths_status status;
(void) lcore_loop_getnpaths (l, 0, &status);
......@@ -831,7 +835,7 @@ static void _upd_cycle (queue_t *cycle, void *_data)
/* For each edge */
array_t *edges = graph_cycle_get_edges (cycle, ignore_non_RAW);
FOREACH_INARRAY(edges, edge_iter) {
graph_edge_t *edge = ARRAY_GET_DATA(edge, edge_iter);
graph_edge_t *edge = ARRAY_GET_DATA_T(graph_edge_t *, edge_iter);
data_dependence_t *data_dep = edge->data;
sum_min_latency += data_dep->latency.min;
......
......@@ -31,8 +31,8 @@
///////////////////////////////////////////////////////////////////////////////
static void _DFS_postorder(graph_node_t* node, void* user)
{
queue_t* postorder = (queue_t*) user;
queue_add_tail(postorder, node->data);
array_t* postorder = (array_t*) user;
array_add(postorder, node->data);
}
static block_t* _intersect(block_t* b1, block_t* b2, block_t** doms,
......@@ -53,8 +53,7 @@ static block_t* _intersect(block_t* b1, block_t* b2, block_t** doms,
void _compute_dominance(fct_t* fct)
{
block_t* start_node = FCT_ENTRY(fct);
queue_t* postorder = queue_new();
queue_t* reverse_postorder = queue_new();
array_t* postorder = array_new();
int* postorder_index = lc_malloc(fct_get_nb_blocks(fct) * sizeof(int));
block_t** doms = lc_malloc(fct_get_nb_blocks(fct) * sizeof(block_t*));
int i = 0;
......@@ -65,9 +64,8 @@ void _compute_dominance(fct_t* fct)
// Order nodes in reverse-postorder
i = 0;
graph_node_DFS(start_node->cfg_node, NULL, &_DFS_postorder, NULL, postorder);
FOREACH_INQUEUE(postorder, it_b) {
block_t* b = GET_DATA_T(block_t*, it_b);
queue_add_head(reverse_postorder, b);
FOREACH_INARRAY(postorder, it_b) {
block_t* b = ARRAY_GET_DATA_T(block_t*, it_b);
postorder_index[b->id] = i++;
}
......@@ -77,9 +75,9 @@ void _compute_dominance(fct_t* fct)
doms[start_node->id] = start_node;
while (changed == TRUE) {
changed = FALSE;
FOREACH_INQUEUE(reverse_postorder, it_b)
FOREACH_INARRAY_REVERSE(postorder, it_b)
{
block_t* b = GET_DATA_T(block_t*, it_b);
block_t* b = ARRAY_GET_DATA_T(block_t*, it_b);
if (b != start_node) {
new_idom = NULL;
......@@ -112,16 +110,17 @@ void _compute_dominance(fct_t* fct)
}
// Create the dominance tree using computed results
FOREACH_INQUEUE(fct->blocks, it_b1) {
block_t* b = GET_DATA_T(block_t*, it_b1);
array_t *blocks = fct_get_blocks (fct);
assert (blocks != NULL);
FOREACH_INARRAY(blocks, it_b1) {
block_t* b = ARRAY_GET_DATA_T(block_t*, it_b1);
block_t* Db = doms[b->id];
if (block_is_padding(b) == 0 && Db != b)
tree_insert(Db->domination_node, b->domination_node);
}
lc_free(doms);
lc_free(postorder_index);
queue_free(reverse_postorder, NULL);
queue_free(postorder, NULL);
array_free(postorder, NULL);
}
/*
......@@ -137,8 +136,8 @@ void lcore_analyze_dominance(asmfile_t *asmfile)
return;
DBGMSG0("computing domination\n");
FOREACH_INQUEUE(asmfile_get_fcts(asmfile), iter) {
fct_t *f = GET_DATA_T(fct_t*, iter);
FOREACH_INARRAY(asmfile_get_fcts(asmfile), iter) {
fct_t *f = ARRAY_GET_DATA_T(fct_t*, iter);
_compute_dominance(f);
}
......@@ -152,13 +151,16 @@ static void add_virtual_end(fct_t* f)
{
// create the virtual node
block_t* vn = block_new(f, NULL);
queue_add_tail(f->blocks, vn);
array_t *blocks = fct_get_blocks (f);
if (blocks == NULL) return;
array_add(blocks, vn);
f->virtual_exit = vn;
// link exits to it
FOREACH_INQUEUE(f->blocks, it_b)
FOREACH_INARRAY(blocks, it_b)
{
block_t* b = GET_DATA_T(block_t*, it_b);
block_t* b = ARRAY_GET_DATA_T(block_t*, it_b);
if (b->cfg_node->out == NULL && !block_is_padding(b)
&& b != f->virtual_exit) {
graph_add_edge(b->cfg_node, vn->cfg_node, NULL);
......@@ -170,7 +172,11 @@ static void remove_virtual_end(fct_t* f)
{
if (f->virtual_exit == NULL)
return;
queue_remove_tail(f->blocks);
array_t *blocks = fct_get_blocks (f);
if (blocks == NULL) return;
array_remove(blocks);
block_t* vn = f->virtual_exit;
f->virtual_exit = NULL;
block_free(vn);
......@@ -178,10 +184,12 @@ static void remove_virtual_end(fct_t* f)
void _compute_post_dominance(fct_t* fct)
{
queue_t* postorder = queue_new();
queue_t* reverse_postorder = queue_new();
int* postorder_index = lc_malloc(fct_get_nb_blocks(fct) * sizeof(int));
block_t** postdoms = lc_malloc(fct_get_nb_blocks(fct) * sizeof(block_t*));
const int nb_blocks = fct_get_nb_blocks(fct);
if (nb_blocks == 0) return;
array_t* postorder = array_new();
int* postorder_index = lc_malloc(nb_blocks * sizeof(int));
block_t** postdoms = lc_malloc(nb_blocks * sizeof(block_t*));
int i = 0;
block_t* start_node = fct->virtual_exit;
block_t* new_ipostdom = NULL;
......@@ -190,29 +198,29 @@ void _compute_post_dominance(fct_t* fct)
fct_upd_blocks_id(fct);
FOREACH_INQUEUE(fct->blocks, it_b2) {
block_t* b = GET_DATA_T(block_t*, it_b2);
array_t *blocks = fct_get_blocks (fct);
FOREACH_INARRAY(blocks, it_b2) {
block_t* b = ARRAY_GET_DATA_T(block_t*, it_b2);
b->postdom_node = tree_new(b);
}
// Order nodes in reverse-postorder
i = 0;
graph_node_BackDFS(start_node->cfg_node, NULL, &_DFS_postorder, NULL, postorder);
FOREACH_INQUEUE(postorder, it_b) {
block_t* b = GET_DATA_T(block_t*, it_b);
queue_add_head(reverse_postorder, b);
FOREACH_INARRAY(postorder, it_b) {
block_t* b = ARRAY_GET_DATA_T(block_t*, it_b);
postorder_index[b->id] = i++;
}
// Initialize the post-dominator array
for (i = 0; i < fct_get_nb_blocks(fct); i++)
for (i = 0; i < nb_blocks; i++)
postdoms[i] = NULL;
postdoms[start_node->id] = start_node;
while (changed == TRUE) {
changed = FALSE;
FOREACH_INQUEUE(reverse_postorder, it_b)
FOREACH_INARRAY_REVERSE(postorder, it_b)
{
block_t* b = GET_DATA_T(block_t*, it_b);
block_t* b = ARRAY_GET_DATA_T(block_t*, it_b);
if (b != start_node) {
new_ipostdom = NULL;
......@@ -246,8 +254,8 @@ void _compute_post_dominance(fct_t* fct)
}
// Create the post-dominance tree using computed results
FOREACH_INQUEUE(fct->blocks, it_b1) {
block_t* b = GET_DATA_T(block_t*, it_b1);
FOREACH_INARRAY(blocks, it_b1) {
block_t* b = ARRAY_GET_DATA_T(block_t*, it_b1);
block_t* Db = postdoms[b->id];
if (block_is_padding(b) == 0 && Db != b) {
tree_insert(Db->postdom_node, b->postdom_node);
......@@ -256,8 +264,7 @@ void _compute_post_dominance(fct_t* fct)
lc_free(postdoms);
lc_free(postorder_index);
queue_free(reverse_postorder, NULL);
queue_free(postorder, NULL);
array_free(postorder, NULL);
}
/*
......@@ -275,8 +282,8 @@ void lcore_analyze_post_dominance(asmfile_t *asmfile)
return;
DBGMSG0("computing post-domination\n");
FOREACH_INQUEUE(asmfile_get_fcts(asmfile), iter) {
fct_t *f = GET_DATA_T(fct_t*, iter);
FOREACH_INARRAY(asmfile_get_fcts(asmfile), iter) {
fct_t *f = ARRAY_GET_DATA_T(fct_t*, iter);
add_virtual_end(f);
_compute_post_dominance(f);
remove_virtual_end(f);
......
......@@ -53,6 +53,8 @@
* During the extraction, function entries are computed.
*/
#define BIG_FCT_THRESHOLD 1000 // Above this number of blocks/loops, use a tmp queue
/*
* \struct cntxt_s
* Structure used to pass several parameters trough a void* pointer
......@@ -62,6 +64,8 @@ typedef struct cntxt_s {
char* flags; // One flag per block
fct_t* newf; // Current function (created from a CC)
fct_t* orig; // Original function
queue_t *blocks;// Original blocks
queue_t *loops; // Original loop
} cntxt_t;
/*
......@@ -79,14 +83,32 @@ void _DFS_move_block(graph_node_t* node, void* context)
return;
if (cntxt->flags[b->id] == 0) {
cntxt->flags[b->id] = 1;
queue_remove(b->function->blocks, b, NULL);
queue_add_tail(cntxt->newf->blocks, b);
if (cntxt->blocks != NULL)
queue_remove(cntxt->blocks, b, NULL);
else {
unsigned pos;
boolean_t found = array_lookup_data (fct_get_blocks (b->function), b, &pos);
assert (found == TRUE);
if (found == TRUE) array_remove_inside (fct_get_blocks (b->function), pos);
}
array_add(fct_get_blocks (cntxt->newf), b);
b->function = cntxt->newf;
if (b->loop && b->loop->function != cntxt->newf) {
loop_t* loop = b->loop;
queue_remove(loop->function->loops, loop, NULL);
queue_add_tail(cntxt->newf->loops, loop);
if (cntxt->loops != NULL)
queue_remove(cntxt->loops, loop, NULL);
else {
unsigned pos;
boolean_t found = array_lookup_data (fct_get_loops (loop->function), loop, &pos);
assert (found == TRUE);
if (found == TRUE) array_remove_inside (fct_get_loops (loop->function), pos);
}
array_add(fct_get_loops (cntxt->newf), loop);
loop->function = cntxt->newf;
}
}
......@@ -127,15 +149,17 @@ void lcore_function_extract_functions_from_cc(fct_t* f)
{
asmfile_t* asmf = f->asmfile;
fct_upd_blocks_id(f);
const array_t *components = fct_get_components (f);
const unsigned nb_components = array_length (components);
// Check if the functions has CCs
if (queue_length(f->components) < 1) {
if (nb_components < 1) {
DBGMSG0(
"WARNING : this function has no connected components => verify that it is nor an empty function\n");
return;
} else {
DBGMSG("INFO : Current function has %d CC(s)\n",
queue_length(f->components));
nb_components);
}
// Now extract functions from CC. For each CC, all its blocks and all its loops
// are removed from the current function, then added in a new function.
......@@ -144,9 +168,32 @@ void lcore_function_extract_functions_from_cc(fct_t* f)
queue_t* new_fcts = queue_new();
queue_t* not_extracted = queue_new();
cntxt.orig = f;
cntxt.flags = lc_malloc0(sizeof(char) * queue_length(f->blocks));
FOREACH_INQUEUE(f->components, it_cc1) {
queue_t* cbs = GET_DATA_T(queue_t*, it_cc1); //list of entries in the CC
cntxt.flags = lc_malloc0(sizeof(char) * fct_get_nb_blocks (f));
if (nb_components > 1 && fct_get_nb_blocks (f) > BIG_FCT_THRESHOLD) {
cntxt.blocks = queue_new();
FOREACH_INARRAY (fct_get_blocks(f), block_it1) {
void *block = ARRAY_GET_DATA (block_it1);
queue_add_tail (cntxt.blocks, block);
}
array_flush (fct_get_blocks(f), NULL);
} else {
cntxt.blocks = NULL;
}
if (nb_components > 1 && fct_get_nb_loops (f) > BIG_FCT_THRESHOLD) {
cntxt.loops = queue_new();
FOREACH_INARRAY (fct_get_loops(f), loop_it) {
void *loop = ARRAY_GET_DATA (loop_it);
queue_add_tail (cntxt.loops, loop);
}
array_flush (fct_get_loops(f), NULL);
} else {
cntxt.loops = NULL;
}
FOREACH_INARRAY(components, it_cc1) {
queue_t* cbs = ARRAY_GET_DATA_T(queue_t*, it_cc1); //list of entries in the CC
//ccid == 0 means this is the primary CC. In this case, there is nothing
//to do. Else, a function must be create and blocks must be changed of function
......@@ -227,21 +274,21 @@ void lcore_function_extract_functions_from_cc(fct_t* f)
fct_t* fnew = (fct_t *) lc_malloc0(sizeof(fct_t));
queue_add_tail(new_fcts, fnew);
fnew->namelbl = fnew_namelbl;
fnew->id = queue_length(asmf->functions); //uniq_id;
fnew->id = array_length(asmfile_get_fcts (asmf)); //uniq_id;
fnew->global_id = asmf->maxid_fct++;
fnew->asmfile = asmf;
fnew->blocks = queue_new();
fnew->loops = queue_new();
fnew->blocks = array_new();
fnew->loops = array_new();
fnew->cg_node = graph_node_new(fnew);
fnew->entries = queue_new();
fnew->exits = queue_new();
fnew->ranges = queue_new();
fnew->entries = array_new();
fnew->exits = array_new();
fnew->ranges = array_new();
fnew->original_function = f;
fnew->first_insn = entry_insn;
fnew->components = queue_new();
fnew->components = array_new();
fnew->dbg_addr = dbg_address;
queue_add_head(fnew->components, cbs);
queue_add_tail(asmf->functions, fnew);
array_add(fnew->components, cbs);
array_add(asmfile_get_fcts (asmf), fnew);
if (asmf->load_fct_dbg != NULL)
asmf->load_fct_dbg(fnew);
......@@ -252,7 +299,7 @@ void lcore_function_extract_functions_from_cc(fct_t* f)
cntxt.newf = fnew;
FOREACH_INQUEUE(cbs, it_entry) {
block_t* entry = GET_DATA_T(block_t*, it_entry);
queue_add_tail(fnew->entries, entry);
array_add(fnew->entries, entry);
graph_node_DFS(entry->cfg_node, &_DFS_move_block, NULL, NULL, &cntxt);
//If needed, remove edges from virtual node
......@@ -268,14 +315,14 @@ void lcore_function_extract_functions_from_cc(fct_t* f)
}
block_t * vb = (block_t*) lc_malloc0(sizeof(block_t));
vb->id = queue_length(fnew->blocks);
vb->id = fct_get_nb_blocks (fnew);
vb->global_id = fnew->asmfile->