]> de.git.xonotic.org Git - voretournament/voretournament.git/blobdiff - misc/source/fteqcc-src/qccmain.c
Update fteqcc source
[voretournament/voretournament.git] / misc / source / fteqcc-src / qccmain.c
index cad17a6cb73e8db1788c6fb63b777afdd33a3dec..8c84930746c6b6e6d04c9d61383eea3eae072990 100644 (file)
@@ -27,8 +27,6 @@ void QCC_PR_LexWhitespace (void);
 void *FS_ReadToMem(char *fname, void *membuf, int *len);
 void FS_CloseFromMem(void *mem);
 
-struct qcc_includechunk_s *currentchunk;
-
 unsigned int MAX_REGS;
 
 int    MAX_STRINGS;
@@ -78,14 +76,17 @@ int                 numfielddefs;
 
 PATHSTRING             *precache_sounds;
 int                    *precache_sounds_block;
+int                    *precache_sounds_used;
 int                    numsounds;
 
 PATHSTRING             *precache_textures;
 int                    *precache_textures_block;
+int                    *precache_textures_block;
 int                    numtextures;
 
 PATHSTRING             *precache_models;
 int                    *precache_models_block;
+int                    *precache_models_used;
 int                    nummodels;
 
 PATHSTRING             *precache_files;
@@ -96,11 +97,13 @@ extern int numCompilerConstants;
 hashtable_t compconstantstable;
 hashtable_t globalstable;
 hashtable_t localstable;
+#ifdef WRITEASM
+FILE *asmfile;
+#endif
 hashtable_t floatconstdefstable;
 hashtable_t stringconstdefstable;
-hashtable_t stringconstdefstable_dotranslate;
-int dotranslate;
-int dotranslate_count;
+hashtable_t stringconstdefstable_trans;
+extern int dotranslate_count;
 
 pbool qccwarningdisabled[WARN_MAX];
 
@@ -184,7 +187,7 @@ optimisations_t optimisations[] =
        {&opt_return_only,                              "ro",   3,      FLAG_KILLSDEBUGGERS,                                    "return_only",          "Functions ending in a return statement do not need a done statement at the end of the function. This can confuse some decompilers, making functions appear larger than they were."},
        {&opt_compound_jumps,                   "cj",   3,      FLAG_KILLSDEBUGGERS,                                    "compound_jumps",       "This optimisation plays an effect mostly with nested if/else statements, instead of jumping to an unconditional jump statement, it'll jump to the final destination instead. This will bewilder decompilers."},
 //     {&opt_comexprremoval,                   "cer",  4,      0,                                              "expression_removal",   "Eliminate common sub-expressions"},    //this would be too hard...
-       {&opt_stripfunctions,                   "sf",   3,      0,                                              "strip_functions",      "Strips out the 'defs' of functions that were only ever called directly. This does not affect saved games."},
+       {&opt_stripfunctions,                   "sf",   4,      0,                                              "strip_functions",      "Strips out the 'defs' of functions that were only ever called directly. This does not affect saved games. This can affect FTE_MULTIPROGS."},
        {&opt_locals_marshalling,               "lm",   4,      FLAG_KILLSDEBUGGERS,            "locals_marshalling", "Store all locals in one section of the pr_globals. Vastly reducing it. This effectivly does the job of overlaptemps. It's been noticed as buggy by a few, however, and the curcumstances where it causes problems are not yet known."},
        {&opt_vectorcalls,                              "vc",   4,      FLAG_KILLSDEBUGGERS,                                    "vectorcalls",          "Where a function is called with just a vector, this causes the function call to store three floats instead of one vector. This can save a good number of pr_globals where those vectors contain many duplicate coordinates but do not match entirly."},
        {NULL}
@@ -215,6 +218,7 @@ compiler_flag_t compiler_flag[] = {
        {&keyword_nosave,               defaultkeyword, "nosave",               "Keyword: nosave",              "Disables the 'nosave' keyword."},      //don't write the def to the output.
        {&keyword_shared,               defaultkeyword, "shared",               "Keyword: shared",              "Disables the 'shared' keyword."},      //mark global to be copied over when progs changes (part of FTE_MULTIPROGS)
        {&keyword_state,                nondefaultkeyword,"state",              "Keyword: state",               "Disables the 'state' keyword."},
+       {&keyword_optional,             defaultkeyword,"optional",              "Keyword: optional",    "Disables the 'optional' keyword."},
        {&keyword_string,               defaultkeyword, "string",               "Keyword: string",              "Disables the 'string' keyword."},
        {&keyword_struct,               defaultkeyword, "struct",               "Keyword: struct",              "Disables the 'struct' keyword."},
        {&keyword_switch,               defaultkeyword, "switch",               "Keyword: switch",              "Disables the 'switch' keyword."},
@@ -241,7 +245,9 @@ compiler_flag_t compiler_flag[] = {
        {&flag_filetimes,               0,                              "filetimes",    "Check Filetimes",              "Recompiles the progs only if the file times are modified."},
        {&flag_fasttrackarrays, FLAG_MIDCOMPILE|FLAG_ASDEFAULT,"fastarrays","fast arrays where possible",       "Generates extra instructions inside array handling functions to detect engine and use extension opcodes only in supporting engines.\nAdds a global which is set by the engine if the engine supports the extra opcodes. Note that this applies to all arrays or none."},
        {&flag_assume_integer,  FLAG_MIDCOMPILE,"assumeint",    "Assume Integers",              "Numerical constants are assumed to be integers, instead of floats."},
-       {&pr_subscopedlocals,           FLAG_MIDCOMPILE,                "subscope",     "Subscoped Locals",             "Restrict the scope of locals to the block they are actually defined within, as in C."},
+       {&pr_subscopedlocals,   FLAG_MIDCOMPILE,"subscope",             "Subscoped Locals",             "Restrict the scope of locals to the block they are actually defined within, as in C."},
+       {&verbose,                              FLAG_MIDCOMPILE,"verbose",              "Verbose",                              "Lots of extra compiler messages."},
+       {&flag_typeexplicit,    FLAG_MIDCOMPILE,"typeexplicit", "Explicit types",               "All type conversions must be explicit or directly supported by instruction set."},
        {NULL}
 };
 
@@ -313,11 +319,13 @@ int       QCC_CopyString (char *str)
        int             old;
        char *s;
 
+       if (!str)
+               return 0;
+       if (!*str)
+               return 1;
+
        if (opt_noduplicatestrings)
        {
-               if (!str || !*str)
-                       return 0;
-
                for (s = strings; s < strings+strofs; s++)
                        if (!strcmp(s, str))
                        {
@@ -482,7 +490,7 @@ void QCC_InitData (void)
        qcc_sourcefile = NULL;
 
        numstatements = 1;
-       strofs = 1;
+       strofs = 2;
        numfunctions = 1;
        numglobaldefs = 1;
        numfielddefs = 1;
@@ -516,7 +524,7 @@ int WriteBodylessFuncs (int handle)
        {
                if (d->type->type == ev_function && !d->scope)// function parms are ok
                {
-                       if (d->initialized != 1 && d->references>0)
+                       if (!(d->initialized & 1) && d->references>0)
                        {
                                SafeWrite(handle, d->name, strlen(d->name)+1);
                                ret++;
@@ -648,8 +656,8 @@ pbool QCC_WriteData (int crc)
                if (compressoutput)             progs.blockscompressed |=64;    //line numbers
                if (compressoutput)             progs.blockscompressed |=128;   //types
                //include a type block?
-               types = debugtarget;//!!QCC_PR_CheckCompConstDefined("TYPES");  //useful for debugging and saving (maybe, anyway...).
-               if (sizeof(char *) != sizeof(string_t))
+               types = debugtarget;
+               if (types && sizeof(char *) != sizeof(string_t))
                {
                        //qcc_typeinfo_t has a char* inside it, which changes size
                        printf("AMD64 builds cannot write typeinfo structures\n");
@@ -692,6 +700,18 @@ pbool QCC_WriteData (int crc)
 
        for (def = pr.def_head.next ; def ; def = def->next)
        {
+               if ((def->type->type == ev_struct || def->type->type == ev_union || def->arraysize) && def->deftail)
+               {
+                       QCC_def_t               *d;
+                       d = def;
+                       while (d != def->deftail)
+                       {
+                               d = d->next;
+                               h = d->references;
+                               d->references += def->references;
+                               def->references += h;
+                       }
+               }
                if (def->type->type == ev_vector || (def->type->type == ev_field && def->type->aux_type->type == ev_vector))
                {       //do the references, so we don't get loadsa not referenced VEC_HULL_MINS_x
                        sprintf(element, "%s_x", def->name);
@@ -727,14 +747,14 @@ pbool QCC_WriteData (int crc)
                }
                if (def->references<=0)
                {
-                       if (def->constant)
-                               QCC_PR_Warning(WARN_NOTREFERENCEDCONST, strings + def->s_file, def->s_line, "%s  no references", def->name);
-                       else
-                               QCC_PR_Warning(WARN_NOTREFERENCED, strings + def->s_file, def->s_line, "%s  no references", def->name);
-                       if (!warnedunref)
+                       int wt = def->constant?WARN_NOTREFERENCEDCONST:WARN_NOTREFERENCED;
+                       if (QCC_PR_Warning(wt, strings + def->s_file, def->s_line, "%s  no references", def->name))
                        {
-                               QCC_PR_Note(WARN_NOTREFERENCED, NULL, 0, "You can use the noref prefix or pragma to silence this message.");
-                               warnedunref = true;
+                               if (!warnedunref)
+                               {
+                                       QCC_PR_Note(WARN_NOTREFERENCED, NULL, 0, "You can use the noref prefix or pragma to silence this message.");
+                                       warnedunref = true;
+                               }
                        }
 
                        if (opt_unreferenced && def->type->type != ev_field)
@@ -770,13 +790,15 @@ pbool QCC_WriteData (int crc)
                }
                else if (def->type->type == ev_field && def->constant)
                {
+                       if (numfielddefs >= MAX_FIELDS)
+                               QCC_PR_ParseError(0, "Too many fields. Limit is %u\n", MAX_FIELDS);
                        dd = &fields[numfielddefs];
                        numfielddefs++;
                        dd->type = def->type->aux_type->type;
                        dd->s_name = QCC_CopyString (def->name);
                        dd->ofs = G_INT(def->ofs);
                }
-               else if ((def->scope||def->constant) && (def->type->type != ev_string || opt_constant_names_strings))
+               else if ((def->scope||def->constant) && (def->type->type != ev_string || (strncmp(def->name, "dotranslate_", 12) && opt_constant_names_strings)))
                {
                        if (opt_constant_names)
                        {
@@ -831,9 +853,10 @@ pbool QCC_WriteData (int crc)
                                continue;
                        if (dd->ofs == qcc_globals[h].ofs)
                        {
-                               if (dd->type != qcc_globals[h].type)
+                               if ((dd->type&~DEF_SAVEGLOBAL) != (qcc_globals[h].type&~DEF_SAVEGLOBAL))
                                {
-                                       if (dd->type != ev_vector && qcc_globals[h].type != ev_float)
+                                       if (!(((dd->type&~DEF_SAVEGLOBAL) == ev_vector && (qcc_globals[h].type&~DEF_SAVEGLOBAL) == ev_float) ||
+                                               ((dd->type&~DEF_SAVEGLOBAL) == ev_struct || (dd->type&~DEF_SAVEGLOBAL) == ev_union)))
                                                QCC_PR_Warning(0, NULL, 0, "Mismatched union global types (%s and %s)", strings+dd->s_name, strings+qcc_globals[h].s_name);
                                }
                                //remove the saveglobal flag on the duplicate globals.
@@ -1593,7 +1616,7 @@ PR_PrintDefs
                QCC_PR_PrintOfs (d->ofs);
 }*/
 
-QCC_type_t *QCC_PR_NewType (char *name, int basictype)
+QCC_type_t *QCC_PR_NewType (char *name, int basictype, pbool typedefed)
 {
        if (numtypeinfos>= maxtypeinfos)
                QCC_Error(ERR_TOOMANYTYPES, "Too many types");
@@ -1603,6 +1626,8 @@ QCC_type_t *QCC_PR_NewType (char *name, int basictype)
        qcc_typeinfo[numtypeinfos].num_parms = 0;
        qcc_typeinfo[numtypeinfos].param = NULL;
        qcc_typeinfo[numtypeinfos].size = type_size[basictype];
+       qcc_typeinfo[numtypeinfos].arraysize = 0;
+       qcc_typeinfo[numtypeinfos].typedefed = typedefed;
 
 
        numtypeinfos++;
@@ -1638,40 +1663,44 @@ void    QCC_PR_BeginCompilation (void *memory, int memsize)
                pr_global_defs[i] = &def_void;
 */
 
-       type_void = QCC_PR_NewType("void", ev_void);
-       type_string = QCC_PR_NewType("string", ev_string);
-       type_float = QCC_PR_NewType("float", ev_float);
-       type_vector = QCC_PR_NewType("vector", ev_vector);
-       type_entity = QCC_PR_NewType("entity", ev_entity);
-       type_field = QCC_PR_NewType("field", ev_field);
-       type_function = QCC_PR_NewType("function", ev_function);
-       type_pointer = QCC_PR_NewType("pointer", ev_pointer);
-       type_integer = QCC_PR_NewType("__integer", ev_integer);
-       type_variant = QCC_PR_NewType("__variant", ev_variant);
-
-       type_floatfield = QCC_PR_NewType("fieldfloat", ev_field);
+       type_void = QCC_PR_NewType("void", ev_void, true);
+       type_string = QCC_PR_NewType("string", ev_string, true);
+       type_float = QCC_PR_NewType("float", ev_float, true);
+       type_vector = QCC_PR_NewType("vector", ev_vector, true);
+       type_entity = QCC_PR_NewType("entity", ev_entity, true);
+       type_field = QCC_PR_NewType("__field", ev_field, false);
+       type_function = QCC_PR_NewType("__function", ev_function, false);
+       type_pointer = QCC_PR_NewType("__pointer", ev_pointer, false);
+       type_integer = QCC_PR_NewType("__integer", ev_integer, true);
+       type_variant = QCC_PR_NewType("variant", ev_variant, true);
+       type_variant = QCC_PR_NewType("__variant", ev_variant, true);
+
+       type_floatfield = QCC_PR_NewType("fieldfloat", ev_field, false);
        type_floatfield->aux_type = type_float;
-       type_pointer->aux_type = QCC_PR_NewType("pointeraux", ev_float);
+       type_pointer->aux_type = QCC_PR_NewType("pointeraux", ev_float, false);
+
+       type_intpointer = QCC_PR_NewType("__intpointer", ev_pointer, false);
+       type_intpointer->aux_type = type_integer;
+       type_floatpointer = QCC_PR_NewType("__floatpointer", ev_pointer, false);
+       type_floatpointer->aux_type = type_float;
 
        type_function->aux_type = type_void;
 
        //type_field->aux_type = type_float;
 
-       if (keyword_integer)
-               type_integer = QCC_PR_NewType("integer", ev_integer);
-       if (keyword_int)
-               type_integer = QCC_PR_NewType("int", ev_integer);
+       type_integer = QCC_PR_NewType("integer", ev_integer, keyword_integer?true:false);
+       type_integer = QCC_PR_NewType("int", ev_integer, keyword_integer?true:false);
 
 
 
        if (output_parms)
        {       //this tends to confuse the brains out of decompilers. :)
                numpr_globals = 1;
-               QCC_PR_GetDef(type_vector, "RETURN", NULL, true, 1, false)->references++;
+               QCC_PR_GetDef(type_vector, "RETURN", NULL, true, 0, false)->references++;
                for (i = 0; i < MAX_PARMS; i++)
                {
                        sprintf(name, "PARM%i", i);
-                       QCC_PR_GetDef(type_vector, name, NULL, true, 1, false)->references++;
+                       QCC_PR_GetDef(type_vector, name, NULL, true, 0, false)->references++;
                }
        }
        else
@@ -1733,11 +1762,12 @@ int QCC_PR_FinishCompilation (void)
                                }
                                else
                                {
-                                       QCC_PR_ParseErrorPrintDef(ERR_NOFUNC, d, "function %s was not defined",d->name);
+                                       QCC_PR_ParseWarning(ERR_NOFUNC, "function %s was not defined",d->name);
+                                       QCC_PR_ParsePrintDef(ERR_NOFUNC, d);
                                        bodylessfuncs = true;
                                        errors = true;
                                }
-                               s_file = NULL;
+                               s_file = 0;
 //                             errors = true;
                        }
                        else if (d->initialized==2)
@@ -1870,6 +1900,7 @@ unsigned short QCC_PR_WriteProgdefs (char *filename)
        QCC_def_t       *d;
        int     f;
        unsigned short          crc;
+       QCC_def_t *ld;
 //     int             c;
 
        file[0] = '\0';
@@ -1904,6 +1935,7 @@ unsigned short QCC_PR_WriteProgdefs (char *filename)
        ADD3(qcva("\tint\tpad[%i];\n", RESERVED_OFS));
        for (d=pr.def_head.next ; d ; d=d->next)
        {
+               ld = d;
                if (!strcmp (d->name, "end_sys_globals"))
                        break;
                if (d->ofs<RESERVED_OFS)
@@ -1916,7 +1948,8 @@ unsigned short QCC_PR_WriteProgdefs (char *filename)
                        break;
                case ev_vector:
                        ADD(qcva("\tvec3_t\t%s;\n",d->name));
-                       d=d->next->next->next;  // skip the elements
+                       if (d->deftail)
+                               d=d->deftail;   // skip the elements
                        break;
                case ev_string:
                        ADD(qcva("\tstring_t\t%s;\n",d->name));
@@ -1956,7 +1989,8 @@ unsigned short QCC_PR_WriteProgdefs (char *filename)
                        break;
                case ev_vector:
                        ADD(qcva("\tvec3_t\t%s;\n",d->name));
-                       d=d->next->next->next;  // skip the elements
+                       if (d->deftail)
+                               d=d->deftail;   // skip the elements
                        break;
                case ev_string:
                        ADD(qcva("\tstring_t\t%s;\n",d->name));
@@ -2755,6 +2789,7 @@ void QCC_SetDefaultProperties (void)
        qccwarningdisabled[WARN_FTE_SPECIFIC] = true;
        qccwarningdisabled[WARN_EXTENSION_USED] = true;
        qccwarningdisabled[WARN_IFSTRING_USED] = true;
+       qccwarningdisabled[WARN_CORRECTEDRETURNTYPE] = true;
 
 
 
@@ -2866,10 +2901,10 @@ void QCC_main (int argc, char **argv)   //as part of the quake engine
        pHash_GetNext = &Hash_GetNext;
        pHash_Add = &Hash_Add;
 
-       MAX_REGS                = 65536;
+       MAX_REGS                = 1<<17;
        MAX_STRINGS             = 1000000;
-       MAX_GLOBALS             = 65535;
-       MAX_FIELDS              = 2048;
+       MAX_GLOBALS             = 1<<17;
+       MAX_FIELDS              = 1<<12;
        MAX_STATEMENTS  = 0x80000;
        MAX_FUNCTIONS   = 16384;
        maxtypeinfos    = 16384;
@@ -2977,7 +3012,7 @@ void QCC_main (int argc, char **argv)     //as part of the quake engine
        QCC_PurgeTemps();
 
        strings = (void *)qccHunkAlloc(sizeof(char) * MAX_STRINGS);
-       strofs = 1;
+       strofs = 2;
 
        statements = (void *)qccHunkAlloc(sizeof(QCC_dstatement_t) * MAX_STATEMENTS);
        numstatements = 0;
@@ -2991,13 +3026,12 @@ void QCC_main (int argc, char **argv)   //as part of the quake engine
        qcc_pr_globals = (void *)qccHunkAlloc(sizeof(float) * MAX_REGS);
        numpr_globals=0;
 
-       Hash_InitTable(&globalstable, MAX_REGS, qccHunkAlloc(Hash_BytesForBuckets(MAX_REGS)));
-       Hash_InitTable(&localstable, MAX_REGS, qccHunkAlloc(Hash_BytesForBuckets(MAX_REGS)));
-       Hash_InitTable(&floatconstdefstable, MAX_REGS+1, qccHunkAlloc(Hash_BytesForBuckets(MAX_REGS+1)));
-       Hash_InitTable(&stringconstdefstable, MAX_REGS, qccHunkAlloc(Hash_BytesForBuckets(MAX_REGS)));
-       Hash_InitTable(&stringconstdefstable_dotranslate, MAX_REGS, qccHunkAlloc(Hash_BytesForBuckets(MAX_REGS)));
-       dotranslate=0;
-       dotranslate_count=0;
+       Hash_InitTable(&globalstable, MAX_REGS/2, qccHunkAlloc(Hash_BytesForBuckets(MAX_REGS/2)));
+       Hash_InitTable(&localstable, MAX_REGS/2, qccHunkAlloc(Hash_BytesForBuckets(MAX_REGS/2)));
+       Hash_InitTable(&floatconstdefstable, MAX_REGS/2+1, qccHunkAlloc(Hash_BytesForBuckets(MAX_REGS/2+1)));
+       Hash_InitTable(&stringconstdefstable, MAX_REGS/2, qccHunkAlloc(Hash_BytesForBuckets(MAX_REGS/2)));
+       Hash_InitTable(&stringconstdefstable_trans, 1000, qccHunkAlloc(Hash_BytesForBuckets(1000)));
+       dotranslate_count = 0;
 
 //     pr_global_defs = (QCC_def_t **)qccHunkAlloc(sizeof(QCC_def_t *) * MAX_REGS);