From: Dale Weiler Date: Fri, 26 Jul 2013 13:58:45 +0000 (+0000) Subject: Merge branch 'master' into threading X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=0c7395da1ae45cac8a8a4d6885570b4a44205386;p=xonotic%2Fgmqcc.git Merge branch 'master' into threading Conflicts: Makefile gmqcc.h ir.c ir.h opts.def parser.c --- 0c7395da1ae45cac8a8a4d6885570b4a44205386 diff --cc Makefile index 3a215f2,2e5c1ee..cd26b16 --- a/Makefile +++ b/Makefile @@@ -1,16 -1,20 +1,10 @@@ --DESTDIR := --OPTIONAL:= --PREFIX := /usr/local --BINDIR := $(PREFIX)/bin --DATADIR := $(PREFIX)/share --MANDIR := $(DATADIR)/man ++include include.mk UNAME ?= $(shell uname) CYGWIN = $(findstring CYGWIN, $(UNAME)) MINGW = $(findstring MINGW32, $(UNAME)) - CC ?= clang - CFLAGS += -Wall -Wextra -Werror -I. -fno-strict-aliasing -fsigned-char -pthread $(OPTIONAL) -CC ?= clang -# linker flags and optional additional libraries if required -LDFLAGS += -LIBS += -lm - + CFLAGS += -Wall -Wextra -Werror -fno-strict-aliasing $(OPTIONAL) ifneq ($(shell git describe --always 2>/dev/null),) CFLAGS += -DGMQCC_GITINFO="\"$(shell git describe --always)\"" endif @@@ -25,28 -29,33 +19,29 @@@ ifeq ($(CC), clang -Wno-conversion \ -Wno-missing-prototypes \ -Wno-float-equal \ + -Wno-unknown-warning-option \ + -Wno-cast-align \ - -Wno-missing-variable-declarations \ - -Wno-unknown-warning-option + -Wstrict-prototypes else #Tiny C Compiler doesn't know what -pedantic-errors is # and instead of ignoring .. just errors. ifneq ($(CC), tcc) - CFLAGS +=-pedantic-errors -ffunction-sections -fdata-sections -Wl,-gc-sections - CFLAGS += -Wstrict-prototypes -pedantic-errors ++ CFLAGS += -pedantic-errors else CFLAGS += -Wno-pointer-sign -fno-common endif ++ ++ #-Wstrict-prototypes is not valid in g++ ++ ifneq ($(CC), g++) ++ CFLAGS += -Wstrict-prototypes ++ endif endif --ifeq ($(track), no) -- CFLAGS += -DNOTRACK --endif -- - OBJ_D = util.o code.o ast.o ir.o thread.o conout.o ftepp.o opts.o fs.o utf8.o correct.o - OBJ_P = util.o fs.o conout.o opts.o pak.o - OBJ_T = test.o util.o conout.o fs.o - OBJ_C = main.o lexer.o parser.o fs.o - OBJ_X = exec-standalone.o util.o conout.o fs.o -OBJ_D = util.o code.o ast.o ir.o conout.o ftepp.o opts.o fs.o utf8.o correct.o stat.o -OBJ_P = util.o fs.o conout.o opts.o pak.o stat.o -OBJ_T = test.o util.o conout.o fs.o stat.o -OBJ_C = main.o lexer.o parser.o fs.o stat.o -OBJ_X = exec-standalone.o util.o conout.o fs.o stat.o - + #we have duplicate object files when dealing with creating a simple list + #for dependinces. To combat this we use some clever recrusive-make to + #filter the list and remove duplicates which we use for make depend + RMDUP = $(if $1,$(firstword $1) $(call RMDUP,$(filter-out $(firstword $1),$1))) -DEPS := $(call RMDUP, $(OBJ_D) $(OBJ_P) $(OBJ_T) $(OBJ_C) $(OBJ_X)) ++DEPS := $(call RMDUP, $(OBJ_P) $(OBJ_T) $(OBJ_C) $(OBJ_X)) ifneq ("$(CYGWIN)", "") #nullify the common variables that @@@ -58,7 -67,7 +53,7 @@@ QCVM = qcvm.exe GMQCC = gmqcc.exe TESTSUITE = testsuite.exe -- PAK = pak.exe ++ PAK = gmqpak.exe else ifneq ("$(MINGW)", "") #nullify the common variables that @@@ -85,105 -88,102 +74,24 @@@ els endif endif --#gource flags --GOURCEFLAGS= \ -- --date-format "%d %B, %Y" \ -- --seconds-per-day 0.01 \ -- --auto-skip-seconds 1 \ -- --title "GMQCC" \ -- --key \ -- --camera-mode overview \ -- --highlight-all-users \ -- --file-idle-time 0 \ -- --hide progress,mouse \ -- --stop-at-end \ -- --max-files 99999999999 \ -- --max-file-lag 0.000001 \ -- --bloom-multiplier 1.3 \ - --logo doc/html/gmqcc.png \ -- -1280x720 -- --#ffmpeg flags for gource --FFMPEGFLAGS= \ -- -y \ -- -r 60 \ -- -f image2pipe \ -- -vcodec ppm \ -- -i - \ -- -vcodec libx264 \ -- -preset ultrafast \ -- -crf 1 \ -- -threads 0 \ -- -bf 0 -- --#splint flags --SPLINTFLAGS = \ -- -redef \ -- -noeffect \ -- -nullderef \ -- -usedef \ -- -type \ -- -mustfreeonly \ -- -nullstate \ -- -varuse \ -- -mustfreefresh \ -- -compdestroy \ -- -compmempass \ -- -nullpass \ -- -onlytrans \ -- -predboolint \ -- -boolops \ - -exportlocal \ -- -incondefs \ -- -macroredef \ -- -retvalint \ -- -nullret \ -- -predboolothers \ -- -globstate \ -- -dependenttrans \ -- -branchstate \ -- -compdef \ -- -temptrans \ -- -usereleased \ -- -warnposix \ - -shiftimplementation \ -- +charindex \ -- -kepttrans \ -- -unqualifiedtrans \ -- +matchanyintegral \ -- +voidabstract \ -- -nullassign \ -- -unrecog \ -- -casebreak \ -- -retvalbool \ -- -retvalother \ -- -mayaliasunique \ -- -realcompare \ -- -observertrans \ - -shiftnegative \ - -freshtrans \ -- -abstract \ -- -statictrans \ -- -castfcnptr -- #standard rules --default: all %.o: %.c - $(CC) -c $< -o $@ $(CFLAGS) + $(CC) -c $< -o $@ $(CPPFLAGS) $(CFLAGS) exec-standalone.o: exec.c - $(CC) -c $< -o $@ $(CFLAGS) -DQCVM_EXECUTOR=1 + $(CC) -c $< -o $@ $(CPPFLAGS) $(CFLAGS) -DQCVM_EXECUTOR=1 $(QCVM): $(OBJ_X) - $(CC) -o $@ $^ $(CFLAGS) -lm + $(CC) -o $@ $^ $(LDFLAGS) $(LIBS) $(GMQCC): $(OBJ_C) $(OBJ_D) - $(CC) -o $@ $^ $(CFLAGS) -lm -pthread + $(CC) -o $@ $^ $(LDFLAGS) $(LIBS) $(TESTSUITE): $(OBJ_T) - $(CC) -o $@ $^ $(CFLAGS) -lm + $(CC) -o $@ $^ $(LDFLAGS) $(LIBS) $(PAK): $(OBJ_P) - $(CC) -o $@ $^ $(CFLAGS) + $(CC) -o $@ $^ $(LDFLAGS) all: $(GMQCC) $(QCVM) $(TESTSUITE) $(PAK) @@@ -193,7 -193,7 +101,7 @@@ test: al @ ./$(TESTSUITE) clean: - rm -f *.o $(GMQCC) $(QCVM) $(TESTSUITE) $(PAK) *.dat gource.mp4 - rm -f *.o $(GMQCC) $(QCVM) $(TESTSUITE) $(PAK) *.dat gource.mp4 *.exe ++ rm -rf *.o $(GMQCC) $(QCVM) $(TESTSUITE) $(PAK) *.dat gource.mp4 *.exe gm-qcc.tgz ./cov-int splint: @ splint $(SPLINTFLAGS) *.c *.h @@@ -205,65 -205,49 +113,48 @@@ gource-record @ gource $(GOURCEFLAGS) -o - | ffmpeg $(FFMPEGFLAGS) gource.mp4 depend: -- @makedepend -Y -w 65536 2> /dev/null \ - $(subst .o,.c,$(OBJ_D)) - @makedepend -a -Y -w 65536 2> /dev/null \ - $(subst .o,.c,$(OBJ_T)) - @makedepend -a -Y -w 65536 2> /dev/null \ - $(subst .o,.c,$(OBJ_C)) - @makedepend -a -Y -w 65536 2> /dev/null \ - $(subst .o,.c,$(OBJ_X)) - @makedepend -a -Y -w 65536 2> /dev/null \ - $(subst .o,.c,$(OBJ_P)) - $(subst .o,.c,$(DEPS)) ++ @ makedepend -Y -w 65536 2> /dev/null $(subst .o,.c,$(DEPS)) ++ ++ ++coverity: ++ @cov-build --dir cov-int $(MAKE) ++ @tar czf gm-qcc.tgz cov-int ++ @rm -rf cov-int ++ @echo gm-qcc.tgz generated, submit for analysis #install rules - install: install-gmqcc install-qcvm install-doc + install: install-gmqcc install-qcvm install-gmqpak install-doc install-gmqcc: $(GMQCC) install -d -m755 $(DESTDIR)$(BINDIR) - install -m755 $(GMQCC) $(DESTDIR)$(BINDIR)/gmqcc + install -m755 $(GMQCC) $(DESTDIR)$(BINDIR)/$(GMQCC) install-qcvm: $(QCVM) install -d -m755 $(DESTDIR)$(BINDIR) - install -m755 $(QCVM) $(DESTDIR)$(BINDIR)/qcvm + install -m755 $(QCVM) $(DESTDIR)$(BINDIR)/$(QCVM) + install-gmqpak: $(PAK) + install -d -m755 $(DESTDIR)$(BINDIR) + install -m755 $(PAK) $(DESTDIR)$(BINDIR)/$(PAK) install-doc: install -d -m755 $(DESTDIR)$(MANDIR)/man1 install -m644 doc/gmqcc.1 $(DESTDIR)$(MANDIR)/man1/ install -m644 doc/qcvm.1 $(DESTDIR)$(MANDIR)/man1/ - - uninstall: - rm $(DESTDIR)$(BINDIR)/gmqcc - rm $(DESTDIR)$(BINDIR)/qcvm - rm $(DESTDIR)$(MANDIR)/man1/doc/gmqcc.1 - rm $(DESTDIR)$(MANDIR)/man1/doc/qcvm.1 + install -m644 doc/gmqpak.1 $(DESTDIR)$(MANDIR)/man1/ -uninstall: - rm -f $(DESTDIR)$(BINDIR)/gmqcc - rm -f $(DESTDIR)$(BINDIR)/qcvm - rm -f $(DESTDIR)$(BINDIR)/gmqpak - rm -f $(DESTDIR)$(MANDIR)/man1/doc/gmqcc.1 - rm -f $(DESTDIR)$(MANDIR)/man1/doc/qcvm.1 - rm -f $(DESTDIR)$(MANDIR)/man1/doc/gmqpak.1 - # DO NOT DELETE util.o: gmqcc.h opts.def --code.o: gmqcc.h opts.def --ast.o: gmqcc.h opts.def ast.h ir.h --ir.o: gmqcc.h opts.def ir.h ++fs.o: gmqcc.h opts.def conout.o: gmqcc.h opts.def --ftepp.o: gmqcc.h opts.def lexer.h opts.o: gmqcc.h opts.def --fs.o: gmqcc.h opts.def --utf8.o: gmqcc.h opts.def --correct.o: gmqcc.h opts.def - -stat.o: gmqcc.h opts.def + pak.o: gmqcc.h opts.def ++stat.o: gmqcc.h opts.def test.o: gmqcc.h opts.def - util.o: gmqcc.h opts.def - conout.o: gmqcc.h opts.def - fs.o: gmqcc.h opts.def - main.o: gmqcc.h opts.def lexer.h lexer.o: gmqcc.h opts.def lexer.h parser.o: gmqcc.h opts.def lexer.h ast.h ir.h intrin.h - fs.o: gmqcc.h opts.def - - util.o: gmqcc.h opts.def - conout.o: gmqcc.h opts.def - fs.o: gmqcc.h opts.def - - util.o: gmqcc.h opts.def - fs.o: gmqcc.h opts.def - conout.o: gmqcc.h opts.def - opts.o: gmqcc.h opts.def - pak.o: gmqcc.h opts.def ++code.o: gmqcc.h opts.def ++ast.o: gmqcc.h opts.def ast.h ir.h ++ir.o: gmqcc.h opts.def ir.h ++ftepp.o: gmqcc.h opts.def lexer.h ++utf8.o: gmqcc.h opts.def ++correct.o: gmqcc.h opts.def ++thread.o: gmqcc.h opts.def diff --cc gmqcc.h index a9599ac,d6055db..9a3e432 --- a/gmqcc.h +++ b/gmqcc.h @@@ -430,49 -422,6 +422,11 @@@ void util_htrm (hash_table_t void *util_htget (hash_table_t *ht, const char *key); void *util_htgeth(hash_table_t *ht, const char *key, size_t hash); - /* - * hashset implementation: - * This was designed for pointers: you manage the life of the object yourself - * if you do use this for non-pointers please be warned that the object may not - * be valid if the duration of it exceeds (i.e on stack). So you need to allocate - * yourself, or put those in global scope to ensure duration is for the whole - * runtime. - * - * util_hsnew() -- to make a new hashset - * util_hsadd(set, key) -- to add something in the set - * util_hshas(set, key) -- to check if something is in the set - * util_hsrem(set, key) -- to remove something in the set - * util_hsdel(set) -- to delete the set - * - * example of use: - * - * hs foo = util_hsnew(); - * char *bar = "hello blub\n"; - * char *baz = "hello dale\n"; - * - * util_hsadd(foo, bar); - * util_hsadd(foo, baz); - * util_hsrem(foo, baz); - * - * printf("bar %d | baz %d\n", - * util_hshas(foo, bar), - * util_hshad(foo, baz) - * ); - * - * util_hsdel(foo); - */ - - hash_set_t *util_hsnew(void); - int util_hsadd(hash_set_t *, void *); - int util_hshas(hash_set_t *, void *); - int util_hsrem(hash_set_t *, void *); - void util_hsdel(hash_set_t *); - +/*===================================================================*/ +/*=========================== thread.c ==============================*/ +/*===================================================================*/ +GMQCC_INLINE uint32_t util_atomic_xadd32(volatile uint32_t *x, uint32_t v); + /*===================================================================*/ /*============================ file.c ===============================*/ /*===================================================================*/ diff --cc ir.c index a65b015,fcf4caa..5e88587 --- a/ir.c +++ b/ir.c @@@ -211,8 -213,31 +213,31 @@@ const uint16_t type_not_instr[TYPE_COUN }; /* protos */ - static void ir_gen_extparam (ir_builder *ir); - + static ir_value* ir_value_var(const char *name, int st, int vtype); + static bool ir_value_set_name(ir_value*, const char *name); + static void ir_value_dump(ir_value*, int (*oprintf)(const char*,...)); + + static ir_value* ir_gen_extparam_proto(ir_builder *ir); -static void ir_gen_extparam (code_t *, ir_builder *ir); ++static void ir_gen_extparam (ir_builder *ir); + + static bool ir_builder_set_name(ir_builder *self, const char *name); + + static ir_function* ir_function_new(struct ir_builder_s *owner, int returntype); + static bool ir_function_set_name(ir_function*, const char *name); + static void ir_function_delete(ir_function*); + static void ir_function_dump(ir_function*, char *ind, int (*oprintf)(const char*,...)); + + static ir_value* ir_block_create_general_instr(ir_block *self, lex_ctx, const char *label, + int op, ir_value *a, ir_value *b, int outype); + static void ir_block_delete(ir_block*); + static ir_block* ir_block_new(struct ir_function_s *owner, const char *label); + static bool GMQCC_WARN ir_block_create_store(ir_block*, lex_ctx, ir_value *target, ir_value *what); + static bool ir_block_set_label(ir_block*, const char *label); + static void ir_block_dump(ir_block*, char *ind, int (*oprintf)(const char*,...)); + + static bool ir_instr_op(ir_instr*, int op, ir_value *value, bool writing); + static void ir_instr_delete(ir_instr*); + static void ir_instr_dump(ir_instr* in, char *ind, int (*oprintf)(const char*,...)); /* error functions */ static void irerror(lex_ctx ctx, const char *msg, ...) @@@ -317,11 -341,10 +341,11 @@@ ir_builder* ir_builder_new(const char * return NULL; } - self->nil = ir_value_var("nil", store_global, TYPE_NIL); + self->nil = ir_value_var("nil", store_value, TYPE_NIL); self->nil->cvq = CV_CONST; - self->nil->untracked = true; self->reserved_va_count = NULL; ++ self->code = code_init(); return self; } @@@ -352,6 -376,6 +377,8 @@@ void ir_builder_delete(ir_builder* self vec_free(self->fields); vec_free(self->filenames); vec_free(self->filestrings); ++ ++ code_cleanup(self->code); mem_d(self); } @@@ -1796,14 -1797,14 +1800,33 @@@ ir_value* ir_block_create_binop(ir_bloc ot = TYPE_POINTER; break; #endif ++ /* ++ * after the following default case, the value of opcode can never ++ * be 1, 2, 3, 4, 5, 6, 7, 8, 9, 62, 63, 64, 65 ++ */ default: /* ranges: */ /* boolean operations result in floats */ ++ ++ /* ++ * opcode >= 10 takes true branch opcode is at least 10 ++ * opcode <= 23 takes false branch opcode is at least 24 ++ */ if (opcode >= INSTR_EQ_F && opcode <= INSTR_GT) ot = TYPE_FLOAT; ++ ++ /* ++ * At condition "opcode <= 23", the value of "opcode" must be ++ * at least 24. ++ * At condition "opcode <= 23", the value of "opcode" cannot be ++ * equal to any of {1, 2, 3, 4, 5, 6, 7, 8, 9, 62, 63, 64, 65}. ++ * The condition "opcode <= 23" cannot be true. ++ * ++ * Thus ot=2 (TYPE_FLOAT) can never be true ++ */ ++#if 0 else if (opcode >= INSTR_LE && opcode <= INSTR_GT) ot = TYPE_FLOAT; --#if 0 else if (opcode >= INSTR_LE_I && opcode <= INSTR_EQ_FI) ot = TYPE_FLOAT; #endif @@@ -2569,7 -2562,7 +2584,8 @@@ bool ir_function_calculate_liferanges(i /* parameters live at 0 */ for (i = 0; i < vec_size(self->params); ++i) -- ir_value_life_merge(self->locals[i], 0); ++ if (!ir_value_life_merge(self->locals[i], 0)) ++ compile_error(self->context, "internal error: failed value-life merging"); do { self->run_id++; @@@ -2650,9 -2643,9 +2666,9 @@@ * * Breaking conventions is annoying... */ -static bool ir_builder_gen_global(code_t *, ir_builder *self, ir_value *global, bool islocal); +static bool ir_builder_gen_global(ir_builder *self, ir_value *global, bool islocal); - static bool gen_global_field(ir_value *global) + static bool gen_global_field(code_t *code, ir_value *global) { if (global->hasvalue) { @@@ -3037,7 -3030,7 +3053,7 @@@ static qcint ir_builder_filestring(ir_b return ir->filestrings[i]; } - str = code_genstring(filename); - str = code_genstring(code, filename); ++ str = code_genstring(ir->code, filename); vec_push(ir->filenames, filename); vec_push(ir->filestrings, str); return str; @@@ -3078,11 -3071,11 +3094,11 @@@ static bool gen_global_function(ir_buil if (irfun->builtin) fun.entry = irfun->builtin+1; else { - irfun->code_function_def = vec_size(code_functions); - fun.entry = vec_size(code_statements); - irfun->code_function_def = vec_size(code->functions); - fun.entry = vec_size(code->statements); ++ irfun->code_function_def = vec_size(ir->code->functions); ++ fun.entry = vec_size(ir->code->statements); } - vec_push(code_functions, fun); - vec_push(code->functions, fun); ++ vec_push(ir->code->functions, fun); return true; } @@@ -3109,15 -3101,17 +3124,17 @@@ static void ir_gen_extparam(ir_builder else global = ir->extparam_protos[vec_size(ir->extparams)]; - def.name = code_genstring(global->name); - def.type = TYPE_VECTOR; - def.offset = vec_size(code_globals); - def.name = code_genstring(code, global->name); ++ def.name = code_genstring(ir->code, global->name); + def.type = TYPE_VECTOR; - def.offset = vec_size(code->globals); ++ def.offset = vec_size(ir->code->globals); + - vec_push(code->defs, def); ++ vec_push(ir->code->defs, def); - vec_push(code_defs, def); ir_value_code_setaddr(global, def.offset); - vec_push(code_globals, 0); - vec_push(code_globals, 0); - vec_push(code_globals, 0); + - vec_push(code->globals, 0); - vec_push(code->globals, 0); - vec_push(code->globals, 0); ++ vec_push(ir->code->globals, 0); ++ vec_push(ir->code->globals, 0); ++ vec_push(ir->code->globals, 0); vec_push(ir->extparams, global); } @@@ -3201,13 -3195,13 +3218,13 @@@ static bool gen_function_locals(ir_buil uint32_t firstlocal, firstglobal; irfun = global->constval.vfunc; - def = code_functions + irfun->code_function_def; - def = code->functions + irfun->code_function_def; ++ def = ir->code->functions + irfun->code_function_def; if (OPTS_OPTION_BOOL(OPTION_G) || !OPTS_OPTIMIZATION(OPTIM_OVERLAP_LOCALS) || (irfun->flags & IR_FLAG_MASK_NO_OVERLAP)) { - firstlocal = def->firstlocal = vec_size(code_globals); - firstlocal = def->firstlocal = vec_size(code->globals); ++ firstlocal = def->firstlocal = vec_size(ir->code->globals); } else { firstlocal = def->firstlocal = ir->first_common_local; ++opts_optimizationcount[OPTIM_OVERLAP_LOCALS]; @@@ -3215,8 -3209,8 +3232,8 @@@ firstglobal = (OPTS_OPTIMIZATION(OPTIM_GLOBAL_TEMPS) ? ir->first_common_globaltemp : firstlocal); - for (i = vec_size(code_globals); i < firstlocal + irfun->allocated_locals; ++i) - vec_push(code_globals, 0); - for (i = vec_size(code->globals); i < firstlocal + irfun->allocated_locals; ++i) - vec_push(code->globals, 0); ++ for (i = vec_size(ir->code->globals); i < firstlocal + irfun->allocated_locals; ++i) ++ vec_push(ir->code->globals, 0); for (i = 0; i < vec_size(irfun->locals); ++i) { ir_value *v = irfun->locals[i]; if (v->locked || !OPTS_OPTIMIZATION(OPTIM_GLOBAL_TEMPS)) { @@@ -3266,22 -3260,22 +3283,22 @@@ static bool gen_global_function_code(ir irerror(irfun->context, "`%s`: IR global wasn't generated, failed to access function-def", irfun->name); return false; } - fundef = &code_functions[irfun->code_function_def]; - fundef = &code->functions[irfun->code_function_def]; ++ fundef = &ir->code->functions[irfun->code_function_def]; - fundef->entry = vec_size(code_statements); - fundef->entry = vec_size(code->statements); - if (!gen_function_locals(code, ir, global)) { ++ fundef->entry = vec_size(ir->code->statements); + if (!gen_function_locals(ir, global)) { irerror(irfun->context, "Failed to generate locals for function %s", irfun->name); return false; } - if (!gen_function_extparam_copy(irfun)) { - if (!gen_function_extparam_copy(code, irfun)) { ++ if (!gen_function_extparam_copy(ir->code, irfun)) { irerror(irfun->context, "Failed to generate extparam-copy code for function %s", irfun->name); return false; } - if (irfun->max_varargs && !gen_function_varargs_copy(irfun)) { - if (irfun->max_varargs && !gen_function_varargs_copy(code, irfun)) { ++ if (irfun->max_varargs && !gen_function_varargs_copy(ir->code, irfun)) { irerror(irfun->context, "Failed to generate vararg-copy code for function %s", irfun->name); return false; } - if (!gen_function_code(irfun)) { - if (!gen_function_code(code, irfun)) { ++ if (!gen_function_code(ir->code, irfun)) { irerror(irfun->context, "Failed to generate code for function %s", irfun->name); return false; } @@@ -3356,7 -3350,7 +3373,7 @@@ static bool ir_builder_gen_global(ir_bu bool pushdef = opts.optimizeoff; def.type = global->vtype; - def.offset = vec_size(code_globals); - def.offset = vec_size(code->globals); ++ def.offset = vec_size(self->code->globals); def.name = 0; if (OPTS_OPTION_BOOL(OPTION_G) || !islocal) { @@@ -3372,21 -3366,21 +3389,21 @@@ if (pushdef && global->name) { if (global->name[0] == '#') { if (!self->str_immediate) - self->str_immediate = code_genstring("IMMEDIATE"); - self->str_immediate = code_genstring(code, "IMMEDIATE"); ++ self->str_immediate = code_genstring(self->code, "IMMEDIATE"); def.name = global->code.name = self->str_immediate; } else - def.name = global->code.name = code_genstring(global->name); - def.name = global->code.name = code_genstring(code, global->name); ++ def.name = global->code.name = code_genstring(self->code, global->name); } else def.name = 0; if (islocal) { def.offset = ir_value_code_addr(global); - vec_push(code_defs, def); - vec_push(code->defs, def); ++ vec_push(self->code->defs, def); if (global->vtype == TYPE_VECTOR) - gen_vector_defs(def, global->name); - gen_vector_defs(code, def, global->name); ++ gen_vector_defs(self->code, def, global->name); else if (global->vtype == TYPE_FIELD && global->fieldtype == TYPE_VECTOR) - gen_vector_defs(def, global->name); - gen_vector_defs(code, def, global->name); ++ gen_vector_defs(self->code, def, global->name); return true; } } @@@ -3413,102 -3407,103 +3430,103 @@@ * Maybe this could be an -foption * fteqcc creates data for end_sys_* - of size 1, so let's do the same */ - ir_value_code_setaddr(global, vec_size(code_globals)); - vec_push(code_globals, 0); - ir_value_code_setaddr(global, vec_size(code->globals)); - vec_push(code->globals, 0); ++ ir_value_code_setaddr(global, vec_size(self->code->globals)); ++ vec_push(self->code->globals, 0); /* Add the def */ - if (pushdef) vec_push(code_defs, def); - if (pushdef) vec_push(code->defs, def); ++ if (pushdef) vec_push(self->code->defs, def); return true; case TYPE_POINTER: - if (pushdef) vec_push(code_defs, def); - return gen_global_pointer(global); - if (pushdef) vec_push(code->defs, def); - return gen_global_pointer(code, global); ++ if (pushdef) vec_push(self->code->defs, def); ++ return gen_global_pointer(self->code, global); case TYPE_FIELD: if (pushdef) { - vec_push(code_defs, def); - vec_push(code->defs, def); ++ vec_push(self->code->defs, def); if (global->fieldtype == TYPE_VECTOR) - gen_vector_defs(def, global->name); - gen_vector_defs(code, def, global->name); ++ gen_vector_defs(self->code, def, global->name); } - return gen_global_field(global); - return gen_global_field(code, global); ++ return gen_global_field(self->code, global); case TYPE_ENTITY: /* fall through */ case TYPE_FLOAT: { - ir_value_code_setaddr(global, vec_size(code_globals)); - ir_value_code_setaddr(global, vec_size(code->globals)); ++ ir_value_code_setaddr(global, vec_size(self->code->globals)); if (global->hasvalue) { iptr = (int32_t*)&global->constval.ivec[0]; - vec_push(code_globals, *iptr); - vec_push(code->globals, *iptr); ++ vec_push(self->code->globals, *iptr); } else { - vec_push(code_globals, 0); - vec_push(code->globals, 0); ++ vec_push(self->code->globals, 0); } if (!islocal && global->cvq != CV_CONST) def.type |= DEF_SAVEGLOBAL; - if (pushdef) vec_push(code_defs, def); - if (pushdef) vec_push(code->defs, def); ++ if (pushdef) vec_push(self->code->defs, def); return global->code.globaladdr >= 0; } case TYPE_STRING: { - ir_value_code_setaddr(global, vec_size(code_globals)); - ir_value_code_setaddr(global, vec_size(code->globals)); ++ ir_value_code_setaddr(global, vec_size(self->code->globals)); if (global->hasvalue) { - vec_push(code_globals, code_genstring(global->constval.vstring)); - uint32_t load = code_genstring(code, global->constval.vstring); - vec_push(code->globals, load); ++ uint32_t load = code_genstring(self->code, global->constval.vstring); ++ vec_push(self->code->globals, load); } else { - vec_push(code_globals, 0); - vec_push(code->globals, 0); ++ vec_push(self->code->globals, 0); } if (!islocal && global->cvq != CV_CONST) def.type |= DEF_SAVEGLOBAL; - if (pushdef) vec_push(code_defs, def); - if (pushdef) vec_push(code->defs, def); ++ if (pushdef) vec_push(self->code->defs, def); return global->code.globaladdr >= 0; } case TYPE_VECTOR: { size_t d; - ir_value_code_setaddr(global, vec_size(code_globals)); - ir_value_code_setaddr(global, vec_size(code->globals)); ++ ir_value_code_setaddr(global, vec_size(self->code->globals)); if (global->hasvalue) { iptr = (int32_t*)&global->constval.ivec[0]; - vec_push(code_globals, iptr[0]); - vec_push(code->globals, iptr[0]); ++ vec_push(self->code->globals, iptr[0]); if (global->code.globaladdr < 0) return false; for (d = 1; d < type_sizeof_[global->vtype]; ++d) { - vec_push(code_globals, iptr[d]); - vec_push(code->globals, iptr[d]); ++ vec_push(self->code->globals, iptr[d]); } } else { - vec_push(code_globals, 0); - vec_push(code->globals, 0); ++ vec_push(self->code->globals, 0); if (global->code.globaladdr < 0) return false; for (d = 1; d < type_sizeof_[global->vtype]; ++d) { - vec_push(code_globals, 0); - vec_push(code->globals, 0); ++ vec_push(self->code->globals, 0); } } if (!islocal && global->cvq != CV_CONST) def.type |= DEF_SAVEGLOBAL; if (pushdef) { - vec_push(code_defs, def); - vec_push(code->defs, def); ++ vec_push(self->code->defs, def); def.type &= ~DEF_SAVEGLOBAL; - gen_vector_defs(def, global->name); - gen_vector_defs(code, def, global->name); ++ gen_vector_defs(self->code, def, global->name); } return global->code.globaladdr >= 0; } case TYPE_FUNCTION: - ir_value_code_setaddr(global, vec_size(code_globals)); - ir_value_code_setaddr(global, vec_size(code->globals)); ++ ir_value_code_setaddr(global, vec_size(self->code->globals)); if (!global->hasvalue) { - vec_push(code_globals, 0); - vec_push(code->globals, 0); ++ vec_push(self->code->globals, 0); if (global->code.globaladdr < 0) return false; } else { - vec_push(code_globals, vec_size(code_functions)); - vec_push(code->globals, vec_size(code->functions)); - if (!gen_global_function(code, self, global)) ++ vec_push(self->code->globals, vec_size(self->code->functions)); + if (!gen_global_function(self, global)) return false; } if (!islocal && global->cvq != CV_CONST) def.type |= DEF_SAVEGLOBAL; - if (pushdef) vec_push(code_defs, def); - if (pushdef) vec_push(code->defs, def); ++ if (pushdef) vec_push(self->code->defs, def); return true; case TYPE_VARIANT: /* assume biggest type */ - ir_value_code_setaddr(global, vec_size(code_globals)); - vec_push(code_globals, 0); - ir_value_code_setaddr(global, vec_size(code->globals)); - vec_push(code->globals, 0); ++ ir_value_code_setaddr(global, vec_size(self->code->globals)); ++ vec_push(self->code->globals, 0); for (i = 1; i < type_sizeof_[TYPE_VARIANT]; ++i) - vec_push(code_globals, 0); - vec_push(code->globals, 0); ++ vec_push(self->code->globals, 0); return true; default: /* refuse to create 'void' type or any other fancy business. */ @@@ -3518,12 -3513,12 +3536,12 @@@ } } - static void ir_builder_prepare_field(ir_value *field) + static GMQCC_INLINE void ir_builder_prepare_field(code_t *code, ir_value *field) { - field->code.fieldaddr = code_alloc_field(type_sizeof_[field->fieldtype]); + field->code.fieldaddr = code_alloc_field(code, type_sizeof_[field->fieldtype]); } -static bool ir_builder_gen_field(code_t *code, ir_builder *self, ir_value *field) +static bool ir_builder_gen_field(ir_builder *self, ir_value *field) { prog_section_def def; prog_section_field fld; @@@ -3531,7 -3526,7 +3549,7 @@@ (void)self; def.type = (uint16_t)field->vtype; - def.offset = (uint16_t)vec_size(code_globals); - def.offset = (uint16_t)vec_size(code->globals); ++ def.offset = (uint16_t)vec_size(self->code->globals); /* create a global named the same as the field */ if (OPTS_OPTION_U32(OPTION_STANDARD) == COMPILER_GMQCC) { @@@ -3551,7 -3546,7 +3569,7 @@@ memcpy(name+1, field->name, len); /* no strncpy - we used strlen above */ name[len+1] = 0; - def.name = code_genstring(name); - def.name = code_genstring(code, name); ++ def.name = code_genstring(self->code, name); fld.name = def.name + 1; /* we reuse that string table entry */ } else { /* in plain QC, there cannot be a global with the same name, @@@ -3559,13 -3554,13 +3577,13 @@@ * FIXME: fteqcc should create a global as well * check if it actually uses the same name. Probably does */ - def.name = code_genstring(field->name); - def.name = code_genstring(code, field->name); ++ def.name = code_genstring(self->code, field->name); fld.name = def.name; } field->code.name = def.name; - vec_push(code_defs, def); - vec_push(code->defs, def); ++ vec_push(self->code->defs, def); fld.type = field->fieldtype; @@@ -3576,44 -3571,32 +3594,32 @@@ fld.offset = field->code.fieldaddr; - vec_push(code_fields, fld); - vec_push(code->fields, fld); ++ vec_push(self->code->fields, fld); - ir_value_code_setaddr(field, vec_size(code_globals)); - vec_push(code_globals, fld.offset); - ir_value_code_setaddr(field, vec_size(code->globals)); - vec_push(code->globals, fld.offset); ++ ir_value_code_setaddr(field, vec_size(self->code->globals)); ++ vec_push(self->code->globals, fld.offset); if (fld.type == TYPE_VECTOR) { - vec_push(code_globals, fld.offset+1); - vec_push(code_globals, fld.offset+2); - vec_push(code->globals, fld.offset+1); - vec_push(code->globals, fld.offset+2); ++ vec_push(self->code->globals, fld.offset+1); ++ vec_push(self->code->globals, fld.offset+2); } if (field->fieldtype == TYPE_VECTOR) { - gen_vector_defs(def, field->name); - gen_vector_fields(fld, field->name); - gen_vector_defs (code, def, field->name); - gen_vector_fields(code, fld, field->name); ++ gen_vector_defs (self->code, def, field->name); ++ gen_vector_fields(self->code, fld, field->name); } return field->code.globaladdr >= 0; } - bool ir_builder_prepare(ir_builder *self) - { - size_t extparams = self->max_used_params; - if (extparams > 8) { - for (extparams -= 8; extparams; --extparams) - ir_gen_extparam_proto(self); - } - return true; - } - -bool ir_builder_generate(code_t *code, ir_builder *self, const char *filename) +bool ir_builder_generate(ir_builder *self, const char *filename) { prog_section_statement stmt; size_t i; char *lnofile = NULL; - code_init(); - for (i = 0; i < vec_size(self->fields); ++i) { - ir_builder_prepare_field(self->fields[i]); - ir_builder_prepare_field(code, self->fields[i]); ++ ir_builder_prepare_field(self->code, self->fields[i]); } for (i = 0; i < vec_size(self->globals); ++i) @@@ -3641,20 -3624,20 +3647,20 @@@ } /* generate nil */ - ir_value_code_setaddr(self->nil, vec_size(code_globals)); - vec_push(code_globals, 0); - vec_push(code_globals, 0); - vec_push(code_globals, 0); - ir_value_code_setaddr(self->nil, vec_size(code->globals)); - vec_push(code->globals, 0); - vec_push(code->globals, 0); - vec_push(code->globals, 0); ++ ir_value_code_setaddr(self->nil, vec_size(self->code->globals)); ++ vec_push(self->code->globals, 0); ++ vec_push(self->code->globals, 0); ++ vec_push(self->code->globals, 0); /* generate global temps */ - self->first_common_globaltemp = vec_size(code_globals); - self->first_common_globaltemp = vec_size(code->globals); ++ self->first_common_globaltemp = vec_size(self->code->globals); for (i = 0; i < self->max_globaltemps; ++i) { - vec_push(code_globals, 0); - vec_push(code->globals, 0); ++ vec_push(self->code->globals, 0); } /* generate common locals */ - self->first_common_local = vec_size(code_globals); - self->first_common_local = vec_size(code->globals); ++ self->first_common_local = vec_size(self->code->globals); for (i = 0; i < self->max_locals; ++i) { - vec_push(code_globals, 0); - vec_push(code->globals, 0); ++ vec_push(self->code->globals, 0); } /* generate function code */ @@@ -3667,30 -3650,30 +3673,30 @@@ } } - if (vec_size(code_globals) >= 65536) { - if (vec_size(code->globals) >= 65536) { ++ if (vec_size(self->code->globals) >= 65536) { irerror(vec_last(self->globals)->context, "This progs file would require more globals than the metadata can handle. Bailing out."); return false; } /* DP errors if the last instruction is not an INSTR_DONE. */ - if (vec_last(code_statements).opcode != INSTR_DONE) - if (vec_last(code->statements).opcode != INSTR_DONE) ++ if (vec_last(self->code->statements).opcode != INSTR_DONE) { stmt.opcode = INSTR_DONE; stmt.o1.u1 = 0; stmt.o2.u1 = 0; stmt.o3.u1 = 0; - code_push_statement(&stmt, vec_last(code_linenums)); - code_push_statement(code, &stmt, vec_last(code->linenums)); ++ code_push_statement(self->code, &stmt, vec_last(self->code->linenums)); } if (OPTS_OPTION_BOOL(OPTION_PP_ONLY)) return true; - if (vec_size(code_statements) != vec_size(code_linenums)) { - if (vec_size(code->statements) != vec_size(code->linenums)) { ++ if (vec_size(self->code->statements) != vec_size(self->code->linenums)) { con_err("Linecounter wrong: %lu != %lu\n", - (unsigned long)vec_size(code_statements), - (unsigned long)vec_size(code_linenums)); - (unsigned long)vec_size(code->statements), - (unsigned long)vec_size(code->linenums)); ++ (unsigned long)vec_size(self->code->statements), ++ (unsigned long)vec_size(self->code->linenums)); } else if (OPTS_FLAG(LNO)) { - char *dot; + char *dot; size_t filelen = strlen(filename); memcpy(vec_add(lnofile, filelen+1), filename, filelen+1); @@@ -3709,7 -3692,7 +3715,7 @@@ else con_out("writing '%s'\n", filename); } - if (!code_write(filename, lnofile)) { - if (!code_write(code, filename, lnofile)) { ++ if (!code_write(self->code, filename, lnofile)) { vec_free(lnofile); return false; } @@@ -3774,7 -3757,7 +3780,7 @@@ void ir_function_dump(ir_function *f, c return; } oprintf("%sfunction %s\n", ind, f->name); -- strncat(ind, "\t", IND_BUFSZ); ++ strncat(ind, "\t", IND_BUFSZ-1); if (vec_size(f->locals)) { oprintf("%s%i locals:\n", ind, (int)vec_size(f->locals)); @@@ -3870,7 -3853,7 +3876,7 @@@ void ir_block_dump(ir_block* b, char *i { size_t i; oprintf("%s:%s\n", ind, b->label); -- strncat(ind, "\t", IND_BUFSZ); ++ strncat(ind, "\t", IND_BUFSZ-1); if (b->instr && b->instr[0]) oprintf("%s (%i) [entry]\n", ind, (int)(b->instr[0]->eid-1)); @@@ -3904,7 -3887,7 +3910,7 @@@ void ir_instr_dump(ir_instr *in, char * return; } -- strncat(ind, "\t", IND_BUFSZ); ++ strncat(ind, "\t", IND_BUFSZ-1); if (in->_ops[0] && (in->_ops[1] || in->_ops[2])) { ir_value_dump(in->_ops[0], oprintf); diff --cc ir.h index 50fd0d9,cd38295..f5b47da --- a/ir.h +++ b/ir.h @@@ -337,30 -267,23 +267,26 @@@ typedef struct ir_builder_ /* there should just be this one nil */ ir_value *nil; ir_value *reserved_va_count; ++ ++ /* code generator */ ++ code_t *code; } ir_builder; - ir_builder* ir_builder_new(const char *modulename); - void ir_builder_delete(ir_builder*); - - bool ir_builder_set_name(ir_builder *self, const char *name); - - ir_function* ir_builder_get_function(ir_builder*, const char *fun); + ir_builder* ir_builder_new(const char *modulename); + void ir_builder_delete(ir_builder*); ir_function* ir_builder_create_function(ir_builder*, const char *name, int outtype); + ir_value* ir_builder_create_global(ir_builder*, const char *name, int vtype); + ir_value* ir_builder_create_field(ir_builder*, const char *name, int vtype); + ir_value* ir_builder_get_va_count(ir_builder*); -bool ir_builder_generate(code_t *, ir_builder *self, const char *filename); ++bool ir_builder_generate(ir_builder *self, const char *filename); + void ir_builder_dump(ir_builder*, int (*oprintf)(const char*, ...)); - ir_value* ir_builder_get_global(ir_builder*, const char *fun); - ir_value* ir_builder_create_global(ir_builder*, const char *name, int vtype); - ir_value* ir_builder_get_field(ir_builder*, const char *fun); - ir_value* ir_builder_create_field(ir_builder*, const char *name, int vtype); - - ir_value* ir_builder_get_va_count(ir_builder*); - - bool ir_builder_prepare(ir_builder *self); - bool ir_builder_generate(ir_builder *self, const char *filename); - - void ir_builder_dump(ir_builder*, int (*oprintf)(const char*, ...)); - - /* This code assumes 32 bit floats while generating binary */ - extern int check_int_and_float_size - [ (sizeof(int32_t) == sizeof(qcfloat)) ? 1 : -1 ]; + /* + * This code assumes 32 bit floats while generating binary + * Blub: don't use extern here, it's annoying and shows up in nm - * for some reason :P ++ * for some reason :P + */ + typedef int static_assert_is_32bit_float [(sizeof(int32_t) == 4)?1:-1]; + typedef int static_assert_is_32bit_integer[(sizeof(qcfloat) == 4)?1:-1]; #endif diff --cc opts.def index 47f82ee,071b11a..7efe531 --- a/opts.def +++ b/opts.def @@@ -119,7 -122,7 +122,8 @@@ GMQCC_DEFINE_FLAG(MAX_ARRAY_SIZE) GMQCC_DEFINE_FLAG(ADD_INFO) GMQCC_DEFINE_FLAG(CORRECTION) + GMQCC_DEFINE_FLAG(J) + GMQCC_DEFINE_FLAG(STATISTICS) #endif /* some cleanup so we don't have to */ diff --cc parser.c index 325a030,8a7cf87..8bf4086 --- a/parser.c +++ b/parser.c @@@ -21,10 -21,8 +21,9 @@@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ - #include - #include + #include #include +#include #include "gmqcc.h" #include "lexer.h" @@@ -6117,90 -6285,6 +6286,85 @@@ void parser_cleanup(parser_t *parser mem_d(parser); } +static void function_finalize_worker_do(ast_function **list, size_t count, volatile uint32_t *counter, bool *failure) +{ + do { + uint32_t idx = util_atomic_xadd32(counter, 1); + if (idx >= count) { + *counter = count; + return; + } + if (!ir_function_finalize(list[idx]->ir_func)) { + con_out("failed to finalize function %s\n", list[idx]->name); + *failure = true; + return; + } + } while (true); +} + +typedef struct { + ast_function **list; + size_t count; + volatile uint32_t *counter; + bool *failure; +} function_finalize_worker_data; +static void* function_finalize_worker(void *_d) { + function_finalize_worker_data *d = (function_finalize_worker_data*)_d; + function_finalize_worker_do(d->list, d->count, d->counter, d->failure); + return NULL; +} + +static bool function_finalize_all_threaded(ast_function **list, size_t count) +{ + volatile uint32_t counter = 0; + function_finalize_worker_data wd; + + size_t poolsize = OPTS_OPTION_U32(OPTION_J); + bool failure = false; + size_t i, j; + + pthread_t *threads; + + if (!list || !count) + return true; + + wd.list = list; + wd.count = count; + wd.counter = &counter; + wd.failure = &failure; + - threads = (pthread_t*)alloca(poolsize*sizeof(pthread_t)); ++ threads = (pthread_t*)mem_a(poolsize*sizeof(pthread_t)); + + for (i = 0; i < poolsize; ++i) { + if (pthread_create(threads+i, NULL, &function_finalize_worker, &wd) != 0) + break; + } + if (i < poolsize) { + con_out("failed to spawn worker threads\n"); + for (j = 0; j <= i; ++j) + pthread_join(threads[j], NULL); + return false; + } + for (i = 0; i < poolsize; ++i) + pthread_join(threads[i], NULL); + return !failure; +} + +bool function_finalize_all(ast_function **list, size_t count) +{ + size_t i; - for (i = 0; i < count; ++i) { - if (!ir_function_optimize(list[i]->ir_func)) { - con_out("failed to optimize function %s\n", list[i]->name); - return false; - } - } + if (OPTS_OPTION_U32(OPTION_J) > 1) + return function_finalize_all_threaded(list, count); ++ + for (i = 0; i < count; ++i) { + if (!ir_function_finalize(list[i]->ir_func)) { + con_out("failed to finalize function %s\n", list[i]->name); + return false; + } + } + return true; +} + bool parser_finish(parser_t *parser, const char *output) { size_t i; @@@ -6354,15 -6438,10 +6518,12 @@@ return false; } } + + generate_checksum(parser); if (OPTS_OPTION_BOOL(OPTION_DUMP)) ir_builder_dump(ir, con_out); + - if (!ir_builder_prepare(ir)) { - con_out("failed to prepare builder for output\n"); - ir_builder_delete(ir); - return false; - } +#if 0 for (i = 0; i < vec_size(parser->functions); ++i) { if (!ir_function_finalize(parser->functions[i]->ir_func)) { con_out("failed to finalize function %s\n", parser->functions[i]->name); @@@ -6370,13 -6449,8 +6531,16 @@@ return false; } } ++ +#else + if (!function_finalize_all(parser->functions, vec_size(parser->functions))) { + ir_builder_delete(ir); + return false; + } +#endif + + parser_remove_ast(parser); + if (compile_Werrors) { con_out("*** there were warnings treated as errors\n"); compile_show_werrors(); @@@ -6387,9 -6461,7 +6551,7 @@@ if (OPTS_OPTION_BOOL(OPTION_DUMPFIN)) ir_builder_dump(ir, con_out); - generate_checksum(parser); - - if (!ir_builder_generate(parser->code, ir, output)) { + if (!ir_builder_generate(ir, output)) { con_out("*** failed to generate output file\n"); ir_builder_delete(ir); return false;