aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
authorLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2017-08-07 15:36:22 +0200
committerLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2017-08-11 16:24:13 +0200
commit64c9129b5beee61f0a311556259d97d7e56d2879 (patch)
tree24bb3b50e2484150b74caed7f4bed7a23a4c352d
parentd9ff34f2e0d52351ec9e5c5b33002b7be3937123 (diff)
downloadsparse-dev-64c9129b5beee61f0a311556259d97d7e56d2879.tar.gz
Remove single-store shortcut
Current sparse code doesn't handle very gracefully code with undefined pseudos. These can occurs, of course because the dev has not initialize them, maybe by error, but they can also occurs when they are only set (and used) in a single path or even worse, hen initiializing a bitfield. The origin of the problem is the single store shortcut in simplify_one_symbol() which doesn't take in account the (absence of) dominance when loads exist without stores. Fix this by removing this single-store shortcut and leave all the work for the general case which handle this situation quite well (and/but set those variables to 0). Warning: this change impact the performance (but not too much) Note: This patch will also avoid internal infinite loops occuring when processing undefined vars present during the SSA construction. Note: This patch will not avoid all similar problems because they can also be created after the SSA construction, for example when processing code that really is unreachable (then, typically, some of the involved pseudos are, in fact, not defined). It shouldn't be a problem since the code is unreachable. But if we process the code anyway (possibly because we simply don't know that the code is unreachable) then we create the same situation with the same consequences. Acked-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
-rw-r--r--flow.c39
-rw-r--r--validation/infinite-loop0.c1
2 files changed, 2 insertions, 38 deletions
diff --git a/flow.c b/flow.c
index c7161d47..5a3d55f7 100644
--- a/flow.c
+++ b/flow.c
@@ -650,11 +650,10 @@ void check_access(struct instruction *insn)
static void simplify_one_symbol(struct entrypoint *ep, struct symbol *sym)
{
- pseudo_t pseudo, src;
+ pseudo_t pseudo;
struct pseudo_user *pu;
- struct instruction *def;
unsigned long mod;
- int all, stores, complex;
+ int all;
/* Never used as a symbol? */
pseudo = sym->pseudo;
@@ -670,17 +669,12 @@ static void simplify_one_symbol(struct entrypoint *ep, struct symbol *sym)
if (mod)
goto external_visibility;
- def = NULL;
- stores = 0;
- complex = 0;
FOR_EACH_PTR(pseudo->users, pu) {
/* We know that the symbol-pseudo use is the "src" in the instruction */
struct instruction *insn = pu->insn;
switch (insn->opcode) {
case OP_STORE:
- stores++;
- def = insn;
break;
case OP_LOAD:
break;
@@ -697,37 +691,8 @@ static void simplify_one_symbol(struct entrypoint *ep, struct symbol *sym)
default:
warning(sym->pos, "symbol '%s' pseudo used in unexpected way", show_ident(sym->ident));
}
- complex |= insn->offset;
} END_FOR_EACH_PTR(pu);
- if (complex)
- goto complex_def;
- if (stores > 1)
- goto multi_def;
-
- /*
- * Goodie, we have a single store (if even that) in the whole
- * thing. Replace all loads with moves from the pseudo,
- * replace the store with a def.
- */
- src = VOID;
- if (def)
- src = def->target;
-
- FOR_EACH_PTR(pseudo->users, pu) {
- struct instruction *insn = pu->insn;
- if (insn->opcode == OP_LOAD) {
- check_access(insn);
- convert_load_instruction(insn, src);
- }
- } END_FOR_EACH_PTR(pu);
-
- /* Turn the store into a no-op */
- kill_store(def);
- return;
-
-multi_def:
-complex_def:
external_visibility:
all = 1;
FOR_EACH_PTR_REVERSE(pseudo->users, pu) {
diff --git a/validation/infinite-loop0.c b/validation/infinite-loop0.c
index a2849230..0e3e3805 100644
--- a/validation/infinite-loop0.c
+++ b/validation/infinite-loop0.c
@@ -8,5 +8,4 @@ void foo(void)
* check-name: internal infinite loop (0)
* check-command: sparse -Wno-decl $file
* check-timeout:
- * check-known-to-fail
*/