diff options
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" +# + |