006eff06c7adcfb0d06c6fadf6e9b64f0488b2bf URL: git://git.kernel.org/pub/scm/linux/kernel/git/josh/sparse.git commit 006eff06c7adcfb0d06c6fadf6e9b64f0488b2bf Author: James Westby Date: Mon Dec 18 20:44:35 2006 +0000 Fix mistaken comparison that becomes a no-op. Fix a mistake in same_cast_type where the second test became a no-op as it compared a value to itself, rather than to the second operand. Signed-off-by: James Westby commit a12d4528ffc4e66b14519d739806f0eb793f72cf Author: Christopher Li Date: Tue Jan 16 18:45:45 2007 -0800 Marking anonymous string. The back end need to generate some storage for anonymous string. This simplify testing of anonymous string. Signed-off-by: Christopher Li commit 43972b481fb9daf8708b23ca525c96197c1c0491 Author: Christopher Li Date: Tue Jan 16 18:43:57 2007 -0800 Another attempt to fix the attribute parsing. This patch delay the finalized of the abstract int type so it can take the __attribute__ in the end of declaration. It complicate the bit field parsing because abstract type can show up in the base type of bit field. Signed-off-by: Christopher Li commit b775e61481c6c5dcc44088116a42c3f1b2a415c7 Author: Josh Triplett Date: Sat Jan 27 01:11:22 2007 -0800 Add missing #include "allocate.h" in linearize.h for DECLARE_ALLOCATOR. Signed-off-by: Josh Triplett commit c2f0f35a3fa25ab66e07e5eec3634df4d0432230 Author: Josh Triplett Date: Sat Jan 27 01:00:23 2007 -0800 Coding style fix: in a pointer type, * goes with the name, not the type. Signed-off-by: Josh Triplett commit 6a35332d4512044c2f924c406dbebc88e83f8ae5 Author: Christopher Li Date: Tue Jan 16 18:42:39 2007 -0800 Enhance debug information. I found it very useful for debug_symbol to show the builtin type name. Signed-off-by: Christopher Li Signed-off-by: Josh Triplett commit 2cf4d199235e7b39a14f2b3b6d396de6aa856c42 Author: Christopher Li Date: Tue Jan 16 18:40:05 2007 -0800 Allow more than one command line include file. Signed-off-by: Christopher Li commit 0b96e6ec62cdb25837e79a35ac6254ec704aea79 Author: Christopher Li Date: Tue Jan 16 18:38:04 2007 -0800 Update usage chain for dead branch instruction. A branch like this: br %c, 0x10, 0x10 will be simplified and removed, but the usage information was not updated. Signed-Off-By: Christopher Li commit 5816690643b28c606b63ae4bcd7429e53ef47316 Author: Josh Triplett Date: Tue Jan 16 20:52:36 2007 -0800 Add a return in the last case of a switch; redundant but less error-prone. Signed-off-by: Josh Triplett commit 556dbc8d75b051eb3b7af2997110e24c4356af8d Author: Christopher Li Date: Tue Jan 16 18:37:17 2007 -0800 Update usage chain for dead instructions This patch address some of the dead instructions left in the usage chain. Signed-Off-By: Christopher Li commit e7fb6e092055425e404052bfc9ffefd38365c009 Author: Christopher Li Date: Tue Jan 16 18:36:16 2007 -0800 Add instruction to pseudo user tracking. The current way of tracking pseudo register user is by keeping a list of the address of the pseudo_t member. This address can be in part of the instruction member, the worse case is in the argument list of the call instruction. As the comment for address_taken() said, using the container to get instruction pointer is wrong. It use to work with instruction that relate to symbol address. But that is not true any more. Even worse, it is very hard to track the pseudo usage other than symbol address. The only reason symbol address used to works for call instruction is because call instruction did not directly use the symbol address. I bit the bullet and just add the instruction pointer to pair with the pseudo user pointer. So it will work with the case that the user instruction is call as well. Testing: I compare the linearize result with/without the patch on a few sparse source file it self. The linearize generate exactly the same result except the symbol address changes. Which is predictable different because the pseudo user structure allocate memory. Singed-Off-By: Christopher Li commit 97c576befecb9024dcc13aceb78742b97902a133 Author: Christopher Li Date: Tue Jan 16 18:34:41 2007 -0800 Change the symbol access list to a pseudo list A pseudo list contains more information. It can get to the symbol as well as the usage information. Now it is much easier to answer questions like "What functions does this function call?". Signed-Off-By: Christopher Li commit 1a6673b7dc40de07c1f66a1c99daab3c0918dd2d Author: Josh Triplett Date: Tue Jan 16 20:11:11 2007 -0800 Add ctags to .gitignore Signed-off-by: Josh Triplett commit a77a4bce372094fc3bab441fa8c136c4544d24ff Author: Christopher Li Date: Tue Jan 16 18:33:42 2007 -0800 Sparse-based Ctags implementation Here is my attempt to write a Ctags base on sparse. It depends on the result from actually preprocessing the C source file. It can handle the tags from macro expansion. It works well enough for me to locate "int32_t" and "clear_token_alloc". This is the updated ctags that actually generates output to a tags file. Signed-Off-By: Christopher Li Signed-Off-By: Josh Triplett .gitignore | 1 + Makefile | 7 +- ctags.c | 207 ++++++++++++++++++++++++++++++++++++++++++ dissect.c | 4 +- dissect.h | 8 +- evaluate.c | 3 +- example.c | 2 +- flow.c | 62 +++++++------ lib.c | 47 +++++---- lib.h | 23 +++-- linearize.c | 86 +++++++++--------- linearize.h | 31 ++++++- memops.c | 22 +---- parse.c | 85 +++++++++++------ ptrlist.h | 2 +- show-parse.c | 112 ++++++++++++++--------- simplify.c | 53 ++++++++--- symbol.h | 9 ++- test-sort.c | 2 +- token.h | 2 +- validation/badtype3.c | 2 +- validation/init-char-array.c | 2 +- 22 files changed, 547 insertions(+), 225 deletions(-) diff --git a/.gitignore b/.gitignore index b92d678..e22a8c6 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,7 @@ test-dissect test-linearize example test-unssa +ctags # tags tags diff --git a/Makefile b/Makefile index 3bc789b..f7c647b 100644 --- a/Makefile +++ b/Makefile @@ -22,7 +22,8 @@ LIBDIR=$(PREFIX)/lib INCLUDEDIR=$(PREFIX)/include PKGCONFIGDIR=$(PREFIX)/share/pkgconfig -PROGRAMS=test-lexing test-parsing obfuscate compile graph sparse test-linearize example test-unssa test-dissect +PROGRAMS=test-lexing test-parsing obfuscate compile graph sparse test-linearize example \ + test-unssa test-dissect ctags INST_PROGRAMS=sparse cgcc LIB_H= token.h parse.h lib.h symbol.h scope.h expression.h target.h \ @@ -93,6 +94,9 @@ test-unssa: test-unssa.o $(LIBS) test-dissect: test-dissect.o $(LIBS) $(CC) $(LDFLAGS) -o $@ $< $(LIBS) +ctags: ctags.o $(LIBS) + $(CC) $(LDFLAGS) -o $@ $< $(LIBS) + $(LIB_FILE): $(LIB_OBJS) $(AR) rcs $@ $(LIB_OBJS) @@ -122,6 +126,7 @@ test-lexing.o: $(LIB_H) test-parsing.o: $(LIB_H) test-linearize.o: $(LIB_H) test-dissect.o: $(LIB_H) +ctags.o: $(LIB_H) compile.o: $(LIB_H) compile.h compile-i386.o: $(LIB_H) compile.h tokenize.o: $(LIB_H) diff --git a/ctags.c b/ctags.c new file mode 100644 index 0000000..17dd1c1 --- /dev/null +++ b/ctags.c @@ -0,0 +1,207 @@ +/* + * Sparse Ctags + * + * Ctags generates tags from preprocessing results. + * + * Copyright (C) 2006 Christopher Li + * + * Licensed under the Open Software License version 1.1 + */ +#include +#include +#include +#include +#include + +#include "parse.h" +#include "scope.h" + +static struct symbol_list *taglist = NULL; + +static void examine_symbol(struct symbol *sym); + +#define MAX(_x,_y) ((_x) > (_y) ? (_x) : (_y)) + +static int cmp_sym(const void *m, const void *n) +{ + struct ident *a = ((struct symbol *)m)->ident; + struct ident *b = ((struct symbol *)n)->ident; + int ret = strncmp(a->name, b->name, MAX(a->len, b->len)); + if (!ret) { + struct position a = ((struct symbol *)m)->pos; + struct position b = ((struct symbol *)n)->pos; + + ret = strcmp(stream_name(a.stream), stream_name(b.stream)); + if (!ret) + return a.line < b.line; + } + return ret; +} + +static void show_tag_header(FILE *fp) +{ + fprintf(fp, "!_TAG_FILE_FORMAT\t2\t/extended format; --format=1 will not append ;\" to lines/\n"); + fprintf(fp, "!_TAG_FILE_SORTED\t0\t/0=unsorted, 1=sorted, 2=foldcase/\n"); + fprintf(fp, "!_TAG_PROGRAM_AUTHOR\tChristopher Li\t/sparse@chrisli.org/\n"); + fprintf(fp, "!_TAG_PROGRAM_NAME\tSparse Ctags\t//\n"); + fprintf(fp, "!_TAG_PROGRAM_URL\thttp://kernel.org/pub/linux/kernel/people/josh/sparse/\t/official site/\n"); + fprintf(fp, "!_TAG_PROGRAM_VERSION\t0.01\t//\n"); +} + +static inline void show_symbol_tag(FILE *fp, struct symbol *sym) +{ + fprintf(fp, "%s\t%s\t%d;\"\t%c\tfile:\n", show_ident(sym->ident), + stream_name(sym->pos.stream), sym->pos.line, (int)sym->kind); +} + +static void show_tags(struct symbol_list *list) +{ + struct symbol *sym; + struct ident *ident = NULL; + struct position pos = {}; + static const char *filename; + FILE *fp; + + if (!list) + return; + + fp = fopen("tags", "w"); + if (!fp) { + perror("open tags file"); + return; + } + show_tag_header(fp); + FOR_EACH_PTR(list, sym) { + if (ident == sym->ident && pos.line == sym->pos.line && + !strcmp(filename, stream_name(sym->pos.stream))) + continue; + + show_symbol_tag(fp, sym); + ident = sym->ident; + pos = sym->pos; + filename = stream_name(sym->pos.stream); + } END_FOR_EACH_PTR(sym); + fclose(fp); +} + +static inline void add_tag(struct symbol *sym) +{ + if (sym->ident && !sym->visited) { + sym->visited = 1; + add_symbol(&taglist, sym); + } +} + +static inline void examine_members(struct symbol_list *list) +{ + struct symbol *sym; + + FOR_EACH_PTR(list, sym) { + sym->kind = 'm'; + examine_symbol(sym); + } END_FOR_EACH_PTR(sym); +} + +static void examine_symbol(struct symbol *sym) +{ + struct symbol *base = sym; + + if (!sym || sym->visited) + return; + if (sym->ident && sym->ident->reserved) + return; + + add_tag(sym); + base = sym->ctype.base_type; + + switch (sym->type) { + case SYM_NODE: + if (base->type == SYM_FN) + sym->kind = 'f'; + examine_symbol(base); + break; + case SYM_STRUCT: + sym->kind = 's'; + examine_members(sym->symbol_list); + break; + case SYM_UNION: + sym->kind = 'u'; + examine_members(sym->symbol_list); + break; + case SYM_ENUM: + sym->kind = 'e'; + case SYM_PTR: + case SYM_TYPEOF: + case SYM_BITFIELD: + case SYM_FN: + case SYM_ARRAY: + examine_symbol(sym->ctype.base_type); + break; + case SYM_BASETYPE: + break; + + default: + die("unknown symbol %s namespace:%d type:%d\n", show_ident(sym->ident), + sym->namespace, sym->type); + } + if (!sym->kind) + sym->kind = 'v'; + return; +} + +static void examine_namespace(struct symbol *sym) +{ + if (sym->visited) + return; + if (sym->ident && sym->ident->reserved) + return; + + switch(sym->namespace) { + case NS_LABEL: + sym->kind = 'l'; + break; + case NS_PREPROCESSOR: + break; + case NS_MACRO: + case NS_UNDEF: + sym->kind = 'd'; + break; + case NS_TYPEDEF: + sym->kind = 't'; + case NS_SYMBOL: + case NS_STRUCT: + examine_symbol(sym); + break; + default: + die("unknown namespace %d symbol:%s type:%d\n", sym->namespace, + show_ident(sym->ident), sym->type); + } + add_tag(sym); +} + +static inline void examine_symbol_list(struct symbol_list *list) +{ + struct symbol *sym; + + if (!list) + return; + FOR_EACH_PTR(list, sym) { + examine_namespace(sym); + } END_FOR_EACH_PTR(sym); +} + +int main(int argc, char **argv) +{ + struct string_list *filelist = NULL; + char *file; + + examine_symbol_list(sparse_initialize(argc, argv, &filelist)); + FOR_EACH_PTR_NOTAG(filelist, file) { + sparse(file); + examine_symbol_list(file_scope->symbols); + } END_FOR_EACH_PTR_NOTAG(file); + examine_symbol_list(global_scope->symbols); + sort_list((struct ptr_list **)&taglist, cmp_sym); + show_tags(taglist); + return 0; +} diff --git a/dissect.c b/dissect.c index 018cebb..471eac0 100644 --- a/dissect.c +++ b/dissect.c @@ -42,7 +42,7 @@ static void do_sym_list(struct symbol_list *list); static struct symbol *base_type(struct symbol *sym), - *do_initializer(struct symbol *type, struct expression* expr), + *do_initializer(struct symbol *type, struct expression *expr), *do_expression(usage_t mode, struct expression *expr), *do_statement(usage_t mode, struct statement *stmt); @@ -497,7 +497,7 @@ static struct symbol *do_statement(usage_t mode, struct statement *stmt) return ret; } -static struct symbol *do_initializer(struct symbol *type, struct expression* expr) +static struct symbol *do_initializer(struct symbol *type, struct expression *expr) { struct symbol *m_type; struct expression *m_expr; diff --git a/dissect.h b/dissect.h index ffac806..3b72b89 100644 --- a/dissect.h +++ b/dissect.h @@ -18,13 +18,13 @@ struct reporter { - void (*r_symdef)(struct symbol*); + void (*r_symdef)(struct symbol *); - void (*r_symbol)(unsigned, struct position*, struct symbol*); - void (*r_member)(unsigned, struct position*, struct symbol*, struct symbol*); + void (*r_symbol)(unsigned, struct position *, struct symbol *); + void (*r_member)(unsigned, struct position *, struct symbol *, struct symbol *); }; -extern void dissect(struct symbol_list*, struct reporter*); +extern void dissect(struct symbol_list *, struct reporter *); #define MK_IDENT(s) ({ \ static struct { \ diff --git a/evaluate.c b/evaluate.c index ca49ed0..5b52e2b 100644 --- a/evaluate.c +++ b/evaluate.c @@ -74,6 +74,7 @@ static struct symbol *evaluate_string(struct expression *expr) sym->array_size = alloc_const_expression(expr->pos, length); sym->bit_size = bits_in_char * length; sym->ctype.alignment = 1; + sym->string = 1; sym->ctype.modifiers = MOD_STATIC; sym->ctype.base_type = array; sym->initializer = initstr; @@ -179,7 +180,7 @@ left: static int same_cast_type(struct symbol *orig, struct symbol *new) { - return orig->bit_size == new->bit_size && orig->bit_offset == orig->bit_offset; + return orig->bit_size == new->bit_size && orig->bit_offset == new->bit_offset; } static struct symbol *base_type(struct symbol *node, unsigned long *modp, unsigned long *asp) diff --git a/example.c b/example.c index fb0ad1a..9515435 100644 --- a/example.c +++ b/example.c @@ -14,7 +14,7 @@ #include "storage.h" #include "target.h" -static const char* opcodes[] = { +static const char *opcodes[] = { [OP_BADOP] = "bad_op", /* Fn entrypoint */ diff --git a/flow.c b/flow.c index 00bc807..fa4764a 100644 --- a/flow.c +++ b/flow.c @@ -195,6 +195,7 @@ try_to_rewrite_target: if (bb_list_size(target->parents) != 1) return retval; insert_branch(target, insn, final); + kill_instruction(insn); return 1; } @@ -229,27 +230,27 @@ int simplify_flow(struct entrypoint *ep) return simplify_branch_nodes(ep); } -static inline void concat_user_list(struct pseudo_ptr_list *src, struct pseudo_ptr_list **dst) +static inline void concat_user_list(struct pseudo_user_list *src, struct pseudo_user_list **dst) { concat_ptr_list((struct ptr_list *)src, (struct ptr_list **)dst); } void convert_instruction_target(struct instruction *insn, pseudo_t src) { - pseudo_t target, *usep; - + pseudo_t target; + struct pseudo_user *pu; /* * Go through the "insn->users" list and replace them all.. */ target = insn->target; if (target == src) return; - FOR_EACH_PTR(target->users, usep) { - if (*usep != VOID) { - assert(*usep == target); - *usep = src; + FOR_EACH_PTR(target->users, pu) { + if (*pu->userp != VOID) { + assert(*pu->userp == target); + *pu->userp = src; } - } END_FOR_EACH_PTR(usep); + } END_FOR_EACH_PTR(pu); concat_user_list(target->users, &src->users); target->users = NULL; } @@ -360,7 +361,7 @@ found_dominator: phi = alloc_phi(parent, one->target, one->size); phi->ident = phi->ident ? : pseudo->ident; add_instruction(&parent->insns, br); - use_pseudo(phi, add_pseudo(dominators, phi)); + use_pseudo(insn, phi, add_pseudo(dominators, phi)); } END_FOR_EACH_PTR(parent); return 1; } @@ -592,7 +593,8 @@ void check_access(struct instruction *insn) static void simplify_one_symbol(struct entrypoint *ep, struct symbol *sym) { - pseudo_t pseudo, src, *pp; + pseudo_t pseudo, src; + struct pseudo_user *pu; struct instruction *def; unsigned long mod; int all, stores, complex; @@ -614,9 +616,9 @@ static void simplify_one_symbol(struct entrypoint *ep, struct symbol *sym) def = NULL; stores = 0; complex = 0; - FOR_EACH_PTR(pseudo->users, pp) { + FOR_EACH_PTR(pseudo->users, pu) { /* We know that the symbol-pseudo use is the "src" in the instruction */ - struct instruction *insn = container(pp, struct instruction, src); + struct instruction *insn = pu->insn; switch (insn->opcode) { case OP_STORE: @@ -639,7 +641,7 @@ static void simplify_one_symbol(struct entrypoint *ep, struct symbol *sym) warning(sym->pos, "symbol '%s' pseudo used in unexpected way", show_ident(sym->ident)); } complex |= insn->offset; - } END_FOR_EACH_PTR(pp); + } END_FOR_EACH_PTR(pu); if (complex) goto complex_def; @@ -655,13 +657,13 @@ static void simplify_one_symbol(struct entrypoint *ep, struct symbol *sym) if (def) src = def->target; - FOR_EACH_PTR(pseudo->users, pp) { - struct instruction *insn = container(pp, struct instruction, src); + 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(pp); + } END_FOR_EACH_PTR(pu); /* Turn the store into a no-op */ kill_store(def); @@ -671,29 +673,29 @@ multi_def: complex_def: external_visibility: all = 1; - FOR_EACH_PTR_REVERSE(pseudo->users, pp) { - struct instruction *insn = container(pp, struct instruction, src); + FOR_EACH_PTR_REVERSE(pseudo->users, pu) { + struct instruction *insn = pu->insn; if (insn->opcode == OP_LOAD) all &= find_dominating_stores(pseudo, insn, ++bb_generation, !mod); - } END_FOR_EACH_PTR_REVERSE(pp); + } END_FOR_EACH_PTR_REVERSE(pu); /* If we converted all the loads, remove the stores. They are dead */ if (all && !mod) { - FOR_EACH_PTR(pseudo->users, pp) { - struct instruction *insn = container(pp, struct instruction, src); + FOR_EACH_PTR(pseudo->users, pu) { + struct instruction *insn = pu->insn; if (insn->opcode == OP_STORE) kill_store(insn); - } END_FOR_EACH_PTR(pp); + } END_FOR_EACH_PTR(pu); } else { /* * If we couldn't take the shortcut, see if we can at least kill some * of them.. */ - FOR_EACH_PTR(pseudo->users, pp) { - struct instruction *insn = container(pp, struct instruction, src); + FOR_EACH_PTR(pseudo->users, pu) { + struct instruction *insn = pu->insn; if (insn->opcode == OP_STORE) kill_dominated_stores(pseudo, insn, ++bb_generation, insn->bb, !mod, 0); - } END_FOR_EACH_PTR(pp); + } END_FOR_EACH_PTR(pu); if (!(mod & (MOD_NONLOCAL | MOD_STATIC))) { struct basic_block *bb; @@ -709,11 +711,11 @@ external_visibility: void simplify_symbol_usage(struct entrypoint *ep) { - struct symbol *sym; + pseudo_t pseudo; - FOR_EACH_PTR(ep->accesses, sym) { - simplify_one_symbol(ep, sym); - } END_FOR_EACH_PTR(sym); + FOR_EACH_PTR(ep->accesses, pseudo) { + simplify_one_symbol(ep, pseudo->sym); + } END_FOR_EACH_PTR(pseudo); } static void mark_bb_reachable(struct basic_block *bb, unsigned long generation) @@ -985,7 +987,7 @@ out: replace_bb_in_list(&child->parents, bb, parent, 0); } END_FOR_EACH_PTR(child); - delete_last_instruction(&parent->insns); + kill_instruction(delete_last_instruction(&parent->insns)); FOR_EACH_PTR(bb->insns, insn) { if (insn->bb) { assert(insn->bb == bb); diff --git a/lib.c b/lib.c index 51c415d..8adb2ab 100644 --- a/lib.c +++ b/lib.c @@ -192,7 +192,10 @@ int Wdo_while = 1; int Wuninitialized = 1; int preprocess_only; char *include; -int include_fd = -1; + +#define CMDLINE_INCLUDE 20 +int cmdline_include_nr = 0; +struct cmdline_include cmdline_include[CMDLINE_INCLUDE]; void add_pre_buffer(const char *fmt, ...) @@ -262,26 +265,26 @@ static char **handle_switch_I(char *arg, char **next) return next; } -static char **handle_switch_i(char *arg, char **next) +static void add_cmdline_include(char *filename) { - if (*next && !strcmp(arg, "include")) { - char *name = *++next; - int fd = open(name, O_RDONLY); - - include_fd = fd; - include = name; - if (fd < 0) - perror(name); + int fd = open(filename, O_RDONLY); + if (fd < 0) { + perror(filename); + return; } - if (*next && !strcmp(arg, "imacros")) { - char *name = *++next; - int fd = open(name, O_RDONLY); + if (cmdline_include_nr >= CMDLINE_INCLUDE) + die("too many include files for %s\n", filename); + cmdline_include[cmdline_include_nr].filename = filename; + cmdline_include[cmdline_include_nr].fd = fd; + cmdline_include_nr++; +} - include_fd = fd; - include = name; - if (fd < 0) - perror(name); - } +static char **handle_switch_i(char *arg, char **next) +{ + if (*next && !strcmp(arg, "include")) + add_cmdline_include(*++next); + else if (*next && !strcmp(arg, "imacros")) + add_cmdline_include(*++next); else if (*next && !strcmp(arg, "isystem")) { char *path = *++next; if (!path) @@ -446,7 +449,7 @@ static char **handle_dirafter(char *arg, char **next) struct switches { const char *name; - char **(*fn)(char *, char**); + char **(*fn)(char *, char **); }; char **handle_switch(char *arg, char **next) @@ -623,12 +626,14 @@ static struct symbol_list *sparse_file(const char *filename) static struct symbol_list *sparse_initial(void) { struct token *token; + int i; // Prepend any "include" file to the stream. // We're in global scope, it will affect all files! token = NULL; - if (include_fd >= 0) - token = tokenize(include, include_fd, NULL, includepath); + for (i = cmdline_include_nr - 1; i >= 0; i--) + token = tokenize(cmdline_include[i].filename, cmdline_include[i].fd, + token, includepath); // Prepend the initial built-in stream token = tokenize_buffer(pre_buffer, pre_buffer_size, token); diff --git a/lib.h b/lib.h index e133c16..893b7db 100644 --- a/lib.h +++ b/lib.h @@ -33,6 +33,15 @@ struct position { noexpand:1; }; +struct cmdline_include { + char *filename; + int fd; +}; + +extern struct cmdline_include cmdline_include[]; +extern int cmdline_include_nr; + + struct ident; struct token; struct symbol; @@ -90,36 +99,36 @@ extern int Wuninitialized; extern void declare_builtin_functions(void); extern void create_builtin_stream(void); -extern struct symbol_list *sparse_initialize(int argc, char **argv, struct string_list** files); +extern struct symbol_list *sparse_initialize(int argc, char **argv, struct string_list **files); extern struct symbol_list *__sparse(char *filename); extern struct symbol_list *sparse(char *filename); -static inline int symbol_list_size(struct symbol_list* list) +static inline int symbol_list_size(struct symbol_list *list) { return ptr_list_size((struct ptr_list *)(list)); } -static inline int statement_list_size(struct statement_list* list) +static inline int statement_list_size(struct statement_list *list) { return ptr_list_size((struct ptr_list *)(list)); } -static inline int expression_list_size(struct expression_list* list) +static inline int expression_list_size(struct expression_list *list) { return ptr_list_size((struct ptr_list *)(list)); } -static inline int instruction_list_size(struct instruction_list* list) +static inline int instruction_list_size(struct instruction_list *list) { return ptr_list_size((struct ptr_list *)(list)); } -static inline int pseudo_list_size(struct pseudo_list* list) +static inline int pseudo_list_size(struct pseudo_list *list) { return ptr_list_size((struct ptr_list *)(list)); } -static inline int bb_list_size(struct basic_block_list* list) +static inline int bb_list_size(struct basic_block_list *list) { return ptr_list_size((struct ptr_list *)(list)); } diff --git a/linearize.c b/linearize.c index 8a8a2d3..13cdf71 100644 --- a/linearize.c +++ b/linearize.c @@ -37,6 +37,8 @@ struct pseudo void_pseudo = {}; static struct position current_pos; +ALLOCATOR(pseudo_user, "pseudo_user"); + static struct instruction *alloc_instruction(int opcode, int size) { struct instruction * insn = __alloc_instruction(0); @@ -70,7 +72,7 @@ static struct basic_block *alloc_basic_block(struct entrypoint *ep, struct posit return bb; } -static struct multijmp* alloc_multijmp(struct basic_block *target, int begin, int end) +static struct multijmp *alloc_multijmp(struct basic_block *target, int begin, int end) { struct multijmp *multijmp = __alloc_multijmp(0); multijmp->target = target; @@ -152,7 +154,7 @@ const char *show_pseudo(pseudo_t pseudo) return buf; } -static const char* opcodes[] = { +static const char *opcodes[] = { [OP_BADOP] = "bad_op", /* Fn entrypoint */ @@ -517,12 +519,12 @@ void show_bb(struct basic_block *bb) static void show_symbol_usage(pseudo_t pseudo) { + struct pseudo_user *pu; + if (pseudo) { - pseudo_t *pp; - FOR_EACH_PTR(pseudo->users, pp) { - struct instruction *insn = container(pp, struct instruction, src); - printf("\t%s\n", show_instruction(insn)); - } END_FOR_EACH_PTR(pp); + FOR_EACH_PTR(pseudo->users, pu) { + printf("\t%s\n", show_instruction(pu->insn)); + } END_FOR_EACH_PTR(pu); } } @@ -667,15 +669,15 @@ void insert_select(struct basic_block *bb, struct instruction *br, struct instru select->bb = bb; assert(br->cond); - use_pseudo(br->cond, &select->src1); + use_pseudo(select, br->cond, &select->src1); target = phi_node->target; assert(target->def == phi_node); select->target = target; target->def = select; - use_pseudo(true, &select->src2); - use_pseudo(false, &select->src3); + use_pseudo(select, true, &select->src2); + use_pseudo(select, false, &select->src3); add_instruction(&bb->insns, select); add_instruction(&bb->insns, br); @@ -711,7 +713,7 @@ static void add_branch(struct entrypoint *ep, struct expression *expr, pseudo_t if (bb_reachable(bb)) { br = alloc_instruction(OP_BR, 0); - use_pseudo(cond, &br->cond); + use_pseudo(br, cond, &br->cond); br->bb_true = bb_true; br->bb_false = bb_false; add_bb(&bb_true->parents, bb); @@ -735,11 +737,11 @@ pseudo_t alloc_pseudo(struct instruction *def) static void clear_symbol_pseudos(struct entrypoint *ep) { - struct symbol *sym; + pseudo_t pseudo; - FOR_EACH_PTR(ep->accesses, sym) { - sym->pseudo = NULL; - } END_FOR_EACH_PTR(sym); + FOR_EACH_PTR(ep->accesses, pseudo) { + pseudo->sym->pseudo = NULL; + } END_FOR_EACH_PTR(pseudo); } static pseudo_t symbol_pseudo(struct entrypoint *ep, struct symbol *sym) @@ -757,7 +759,7 @@ static pseudo_t symbol_pseudo(struct entrypoint *ep, struct symbol *sym) pseudo->sym = sym; pseudo->ident = sym->ident; sym->pseudo = pseudo; - add_symbol(&ep->accesses, sym); + add_pseudo(&ep->accesses, pseudo); } /* Symbol pseudos have neither nr, usage nor def */ return pseudo; @@ -809,7 +811,7 @@ pseudo_t alloc_phi(struct basic_block *source, pseudo_t pseudo, int size) phi->nr = ++nr; phi->def = insn; - use_pseudo(pseudo, &insn->phi_src); + use_pseudo(insn, pseudo, &insn->phi_src); insn->bb = source; insn->target = phi; add_instruction(&source->insns, insn); @@ -905,7 +907,7 @@ static pseudo_t add_load(struct entrypoint *ep, struct access_data *ad) insn->target = new; insn->offset = ad->offset; - use_pseudo(ad->address, &insn->src); + use_pseudo(insn, ad->address, &insn->src); add_one_insn(ep, insn); return new; } @@ -917,8 +919,8 @@ static void add_store(struct entrypoint *ep, struct access_data *ad, pseudo_t va if (bb_reachable(bb)) { struct instruction *store = alloc_typed_instruction(OP_STORE, ad->source_type); store->offset = ad->offset; - use_pseudo(value, &store->target); - use_pseudo(ad->address, &store->src); + use_pseudo(store, value, &store->target); + use_pseudo(store, ad->address, &store->src); add_one_insn(ep, store); } } @@ -950,8 +952,8 @@ static pseudo_t add_binary_op(struct entrypoint *ep, struct symbol *ctype, int o struct instruction *insn = alloc_typed_instruction(op, ctype); pseudo_t target = alloc_pseudo(insn); insn->target = target; - use_pseudo(left, &insn->src1); - use_pseudo(right, &insn->src2); + use_pseudo(insn, left, &insn->src1); + use_pseudo(insn, right, &insn->src2); add_one_insn(ep, insn); return target; } @@ -972,7 +974,7 @@ static pseudo_t add_symbol_address(struct entrypoint *ep, struct symbol *sym) pseudo_t target = alloc_pseudo(insn); insn->target = target; - use_pseudo(symbol_pseudo(ep, sym), &insn->symbol); + use_pseudo(insn, symbol_pseudo(ep, sym), &insn->symbol); add_one_insn(ep, insn); return target; } @@ -1026,7 +1028,7 @@ static pseudo_t add_uniop(struct entrypoint *ep, struct expression *expr, int op pseudo_t new = alloc_pseudo(insn); insn->target = new; - use_pseudo(src, &insn->src1); + use_pseudo(insn, src, &insn->src1); add_one_insn(ep, insn); return new; } @@ -1040,7 +1042,7 @@ static pseudo_t linearize_slice(struct entrypoint *ep, struct expression *expr) insn->target = new; insn->from = expr->r_bitpos; insn->len = expr->r_nrbits; - use_pseudo(pre, &insn->base); + use_pseudo(insn, pre, &insn->base); add_one_insn(ep, insn); return new; } @@ -1122,7 +1124,7 @@ static pseudo_t cast_pseudo(struct entrypoint *ep, pseudo_t src, struct symbol * result = alloc_pseudo(insn); insn->target = result; insn->orig_type = from; - use_pseudo(src, &insn->src); + use_pseudo(insn, src, &insn->src); add_one_insn(ep, insn); return result; } @@ -1193,7 +1195,7 @@ static pseudo_t linearize_call_expression(struct entrypoint *ep, struct expressi FOR_EACH_PTR(expr->args, arg) { pseudo_t new = linearize_expression(ep, arg); - use_pseudo(new, add_pseudo(&insn->arguments, new)); + use_pseudo(insn, new, add_pseudo(&insn->arguments, new)); } END_FOR_EACH_PTR(arg); fn = expr->fn; @@ -1213,7 +1215,7 @@ static pseudo_t linearize_call_expression(struct entrypoint *ep, struct expressi } else { call = linearize_expression(ep, fn); } - use_pseudo(call, &insn->func); + use_pseudo(insn, call, &insn->func); retval = VOID; if (expr->ctype != &void_ctype) retval = alloc_pseudo(insn); @@ -1286,9 +1288,9 @@ static pseudo_t linearize_select(struct entrypoint *ep, struct expression *expr) insn = alloc_typed_instruction(OP_SEL, expr->ctype); if (!expr->cond_true) true = cond; - use_pseudo(cond, &insn->src1); - use_pseudo(true, &insn->src2); - use_pseudo(false, &insn->src3); + use_pseudo(insn, cond, &insn->src1); + use_pseudo(insn, true, &insn->src2); + use_pseudo(insn, false, &insn->src3); res = alloc_pseudo(insn); insn->target = res; @@ -1308,8 +1310,8 @@ static pseudo_t add_join_conditional(struct entrypoint *ep, struct expression *e return phi1; phi_node = alloc_typed_instruction(OP_PHI, expr->ctype); - use_pseudo(phi1, add_pseudo(&phi_node->phi_list, phi1)); - use_pseudo(phi2, add_pseudo(&phi_node->phi_list, phi2)); + use_pseudo(phi_node, phi1, add_pseudo(&phi_node->phi_list, phi1)); + use_pseudo(phi_node, phi2, add_pseudo(&phi_node->phi_list, phi2)); phi_node->target = target = alloc_pseudo(phi_node); add_one_insn(ep, phi_node); return target; @@ -1652,9 +1654,9 @@ static pseudo_t linearize_range(struct entrypoint *ep, struct statement *stmt) { struct instruction *insn = alloc_instruction(OP_RANGE, 0); - use_pseudo(linearize_expression(ep, stmt->range_expression), &insn->src1); - use_pseudo(linearize_expression(ep, stmt->range_low), &insn->src2); - use_pseudo(linearize_expression(ep, stmt->range_high), &insn->src3); + use_pseudo(insn, linearize_expression(ep, stmt->range_expression), &insn->src1); + use_pseudo(insn, linearize_expression(ep, stmt->range_low), &insn->src2); + use_pseudo(insn, linearize_expression(ep, stmt->range_high), &insn->src3); add_one_insn(ep, insn); return VOID; } @@ -1670,7 +1672,7 @@ static void add_asm_input(struct entrypoint *ep, struct instruction *insn, struc rule->ident = ident; rule->constraint = constraint; - use_pseudo(pseudo, &rule->pseudo); + use_pseudo(insn, pseudo, &rule->pseudo); add_ptr_list(&insn->asm_rules->inputs, rule); } @@ -1688,7 +1690,7 @@ static void add_asm_output(struct entrypoint *ep, struct instruction *insn, stru rule = __alloc_asm_constraint(0); rule->ident = ident; rule->constraint = constraint; - use_pseudo(pseudo, &rule->pseudo); + use_pseudo(insn, pseudo, &rule->pseudo); add_ptr_list(&insn->asm_rules->outputs, rule); } @@ -1847,7 +1849,7 @@ pseudo_t linearize_statement(struct entrypoint *ep, struct statement *stmt) } phi = alloc_phi(active, src, type_size(expr->ctype)); phi->ident = &return_ident; - use_pseudo(phi, add_pseudo(&phi_node->phi_list, phi)); + use_pseudo(phi_node, phi, add_pseudo(&phi_node->phi_list, phi)); } add_goto(ep, bb_return); return VOID; @@ -1897,7 +1899,7 @@ pseudo_t linearize_statement(struct entrypoint *ep, struct statement *stmt) pseudo = linearize_expression(ep, expr); goto_ins = alloc_instruction(OP_COMPUTEDGOTO, 0); - use_pseudo(pseudo, &goto_ins->target); + use_pseudo(goto_ins, pseudo, &goto_ins->target); add_one_insn(ep, goto_ins); FOR_EACH_PTR(stmt->target_list, sym) { @@ -1956,7 +1958,7 @@ pseudo_t linearize_statement(struct entrypoint *ep, struct statement *stmt) break; switch_ins = alloc_instruction(OP_SWITCH, 0); - use_pseudo(pseudo, &switch_ins->cond); + use_pseudo(switch_ins, pseudo, &switch_ins->cond); add_one_insn(ep, switch_ins); finish_block(ep); @@ -2086,7 +2088,7 @@ static struct entrypoint *linearize_fn(struct symbol *sym, struct symbol *base_t struct instruction *insn = alloc_typed_instruction(OP_RET, ret_type); if (type_size(ret_type) > 0) - use_pseudo(result, &insn->src); + use_pseudo(insn, result, &insn->src); add_one_insn(ep, insn); } diff --git a/linearize.h b/linearize.h index 517ec67..673d13e 100644 --- a/linearize.h +++ b/linearize.h @@ -2,6 +2,7 @@ #define LINEARIZE_H #include "lib.h" +#include "allocate.h" #include "token.h" #include "parse.h" #include "symbol.h" @@ -9,6 +10,15 @@ struct instruction; DECLARE_PTR_LIST(pseudo_ptr_list, pseudo_t); +struct pseudo_user { + struct instruction *insn; + pseudo_t *userp; +}; + +DECLARE_ALLOCATOR(pseudo_user); +DECLARE_PTR_LIST(pseudo_user_list, struct pseudo_user); + + enum pseudo_type { PSEUDO_VOID, PSEUDO_REG, @@ -21,7 +31,7 @@ enum pseudo_type { struct pseudo { int nr; enum pseudo_type type; - struct pseudo_ptr_list *users; + struct pseudo_user_list *users; struct ident *ident; union { struct symbol *sym; @@ -268,16 +278,29 @@ static inline void add_pseudo_ptr(pseudo_t *ptr, struct pseudo_ptr_list **list) add_ptr_list(list, ptr); } +static inline void add_pseudo_user_ptr(struct pseudo_user *user, struct pseudo_user_list **list) +{ + add_ptr_list(list, user); +} + static inline int has_use_list(pseudo_t p) { return (p && p->type != PSEUDO_VOID && p->type != PSEUDO_VAL); } -static inline void use_pseudo(pseudo_t p, pseudo_t *pp) +static inline struct pseudo_user *alloc_pseudo_user(struct instruction *insn, pseudo_t *pp) +{ + struct pseudo_user *user = __alloc_pseudo_user(0); + user->userp = pp; + user->insn = insn; + return user; +} + +static inline void use_pseudo(struct instruction *insn, pseudo_t p, pseudo_t *pp) { *pp = p; if (has_use_list(p)) - add_pseudo_ptr(pp, &p->users); + add_pseudo_user_ptr(alloc_pseudo_user(insn, pp), &p->users); } static inline void remove_bb_from_list(struct basic_block_list **list, struct basic_block *entry, int count) @@ -294,7 +317,7 @@ static inline void replace_bb_in_list(struct basic_block_list **list, struct entrypoint { struct symbol *name; struct symbol_list *syms; - struct symbol_list *accesses; + struct pseudo_list *accesses; struct basic_block_list *bbs; struct basic_block *active; struct instruction *entry; diff --git a/memops.c b/memops.c index bdecf14..027f05e 100644 --- a/memops.c +++ b/memops.c @@ -59,31 +59,19 @@ found_dominator: phi = alloc_phi(parent, one->target, one->size); phi->ident = phi->ident ? : one->target->ident; add_instruction(&parent->insns, br); - use_pseudo(phi, add_pseudo(dominators, phi)); + use_pseudo(insn, phi, add_pseudo(dominators, phi)); } END_FOR_EACH_PTR(parent); return 1; } -/* - * FIXME! This is wrong. Since we now distribute out the OP_SYMADDR, - * we can no longer really use "container()" to get from a user to - * the instruction that uses it. - * - * This happens to work, simply because the likelihood of the - * (possibly non-instruction) containing the right bitpattern - * in the right place is pretty low. But this is still wrong. - * - * We should make symbol-pseudos count non-load/store usage, - * or something. - */ static int address_taken(pseudo_t pseudo) { - pseudo_t *usep; - FOR_EACH_PTR(pseudo->users, usep) { - struct instruction *insn = container(usep, struct instruction, src); + struct pseudo_user *pu; + FOR_EACH_PTR(pseudo->users, pu) { + struct instruction *insn = pu->insn; if (insn->bb && (insn->opcode != OP_LOAD || insn->opcode != OP_STORE)) return 1; - } END_FOR_EACH_PTR(usep); + } END_FOR_EACH_PTR(pu); return 0; } diff --git a/parse.c b/parse.c index dc20812..5077ee6 100644 --- a/parse.c +++ b/parse.c @@ -70,6 +70,50 @@ struct statement *alloc_statement(struct position pos, int type) static struct token *struct_declaration_list(struct token *token, struct symbol_list **list); +static int apply_modifiers(struct position pos, struct ctype *ctype) +{ + struct symbol *base; + + while ((base = ctype->base_type)) { + switch (base->type) { + case SYM_FN: + case SYM_ENUM: + case SYM_ARRAY: + case SYM_BITFIELD: + case SYM_PTR: + ctype = &base->ctype; + continue; + } + break; + } + + /* Turn the "virtual types" into real types with real sizes etc */ + if (ctype->base_type == &int_type) { + ctype->base_type = ctype_integer(ctype->modifiers); + ctype->modifiers &= ~MOD_SPECIFIER; + } else if (ctype->base_type == &fp_type) { + ctype->base_type = ctype_fp(ctype->modifiers); + ctype->modifiers &= ~MOD_SPECIFIER; + } + + if (ctype->modifiers & MOD_BITWISE) { + struct symbol *type; + ctype->modifiers &= ~(MOD_BITWISE | MOD_SPECIFIER); + if (!is_int_type(ctype->base_type)) { + sparse_error(pos, "invalid modifier"); + return 1; + } + type = alloc_symbol(pos, SYM_BASETYPE); + *type = *ctype->base_type; + type->ctype.base_type = ctype->base_type; + type->type = SYM_RESTRICT; + type->ctype.modifiers &= ~MOD_SPECIFIER; + ctype->base_type = type; + create_fouled(type); + } + return 0; +} + static struct symbol * indirect(struct position pos, struct ctype *ctype, int type) { struct symbol *sym = alloc_symbol(pos, type); @@ -724,7 +768,6 @@ static void check_modifiers(struct position *pos, struct symbol *s, unsigned lon modifier_string (wrong)); } - static struct token *declaration_specifiers(struct token *next, struct ctype *ctype, int qual) { struct token *token; @@ -778,7 +821,6 @@ static struct token *declaration_specifiers(struct token *next, struct ctype *ct apply_ctype(token->pos, &thistype, ctype); } - /* Turn the "virtual types" into real types with real sizes etc */ if (!ctype->base_type) { struct symbol *base = &incomplete_ctype; @@ -791,28 +833,6 @@ static struct token *declaration_specifiers(struct token *next, struct ctype *ct base = &int_type; ctype->base_type = base; } - if (ctype->base_type == &int_type) { - ctype->base_type = ctype_integer(ctype->modifiers); - ctype->modifiers &= ~MOD_SPECIFIER; - } else if (ctype->base_type == &fp_type) { - ctype->base_type = ctype_fp(ctype->modifiers); - ctype->modifiers &= ~MOD_SPECIFIER; - } - if (ctype->modifiers & MOD_BITWISE) { - struct symbol *type; - ctype->modifiers &= ~(MOD_BITWISE | MOD_SPECIFIER); - if (!is_int_type(ctype->base_type)) { - sparse_error(token->pos, "invalid modifier"); - return token; - } - type = alloc_symbol(token->pos, SYM_BASETYPE); - *type = *ctype->base_type; - type->ctype.base_type = ctype->base_type; - type->type = SYM_RESTRICT; - type->ctype.modifiers &= ~MOD_SPECIFIER; - ctype->base_type = type; - create_fouled(type); - } return token; } @@ -947,7 +967,7 @@ static struct token *handle_bitfield(struct token *token, struct symbol *decl) struct symbol *bitfield; long long width; - if (!is_int_type(ctype->base_type)) { + if (ctype->base_type != &int_type && !is_int_type(ctype->base_type)) { sparse_error(token->pos, "invalid bitfield specifier for type %s.", show_typename(ctype->base_type)); // Parse this to recover gracefully. @@ -968,15 +988,16 @@ static struct token *handle_bitfield(struct token *token, struct symbol *decl) width = -1; } else if (decl->ident) { struct symbol *base_type = bitfield->ctype.base_type; - int is_signed = !(base_type->ctype.modifiers & MOD_UNSIGNED); + struct symbol *bitfield_type = base_type == &int_type ? bitfield : base_type; + int is_signed = !(bitfield_type->ctype.modifiers & MOD_UNSIGNED); if (Wone_bit_signed_bitfield && width == 1 && is_signed) { // Valid values are either {-1;0} or {0}, depending on integer // representation. The latter makes for very efficient code... sparse_error(token->pos, "dubious one-bit signed bitfield"); } if (Wdefault_bitfield_sign && - base_type->type != SYM_ENUM && - !(base_type->ctype.modifiers & MOD_EXPLICITLY_SIGNED) && + bitfield_type->type != SYM_ENUM && + !(bitfield_type->ctype.modifiers & MOD_EXPLICITLY_SIGNED) && is_signed) { // The sign of bitfields is unspecified by default. sparse_error(token->pos, "dubious bitfield without explicit `signed' or `unsigned'"); @@ -1001,6 +1022,7 @@ static struct token *declaration_list(struct token *token, struct symbol_list ** token = handle_bitfield(token, decl); token = handle_attributes(token, &decl->ctype); } + apply_modifiers(token->pos, &decl->ctype); add_symbol(list, decl); if (!match_op(token, ',')) break; @@ -1034,6 +1056,7 @@ static struct token *parameter_declaration(struct token *token, struct symbol ** *tree = sym; token = declarator(token, sym, &ident); sym->ident = ident; + apply_modifiers(token->pos, &sym->ctype); return token; } @@ -1042,7 +1065,9 @@ struct token *typename(struct token *token, struct symbol **p) struct symbol *sym = alloc_symbol(token->pos, SYM_NODE); *p = sym; token = declaration_specifiers(token, &sym->ctype, 0); - return declarator(token, sym, NULL); + token = declarator(token, sym, NULL); + apply_modifiers(token->pos, &sym->ctype); + return token; } static struct token *expression_statement(struct token *token, struct expression **tree) @@ -1770,6 +1795,7 @@ struct token *external_declaration(struct token *token, struct symbol_list **lis decl = alloc_symbol(token->pos, SYM_NODE); decl->ctype = ctype; token = declarator(token, decl, &ident); + apply_modifiers(token->pos, &decl->ctype); /* Just a type declaration? */ if (!ident) @@ -1830,6 +1856,7 @@ struct token *external_declaration(struct token *token, struct symbol_list **lis decl->ctype = ctype; token = declaration_specifiers(token, &decl->ctype, 1); token = declarator(token, decl, &ident); + apply_modifiers(token->pos, &decl->ctype); if (!ident) { sparse_error(token->pos, "expected identifier name in type definition"); return token; diff --git a/ptrlist.h b/ptrlist.h index 8a58bad..dae0906 100644 --- a/ptrlist.h +++ b/ptrlist.h @@ -56,7 +56,7 @@ extern int linearize_ptr_list(struct ptr_list *, void **, int); MKTYPE(*(list), (CHECK_TYPE(*(list),(entry)),__add_ptr_list((struct ptr_list **)(list), (entry), (tag)))) #define add_ptr_list_notag(list,entry) \ MKTYPE(*(list), (CHECK_TYPE(*(list),(entry)),__add_ptr_list((struct ptr_list **)(list), \ - (void*)((unsigned long)(entry) & ~3UL), \ + (void *)((unsigned long)(entry) & ~3UL), \ (unsigned long)(entry) & 3))) #define add_ptr_list(list,entry) \ add_ptr_list_tag(list,entry,0) diff --git a/show-parse.c b/show-parse.c index 2701d17..ed6ef80 100644 --- a/show-parse.c +++ b/show-parse.c @@ -56,11 +56,12 @@ static void do_debug_symbol(struct symbol *sym, int indent) if (!sym) return; - fprintf(stderr, "%.*s%s%3d:%lu %lx %s (as: %d) %p (%s:%d:%d)\n", + fprintf(stderr, "%.*s%s%3d:%lu %s %s (as: %d) %p (%s:%d:%d) %s\n", indent, indent_string, typestr[sym->type], sym->bit_size, sym->ctype.alignment, - sym->ctype.modifiers, show_ident(sym->ident), sym->ctype.as, - sym, stream_name(sym->pos.stream), sym->pos.line, sym->pos.pos); + modifier_string(sym->ctype.modifiers), show_ident(sym->ident), sym->ctype.as, + sym, stream_name(sym->pos.stream), sym->pos.line, sym->pos.pos, + builtin_typename(sym) ?: ""); i = 0; FOR_EACH_PTR(sym->ctype.contexts, context) { /* FIXME: should print context expression */ @@ -98,7 +99,7 @@ const char *modifier_string(unsigned long mod) const char *res,**ptr, *names[] = { "auto", "register", "static", "extern", "const", "volatile", "[signed]", "[unsigned]", - "[char]", "[short]", "[long]", "[long]", + "[char]", "[short]", "[long]", "[long long]", "[typdef]", "[structof]", "[unionof]", "[enum]", "[typeof]", "[attribute]", "inline", "[addressable]", "[nocast]", "[noderef]", "[accessed]", "[toplevel]", @@ -171,53 +172,74 @@ static void append(struct type_name *name, const char *fmt, ...) name->end += n; } +static struct ctype_name { + struct symbol *sym; + const char *name; +} typenames[] = { + { & char_ctype, "char" }, + { &schar_ctype, "signed char" }, + { &uchar_ctype, "unsigned char" }, + { & short_ctype, "short" }, + { &sshort_ctype, "signed short" }, + { &ushort_ctype, "unsigned short" }, + { & int_ctype, "int" }, + { &sint_ctype, "signed int" }, + { &uint_ctype, "unsigned int" }, + { &slong_ctype, "signed long" }, + { & long_ctype, "long" }, + { &ulong_ctype, "unsigned long" }, + { & llong_ctype, "long long" }, + { &sllong_ctype, "signed long long" }, + { &ullong_ctype, "unsigned long long" }, + + { &void_ctype, "void" }, + { &bool_ctype, "bool" }, + { &string_ctype, "string" }, + + { &float_ctype, "float" }, + { &double_ctype, "double" }, + { &ldouble_ctype,"long double" }, + { &incomplete_ctype, "incomplete type" }, + { &int_type, "abstract int" }, + { &fp_type, "abstract fp" }, + { &label_ctype, "label type" }, + { &bad_ctype, "bad type" }, +}; + +const char *builtin_typename(struct symbol *sym) +{ + int i; + + for (i = 0; i < sizeof(typenames)/sizeof(typenames[0]); i++) + if (typenames[i].sym == sym) + return typenames[i].name; + return NULL; +} + +const char *builtin_ctypename(struct ctype *ctype) +{ + int i; + + for (i = 0; i < sizeof(typenames)/sizeof(typenames[0]); i++) + if (&typenames[i].sym->ctype == ctype) + return typenames[i].name; + return NULL; +} + static void do_show_type(struct symbol *sym, struct type_name *name) { - int i, modlen; + int modlen; const char *mod; - static struct ctype_name { - struct symbol *sym; - const char *name; - } typenames[] = { - { & char_ctype, "char" }, - { &schar_ctype, "signed char" }, - { &uchar_ctype, "unsigned char" }, - { & short_ctype, "short" }, - { &sshort_ctype, "signed short" }, - { &ushort_ctype, "unsigned short" }, - { & int_ctype, "int" }, - { &sint_ctype, "signed int" }, - { &uint_ctype, "unsigned int" }, - { &slong_ctype, "signed long" }, - { & long_ctype, "long" }, - { &ulong_ctype, "unsigned long" }, - { & llong_ctype, "long long" }, - { &sllong_ctype, "signed long long" }, - { &ullong_ctype, "unsigned long long" }, - - { &void_ctype, "void" }, - { &bool_ctype, "bool" }, - { &string_ctype, "string" }, - - { &float_ctype, "float" }, - { &double_ctype, "double" }, - { &ldouble_ctype,"long double" }, - { &incomplete_ctype, "incomplete type" }, - { &label_ctype, "label type" }, - { &bad_ctype, "bad type" }, - }; - + const char *typename; if (!sym) return; - for (i = 0; i < sizeof(typenames)/sizeof(typenames[0]); i++) { - if (typenames[i].sym == sym) { - int len = strlen(typenames[i].name); - *--name->start = ' '; - name->start -= len; - memcpy(name->start, typenames[i].name, len); - return; - } + if ((typename = builtin_typename(sym))) { + int len = strlen(typename); + *--name->start = ' '; + name->start -= len; + memcpy(name->start, typename, len); + return; } /* Prepend */ diff --git a/simplify.c b/simplify.c index a8b736b..26a72f4 100644 --- a/simplify.c +++ b/simplify.c @@ -146,10 +146,27 @@ static int clean_up_phi(struct instruction *insn) return if_convert_phi(insn); } +int delete_pseudo_user_list_entry(struct pseudo_user_list **list, pseudo_t *entry, int count) +{ + struct pseudo_user *pu; + + FOR_EACH_PTR(*list, pu) { + if (pu->userp == entry) { + DELETE_CURRENT_PTR(pu); + if (!--count) + goto out; + } + } END_FOR_EACH_PTR(pu); + assert(count <= 0); +out: + pack_ptr_list((struct ptr_list **)list); + return count; +} + static inline void remove_usage(pseudo_t p, pseudo_t *usep) { if (has_use_list(p)) { - delete_ptr_list_entry((struct ptr_list **)&p->users, usep, 1); + delete_pseudo_user_list_entry(&p->users, usep, 1); if (!p->users) kill_instruction(p->def); } @@ -200,6 +217,12 @@ void kill_instruction(struct instruction *insn) kill_use(&insn->src2); kill_use(&insn->src3); return; + case OP_BR: + insn->bb = NULL; + repeat_phase |= REPEAT_CSE; + if (insn->cond) + kill_use(&insn->cond); + return; } } @@ -208,11 +231,11 @@ void kill_instruction(struct instruction *insn) */ static int dead_insn(struct instruction *insn, pseudo_t *src1, pseudo_t *src2, pseudo_t *src3) { - pseudo_t *usep; - FOR_EACH_PTR(insn->target->users, usep) { - if (*usep != VOID) + struct pseudo_user *pu; + FOR_EACH_PTR(insn->target->users, pu) { + if (*pu->userp != VOID) return 0; - } END_FOR_EACH_PTR(usep); + } END_FOR_EACH_PTR(pu); insn->bb = NULL; kill_use(src1); @@ -419,12 +442,12 @@ static int simplify_binop(struct instruction *insn) return 0; } -static void switch_pseudo(pseudo_t *pp1, pseudo_t *pp2) +static void switch_pseudo(struct instruction *insn1, pseudo_t *pp1, struct instruction *insn2, pseudo_t *pp2) { pseudo_t p1 = *pp1, p2 = *pp2; - use_pseudo(p2, pp1); - use_pseudo(p1, pp2); + use_pseudo(insn1, p2, pp1); + use_pseudo(insn2, p1, pp2); remove_usage(p1, pp1); remove_usage(p2, pp2); } @@ -444,7 +467,7 @@ static int canonical_order(pseudo_t p1, pseudo_t p2) static int simplify_commutative_binop(struct instruction *insn) { if (!canonical_order(insn->src1, insn->src2)) { - switch_pseudo(&insn->src1, &insn->src2); + switch_pseudo(insn, &insn->src1, insn, &insn->src2); return REPEAT_CSE; } return 0; @@ -473,7 +496,7 @@ static int simplify_associative_binop(struct instruction *insn) return 0; if (ptr_list_size((struct ptr_list *)def->target->users) != 1) return 0; - switch_pseudo(&def->src1, &insn->src2); + switch_pseudo(def, &def->src1, insn, &insn->src2); return REPEAT_CSE; } @@ -517,7 +540,7 @@ static int simplify_one_memop(struct instruction *insn, pseudo_t orig) struct instruction *def = addr->def; if (def->opcode == OP_SYMADDR && def->src) { kill_use(&insn->src); - use_pseudo(def->src, &insn->src); + use_pseudo(insn, def->src, &insn->src); return REPEAT_CSE | REPEAT_SYMBOL_CLEANUP; } if (def->opcode == OP_ADD) { @@ -543,7 +566,7 @@ offset: warning(insn->pos, "crazy programmer"); } insn->offset += off->value; - use_pseudo(new, &insn->src); + use_pseudo(insn, new, &insn->src); remove_usage(addr, &insn->src); return REPEAT_CSE | REPEAT_SYMBOL_CLEANUP; } @@ -699,7 +722,7 @@ static int simplify_range(struct instruction *insn) */ static int simplify_cond_branch(struct instruction *br, pseudo_t cond, struct instruction *def, pseudo_t *pp) { - use_pseudo(*pp, &br->cond); + use_pseudo(br, *pp, &br->cond); remove_usage(cond, &br->cond); if (def->opcode == OP_SET_EQ) { struct basic_block *true = br->bb_true; @@ -763,7 +786,7 @@ static int simplify_branch(struct instruction *insn) insn->bb_false = true; insn->bb_true = false; } - use_pseudo(def->src1, &insn->cond); + use_pseudo(insn, def->src1, &insn->cond); remove_usage(cond, &insn->cond); return REPEAT_CSE; } @@ -771,7 +794,7 @@ static int simplify_branch(struct instruction *insn) if (def->opcode == OP_CAST || def->opcode == OP_SCAST) { int orig_size = def->orig_type ? def->orig_type->bit_size : 0; if (def->size > orig_size) { - use_pseudo(def->src, &insn->cond); + use_pseudo(insn, def->src, &insn->cond); remove_usage(cond, &insn->cond); return REPEAT_CSE; } diff --git a/symbol.h b/symbol.h index 91cc06a..eb69d41 100644 --- a/symbol.h +++ b/symbol.h @@ -118,7 +118,8 @@ struct symbol { initialized:1, examined:1, expanding:1, - evaluated:1; + evaluated:1, + string:1; struct expression *array_size; struct ctype ctype; struct symbol_list *arguments; @@ -133,6 +134,10 @@ struct symbol { union /* backend */ { struct basic_block *bb_target; /* label */ void *aux; /* Auxiliary info, eg. backend information */ + struct { /* sparse ctags */ + char kind; + unsigned char visited:1; + }; }; pseudo_t pseudo; }; @@ -239,6 +244,8 @@ extern void bind_symbol(struct symbol *, struct ident *, enum namespace); extern struct symbol *examine_symbol_type(struct symbol *); extern void examine_simple_symbol_type(struct symbol *); extern const char *show_typename(struct symbol *sym); +extern const char *builtin_typename(struct symbol *sym); +extern const char *builtin_ctypename(struct ctype *ctype); extern void debug_symbol(struct symbol *); extern void merge_type(struct symbol *sym, struct symbol *base_type); diff --git a/test-sort.c b/test-sort.c index d0ffb67..5f17676 100644 --- a/test-sort.c +++ b/test-sort.c @@ -37,7 +37,7 @@ main (int argc, char **argv) do { l2->nr = MIN (l2->nr, rand () % 3); for (i = 0; i < l2->nr; i++) - *((int*)(l2->list[i])) = rand(); + *((int *)(l2->list[i])) = rand(); l2 = l2->next; } while (l2 != l); sort_list (&l, int_cmp); diff --git a/token.h b/token.h index 1f6ffb3..d60bb46 100644 --- a/token.h +++ b/token.h @@ -170,7 +170,7 @@ struct token { static inline struct token *containing_token(struct token **p) { - void *addr = (char*)p - ((char*)&((struct token *)0)->next - (char*)0); + void *addr = (char *)p - ((char *)&((struct token *)0)->next - (char *)0); return addr; } diff --git a/validation/badtype3.c b/validation/badtype3.c index 0aefe6a..198ef87 100644 --- a/validation/badtype3.c +++ b/validation/badtype3.c @@ -1,5 +1,5 @@ int -foo (int (*func) (undef, void*), void* data) +foo (int (*func) (undef, void *), void *data) { int err = 0; while (cur) { diff --git a/validation/init-char-array.c b/validation/init-char-array.c index 390f29d..cd19fdf 100644 --- a/validation/init-char-array.c +++ b/validation/init-char-array.c @@ -7,7 +7,7 @@ char u[] = {"aaaaaaaaa"}; char v[] = "aaaaaaaaa"; void f(void) { - char x[1/(sizeof(s) == sizeof(char*))]; + char x[1/(sizeof(s) == sizeof(char *))]; char y[1/(sizeof(u) == 10)]; char z[1/(sizeof(v) == 10)]; char w[1/(sizeof(t) == 10)];