aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--mk/build.mk12
-rw-r--r--src/mds-kbdc/eliminate-dead-code.c52
-rw-r--r--src/mds-kbdc/tree.h44
-rw-r--r--test-files/mds-kbdc/eliminate-dead-code/alive-code/for-for-break-end-alive25
-rw-r--r--test-files/mds-kbdc/eliminate-dead-code/dead-code/for-break-dead14
-rw-r--r--test-files/mds-kbdc/eliminate-dead-code/dead-code/for-if-continue-else-continue-end-dead25
-rw-r--r--test-files/mds-kbdc/eliminate-dead-code/dead-code/function-for-return-end-dead20
-rw-r--r--test-files/mds-kbdc/eliminate-dead-code/dead-code/macro-for-return-end-dead20
8 files changed, 172 insertions, 40 deletions
diff --git a/mk/build.mk b/mk/build.mk
index 7fa2d24..57ee222 100644
--- a/mk/build.mk
+++ b/mk/build.mk
@@ -80,13 +80,13 @@ obj/%.o: src/%.c src/%.h src/mds-base.h src/libmdsserver/*.h $(SEDED)
obj/%.o: src/%.c src/mds-base.h src/libmdsserver/*.h $(SEDED)
mkdir -p $(shell dirname $@)
$(CC) $(C_FLAGS) -Isrc -c -o $@ $<
-obj/mds-server/%.o: src/%.c src/mds-server/*.h src/mds-base.h src/libmdsserver/*.h $(SEDED)
+obj/mds-server/%.o: src/mds-server/%.c src/mds-server/*.h src/mds-base.h src/libmdsserver/*.h $(SEDED)
mkdir -p $(shell dirname $@)
$(CC) $(C_FLAGS) -Isrc -c -o $@ $<
-obj/mds-registry/%.o: src/%.c src/mds-registry/*.h src/mds-base.h src/libmdsserver/*.h $(SEDED)
+obj/mds-registry/%.o: src/mds-registry/%.c src/mds-registry/*.h src/mds-base.h src/libmdsserver/*.h $(SEDED)
mkdir -p $(shell dirname $@)
$(CC) $(C_FLAGS) -Isrc -c -o $@ $<
-obj/mds-kbdc/%.o: src/%.c src/mds-kbdc/*.h src/libmdsserver/*.h $(SEDED)
+obj/mds-kbdc/%.o: src/mds-kbdc/%.c src/mds-kbdc/*.h src/libmdsserver/*.h $(SEDED)
mkdir -p $(shell dirname $@)
$(CC) $(C_FLAGS) -Isrc -c -o $@ $<
else
@@ -96,13 +96,13 @@ obj/%.o: src/%.c src/%.h src/mds-base.h $(SEDED)
obj/%.o: src/%.c src/mds-base.h $(SEDED)
mkdir -p $(shell dirname $@)
$(CC) $(C_FLAGS) -c -o $@ $<
-obj/mds-server/%.o: src/%.c src/mds-server/*.h src/mds-base.h $(SEDED)
+obj/mds-server/%.o: src/mds-server/%.c src/mds-server/*.h src/mds-base.h $(SEDED)
mkdir -p $(shell dirname $@)
$(CC) $(C_FLAGS) -c -o $@ $<
-obj/mds-registry/%.o: src/%.c src/mds-registry/*.h src/mds-base.h $(SEDED)
+obj/mds-registry/%.o: src/mds-registry/%.c src/mds-registry/*.h src/mds-base.h $(SEDED)
mkdir -p $(shell dirname $@)
$(CC) $(C_FLAGS) -c -o $@ $<
-obj/mds-kbdc/%.o: src/%.c src/mds-kbdc/*.h $(SEDED)
+obj/mds-kbdc/%.o: src/mds-kbdc/%.c src/mds-kbdc/*.h $(SEDED)
mkdir -p $(shell dirname $@)
$(CC) $(C_FLAGS) -c -o $@ $<
endif
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;
diff --git a/test-files/mds-kbdc/eliminate-dead-code/alive-code/for-for-break-end-alive b/test-files/mds-kbdc/eliminate-dead-code/alive-code/for-for-break-end-alive
new file mode 100644
index 0000000..6523352
--- /dev/null
+++ b/test-files/mds-kbdc/eliminate-dead-code/alive-code/for-for-break-end-alive
@@ -0,0 +1,25 @@
+for 1 to 2 as \1
+ for 1 to 2 as \2
+ break
+ end for
+ <alive> : "code"
+end for
+
+# (for (@ 1 0-3) ‘1’ ‘2’ (.variable ‘\1’)
+# (.inner
+# (for (@ 2 2-5) ‘1’ ‘2’ (.variable ‘\2’)
+# (.inner
+# (break (@ 3 4-9))
+# )
+# )
+# (map (@ 5 2-2)
+# (.sequence
+# (keys (@ 5 2-9) ‘<alive>’)
+# )
+# (.result
+# (string (@ 5 12-18) ‘"code"’)
+# )
+# )
+# )
+# )
+
diff --git a/test-files/mds-kbdc/eliminate-dead-code/dead-code/for-break-dead b/test-files/mds-kbdc/eliminate-dead-code/dead-code/for-break-dead
new file mode 100644
index 0000000..f8037a3
--- /dev/null
+++ b/test-files/mds-kbdc/eliminate-dead-code/dead-code/for-break-dead
@@ -0,0 +1,14 @@
+for 1 to 2 as \1
+ break
+ break
+end for
+
+# (for (@ 1 0-3) ‘1’ ‘2’ (.variable ‘\1’)
+# (.inner
+# (break (@ 2 2-7))
+# )
+# )
+# :3:2–7: warning: statement is unreachable
+# break
+# ^^^^^
+
diff --git a/test-files/mds-kbdc/eliminate-dead-code/dead-code/for-if-continue-else-continue-end-dead b/test-files/mds-kbdc/eliminate-dead-code/dead-code/for-if-continue-else-continue-end-dead
new file mode 100644
index 0000000..108c7b0
--- /dev/null
+++ b/test-files/mds-kbdc/eliminate-dead-code/dead-code/for-if-continue-else-continue-end-dead
@@ -0,0 +1,25 @@
+for 1 to 2 as \1
+ if 1
+ continue
+ else
+ continue
+ end if
+ <dead code> : "dead code"
+end for
+
+# (for (@ 1 0-3) ‘1’ ‘2’ (.variable ‘\1’)
+# (.inner
+# (if (@ 2 2-4) ‘1’
+# (.inner
+# (continue (@ 3 4-12))
+# )
+# (.otherwise
+# (continue (@ 5 4-12))
+# )
+# )
+# )
+# )
+# :7:2–2: warning: statement is unreachable
+# <dead code> : "dead code"
+#
+
diff --git a/test-files/mds-kbdc/eliminate-dead-code/dead-code/function-for-return-end-dead b/test-files/mds-kbdc/eliminate-dead-code/dead-code/function-for-return-end-dead
new file mode 100644
index 0000000..39fb763
--- /dev/null
+++ b/test-files/mds-kbdc/eliminate-dead-code/dead-code/function-for-return-end-dead
@@ -0,0 +1,20 @@
+function f/0
+ for 1 to 1 as \1
+ return
+ end for
+ "dead code"
+end function
+
+# (function (@ 1 0-8) ‘f/0’
+# (.inner
+# (for (@ 2 2-5) ‘1’ ‘1’ (.variable ‘\1’)
+# (.inner
+# (return (@ 3 4-10))
+# )
+# )
+# )
+# )
+# :5:2–2: warning: statement is unreachable
+# "dead code"
+#
+
diff --git a/test-files/mds-kbdc/eliminate-dead-code/dead-code/macro-for-return-end-dead b/test-files/mds-kbdc/eliminate-dead-code/dead-code/macro-for-return-end-dead
new file mode 100644
index 0000000..eb8fdaa
--- /dev/null
+++ b/test-files/mds-kbdc/eliminate-dead-code/dead-code/macro-for-return-end-dead
@@ -0,0 +1,20 @@
+macro m/0
+ for 1 to 1 as \1
+ return
+ end for
+ <dead code> : "dead code"
+end macro
+
+# (macro (@ 1 0-5) ‘m/0’
+# (.inner
+# (for (@ 2 2-5) ‘1’ ‘1’ (.variable ‘\1’)
+# (.inner
+# (return (@ 3 4-10))
+# )
+# )
+# )
+# )
+# :5:2–2: warning: statement is unreachable
+# <dead code> : "dead code"
+#
+