aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMattias Andrée <maandree@operamail.com>2014-12-02 01:44:49 +0100
committerMattias Andrée <maandree@operamail.com>2014-12-02 01:44:49 +0100
commit5bbcf6a723a45989e0a189a30e663a4d38b5f006 (patch)
treedc36dcb7af93742750ece63eeb615f2508d71d1a /src
parentm (diff)
downloadmds-5bbcf6a723a45989e0a189a30e663a4d38b5f006.tar.gz
mds-5bbcf6a723a45989e0a189a30e663a4d38b5f006.tar.bz2
mds-5bbcf6a723a45989e0a189a30e663a4d38b5f006.tar.xz
mds-kbdc: dead code elimination
Signed-off-by: Mattias Andrée <maandree@operamail.com>
Diffstat (limited to 'src')
-rw-r--r--src/mds-kbdc/eliminate-dead-code.c52
-rw-r--r--src/mds-kbdc/tree.h44
2 files changed, 62 insertions, 34 deletions
diff --git a/src/mds-kbdc/eliminate-dead-code.c b/src/mds-kbdc/eliminate-dead-code.c
index 5f16bc3..cedf576 100644
--- a/src/mds-kbdc/eliminate-dead-code.c
+++ b/src/mds-kbdc/eliminate-dead-code.c
@@ -101,6 +101,13 @@ static size_t includes_size = 0;
*/
static size_t includes_ptr = 0;
+/**
+ * 2: Eliminating because of a return-statement
+ * 1: Eliminating because of a break- or continue-statement
+ * 0: Not eliminating
+ */
+static int elimination_level = 0;
+
/**
@@ -165,18 +172,6 @@ static int eliminate_include(mds_kbdc_tree_include_t* restrict tree)
/**
- * Eliminate dead code in a for-loop
- *
- * @param tree The tree to reduce
- * @return Zero on success, -1 on error
- */
-static int eliminate_for(mds_kbdc_tree_for_t* restrict tree)
-{
- return eliminate_subtree(tree->inner);
-}
-
-
-/**
* Eliminate dead code in an if-statement
*
* @param tree The tree to reduce
@@ -184,8 +179,15 @@ static int eliminate_for(mds_kbdc_tree_for_t* restrict tree)
*/
static int eliminate_if(mds_kbdc_tree_if_t* restrict tree)
{
- return -(eliminate_subtree(tree->inner) ||
- eliminate_subtree(tree->otherwise));
+ int elimination;
+ fail_if (eliminate_subtree(tree->inner));
+ elimination = elimination_level, elimination_level = 0;
+ fail_if (eliminate_subtree(tree->otherwise));
+ if (elimination > elimination_level)
+ elimination = elimination_level;
+ return 0;
+ pfail:
+ return -1;
}
@@ -206,22 +208,37 @@ static int eliminate_subtree(mds_kbdc_tree_t* restrict tree)
switch (tree->type)
{
+ case C(INCLUDE): e(include); break;
+ case C(IF): E(if); break;
case C(INFORMATION):
case C(FUNCTION):
case C(MACRO):
case C(ASSUMPTION):
+ case C(FOR):
if ((r = eliminate_subtree(tree->information.inner)))
return r;
+ if ((tree->type == C(FUNCTION)) || (tree->type == C(MACRO))) elimination_level = 0;
+ else if ((tree->type == C(FOR)) && (elimination_level == 1)) elimination_level = 0;
+ break;
+ case C(RETURN):
+ case C(BREAK):
+ case C(CONTINUE):
+ elimination_level = tree->type == C(RETURN) ? 2 : 1;
break;
- case C(INCLUDE): e(include); break;
- case C(FOR): E(for); break;
- case C(IF): E(if); break;
default:
break;
}
+ if (tree->next && elimination_level)
+ {
+ NEW_ERROR(tree->next, includes_ptr, WARNING, "statement is unreachable");
+ mds_kbdc_tree_free(tree->next), tree->next = NULL;
+ }
+
tree = tree->next;
goto again;
+ pfail:
+ return -1;
#undef E
#undef e
}
@@ -255,4 +272,3 @@ int eliminate_dead_code(mds_kbdc_parsed_t* restrict result_)
#undef NEW_ERROR_WITHOUT_INCLUDES
#undef C
-
diff --git a/src/mds-kbdc/tree.h b/src/mds-kbdc/tree.h
index fe67faf..2d9a278 100644
--- a/src/mds-kbdc/tree.h
+++ b/src/mds-kbdc/tree.h
@@ -283,14 +283,14 @@ typedef struct mds_kbdc_tree_include
MDS_KBDC_TREE_COMMON;
/**
- * The filename of the file to include
+ * The included layout code tree
*/
- char* filename;
+ mds_kbdc_tree_t* inner;
/**
- * The included layout code tree
+ * The filename of the file to include
*/
- mds_kbdc_tree_t* inner;
+ char* filename;
/**
* The source code of the file included by this statement
@@ -313,16 +313,22 @@ struct mds_kbdc_tree_callable
MDS_KBDC_TREE_COMMON;
/**
- * The name of the callable
- */
- char* name;
-
- /**
* The first child node, `.inner.next`
* is used to access the second child node
*/
mds_kbdc_tree_t* inner;
+ /* It is important that `.inner` is first because
+ * it is first in `struct mds_kbdc_tree_nesting`
+ * too which means that `.inner` has to same
+ * offset everyever (except in `mds_kbdc_tree_if_t`).
+ */
+
+ /**
+ * The name of the callable
+ */
+ char* name;
+
MDS_KBDC_TREE_PADDING(2);
};
@@ -411,6 +417,19 @@ typedef struct mds_kbdc_tree_for
MDS_KBDC_TREE_COMMON;
/**
+ * The first child node, `.inner.next` is
+ * used to access the second child node.
+ * This is what should be done inside the loop.
+ */
+ mds_kbdc_tree_t* inner;
+
+ /* It is important that `.inner` is first because
+ * it is first in `struct mds_kbdc_tree_nesting`
+ * too which means that `.inner` has to same
+ * offset everyever (except in `mds_kbdc_tree_if_t`).
+ */
+
+ /**
* The first value to variable should take, inclusive
*/
char* first;
@@ -425,13 +444,6 @@ typedef struct mds_kbdc_tree_for
*/
char* variable;
- /**
- * The first child node, `.inner.next` is
- * used to access the second child node.
- * This is what should be done inside the loop.
- */
- mds_kbdc_tree_t* inner;
-
MDS_KBDC_TREE_PADDING(4);
} mds_kbdc_tree_for_t;