Rename "register.c" into "liveness.c". That's what it does.
[smatch.git] / check.c
blobe7f8a497600df2dc0c4820ef47eeab218e1d02f4
1 /*
2 * Example trivial client program that uses the sparse library
3 * to tokenize, pre-process and parse a C file, and prints out
4 * the results.
6 * Copyright (C) 2003 Transmeta Corp.
7 * 2003-2004 Linus Torvalds
9 * Licensed under the Open Software License version 1.1
11 #include <stdarg.h>
12 #include <stdlib.h>
13 #include <stdio.h>
14 #include <string.h>
15 #include <ctype.h>
16 #include <unistd.h>
17 #include <fcntl.h>
19 #include "lib.h"
20 #include "token.h"
21 #include "parse.h"
22 #include "symbol.h"
23 #include "expression.h"
24 #include "linearize.h"
26 static int context_increase(struct basic_block *bb)
28 int sum = 0;
29 struct instruction *insn;
31 FOR_EACH_PTR(bb->insns, insn) {
32 if (insn->opcode == OP_CONTEXT)
33 sum += insn->increment;
34 } END_FOR_EACH_PTR(insn);
35 return sum;
38 static int imbalance(struct entrypoint *ep, struct basic_block *bb, int entry, int exit, const char *why)
40 if (Wcontext) {
41 struct symbol *sym = ep->name;
42 warning(bb->pos, "context imbalance in '%s' - %s", show_ident(sym->ident), why);
44 return -1;
47 static int check_bb_context(struct entrypoint *ep, struct basic_block *bb, int entry, int exit);
49 static int check_children(struct entrypoint *ep, struct basic_block *bb, int entry, int exit)
51 struct instruction *insn;
52 struct basic_block *child;
54 insn = last_instruction(bb->insns);
55 if (!insn)
56 return 0;
57 if (insn->opcode == OP_RET)
58 return entry != exit ? imbalance(ep, bb, entry, exit, "wrong count at exit") : 0;
60 FOR_EACH_PTR(bb->children, child) {
61 if (check_bb_context(ep, child, entry, exit))
62 return -1;
63 } END_FOR_EACH_PTR(child);
64 return 0;
67 static int check_bb_context(struct entrypoint *ep, struct basic_block *bb, int entry, int exit)
69 if (!bb)
70 return 0;
71 if (bb->context == entry)
72 return 0;
74 /* Now that's not good.. */
75 if (bb->context >= 0)
76 return imbalance(ep, bb, entry, bb->context, "different lock contexts for basic block");
78 bb->context = entry;
79 entry += context_increase(bb);
80 if (entry < 0)
81 return imbalance(ep, bb, entry, exit, "unexpected unlock");
83 return check_children(ep, bb, entry, exit);
86 static void check_context(struct entrypoint *ep)
88 struct symbol *sym = ep->name;
90 if (verbose && ep->entry->needs)
91 warning(sym->pos, "%s: possible uninitialized variable", show_ident(sym->ident));
93 check_bb_context(ep, ep->entry, sym->ctype.in_context, sym->ctype.out_context);
96 static void check_symbols(struct symbol_list *list)
98 struct symbol *sym;
100 FOR_EACH_PTR(list, sym) {
101 struct entrypoint *ep;
103 expand_symbol(sym);
104 ep = linearize_symbol(sym);
105 if (ep)
106 check_context(ep);
107 } END_FOR_EACH_PTR(sym);
110 int main(int argc, char **argv)
112 // Expand, linearize and show it.
113 check_symbols(sparse(argc, argv));
114 return 0;