1
0
Fork 0
forked from fte/fteqw

Add support for char/short/bitfields. Fix up some other stuff for better C compat.

This commit is contained in:
Shpoike 2024-12-12 13:13:12 +00:00
parent 0650610667
commit affb96a3b3
11 changed files with 1334 additions and 425 deletions

View file

@ -1259,6 +1259,19 @@ ELSE()
#SET(INSTALLTARGS ${INSTALLTARGS} httpserver) #SET(INSTALLTARGS ${INSTALLTARGS} httpserver)
ENDIF() ENDIF()
SET(FTE_TOOL_QCVM false CACHE BOOL "Compile standalone qcvm.")
IF(FTE_TOOL_QCVM)
ADD_EXECUTABLE(qcvm
engine/qclib/test.c
engine/qclib/hash.c
${FTE_QCVM_FILES}
)
SET_TARGET_PROPERTIES(qcvm PROPERTIES COMPILE_DEFINITIONS "${FTE_LIB_DEFINES};${FTE_REVISON}")
TARGET_LINK_LIBRARIES(qcvm ${FTEQCC_LIBS} ${SYS_LIBS})
SET(INSTALLTARGS ${INSTALLTARGS} qcvm)
ENDIF()
SET(FTE_TOOL_QCC true CACHE BOOL "Compile commandline qc compiler.") SET(FTE_TOOL_QCC true CACHE BOOL "Compile commandline qc compiler.")
IF(FTE_TOOL_QCC) IF(FTE_TOOL_QCC)
ADD_EXECUTABLE(fteqcc ADD_EXECUTABLE(fteqcc

View file

@ -468,7 +468,7 @@ reeval:
ptr = QCPOINTERM(i); ptr = QCPOINTERM(i);
*(unsigned char *)ptr = (char)OPA->_float; *(unsigned char *)ptr = (char)OPA->_float;
break; break;
case OP_STOREP_B: //store (byte) character in a string case OP_STOREP_I8: //store (byte) character in a string
i = OPB->_int + (OPC->_int)*sizeof(pbyte); i = OPB->_int + (OPC->_int)*sizeof(pbyte);
errorif (QCPOINTERWRITEFAIL(i, sizeof(pbyte))) errorif (QCPOINTERWRITEFAIL(i, sizeof(pbyte)))
{ {
@ -483,6 +483,21 @@ reeval:
ptr = QCPOINTERM(i); ptr = QCPOINTERM(i);
*(pbyte *)ptr = (pbyte)OPA->_int; *(pbyte *)ptr = (pbyte)OPA->_int;
break; break;
case OP_STOREP_I16: //store short to a pointer
i = OPB->_int + (OPC->_int)*sizeof(short);
errorif (QCPOINTERWRITEFAIL(i, sizeof(short)))
{
if (!(ptr=PR_GetWriteTempStringPtr(progfuncs, OPB->_int, OPC->_int*sizeof(short), sizeof(short))))
{
if (i == -1)
break;
QCFAULT(&progfuncs->funcs, "bad pointer write in %s (%x >= %x)", PR_StringToNative(&progfuncs->funcs, prinst.pr_xfunction->s_name), i, prinst.addressableused);
}
}
else
ptr = QCPOINTERM(i);
*(short *)ptr = (short)OPA->_int;
break;
case OP_STOREF_F: case OP_STOREF_F:
case OP_STOREF_I: case OP_STOREF_I:
@ -1106,7 +1121,7 @@ reeval:
ptr = QCPOINTERM(i); ptr = QCPOINTERM(i);
OPC->_float = *(unsigned char *)ptr; OPC->_float = *(unsigned char *)ptr;
break; break;
case OP_LOADP_B: //load character from a string/pointer case OP_LOADP_U8: //load character from a string/pointer
i = (unsigned int)OPA->_int + (int)OPB->_int; i = (unsigned int)OPA->_int + (int)OPB->_int;
errorif (QCPOINTERREADFAIL(i, sizeof(pbyte))) errorif (QCPOINTERREADFAIL(i, sizeof(pbyte)))
{ {
@ -1124,6 +1139,60 @@ reeval:
ptr = QCPOINTERM(i); ptr = QCPOINTERM(i);
OPC->_int = *(pbyte *)ptr; OPC->_int = *(pbyte *)ptr;
break; break;
case OP_LOADP_I8: //load character from a string/pointer
i = (unsigned int)OPA->_int + (int)OPB->_int;
errorif (QCPOINTERREADFAIL(i, sizeof(pbyte)))
{
if (!(ptr=PR_GetReadTempStringPtr(progfuncs, OPA->_int, OPB->_int, sizeof(pbyte))))
{
if (i == -1)
{
OPC->_int = 0;
break;
}
QCFAULT(&progfuncs->funcs, "bad pointer read in %s (%i bytes into %s)", PR_StringToNative(&progfuncs->funcs, prinst.pr_xfunction->s_name), i, ptr);
}
}
else
ptr = QCPOINTERM(i);
OPC->_int = *(char *)ptr;
break;
case OP_LOADP_U16: //load character from a string/pointer
i = (unsigned int)OPA->_int + (int)OPB->_int*2;
errorif (QCPOINTERREADFAIL(i, sizeof(short)))
{
if (!(ptr=PR_GetReadTempStringPtr(progfuncs, OPA->_int, OPB->_int*2, sizeof(short))))
{
if (i == -1)
{
OPC->_int = 0;
break;
}
QCFAULT(&progfuncs->funcs, "bad pointer read in %s (%i bytes into %s)", PR_StringToNative(&progfuncs->funcs, prinst.pr_xfunction->s_name), i, ptr);
}
}
else
ptr = QCPOINTERM(i);
OPC->_int = *(unsigned short *)ptr;
break;
case OP_LOADP_I16: //load character from a string/pointer
i = (unsigned int)OPA->_int + (int)OPB->_int*2;
errorif (QCPOINTERREADFAIL(i, sizeof(short)))
{
if (!(ptr=PR_GetReadTempStringPtr(progfuncs, OPA->_int, OPB->_int*2, sizeof(short))))
{
if (i == -1)
{
OPC->_int = 0;
break;
}
QCFAULT(&progfuncs->funcs, "bad pointer read in %s (%i bytes into %s)", PR_StringToNative(&progfuncs->funcs, prinst.pr_xfunction->s_name), i, ptr);
}
}
else
ptr = QCPOINTERM(i);
OPC->_int = *(short *)ptr;
break;
case OP_LOADP_I: case OP_LOADP_I:
case OP_LOADP_F: case OP_LOADP_F:
case OP_LOADP_FLD: case OP_LOADP_FLD:
@ -1653,6 +1722,8 @@ reeval:
case OP_CONV_FI64: OPC->i64 = OPA->_float; break; case OP_CONV_FI64: OPC->i64 = OPA->_float; break;
case OP_CONV_I64D: OPC->_double = OPA->i64; break; case OP_CONV_I64D: OPC->_double = OPA->i64; break;
case OP_CONV_DI64: OPC->i64 = OPA->_double; break; case OP_CONV_DI64: OPC->i64 = OPA->_double; break;
case OP_CONV_U64D: OPC->_double = OPA->u64; break;
case OP_CONV_DU64: OPC->u64 = OPA->_double; break;
case OP_ADD_D: OPC->_double = OPA->_double + OPB->_double; break; case OP_ADD_D: OPC->_double = OPA->_double + OPB->_double; break;
case OP_SUB_D: OPC->_double = OPA->_double - OPB->_double; break; case OP_SUB_D: OPC->_double = OPA->_double - OPB->_double; break;
case OP_MUL_D: OPC->_double = OPA->_double * OPB->_double; break; case OP_MUL_D: OPC->_double = OPA->_double * OPB->_double; break;
@ -1662,8 +1733,11 @@ reeval:
case OP_EQ_D: OPC->_int = OPA->_double == OPB->_double; break; case OP_EQ_D: OPC->_int = OPA->_double == OPB->_double; break;
case OP_NE_D: OPC->_int = OPA->_double != OPB->_double; break; case OP_NE_D: OPC->_int = OPA->_double != OPB->_double; break;
case OP_BITEXTEND_I: OPC->_int = ( signed int)(OPA->_int << (32-(OPB->_uint&0xff)-(OPB->_uint>>8))) >> (32-(OPB->_uint&0xff)); break; //shift it up and down. should sign extend.
case OP_BITEXTEND_U: OPC->_uint = (unsigned int)(OPA->_uint << (32-(OPB->_uint&0xff)-(OPB->_uint>>8))) >> (32-(OPB->_uint&0xff)); break; //shift it up and down. should clear the bits.
case OP_BITCOPY_I: i=((1<<(OPB->_uint&0xff))-1);OPC->_int=(OPC->_int&~(i<<(OPB->_uint>>8)))|(((OPA->_int&i)<<(OPB->_uint>>8)));break; //replaces the specified bits (uses the same format bitextend uses to select its input to extend)
case OP_CONV_UF: OPC->_float = OPA->_uint; break;
case OP_CONV_FU: OPC->_uint = OPA->_float; break;
case OP_UNUSED: case OP_UNUSED:
case OP_POP: case OP_POP:

View file

@ -339,8 +339,8 @@ enum qcop_e {
OP_STOREF_I, //1 non-string reference/int OP_STOREF_I, //1 non-string reference/int
//r5744+ //r5744+
OP_STOREP_B,//((char*)b)[(int)c] = (int)a OP_STOREP_I8, //((char*)b)[(int)c] = (int)a
OP_LOADP_B, //(int)c = *(char*) OP_LOADP_U8, //(int)c = *(unsigned char*)
//r5768+ //r5768+
//opcodes for 32bit uints //opcodes for 32bit uints
@ -397,6 +397,18 @@ enum qcop_e {
OP_EQ_D, OP_EQ_D,
OP_NE_D, OP_NE_D,
//r6614+
OP_STOREP_I16, //((short*)b)[(int)c] = (int)a
OP_LOADP_I16, //(int)c = *(signed short*)a (sign extends)
OP_LOADP_U16, //(unsigned int)c = *(unsigned short*)a
OP_LOADP_I8, //(unsigned int)c = *(signed char*)a (sign extends)
OP_BITEXTEND_I, //sign extend (for signed bitfields)
OP_BITEXTEND_U, //zero extend (for unsigned bitfields)
OP_BITCOPY_I, //copy lower bits from the input to some part of the output
OP_CONV_UF, //OPC.f=(float)OPA.i -- 0xffffffffu*0.5=0 otherwise.
OP_CONV_FU, //OPC.i=(int)OPA.f
OP_CONV_U64D, //OPC.d=(double)OPA.u64 -- useful mostly so decompilers don't do weird stuff.
OP_CONV_DU64, //OPC.u64=(uint64_t)OPA.d
OP_NUMREALOPS, OP_NUMREALOPS,
@ -531,8 +543,8 @@ enum qcop_e {
//uint64 opcodes. they match the int32 ones so emulation is basically swapping them over. //uint64 opcodes. they match the int32 ones so emulation is basically swapping them over.
OP_BITNOT_I64, //BITXOR ~0 OP_BITNOT_I64, //BITXOR ~0
OP_BITCLR_I64, OP_BITCLR_I64,
OP_GE_I64, //LT_I64 OP_GE_I64, //LE_I64
OP_GT_I64, //LE_I64 OP_GT_I64, //LT_I64
OP_ADD_U64, OP_ADD_U64,
OP_SUB_U64, OP_SUB_U64,
@ -544,8 +556,8 @@ enum qcop_e {
OP_BITNOT_U64, //BITXOR ~0 OP_BITNOT_U64, //BITXOR ~0
OP_BITCLR_U64, OP_BITCLR_U64,
OP_LSHIFT_U64I, OP_LSHIFT_U64I,
OP_GE_U64, //LT_U64 OP_GE_U64, //LE_U64
OP_GT_U64, //LE_U64 OP_GT_U64, //LT_U64
OP_EQ_U64, OP_EQ_U64,
OP_NE_U64, OP_NE_U64,
@ -557,6 +569,8 @@ enum qcop_e {
OP_BITCLR_D, OP_BITCLR_D,
OP_LSHIFT_DI, OP_LSHIFT_DI,
OP_RSHIFT_DI, OP_RSHIFT_DI,
OP_GE_D, //LE_D
OP_GT_D, //LT_D
OP_WSTATE, //for the 'w' part of CWSTATE. will probably never be used, but hey, hexen2... OP_WSTATE, //for the 'w' part of CWSTATE. will probably never be used, but hey, hexen2...
@ -618,7 +632,12 @@ typedef struct statement32_s
typedef struct typedef struct
{ {
struct QCC_def_s *sym; struct QCC_def_s *sym;
unsigned int ofs; union
{
unsigned int ofs;
// unsigned int bofs;
signed int jumpofs;
};
struct QCC_type_s *cast; //the entire sref is considered null if there is no cast, although it *MAY* have an ofs specified if its part of a jump instruction struct QCC_type_s *cast; //the entire sref is considered null if there is no cast, although it *MAY* have an ofs specified if its part of a jump instruction
} QCC_sref_t; } QCC_sref_t;
typedef struct qcc_statement_s typedef struct qcc_statement_s

View file

@ -562,6 +562,7 @@ static int ASMCALL PR_EnterFunction (progfuncs_t *progfuncs, mfunction_t *f, int
} }
prinst.pr_xfunction = f; prinst.pr_xfunction = f;
prinst.spushed = 0;
return f->first_statement - 1; // offset the s++ return f->first_statement - 1; // offset the s++
} }
@ -1911,6 +1912,7 @@ typedef struct {
int fnum; int fnum;
int progsnum; int progsnum;
int statement; int statement;
int spushed;
} qcthreadstack_t; } qcthreadstack_t;
typedef struct qcthread_s { typedef struct qcthread_s {
int fstackdepth; int fstackdepth;
@ -1947,6 +1949,7 @@ struct qcthread_s *PDECL PR_ForkStack(pubprogfuncs_t *ppf)
thread->fstack[i-ed].fnum = prinst.pr_stack[i].f - pr_progstate[prinst.pr_stack[i].progsnum].functions; thread->fstack[i-ed].fnum = prinst.pr_stack[i].f - pr_progstate[prinst.pr_stack[i].progsnum].functions;
thread->fstack[i-ed].progsnum = prinst.pr_stack[i].progsnum; thread->fstack[i-ed].progsnum = prinst.pr_stack[i].progsnum;
thread->fstack[i-ed].statement = prinst.pr_stack[i].s; thread->fstack[i-ed].statement = prinst.pr_stack[i].s;
thread->fstack[i-ed].spushed = prinst.pr_stack[i].pushed;
if (i+1 == prinst.pr_depth) if (i+1 == prinst.pr_depth)
f = prinst.pr_xfunction; f = prinst.pr_xfunction;
@ -1996,7 +1999,7 @@ void PDECL PR_ResumeThread (pubprogfuncs_t *ppf, struct qcthread_s *thread)
{ {
progfuncs_t *progfuncs = (progfuncs_t*)ppf; progfuncs_t *progfuncs = (progfuncs_t*)ppf;
mfunction_t *f, *oldf; mfunction_t *f, *oldf;
int i,l,ls, olds; int i,l,ls, olds, oldp;
progsnum_t initial_progs; progsnum_t initial_progs;
int oldexitdepth; int oldexitdepth;
int *glob; int *glob;
@ -2033,12 +2036,14 @@ void PDECL PR_ResumeThread (pubprogfuncs_t *ppf, struct qcthread_s *thread)
prinst.pr_stack[prinst.pr_depth].f = prinst.pr_xfunction; prinst.pr_stack[prinst.pr_depth].f = prinst.pr_xfunction;
prinst.pr_stack[prinst.pr_depth].s = prinst.pr_xstatement; prinst.pr_stack[prinst.pr_depth].s = prinst.pr_xstatement;
prinst.pr_stack[prinst.pr_depth].progsnum = initial_progs; prinst.pr_stack[prinst.pr_depth].progsnum = initial_progs;
prinst.pr_stack[prinst.pr_depth].pushed = prinst.spushed;
} }
else else
{ {
prinst.pr_stack[prinst.pr_depth].progsnum = thread->fstack[i].progsnum; prinst.pr_stack[prinst.pr_depth].progsnum = thread->fstack[i].progsnum;
prinst.pr_stack[prinst.pr_depth].f = pr_progstate[thread->fstack[i].progsnum].functions + thread->fstack[i].fnum; prinst.pr_stack[prinst.pr_depth].f = pr_progstate[thread->fstack[i].progsnum].functions + thread->fstack[i].fnum;
prinst.pr_stack[prinst.pr_depth].s = thread->fstack[i].statement; prinst.pr_stack[prinst.pr_depth].s = thread->fstack[i].statement;
prinst.pr_stack[prinst.pr_depth].pushed = thread->fstack[i].spushed;
} }
if (i+1 == thread->fstackdepth) if (i+1 == thread->fstackdepth)
@ -2080,6 +2085,7 @@ void PDECL PR_ResumeThread (pubprogfuncs_t *ppf, struct qcthread_s *thread)
// PR_EnterFunction (progfuncs, f, initial_progs); // PR_EnterFunction (progfuncs, f, initial_progs);
oldf = prinst.pr_xfunction; oldf = prinst.pr_xfunction;
olds = prinst.pr_xstatement; olds = prinst.pr_xstatement;
oldp = prinst.spushed;
prinst.pr_xfunction = f; prinst.pr_xfunction = f;
s = thread->xstatement; s = thread->xstatement;
@ -2098,6 +2104,7 @@ void PDECL PR_ResumeThread (pubprogfuncs_t *ppf, struct qcthread_s *thread)
prinst.exitdepth = oldexitdepth; prinst.exitdepth = oldexitdepth;
prinst.pr_xfunction = oldf; prinst.pr_xfunction = oldf;
prinst.pr_xstatement = olds; prinst.pr_xstatement = olds;
prinst.spushed = oldp;
} }
void PDECL PR_AbortStack (pubprogfuncs_t *ppf) void PDECL PR_AbortStack (pubprogfuncs_t *ppf)

View file

@ -95,7 +95,8 @@ ev_union, //not really sure why this is separate from struct
ev_accessor,//some weird type to provide class-like functions over a basic type. ev_accessor,//some weird type to provide class-like functions over a basic type.
ev_enum, //just a numeric type ev_enum, //just a numeric type
ev_typedef, //so typedefs can refer to their original type (primarily for structs). ev_typedef, //so typedefs can refer to their original type (primarily for structs).
ev_boolean, //exists to optimise if(-0) workarounds. engine just sees int/float. ev_boolean, //exists to optimise if(-0) workarounds. engine just sees int/float. uses parentclass
ev_bitfld, //erk... structs only... converted to their parentclass on read.
} etype_t; } etype_t;
enum { enum {
DEBUG_TRACE_OFF, //debugging should be off. DEBUG_TRACE_OFF, //debugging should be off.

View file

@ -66,6 +66,12 @@ extern progfuncs_t *qccprogfuncs;
#define LIKEPRINTF(x) #define LIKEPRINTF(x)
#endif #endif
#if __STDC_VERSION__ >= 199901L
#define qc_inlinestatic static inline
#else
#define qc_inlinestatic static
#endif
void *qccHunkAlloc(size_t mem); void *qccHunkAlloc(size_t mem);
void qccClearHunk(void); void qccClearHunk(void);
@ -373,7 +379,8 @@ struct QCC_typeparam_s
pbool optional:1; //argument may safely be omitted, for builtin functions. for qc functions use the defltvalue instead. pbool optional:1; //argument may safely be omitted, for builtin functions. for qc functions use the defltvalue instead.
pbool isvirtual:1; //const, with implicit initialisation only. valid for structs pbool isvirtual:1; //const, with implicit initialisation only. valid for structs
unsigned char out; //0=in,1==inout,2=out unsigned char out; //0=in,1==inout,2=out
unsigned int ofs; //FIXME: make byte offsets, for bytes/shorts. unsigned int ofs; //word offset.
unsigned int bitofs; //for bitfields (and chars/shorts).
unsigned int arraysize; unsigned int arraysize;
char *paramname; char *paramname;
}; };
@ -403,6 +410,8 @@ typedef struct QCC_type_s
pbool typedefed:1; //name is in the typenames list. pbool typedefed:1; //name is in the typenames list.
pbool vargs:1; //function has vargs pbool vargs:1; //function has vargs
pbool vargcount:1; //function has special varg count param pbool vargcount:1; //function has special varg count param
unsigned int bits;//valid for bitfields (and structs).
unsigned int align:7;
const char *name; const char *name;
const char *aname; const char *aname;
@ -487,6 +496,7 @@ struct temp_s {
unsigned int size; unsigned int size;
struct QCC_function_s *lastfunc; struct QCC_function_s *lastfunc;
unsigned int lastline;
unsigned int laststatement; unsigned int laststatement;
}; };
extern size_t tempsused; extern size_t tempsused;
@ -506,6 +516,7 @@ typedef struct
} type; } type;
QCC_sref_t base; QCC_sref_t base;
unsigned int bitofs; //for bitfields.
QCC_sref_t index; QCC_sref_t index;
QCC_type_t *cast; //entity.float is float, not pointer. QCC_type_t *cast; //entity.float is float, not pointer.
struct accessor_s *accessor; //the accessor field of base that we're trying to use struct accessor_s *accessor; //the accessor field of base that we're trying to use
@ -526,7 +537,7 @@ extern int QCC_packid;
extern const unsigned int type_size[]; extern const unsigned int type_size[];
//extern QCC_def_t *def_for_type[9]; //extern QCC_def_t *def_for_type[9];
extern QCC_type_t *type_void, *type_string, *type_float, *type_double, *type_vector, *type_entity, *type_field, *type_function, *type_floatfunction, *type_pointer, *type_floatpointer, *type_intpointer, *type_bint, *type_bfloat, *type_integer, *type_uint, *type_int64, *type_uint64, *type_invalid, *type_variant, *type_floatfield; extern QCC_type_t *type_void, *type_string, *type_float, *type_double, *type_vector, *type_entity, *type_field, *type_function, *type_floatfunction, *type_pointer, *type_floatpointer, *type_intpointer, *type_bint, *type_bfloat, *type_sint8, *type_uint8, *type_sint16, *type_uint16, *type_integer, *type_uint, *type_int64, *type_uint64, *type_invalid, *type_variant, *type_floatfield;
extern char *basictypenames[]; extern char *basictypenames[];
struct QCC_function_s struct QCC_function_s
@ -769,7 +780,7 @@ void QCC_PR_Lex (void);
QCC_type_t *QCC_PR_NewType (const char *name, int basictype, pbool typedefed); //note: name must be hunk/immediate QCC_type_t *QCC_PR_NewType (const char *name, int basictype, pbool typedefed); //note: name must be hunk/immediate
QCC_type_t *QCC_PointerTypeTo(QCC_type_t *type); QCC_type_t *QCC_PointerTypeTo(QCC_type_t *type);
QCC_type_t *QCC_GenArrayType(QCC_type_t *type, unsigned int arraysize); QCC_type_t *QCC_GenArrayType(QCC_type_t *type, unsigned int arraysize);
QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail); QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail, pbool ignoreptr);
QCC_sref_t QCC_PR_ParseDefaultInitialiser(QCC_type_t *type); QCC_sref_t QCC_PR_ParseDefaultInitialiser(QCC_type_t *type);
extern pbool type_inlinefunction; extern pbool type_inlinefunction;
QCC_type_t *QCC_TypeForName(const char *name); QCC_type_t *QCC_TypeForName(const char *name);
@ -777,7 +788,7 @@ QCC_type_t *QCC_PR_ParseFunctionType (int newtype, QCC_type_t *returntype);
QCC_type_t *QCC_PR_ParseFunctionTypeReacc (int newtype, QCC_type_t *returntype); QCC_type_t *QCC_PR_ParseFunctionTypeReacc (int newtype, QCC_type_t *returntype);
QCC_type_t *QCC_PR_GenFunctionType (QCC_type_t *rettype, struct QCC_typeparam_s *args, int numargs); QCC_type_t *QCC_PR_GenFunctionType (QCC_type_t *rettype, struct QCC_typeparam_s *args, int numargs);
char *QCC_PR_ParseName (void); char *QCC_PR_ParseName (void);
struct QCC_typeparam_s *QCC_PR_FindStructMember(QCC_type_t *t, const char *membername, unsigned int *out_ofs); struct QCC_typeparam_s *QCC_PR_FindStructMember(QCC_type_t *t, const char *membername, unsigned int *out_ofs, unsigned int *out_bitofs);
QCC_type_t *QCC_PR_PointerType (QCC_type_t *pointsto); QCC_type_t *QCC_PR_PointerType (QCC_type_t *pointsto);
const char *QCC_VarAtOffset(QCC_sref_t ref); const char *QCC_VarAtOffset(QCC_sref_t ref);

View file

@ -39,6 +39,7 @@ const unsigned int type_size[] = {1, //void
0, //ev_enum... 0, //ev_enum...
0, //ev_typedef 0, //ev_typedef
1, //ev_bool... 1, //ev_bool...
0, //bitfld...
}; };
char *basictypenames[] = { char *basictypenames[] = {
@ -60,7 +61,9 @@ char *basictypenames[] = {
"union", "union",
"accessor", "accessor",
"enum", "enum",
"bool" "typedef",
"bool",
"bitfield",
}; };
/* /*

File diff suppressed because it is too large Load diff

View file

@ -93,9 +93,13 @@ QCC_type_t *type_field; //.void
QCC_type_t *type_function; //void() QCC_type_t *type_function; //void()
QCC_type_t *type_floatfunction; //float() QCC_type_t *type_floatfunction; //float()
QCC_type_t *type_pointer; //??? * - careful with this one QCC_type_t *type_pointer; //??? * - careful with this one
QCC_type_t *type_sint8; //char - these small types are technically ev_bitfield, but typedefed and aligned.
QCC_type_t *type_uint8; //unsigned char
QCC_type_t *type_sint16; //short
QCC_type_t *type_uint16; //unsigned short
QCC_type_t *type_integer; //int32 QCC_type_t *type_integer; //int32
QCC_type_t *type_uint; //uint32 QCC_type_t *type_uint; //uint32
QCC_type_t *type_int64; //int64 QCC_type_t *type_int64; //int64
QCC_type_t *type_uint64; //uint64 QCC_type_t *type_uint64; //uint64
QCC_type_t *type_variant; //__variant QCC_type_t *type_variant; //__variant
QCC_type_t *type_invalid; //technically void, but shouldn't really ever be used. QCC_type_t *type_invalid; //technically void, but shouldn't really ever be used.
@ -1611,8 +1615,33 @@ int QCC_PR_LexEscapedCodepoint(void)
c = '\\'; c = '\\';
else if (c == '\'') else if (c == '\'')
c = '\''; c = '\'';
else if (c >= '0' && c <= '9') //WARNING: This is not octal, but uses 'yellow' numbers instead (as on hud). else if (c >= '0' && c <= '9')
c = 0xe012 + c - '0'; {
if (flag_qcfuncs)
c = 0xe012 + c - '0'; //WARNING: This is not an octal code, but uses 'yellow' numbers instead (as on hud).
else //C compat
{
int d = c, base = 8;
c = 0;
if (d >= '0' && d < '0'+base)
c = c*base + (d - '0');
else
QCC_PR_ParseError(ERR_BADCHARACTERCODE, "Bad character code \\%c", d);
d = (unsigned char)*pr_file_p++;
if (d >= '0' && d < '0'+base)
c = c*base + (d - '0');
else
pr_file_p --; //oops. only one char valid...
d = (unsigned char)*pr_file_p++;
if (d >= '0' && d < '0'+base)
c = c*base + (d - '0');
else
pr_file_p --; //oops. only twoish chars valid...
}
}
else if (c == '\r') else if (c == '\r')
{ //sigh { //sigh
c = *pr_file_p++; c = *pr_file_p++;
@ -2081,6 +2110,7 @@ static void QCC_PR_LexNumber (void)
} }
else if (c == 'f' || c == 'F') else if (c == 'f' || c == 'F')
{ {
pr_immediate_type = type_float;
pr_file_p++; pr_file_p++;
break; break;
} }
@ -2139,7 +2169,7 @@ static void QCC_PR_LexNumber (void)
{ //length suffix was first. { //length suffix was first.
//long-long? //long-long?
if (*pr_file_p == c) if (*pr_file_p == c)
pr_token[tokenlen++] = *pr_file_p++; islong++, pr_token[tokenlen++] = *pr_file_p++;
//check for signed suffix... //check for signed suffix...
c = *pr_file_p; c = *pr_file_p;
isunsigned = (c == 'u')||(c=='U'); isunsigned = (c == 'u')||(c=='U');
@ -2157,13 +2187,13 @@ static void QCC_PR_LexNumber (void)
islong = true; islong = true;
//long-long? //long-long?
if (*pr_file_p == c) if (*pr_file_p == c)
pr_token[tokenlen++] = *pr_file_p++; islong++, pr_token[tokenlen++] = *pr_file_p++;
} }
} }
pr_token[tokenlen++] = 0; pr_token[tokenlen++] = 0;
num *= sign; num *= sign;
if (islong) if (islong >= (flag_ILP32?2:1))
{ { //enough longs for our 64bit type.
pr_immediate_type = (isunsigned)?type_uint64:type_int64; pr_immediate_type = (isunsigned)?type_uint64:type_int64;
pr_immediate.i64 = num; pr_immediate.i64 = num;
} }
@ -2190,7 +2220,16 @@ static void QCC_PR_LexNumber (void)
{ {
//float f = num; //float f = num;
if (flag_assume_integer)// || (base != 10 && sign > 0 && (long long)f != (long long)num)) if (flag_assume_integer)// || (base != 10 && sign > 0 && (long long)f != (long long)num))
pr_immediate_type = type_integer; {
if (num > UINT64_C(0x7fffffffffffffff))
pr_immediate_type = type_uint64;
else if (num > 0xffffffffu)
pr_immediate_type = type_int64;
else if (num > 0x7fffffffu)
pr_immediate_type = type_uint;
else
pr_immediate_type = type_integer;
}
else if (flag_qccx && base == 16) else if (flag_qccx && base == 16)
{ {
pr_immediate_type = type_float; pr_immediate_type = type_float;
@ -2200,9 +2239,10 @@ static void QCC_PR_LexNumber (void)
pr_immediate_type = type_float; pr_immediate_type = type_float;
} }
if (pr_immediate_type == type_integer) if (pr_immediate_type == type_int64 || pr_immediate_type == type_uint64)
pr_immediate.i64 = num*sign;
else if (pr_immediate_type == type_integer || pr_immediate_type == type_uint)
{ {
pr_immediate_type = type_integer;
qccxhex: qccxhex:
pr_immediate._int = num*sign; pr_immediate._int = num*sign;
@ -3376,12 +3416,18 @@ static char *QCC_PR_CheckBuiltinCompConst(char *constname, char *retbuf, size_t
} }
if (!strcmp(constname, "__LINE__")) if (!strcmp(constname, "__LINE__"))
{ {
QC_snprintfz(retbuf, retbufsize, "%i", pr_source_line); int line = pr_source_line;
if (currentchunk && currentchunk->cnst) //if we're in a macro, use the line the macro was on.
line = currentchunk->currentlinenumber;
QC_snprintfz(retbuf, retbufsize, "%i", line);
return retbuf; return retbuf;
} }
if (!strcmp(constname, "__LINESTR__")) if (!strcmp(constname, "__LINESTR__"))
{ {
QC_snprintfz(retbuf, retbufsize, "\"%i\"", pr_source_line); int line = pr_source_line;
if (currentchunk && currentchunk->cnst) //if we're in a macro, use the line the macro was on.
line = currentchunk->currentlinenumber;
QC_snprintfz(retbuf, retbufsize, "\"%i\"", line);
return retbuf; return retbuf;
} }
if (!strcmp(constname, "__FUNC__") || !strcmp(constname, "__func__")) if (!strcmp(constname, "__FUNC__") || !strcmp(constname, "__func__"))
@ -4252,7 +4298,17 @@ Gets the next token
void QCC_PR_Expect (const char *string) void QCC_PR_Expect (const char *string)
{ {
if (STRCMP (string, pr_token)) if (STRCMP (string, pr_token))
QCC_PR_ParseError (ERR_EXPECTED, "expected %s%s%s, found %s%s%s", col_location, string, col_none, col_name, pr_token, col_none); {
if (pr_token_type == tt_immediate && pr_immediate_type == type_string)
{
if (pr_immediate_strlen > 32)
QCC_PR_ParseError (ERR_EXPECTED, "expected %s%s%s, found string immediate", col_location, string, col_none);
else
QCC_PR_ParseError (ERR_EXPECTED, "expected %s%s%s, found %s\"%s\"%s", col_location, string, col_none, col_name, pr_token, col_none);
}
else
QCC_PR_ParseError (ERR_EXPECTED, "expected %s%s%s, found %s%s%s", col_location, string, col_none, col_name, pr_token, col_none);
}
QCC_PR_Lex (); QCC_PR_Lex ();
} }
#endif #endif
@ -4530,7 +4586,7 @@ static int typecmp_strict(QCC_type_t *a, QCC_type_t *b)
if (a->vargcount != b->vargcount) if (a->vargcount != b->vargcount)
return 1; return 1;
if (a->size != b->size) if (a->size != b->size || a->bits != b->bits || a->align != b->align)
return 1; return 1;
if (a->accessors != b->accessors) if (a->accessors != b->accessors)
@ -4579,7 +4635,7 @@ int typecmp(QCC_type_t *a, QCC_type_t *b)
if (a->vargcount != b->vargcount) if (a->vargcount != b->vargcount)
return 1; return 1;
if (a->size != b->size) if (a->size != b->size || a->bits != b->bits)
return 1; return 1;
if ((a->type == ev_entity && a->parentclass) || a->type == ev_struct || a->type == ev_union) if ((a->type == ev_entity && a->parentclass) || a->type == ev_struct || a->type == ev_union)
@ -4957,6 +5013,10 @@ void QCC_PR_SkipToSemicolon (void)
} while (pr_token_type != tt_eof); } while (pr_token_type != tt_eof);
} }
qc_inlinestatic QCC_eval_t *QCC_SRef_Data(QCC_sref_t ref)
{
return (QCC_eval_t*)&ref.sym->symboldata[ref.ofs];
}
/* /*
============ ============
@ -5033,7 +5093,7 @@ QCC_type_t *QCC_PR_ParseFunctionType (int newtype, QCC_type_t *returntype)
if (QCC_PR_CheckToken ("...")) if (QCC_PR_CheckToken ("..."))
{ {
t = QCC_PR_ParseType(false, true); //the evil things I do... t = QCC_PR_ParseType(false, true, false); //the evil things I do...
if (!t) if (!t)
{ {
ftype->vargs = true; ftype->vargs = true;
@ -5078,7 +5138,7 @@ QCC_type_t *QCC_PR_ParseFunctionType (int newtype, QCC_type_t *returntype)
break; break;
} }
t = QCC_PR_ParseType(false, false); t = QCC_PR_ParseType(false, false, false);
} }
paramlist[numparms].defltvalue.cast = NULL; paramlist[numparms].defltvalue.cast = NULL;
paramlist[numparms].ofs = 0; paramlist[numparms].ofs = 0;
@ -5225,7 +5285,7 @@ QCC_type_t *QCC_PR_ParseFunctionTypeReacc (int newtype, QCC_type_t *returntype)
{ {
name = QCC_PR_ParseName(); name = QCC_PR_ParseName();
QCC_PR_Expect(":"); QCC_PR_Expect(":");
nptype = QCC_PR_ParseType(true, false); nptype = QCC_PR_ParseType(true, false, false);
} }
if (!nptype) if (!nptype)
@ -5238,6 +5298,7 @@ QCC_type_t *QCC_PR_ParseFunctionTypeReacc (int newtype, QCC_type_t *returntype)
paramlist[numparms].optional = false; paramlist[numparms].optional = false;
paramlist[numparms].isvirtual = false; paramlist[numparms].isvirtual = false;
paramlist[numparms].ofs = 0; paramlist[numparms].ofs = 0;
paramlist[numparms].bitofs = 0;
paramlist[numparms].arraysize = 0; paramlist[numparms].arraysize = 0;
paramlist[numparms].type = nptype; paramlist[numparms].type = nptype;
@ -5437,7 +5498,7 @@ struct accessor_s *QCC_PR_ParseAccessorMember(QCC_type_t *classtype, pbool isinl
f = QCC_PR_ParseImmediateStatements (def.sym, functype, false); f = QCC_PR_ParseImmediateStatements (def.sym, functype, false);
pr_classtype = NULL; pr_classtype = NULL;
pr_scope = NULL; pr_scope = NULL;
def.sym->symboldata[def.ofs].function = f - functions; QCC_SRef_Data(def)->function = f - functions;
f->def = def.sym; f->def = def.sym;
def.sym->initialized = 1; def.sym->initialized = 1;
} }
@ -5495,7 +5556,7 @@ static QCC_type_t *QCC_PR_ParseStruct(etype_t structtype)
QCC_type_t *newt, *type, *newparm; QCC_type_t *newt, *type, *newparm;
struct QCC_typeparam_s *parms = NULL, *oldparm; struct QCC_typeparam_s *parms = NULL, *oldparm;
int numparms = 0; int numparms = 0;
int ofs; int ofs, bitofs;
unsigned int arraysize; unsigned int arraysize;
char *parmname; char *parmname;
@ -5503,6 +5564,8 @@ static QCC_type_t *QCC_PR_ParseStruct(etype_t structtype)
pbool isstatic = false; pbool isstatic = false;
pbool isvirt = false; pbool isvirt = false;
pbool definedsomething = false; pbool definedsomething = false;
unsigned int bitsize;
unsigned int bitalign = 0; //alignment of largest element...
if (QCC_PR_CheckToken("{")) if (QCC_PR_CheckToken("{"))
{ {
@ -5555,6 +5618,7 @@ static QCC_type_t *QCC_PR_ParseStruct(etype_t structtype)
newt->size = newt->parentclass->size; newt->size = newt->parentclass->size;
else else
newt->size=0; newt->size=0;
bitsize = newt->size<<5;
type = NULL; type = NULL;
@ -5624,7 +5688,7 @@ static QCC_type_t *QCC_PR_ParseStruct(etype_t structtype)
// isignored = true; // isignored = true;
//now parse the actual type. //now parse the actual type.
newparm = QCC_PR_ParseType(false, false); newparm = QCC_PR_ParseType(false, false, true);
definedsomething = false; definedsomething = false;
} }
type = newparm; type = newparm;
@ -5679,8 +5743,26 @@ static QCC_type_t *QCC_PR_ParseStruct(etype_t structtype)
if (QCC_PR_CheckToken(":")) if (QCC_PR_CheckToken(":"))
{ {
QCC_PR_IntConstExpr(); int bits = QCC_PR_IntConstExpr();
QCC_PR_ParseWarning(WARN_IGNOREDKEYWORD, "bitfields are not supported"); if (bits > 64)
QCC_PR_ParseWarning(ERR_BADNOTTYPE, "too many bits");
else if (type->type == ev_integer || type->type == ev_uint || type->type == ev_int64 || type->type == ev_uint64)
{
QCC_type_t *bitfld;
//prmote to bigger if big.
if (bits > 32 && type->type == ev_integer)
type = type_int64;
if (bits > 32 && type->type == ev_uint)
type = type_uint64;
bitfld = QCC_PR_NewType("bitfld", ev_bitfld, false);
bitfld->bits = bits;
bitfld->size = type->size;
bitfld->parentclass = type;
bitfld->align = type->align; //use the parent's alignment, for some reason.
type = bitfld;
}
else
QCC_PR_ParseWarning(ERR_BADNOTTYPE, "bitfields must be integer types");
} }
if ((isnonvirt || isvirt) && type->type != ev_function) if ((isnonvirt || isvirt) && type->type != ev_function)
@ -5727,25 +5809,59 @@ static QCC_type_t *QCC_PR_ParseStruct(etype_t structtype)
} }
parms = realloc(parms, sizeof(*parms) * (numparms+4)); parms = realloc(parms, sizeof(*parms) * (numparms+4));
oldparm = QCC_PR_FindStructMember(newt, parmname, &ofs); oldparm = QCC_PR_FindStructMember(newt, parmname, &ofs, &bitofs);
if (type->align)
{
if (bitalign < type->align)
bitalign = type->align; //bigger than that...
}
else
bitalign = 32; //struct must be word aligned.
if (oldparm && oldparm->arraysize == arraysize && !typecmp_lax(oldparm->type, type)) if (oldparm && oldparm->arraysize == arraysize && !typecmp_lax(oldparm->type, type))
{ {
ofs <<= 5;
ofs += bitofs;
if (!isvirt) if (!isvirt)
continue; continue;
} }
else if (structtype == ev_union) else if (structtype == ev_union)
{ {
ofs = 0; ofs = 0;
if (type->size*(arraysize?arraysize:1) > newt->size) if (type->bits)
newt->size = type->size*(arraysize?arraysize:1); {
if (bitsize < type->bits*(arraysize?arraysize:1))
bitsize = type->bits*(arraysize?arraysize:1);
}
else
{
if (bitsize < 32*type->size*(arraysize?arraysize:1))
bitsize = 32*type->size*(arraysize?arraysize:1);
}
} }
else else
{ {
ofs = newt->size; if (type->bits)
newt->size += type->size*(arraysize?arraysize:1); {
if (type->bits < type->align && type->type == ev_bitfld)
{ //only realigns when it cross its parent's alignment boundary.
if ((bitsize&(type->align-1)) + type->bits > type->align)
bitsize = (bitsize+type->align-1)&~(type->align-1); //these must be aligned, so we can take pointers etc.
}
else if (type->align)
bitsize = (bitsize+type->align-1)&~(type->align-1); //these must be aligned, so we can take pointers etc.
ofs = bitsize;
bitsize += type->bits*(arraysize?arraysize:1);
}
else
{
bitsize = (bitsize+31)&~31; //provide padding to keep non-bitfield stuff word aligned
ofs = bitsize;
bitsize += 32 * type->size*(arraysize?arraysize:1);
}
} }
parms[numparms].ofs = ofs; parms[numparms].ofs = ofs>>5;
parms[numparms].bitofs = ofs - (parms[numparms].ofs<<5);
parms[numparms].arraysize = arraysize; parms[numparms].arraysize = arraysize;
parms[numparms].out = false; parms[numparms].out = false;
parms[numparms].optional = false; parms[numparms].optional = false;
@ -5756,7 +5872,7 @@ static QCC_type_t *QCC_PR_ParseStruct(etype_t structtype)
numparms++; numparms++;
/*if (type->type == ev_vector && arraysize == 0) /*if (type->type == ev_vector && arraysize == 0)
{ //add in vec_x/y/z members too. { //add in vec_x/y/z members too...?
int c; int c;
for (c = 0; c < 3; c++) for (c = 0; c < 3; c++)
{ {
@ -5773,6 +5889,17 @@ static QCC_type_t *QCC_PR_ParseStruct(etype_t structtype)
} }
}*/ }*/
} }
if (bitalign) //compute tail padding.
bitsize = (bitsize+bitalign-1)&~(bitalign-1);
newt->size = (bitsize+31)>>5; //FIXME: change to bytes, for pointers.
newt->align = bitalign;
if (bitalign&31)
newt->bits = bitsize;
else
newt->bits = 0; //all word aligned. nothing special going on sizewise (maybe inside though).
if (!numparms) if (!numparms)
QCC_PR_ParseError(ERR_NOTANAME, "%s %s has no members", structtype==ev_union?"union":"struct", newt->name); QCC_PR_ParseError(ERR_NOTANAME, "%s %s has no members", structtype==ev_union?"union":"struct", newt->name);
@ -5942,7 +6069,7 @@ QCC_type_t *QCC_PR_ParseEntClass(void)
continue; continue;
} }
basetype = QCC_PR_ParseType(false, false); basetype = QCC_PR_ParseType(false, false, false);
if (!basetype) if (!basetype)
QCC_PR_ParseError(ERR_INTERNAL, "In class %s, expected type, found %s", classname, pr_token); QCC_PR_ParseError(ERR_INTERNAL, "In class %s, expected type, found %s", classname, pr_token);
@ -6187,6 +6314,7 @@ QCC_type_t *QCC_PR_ParseEntClass(void)
parms = realloc(parms, sizeof(*parms) * (numparms+1)); parms = realloc(parms, sizeof(*parms) * (numparms+1));
parms[numparms].ofs = 0; parms[numparms].ofs = 0;
parms[numparms].bitofs = 0;
parms[numparms].out = false; parms[numparms].out = false;
parms[numparms].optional = false; parms[numparms].optional = false;
parms[numparms].isvirtual = isvirt; parms[numparms].isvirtual = isvirt;
@ -6376,7 +6504,7 @@ pbool type_inlinefunction;
/*newtype=true: creates a new type always /*newtype=true: creates a new type always
silentfail=true: function is permitted to return NULL if it was not given a type, otherwise never returns NULL silentfail=true: function is permitted to return NULL if it was not given a type, otherwise never returns NULL
*/ */
QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail) QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail, pbool ignoreptr)
{ {
QCC_type_t *newt; QCC_type_t *newt;
QCC_type_t *type; QCC_type_t *type;
@ -6404,7 +6532,7 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
QCC_PR_Lex (); QCC_PR_Lex ();
type = QCC_PR_NewType("FIELD_TYPE", ev_field, false); type = QCC_PR_NewType("FIELD_TYPE", ev_field, false);
type->aux_type = QCC_PR_ParseType (false, false); type->aux_type = QCC_PR_ParseType (false, false, ignoreptr);
type->size = type->aux_type->size; type->size = type->aux_type->size;
newt = QCC_PR_FindType (type); newt = QCC_PR_FindType (type);
@ -6424,7 +6552,7 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
if (QCC_PR_CheckToken ("..")) //so we don't end up with the user specifying '. .vector blah' (hexen2 added the .. token for array ranges) if (QCC_PR_CheckToken ("..")) //so we don't end up with the user specifying '. .vector blah' (hexen2 added the .. token for array ranges)
{ {
newt = QCC_PR_NewType("FIELD_TYPE", ev_field, false); newt = QCC_PR_NewType("FIELD_TYPE", ev_field, false);
newt->aux_type = QCC_PR_ParseType (false, false); newt->aux_type = QCC_PR_ParseType (false, false, ignoreptr);
newt->size = newt->aux_type->size; newt->size = newt->aux_type->size;
@ -6448,7 +6576,7 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
//however, we can't cope parsing that with regular types, so we support that ONLY when . was already specified. //however, we can't cope parsing that with regular types, so we support that ONLY when . was already specified.
//this is pretty much an evil syntax hack. //this is pretty much an evil syntax hack.
pbool ptr = QCC_PR_CheckToken ("*"); pbool ptr = QCC_PR_CheckToken ("*");
type = QCC_PR_ParseType(false, false); type = QCC_PR_ParseType(false, false, ignoreptr);
if (!type) if (!type)
QCC_PR_ParseError(0, "Expected type\n"); QCC_PR_ParseError(0, "Expected type\n");
if (ptr) if (ptr)
@ -6496,7 +6624,7 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
if (QCC_PR_CheckToken(":")) if (QCC_PR_CheckToken(":"))
{ {
type = QCC_PR_ParseType(false, false); type = QCC_PR_ParseType(false, false, false);
if (type) if (type)
TypeName(type, parentname, sizeof(parentname)); TypeName(type, parentname, sizeof(parentname));
else else
@ -6667,9 +6795,9 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
else if (bits > 32) else if (bits > 32)
type = (isunsigned?type_uint64:type_int64); type = (isunsigned?type_uint64:type_int64);
else if (bits <= 8) else if (bits <= 8)
type = (isunsigned?type_uint:type_integer), QCC_PR_ParseWarning (WARN_IGNOREDKEYWORD, "chars are not supported, using int"); //permitted type = (isunsigned?type_uint8:type_sint8);
else if (bits <= 16) else if (bits <= 16)
type = (isunsigned?type_uint:type_integer), QCC_PR_ParseWarning (WARN_IGNOREDKEYWORD, "shorts are not supported, using int"); //permitted type = (isunsigned?type_uint16:type_sint16);
else else
type = (isunsigned?type_uint:type_integer); type = (isunsigned?type_uint:type_integer);
} }
@ -6689,11 +6817,14 @@ wasctype:
if (!type) if (!type)
return NULL; return NULL;
while (QCC_PR_CheckToken("*")) if (!ignoreptr)
{ {
if (QCC_PR_CheckKeyword(keyword_const, "const")) while (QCC_PR_CheckToken("*"))
QCC_PR_ParseWarning (WARN_IGNOREDKEYWORD, "ignoring unsupported const keyword"); {
type = QCC_PointerTypeTo(type); if (QCC_PR_CheckKeyword(keyword_const, "const"))
QCC_PR_ParseWarning (WARN_IGNOREDKEYWORD, "ignoring unsupported const keyword");
type = QCC_PointerTypeTo(type);
}
} }
if (flag_qcfuncs && QCC_PR_CheckToken ("(")) //this is followed by parameters. Must be a function. if (flag_qcfuncs && QCC_PR_CheckToken ("(")) //this is followed by parameters. Must be a function.

View file

@ -1372,7 +1372,7 @@ static void QCC_FinaliseDef(QCC_def_t *def)
} }
if (def->symbolheader != def) if (def->symbolheader != def)
{ { //finalise the parent/root symbol first.
def->symbolheader->used |= def->used; def->symbolheader->used |= def->used;
QCC_FinaliseDef(def->symbolheader); QCC_FinaliseDef(def->symbolheader);
def->referenced = true; def->referenced = true;
@ -1474,11 +1474,6 @@ static void QCC_FinaliseDef(QCC_def_t *def)
} }
else else
{ {
/* globalspertype[def->type->type].size += def->symbolsize;
globalspertype[def->type->type].entries += 1;
globalspertype[def->type->type].vars += !def->constant;
globalspertype[def->type->type].consts += def->constant;
*/
if (def->ofs) if (def->ofs)
{ {
if (def->symbolheader == def) if (def->symbolheader == def)
@ -1529,22 +1524,41 @@ static void QCC_FinaliseDef(QCC_def_t *def)
def->reloc->used = true; def->reloc->used = true;
QCC_FinaliseDef(def->reloc); QCC_FinaliseDef(def->reloc);
if (def->type->type == ev_function/*misordered inits/copies*/ || def->type->type == ev_integer/*dp-style global index*/) if (def->type->type == ev_function/*misordered inits/copies*/ || def->type->type == ev_integer/*dp-style global index*/)
qcc_pr_globals[def->ofs]._int += qcc_pr_globals[def->reloc->ofs]._int; {
//printf("func Reloc %s %s@%i==%x -> %s@%i==%x==%s\n", def->symbolheader->name, def->name,def->ofs, def->symboldata->_int, def->reloc->name,def->reloc->ofs, def->reloc->symboldata->_int, functions[def->reloc->symboldata->_int].name);
def->symboldata->_int += def->reloc->symboldata->_int;
}
else if (def->type->type == ev_pointer/*signal to the engine to fix up the offset*/) else if (def->type->type == ev_pointer/*signal to the engine to fix up the offset*/)
{ {
if (qcc_pr_globals[def->ofs]._int & 0x80000000) //printf("Reloc %s %s@%i==%x -> %s@%i==%x\n", def->symbolheader->name, def->name,def->ofs, def->symboldata->_int, def->reloc->name,def->reloc->ofs, def->symboldata->_int+def->reloc->ofs*VMWORDSIZE);
QCC_Error(ERR_INTERNAL, "dupe reloc, type... %s", def->type->name); if (def->symboldata->_int & 0x80000000)
else if (flag_undefwordsize) QCC_PR_ParseWarning(0, "dupe reloc, %s", def->type->name);
QCC_PR_ParseWarning(ERR_BADEXTENSION, "pointer relocs are disabled for this target."); else
qcc_pr_globals[def->ofs]._int += def->reloc->ofs; {
qcc_pr_globals[def->ofs]._int *= VMWORDSIZE; if (flag_undefwordsize)
QCC_PR_ParseWarning(ERR_BADEXTENSION, "pointer relocs are disabled for this target.");
def->symboldata->_int += def->reloc->ofs*VMWORDSIZE;
qcc_pr_globals[def->ofs]._int |= 0x80000000; def->symboldata->_int |= 0x80000000; //we're using this as a hint to the engine to let it know that there's no dupes.
}
} }
else else
QCC_Error(ERR_INTERNAL, "unknown reloc type... %s", def->type->name); QCC_Error(ERR_INTERNAL, "unknown reloc type... %s", def->type->name);
} }
{
QCC_def_t *prev, *sub;
for (prev = def, sub = prev->next; sub && prev != def->deftail; sub = (prev=sub)->next)
{
if (sub->reloc && !sub->used)
{ //make sure any children are finalised properly if they're relocs.
sub->used = true;
sub->referenced = true;
QCC_FinaliseDef(sub);
}
}
}
#ifdef DEBUG_DUMP_GLOBALMAP #ifdef DEBUG_DUMP_GLOBALMAP
if (!def->referenced) if (!def->referenced)
externs->Printf("Unreferenced "); externs->Printf("Unreferenced ");
@ -2160,7 +2174,7 @@ static pbool QCC_WriteData (int crc)
if (def->symbolheader->used) if (def->symbolheader->used)
{ {
char typestr[256]; char typestr[256];
QCC_sref_t sr = {def, 0, def->type}; QCC_sref_t sr = {def, {0}, def->type};
QCC_PR_Warning(WARN_NOTREFERENCED, def->filen, def->s_line, "%s %s%s%s = %s used, but not referenced.", TypeName(def->type, typestr, sizeof(typestr)), col_symbol, def->name, col_none, QCC_VarAtOffset(sr)); QCC_PR_Warning(WARN_NOTREFERENCED, def->filen, def->s_line, "%s %s%s%s = %s used, but not referenced.", TypeName(def->type, typestr, sizeof(typestr)), col_symbol, def->name, col_none, QCC_VarAtOffset(sr));
} }
/*if (opt_unreferenced && def->type->type != ev_field) /*if (opt_unreferenced && def->type->type != ev_field)
@ -2224,7 +2238,7 @@ static pbool QCC_WriteData (int crc)
def->name = ""; //reloc, can't strip it (engine needs to fix em up), but can clear its name. def->name = ""; //reloc, can't strip it (engine needs to fix em up), but can clear its name.
else if (def->scope && !def->scope->privatelocals && !def->isstatic) else if (def->scope && !def->scope->privatelocals && !def->isstatic)
continue; //def is a local, which got shared and should be 0... continue; //def is a local, which got shared and should be 0...
else if ((def->scope||def->constant||flag_noreflection) && (def->type->type != ev_string || (strncmp(def->name, "dotranslate_", 12) && opt_constant_names_strings))) else if ((def->scope||def->constant||(flag_noreflection&&strncmp(def->name, "autocvar_", 9))) && (def->type->type != ev_string || (strncmp(def->name, "dotranslate_", 12) && opt_constant_names_strings)))
{ {
if (opt_constant_names) if (opt_constant_names)
{ {
@ -3580,6 +3594,7 @@ QCC_type_t *QCC_PR_NewType (const char *name, int basictype, pbool typedefed)
qcc_typeinfo[numtypeinfos].params = NULL; qcc_typeinfo[numtypeinfos].params = NULL;
qcc_typeinfo[numtypeinfos].size = type_size[basictype]; qcc_typeinfo[numtypeinfos].size = type_size[basictype];
qcc_typeinfo[numtypeinfos].typedefed = typedefed; qcc_typeinfo[numtypeinfos].typedefed = typedefed;
qcc_typeinfo[numtypeinfos].align = 32; //assume this alignment for now. some types allow tighter alignment, though mostly only in structs.
qcc_typeinfo[numtypeinfos].filen = s_filen; qcc_typeinfo[numtypeinfos].filen = s_filen;
qcc_typeinfo[numtypeinfos].line = pr_source_line; qcc_typeinfo[numtypeinfos].line = pr_source_line;
@ -3621,22 +3636,27 @@ static void QCC_PR_BeginCompilation (void *memory, int memsize)
*/ */
type_void = QCC_PR_NewType("void", ev_void, true); type_void = QCC_PR_NewType("void", ev_void, true);
type_string = QCC_PR_NewType("string", ev_string, true); type_string = QCC_PR_NewType(flag_qcfuncs?"string":"__string", ev_string, true);
type_float = QCC_PR_NewType("float", ev_float, true); type_float = QCC_PR_NewType("float", ev_float, true);
type_double = QCC_PR_NewType("__double", ev_double, true); type_double = QCC_PR_NewType("__double", ev_double, true);
type_vector = QCC_PR_NewType("vector", ev_vector, true); type_vector = QCC_PR_NewType(flag_qcfuncs?"vector":"__vector", ev_vector, true);
type_entity = QCC_PR_NewType("entity", ev_entity, true); type_entity = QCC_PR_NewType(flag_qcfuncs?"entity":"__entity", ev_entity, true);
type_field = QCC_PR_NewType("__field", ev_field, false); type_field = QCC_PR_NewType("__field", ev_field, false);
type_field->aux_type = type_void; type_field->aux_type = type_void;
type_function = QCC_PR_NewType("__function", ev_function, false); type_function = QCC_PR_NewType("__function", ev_function, false);
type_function->aux_type = type_void; type_function->aux_type = type_void;
type_pointer = QCC_PR_NewType("__pointer", ev_pointer, false); type_pointer = QCC_PR_NewType("__pointer", ev_pointer, false);
type_integer = QCC_PR_NewType("__int", ev_integer, true); type_integer = QCC_PR_NewType("__int32", ev_integer, true);
type_uint = QCC_PR_NewType("__uint", ev_uint, true); type_uint = QCC_PR_NewType("__uint32", ev_uint, true);
type_int64 = QCC_PR_NewType("__int64", ev_int64, true); type_int64 = QCC_PR_NewType("__int64", ev_int64, true);
type_uint64 = QCC_PR_NewType("__uint64", ev_uint64, true); type_uint64 = QCC_PR_NewType("__uint64", ev_uint64, true);
type_variant = QCC_PR_NewType("__variant", ev_variant, true); type_variant = QCC_PR_NewType("__variant", ev_variant, true);
type_sint8 = QCC_PR_NewType("__int8", ev_bitfld, true); type_sint8 ->parentclass = type_integer; type_sint8 ->size = type_sint8 ->parentclass->size; type_sint8 ->align = type_sint8 ->bits = 8;
type_uint8 = QCC_PR_NewType("__uint8", ev_bitfld, true); type_uint8 ->parentclass = type_uint; type_uint8 ->size = type_uint8 ->parentclass->size; type_uint8 ->align = type_uint8 ->bits = 8;
type_sint16 = QCC_PR_NewType("__int16", ev_bitfld, true); type_sint16->parentclass = type_integer; type_sint16->size = type_sint16->parentclass->size; type_sint16->align = type_sint16->bits = 16;
type_uint16 = QCC_PR_NewType("__uint16", ev_bitfld, true); type_uint16->parentclass = type_uint; type_uint16->size = type_uint16->parentclass->size; type_uint16->align = type_uint16->bits = 16;
type_invalid = QCC_PR_NewType("invalid", ev_void, false); type_invalid = QCC_PR_NewType("invalid", ev_void, false);
type_floatfield = QCC_PR_NewType("__fieldfloat", ev_field, false); type_floatfield = QCC_PR_NewType("__fieldfloat", ev_field, false);
@ -3650,10 +3670,8 @@ static void QCC_PR_BeginCompilation (void *memory, int memsize)
type_floatfunction = QCC_PR_NewType("__floatfunction", ev_function, false); type_floatfunction = QCC_PR_NewType("__floatfunction", ev_function, false);
type_floatfunction->aux_type = type_float; type_floatfunction->aux_type = type_float;
type_bfloat = QCC_PR_NewType("__bfloat", ev_boolean, true); type_bfloat = QCC_PR_NewType("__bfloat", ev_boolean, true); type_bfloat->parentclass = type_float; //has value 0.0 or 1.0
type_bfloat->parentclass = type_float; type_bint = QCC_PR_NewType("__bint", ev_boolean, true); type_bint->parentclass = type_uint; //has value 0 or 1
type_bint = QCC_PR_NewType("__bint", ev_boolean, true);
type_bint->parentclass = type_uint;
//type_field->aux_type = type_float; //type_field->aux_type = type_float;
@ -3662,6 +3680,11 @@ static void QCC_PR_BeginCompilation (void *memory, int memsize)
// QCC_PR_NewType("__int", ev_integer, keyword_integer?true:false); // QCC_PR_NewType("__int", ev_integer, keyword_integer?true:false);
QCC_PR_NewType("variant", ev_variant, true); QCC_PR_NewType("variant", ev_variant, true);
if (*type_string->name != '_') QCC_PR_NewType("__string", ev_string, true); //make sure some core types __string always work with a double-underscore prefix
if (*type_vector->name != '_') QCC_PR_NewType("__vector", ev_vector, true); //make sure some core types __string always work with a double-underscore prefix
if (*type_entity->name != '_') QCC_PR_NewType("__entity", ev_entity, true); //make sure some core types __string always work with a double-underscore prefix
QCC_PR_NewType("__int", ev_integer, true);
QCC_PR_NewType("__uint", ev_uint, true);
@ -4684,6 +4707,7 @@ static void QCC_PR_CommandLinePrecompilerOptions (void)
flag_assume_double = true; //and any immediates with a decimal points are assumed to be doubles, consistent with C. flag_assume_double = true; //and any immediates with a decimal points are assumed to be doubles, consistent with C.
flag_qcfuncs = false; //there's a few parsing quirks where our attempt to parse qc functions will misparse valid C. flag_qcfuncs = false; //there's a few parsing quirks where our attempt to parse qc functions will misparse valid C.
flag_macroinstrings = false;//hacky preqcc hack. flag_macroinstrings = false;//hacky preqcc hack.
flag_boundchecks = false; //nope... not C's style.
qccwarningaction[WARN_UNINITIALIZED] = WA_WARN; //C doesn't like that, might as well warn here too. qccwarningaction[WARN_UNINITIALIZED] = WA_WARN; //C doesn't like that, might as well warn here too.
qccwarningaction[WARN_TOOMANYPARAMS] = WA_ERROR; //too many args to function is weeeeird. qccwarningaction[WARN_TOOMANYPARAMS] = WA_ERROR; //too many args to function is weeeeird.
@ -4706,6 +4730,8 @@ static void QCC_PR_CommandLinePrecompilerOptions (void)
val = "201112L"; val = "201112L";
else if (!stricmp(myargv[i]+5, "c17")) else if (!stricmp(myargv[i]+5, "c17"))
val = "201710L"; val = "201710L";
else if (!stricmp(myargv[i]+5, "c23"))
val = "202311L";
else else
val = NULL; val = NULL;
cnst = QCC_PR_DefineName("__STDC_VERSION__"); cnst = QCC_PR_DefineName("__STDC_VERSION__");
@ -5448,7 +5474,7 @@ pbool QCC_main (int argc, const char **argv) //as part of the quake engine
for (p = 0; compiler_flag[p].enabled; p++) for (p = 0; compiler_flag[p].enabled; p++)
{ {
*compiler_flag[p].enabled = compiler_flag[p].flags & FLAG_ASDEFAULT; *compiler_flag[p].enabled = !!(compiler_flag[p].flags & FLAG_ASDEFAULT);
} }
parseonly = autoprototyped = autoprototype = false; parseonly = autoprototyped = autoprototype = false;

View file

@ -13418,8 +13418,8 @@ void PR_DumpPlatform_f(void)
#define globalfloat(need,name) {#name, "float", QW|NQ, "ssqc global"}, #define globalfloat(need,name) {#name, "float", QW|NQ, "ssqc global"},
#define globalentity(need,name) {#name, "entity", QW|NQ, "ssqc global"}, #define globalentity(need,name) {#name, "entity", QW|NQ, "ssqc global"},
#define globalint(need,name) {#name, "int", QW|NQ, "ssqc global"}, #define globalint(need,name) {#name, "int", QW|NQ, "ssqc global"},
#define globaluint(need,name) {#name, "unsigned int", QW|NQ, "ssqc global"}, #define globaluint(need,name) {#name, "__uint", QW|NQ, "ssqc global"},
#define globaluint64(need,name) {#name, "unsigned __long", QW|NQ, "ssqc global"}, #define globaluint64(need,name) {#name, "__uint64", QW|NQ, "ssqc global"},
#define globalstring(need,name) {#name, "string", QW|NQ, "ssqc global"}, #define globalstring(need,name) {#name, "string", QW|NQ, "ssqc global"},
#define globalvec(need,name) {#name, "vector", QW|NQ, "ssqc global"}, #define globalvec(need,name) {#name, "vector", QW|NQ, "ssqc global"},
#define globalfunc(need,name,typestr) {#name, typestr, QW|NQ, "ssqc global"}, #define globalfunc(need,name,typestr) {#name, typestr, QW|NQ, "ssqc global"},
@ -13440,8 +13440,8 @@ void PR_DumpPlatform_f(void)
#define globalvector(name) {#name, "vector", CS}, #define globalvector(name) {#name, "vector", CS},
#define globalstring(name) {#name, "string", CS}, #define globalstring(name) {#name, "string", CS},
#define globalint(name) {#name, "int", CS}, #define globalint(name) {#name, "int", CS},
#define globaluint(name) {#name, "unsigned int", CS}, #define globaluint(name) {#name, "__uint", CS},
#define globaluint64(name) {#name, "unsigned __long", CS}, #define globaluint64(name) {#name, "__uint64", CS},
csqcglobals csqcglobals
#undef globalfunction #undef globalfunction
#undef globalfloat #undef globalfloat