Fix up our support for _Bool.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@6268 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2022-06-19 15:18:00 +00:00
parent d7454f4f78
commit 8faf8a7e96
4 changed files with 280 additions and 95 deletions

View File

@ -394,6 +394,7 @@ typedef struct QCC_type_s
struct accessor_s *accessors;
struct QCC_function_s *scope; //stoopid scoped typedefs...
struct QCC_type_s *ptrto; //(cache) this points to a type that is a pointer back to this type. yeah, weird.
struct QCC_type_s *fldto; //(cache) this points to a type that is a pointer back to this type. yeah, weird.
} QCC_type_t;

View File

@ -697,7 +697,7 @@ QCC_opcode_t pr_opcodes[] =
{7, "-", "SUB_I64", PC_ADDSUB, ASSOC_LEFT, &type_int64, &type_int64, &type_int64, OPF_STD},
{7, "*", "MUL_I64", PC_MULDIV, ASSOC_LEFT, &type_int64, &type_int64, &type_int64, OPF_STD},
{7, "/", "DIV_I64", PC_MULDIV, ASSOC_LEFT, &type_int64, &type_int64, &type_int64, OPF_STD},
{7, "&", "BITAND_L", PC_BITAND, ASSOC_LEFT, &type_int64, &type_int64, &type_int64, OPF_STD},
{7, "&", "BITAND_I64", PC_BITAND, ASSOC_LEFT, &type_int64, &type_int64, &type_int64, OPF_STD},
{7, "|", "BITOR_I64", PC_BITOR, ASSOC_LEFT, &type_int64, &type_int64, &type_int64, OPF_STD},
{7, "^", "BITXOR_I64", PC_BITXOR, ASSOC_LEFT, &type_int64, &type_int64, &type_int64, OPF_STD},
{7, "<<", "LSHIFT_I64I", PC_SHIFT, ASSOC_LEFT, &type_int64, &type_integer, &type_int64, OPF_STD},
@ -1542,83 +1542,80 @@ static pbool QCC_OPCodeValidForTarget(qcc_targetformat_t targfmt, unsigned int q
case OP_STORE_P: //was omitted.
return (qcc_targetversion>=12901);
//maths and conditionals (simple opcodes that read from specific globals and write to a global)
// case OP_STORE_I:
case OP_ADD_I:
case OP_ADD_FI:
// case OP_ADD_IF:
case OP_SUB_I:
case OP_SUB_FI:
case OP_MUL_I:
case OP_MUL_FI:
case OP_MUL_VI:
case OP_DIV_VF:
case OP_DIV_I:
case OP_DIV_FI:
case OP_BITAND_I:
case OP_BITOR_I:
case OP_BITAND_IF:
case OP_BITOR_IF:
case OP_GE_I:
case OP_LE_I:
case OP_GT_I:
case OP_LT_I:
case OP_AND_I:
case OP_OR_I:
case OP_GE_IF:
case OP_LE_IF:
case OP_GT_IF:
case OP_LT_IF:
case OP_AND_IF:
case OP_OR_IF:
case OP_GE_FI:
case OP_LE_FI:
case OP_GT_FI:
case OP_LT_FI:
case OP_AND_FI:
case OP_OR_FI:
case OP_NOT_I:
case OP_EQ_I:
case OP_EQ_IF:
case OP_EQ_FI:
case OP_NE_I:
case OP_NE_IF:
case OP_NE_FI:
// case OP_SUB_IF:
case OP_CONV_ITOF:
case OP_CONV_FTOI:
return true;
//stores into a pointer (generated from 'ent.field=XXX')
case OP_STOREP_I: //no worse than the other OP_STOREP_X functions
//reads from an entity field
case OP_LOAD_I: //no worse than the other OP_LOAD_X functions.
return true;
case OP_BOUNDCHECK:
return true;
//stores into the globals array.
//they can change any global dynamically, but thats supposedly no real security risk.
case OP_GSTOREP_I:
case OP_STOREP_I: //no worse than the other OP_STOREP_X functions
case OP_BITAND_I:
case OP_BITOR_I:
case OP_MUL_I:
case OP_DIV_I:
case OP_EQ_I:
case OP_NE_I:
case OP_NOT_I:
case OP_DIV_VF:
// case OP_STORE_P: //was omitted.
case OP_LE_I:
case OP_GE_I:
case OP_LT_I:
case OP_GT_I:
case OP_LE_IF:
case OP_GE_IF:
case OP_LT_IF:
case OP_GT_IF:
case OP_LE_FI:
case OP_GE_FI:
case OP_LT_FI:
case OP_GT_FI:
case OP_EQ_IF:
case OP_EQ_FI:
// case OP_MUL_IF:
case OP_MUL_FI:
case OP_MUL_VI:
// case OP_DIV_IF:
case OP_DIV_FI:
case OP_BITAND_IF:
case OP_BITOR_IF:
// case OP_BITAND_FI:
// case OP_BITOR_FI:
case OP_AND_I:
case OP_OR_I:
case OP_AND_IF:
case OP_OR_IF:
case OP_AND_FI:
case OP_OR_FI:
case OP_NE_IF:
case OP_NE_FI:
case OP_GSTOREP_I: //stores into the globals array, they can change any global dynamically, but thats supposedly no real security risk.
case OP_GSTOREP_F:
case OP_GSTOREP_ENT:
case OP_GSTOREP_FLD:
case OP_GSTOREP_S:
case OP_GSTOREP_FNC:
case OP_GSTOREP_V:
return true;
//this opcode looks weird
case OP_GADDRESS://floatc = globals[inta + floatb] (fte does not support)
return false;
// case OP_GADDRESS:
case OP_GLOAD_I://c = globals[inta]
case OP_GLOAD_F://note: fte does not support these
case OP_GLOAD_FLD:
case OP_GLOAD_ENT:
case OP_GLOAD_S:
case OP_GLOAD_FNC:
case OP_BOUNDCHECK:
case OP_GLOAD_V:
return true;
//this opcode looks weird
case OP_GADDRESS://floatc = globals[inta + floatb] (fte does not support)
return false;
default: //anything I forgot to mention is new, and doesn't work in DP that I'm aware of.
return false;
}
@ -1919,7 +1916,7 @@ Emits a primitive statement, returning the var it places it's value in
*/
static int QCC_ShouldConvert(QCC_type_t *from, etype_t wanted)
{
if (from->type == ev_boolean)
if (from->type == ev_boolean && wanted != ev_boolean)
from = from->parentclass;
/*no conversion needed*/
@ -1945,6 +1942,31 @@ static int QCC_ShouldConvert(QCC_type_t *from, etype_t wanted)
if (from->type == ev_integer && wanted == ev_float)
return OP_CONV_ITOF;
if ((from->type == ev_integer||from->type == ev_uint) && (wanted == ev_integer||wanted == ev_uint))
return 0;
if ((from->type == ev_int64||from->type == ev_uint64) && (wanted == ev_int64||wanted == ev_uint64))
return 0;
if ((from->type == ev_int64||from->type == ev_uint64) && (wanted == ev_integer||wanted == ev_uint))
return OP_CONV_I64I;
if ((from->type == ev_integer) && (wanted == ev_int64 || wanted == ev_uint64))
return OP_CONV_II64;
if (from->type == ev_uint && (wanted == ev_int64 || wanted == ev_uint64))
return OP_CONV_UI64;
if (from->type == ev_float && wanted == ev_double)
return OP_CONV_FD;
if (from->type == ev_double && wanted == ev_float)
return OP_CONV_DF;
if ((from->type == ev_int64||from->type == ev_uint64) && wanted == ev_float)
return OP_CONV_I64F;
if (from->type == ev_float && (wanted == ev_int64 || wanted == ev_uint64))
return OP_CONV_FI64;
if ((from->type == ev_int64||from->type == ev_uint64) && wanted == ev_double)
return OP_CONV_I64D;
if (from->type == ev_double && (wanted == ev_int64||wanted == ev_uint64))
return OP_CONV_DI64;
if (from->type == ev_float && wanted == ev_vector)
return OP_MUL_FV;
@ -3946,10 +3968,13 @@ QCC_sref_t QCC_PR_StatementFlags ( QCC_opcode_t *op, QCC_sref_t var_a, QCC_sref_
}
else
{
QCC_PR_ParseWarning(WARN_DENORMAL, "OP_ADD_EF: denormals are unsafe");
var_c = QCC_PR_EmulationFunc(nextent);
if (!var_c.cast)
QCC_PR_ParseError(0, "the nextent builtin is not defined");
{
QCC_PR_ParseWarning(0, "the nextent builtin is not defined");
goto badopcode;
}
QCC_PR_ParseWarning(WARN_DENORMAL, "OP_ADD_EF: denormals are unsafe");
var_c = QCC_PR_GenerateFunctionCall1 (nullsref, var_c, QCC_MakeIntConst(0), type_entity);
var_b = QCC_PR_StatementFlags(&pr_opcodes[OP_CONV_FTOI], var_b, nullsref, NULL, flags&STFL_PRESERVEB);
var_b = QCC_PR_StatementFlags(&pr_opcodes[OP_MUL_F], var_c, var_b, NULL, 0);
@ -3967,7 +3992,10 @@ QCC_sref_t QCC_PR_StatementFlags ( QCC_opcode_t *op, QCC_sref_t var_a, QCC_sref_
{
var_c = QCC_PR_EmulationFunc(nextent);
if (!var_c.cast)
QCC_PR_ParseError(0, "the nextent builtin is not defined");
{
QCC_PR_ParseWarning(0, "the nextent builtin is not defined");
goto badopcode;
}
var_c = QCC_PR_GenerateFunctionCall1 (nullsref, var_c, QCC_MakeIntConst(0), type_entity);
var_b = QCC_PR_StatementFlags(&pr_opcodes[OP_MUL_I], var_c, var_b, NULL, flags&STFL_PRESERVEB);
flags&=~STFL_PRESERVEB;
@ -4034,7 +4062,10 @@ QCC_sref_t QCC_PR_StatementFlags ( QCC_opcode_t *op, QCC_sref_t var_a, QCC_sref_
{
QCC_sref_t fnc = QCC_PR_EmulationFunc(BitandInt);
if (!fnc.cast)
QCC_PR_ParseError(0, "BitandInt function not defined: cannot emulate int&int");
{
QCC_PR_ParseWarning(0, "BitandInt function not defined: cannot emulate int&int");
goto badopcode;
}
var_c = QCC_PR_GenerateFunctionCall2(nullsref, fnc, var_a, type_integer, var_b, type_integer);
var_c.cast = type_integer;
return var_c;
@ -4044,7 +4075,10 @@ QCC_sref_t QCC_PR_StatementFlags ( QCC_opcode_t *op, QCC_sref_t var_a, QCC_sref_
{
QCC_sref_t fnc = QCC_PR_EmulationFunc(BitorInt);
if (!fnc.cast)
QCC_PR_ParseError(0, "BitorInt function not defined: cannot emulate int|int");
{
QCC_PR_ParseWarning(0, "BitorInt function not defined: cannot emulate int|int");
goto badopcode;
}
var_c = QCC_PR_GenerateFunctionCall2(nullsref, fnc, var_a, type_integer, var_b, type_integer);
var_c.cast = type_integer;
return var_c;
@ -4070,7 +4104,10 @@ QCC_sref_t QCC_PR_StatementFlags ( QCC_opcode_t *op, QCC_sref_t var_a, QCC_sref_
{
QCC_sref_t fnc = QCC_PR_EmulationFunc(AddInt);
if (!fnc.cast)
QCC_PR_ParseError(0, "AddInt function not defined: cannot emulate int+int");
{
QCC_PR_ParseWarning(0, "AddInt function not defined: cannot emulate int+int");
goto badopcode;
}
var_c = QCC_PR_GenerateFunctionCall2(nullsref, fnc, var_a, type_integer, var_b, type_integer);
var_c.cast = type_integer;
return var_c;
@ -4158,7 +4195,10 @@ QCC_sref_t QCC_PR_StatementFlags ( QCC_opcode_t *op, QCC_sref_t var_a, QCC_sref_
{
QCC_sref_t fnc = QCC_PR_EmulationFunc(ModVec);
if (!fnc.cast)
QCC_PR_ParseError(0, "ModVec function not defined: cannot emulate vector%%vector");
{
QCC_PR_ParseWarning(0, "ModVec function not defined: cannot emulate vector%%vector");
goto badopcode;
}
var_c = QCC_PR_GenerateFunctionCall2(nullsref, fnc, var_a, type_vector, var_b, type_vector);
var_c.cast = type_vector;
return var_c;
@ -4168,7 +4208,10 @@ QCC_sref_t QCC_PR_StatementFlags ( QCC_opcode_t *op, QCC_sref_t var_a, QCC_sref_
{
QCC_sref_t fnc = QCC_PR_EmulationFunc(SubInt);
if (!fnc.cast)
QCC_PR_ParseError(0, "SubInt function not defined: cannot emulate int-int");
{
QCC_PR_ParseWarning(0, "SubInt function not defined: cannot emulate int-int");
goto badopcode;
}
var_c = QCC_PR_GenerateFunctionCall2(nullsref, fnc, var_a, type_integer, var_b, type_integer);
var_c.cast = type_integer;
return var_c;
@ -4178,7 +4221,10 @@ QCC_sref_t QCC_PR_StatementFlags ( QCC_opcode_t *op, QCC_sref_t var_a, QCC_sref_
{
QCC_sref_t fnc = QCC_PR_EmulationFunc(MulInt);
if (!fnc.cast)
QCC_PR_ParseError(0, "MulInt function not defined: cannot emulate int*int");
{
QCC_PR_ParseWarning(0, "MulInt function not defined: cannot emulate int*int");
goto badopcode;
}
var_c = QCC_PR_GenerateFunctionCall2(nullsref, fnc, var_a, type_integer, var_b, type_integer);
var_c.cast = type_integer;
return var_c;
@ -4188,7 +4234,10 @@ QCC_sref_t QCC_PR_StatementFlags ( QCC_opcode_t *op, QCC_sref_t var_a, QCC_sref_
{
QCC_sref_t fnc = QCC_PR_EmulationFunc(DivInt);
if (!fnc.cast)
QCC_PR_ParseError(0, "DivInt function not defined: cannot emulate int/int");
{
QCC_PR_ParseWarning(0, "DivInt function not defined: cannot emulate int/int");
goto badopcode;
}
var_c = QCC_PR_GenerateFunctionCall2(nullsref, fnc, var_a, type_integer, var_b, type_integer);
var_c.cast = type_integer;
return var_c;
@ -4206,7 +4255,10 @@ QCC_sref_t QCC_PR_StatementFlags ( QCC_opcode_t *op, QCC_sref_t var_a, QCC_sref_
{
QCC_sref_t fnc = QCC_PR_EmulationFunc(pow);
if (!fnc.cast)
QCC_PR_ParseError(0, "pow function not defined: cannot emulate float*^float");
{
QCC_PR_ParseWarning(0, "pow function not defined: cannot emulate float*^float");
goto badopcode;
}
var_c = QCC_PR_GenerateFunctionCall2(nullsref, fnc, var_a, type_float, var_b, type_float);
var_c.cast = type_float;
return var_c;
@ -4216,7 +4268,10 @@ QCC_sref_t QCC_PR_StatementFlags ( QCC_opcode_t *op, QCC_sref_t var_a, QCC_sref_
{
QCC_sref_t fnc = QCC_PR_EmulationFunc(pow);
if (!fnc.cast)
QCC_PR_ParseError(0, "pow function not defined: cannot emulate float*^float");
{
QCC_PR_ParseWarning(0, "pow function not defined: cannot emulate float*^float");
goto badopcode;
}
var_a = QCC_PR_StatementFlags(&pr_opcodes[OP_CONV_FTOI], var_a, nullsref, NULL, flags&STFL_PRESERVEA);
var_b = QCC_PR_StatementFlags(&pr_opcodes[OP_CONV_FTOI], var_b, nullsref, NULL, (flags&STFL_PRESERVEB)?STFL_PRESERVEA:0);
var_c = QCC_PR_GenerateFunctionCall2(nullsref, fnc, var_a, type_float, var_b, type_float);
@ -4228,7 +4283,10 @@ QCC_sref_t QCC_PR_StatementFlags ( QCC_opcode_t *op, QCC_sref_t var_a, QCC_sref_
{
QCC_sref_t fnc = QCC_PR_EmulationFunc(pow);
if (!fnc.cast)
QCC_PR_ParseError(0, "pow function not defined: cannot emulate float*^int");
{
QCC_PR_ParseWarning(0, "pow function not defined: cannot emulate float*^int");
goto badopcode;
}
var_b = QCC_PR_StatementFlags(&pr_opcodes[OP_CONV_FTOI], var_b, nullsref, NULL, (flags&STFL_PRESERVEB)?STFL_PRESERVEA:0);
var_c = QCC_PR_GenerateFunctionCall2(nullsref, fnc, var_a, type_float, var_b, type_float);
var_c.cast = type_float;
@ -4239,7 +4297,10 @@ QCC_sref_t QCC_PR_StatementFlags ( QCC_opcode_t *op, QCC_sref_t var_a, QCC_sref_
{
QCC_sref_t fnc = QCC_PR_EmulationFunc(pow);
if (!fnc.cast)
QCC_PR_ParseError(0, "pow function not defined: cannot emulate int*^float");
{
QCC_PR_ParseWarning(0, "pow function not defined: cannot emulate int*^float");
goto badopcode;
}
var_a = QCC_PR_StatementFlags(&pr_opcodes[OP_CONV_FTOI], var_a, nullsref, NULL, flags&STFL_PRESERVEA);
var_c = QCC_PR_GenerateFunctionCall2(nullsref, fnc, var_a, type_float, var_b, type_float);
var_c.cast = type_float;
@ -4370,7 +4431,9 @@ QCC_sref_t QCC_PR_StatementFlags ( QCC_opcode_t *op, QCC_sref_t var_a, QCC_sref_
QCC_sref_t fnc = QCC_PR_EmulationFunc(BitxorInt);
if (!fnc.cast)
{
QCC_PR_ParseError(0, "BitxorInt function not defined: cannot emulate int^int");
QCC_PR_ParseWarning(0, "BitxorInt function not defined: cannot emulate int^int");
goto badopcode;
var_c = QCC_PR_StatementFlags(&pr_opcodes[OP_BITNOT_I], var_b, nullsref, NULL, STFL_PRESERVEA);
var_c = QCC_PR_StatementFlags(&pr_opcodes[OP_BITAND_I], var_a, var_c, NULL, STFL_PRESERVEA);
var_a = QCC_PR_StatementFlags(&pr_opcodes[OP_BITNOT_I], var_a, nullsref, NULL, 0);
@ -4490,7 +4553,10 @@ QCC_sref_t QCC_PR_StatementFlags ( QCC_opcode_t *op, QCC_sref_t var_a, QCC_sref_
{
QCC_sref_t fnc = QCC_PR_EmulationFunc(SubInt);
if (!fnc.cast)
QCC_PR_ParseError(0, "SubInt function not defined: cannot emulate ~int");
{
QCC_PR_ParseWarning(0, "SubInt function not defined: cannot emulate ~int");
goto badopcode;
}
var_c = QCC_PR_GenerateFunctionCall2(nullsref, fnc, QCC_MakeIntConst(~0), type_integer, var_a, type_integer);
var_c.cast = type_integer;
return var_c;
@ -4886,7 +4952,13 @@ QCC_sref_t QCC_PR_StatementFlags ( QCC_opcode_t *op, QCC_sref_t var_a, QCC_sref_
{
QCC_sref_t fnc = QCC_PR_EmulationFunc(LShiftInt);
if (!fnc.cast)
QCC_PR_ParseError(0, "LShiftInt function not defined: cannot emulate int<<int");
{
const QCC_eval_t *eval_b = QCC_SRef_EvalConst(var_b);
if (eval_b)
return QCC_PR_StatementFlags(&pr_opcodes[OP_MUL_I], var_a, QCC_MakeIntConst(1<<eval_b->_int), NULL, flags&STFL_PRESERVEB);
QCC_PR_ParseWarning(0, "LShiftInt function not defined: cannot emulate int<<int");
goto badopcode;
}
var_c = QCC_PR_GenerateFunctionCall2(nullsref, fnc, QCC_MakeIntConst(~0), type_integer, var_a, type_integer);
var_c.cast = type_integer;
return var_c;
@ -4896,7 +4968,13 @@ QCC_sref_t QCC_PR_StatementFlags ( QCC_opcode_t *op, QCC_sref_t var_a, QCC_sref_
{
QCC_sref_t fnc = QCC_PR_EmulationFunc(RShiftInt);
if (!fnc.cast)
QCC_PR_ParseError(0, "RShiftInt function not defined: cannot emulate int>>int");
{
const QCC_eval_t *eval_b = QCC_SRef_EvalConst(var_b);
if (eval_b)
return QCC_PR_StatementFlags(&pr_opcodes[OP_DIV_I], var_a, QCC_MakeIntConst(1<<eval_b->_int), NULL, flags&STFL_PRESERVEB);
QCC_PR_ParseWarning(0, "RShiftInt function not defined: cannot emulate int>>int");
goto badopcode;
}
var_c = QCC_PR_GenerateFunctionCall2(nullsref, fnc, QCC_MakeIntConst(~0), type_integer, var_a, type_integer);
var_c.cast = type_integer;
return var_c;
@ -4940,8 +5018,8 @@ QCC_sref_t QCC_PR_StatementFlags ( QCC_opcode_t *op, QCC_sref_t var_a, QCC_sref_
var_c.cast = *op->type_c;
return var_c;
}
QCC_PR_ParseError(0, "bitshift function not defined: cannot emulate OP_LSHIFT_F*");
break;
QCC_PR_ParseWarning(0, "bitshift function not defined: cannot emulate OP_LSHIFT_F*");
goto badopcode;
}
case OP_RSHIFT_F:
if (QCC_OPCodeValid(&pr_opcodes[OP_RSHIFT_I]))
@ -4973,18 +5051,22 @@ QCC_sref_t QCC_PR_StatementFlags ( QCC_opcode_t *op, QCC_sref_t var_a, QCC_sref_
var_c.cast = *op->type_c;
return var_c;
}
QCC_PR_ParseError(0, "bitshift function not defined: cannot emulate OP_RSHIFT_F*");
break;
QCC_PR_ParseWarning(0, "bitshift function not defined: cannot emulate OP_RSHIFT_F*");
goto badopcode;
}
case OP_BITAND_D:
var_a = QCC_PR_StatementFlags(&pr_opcodes[OP_CONV_DI64], var_a, nullsref, NULL, flags&STFL_PRESERVEA);
var_b = QCC_PR_StatementFlags(&pr_opcodes[OP_CONV_DI64], var_b, nullsref, NULL, (flags&STFL_PRESERVEB)?STFL_PRESERVEA:0);
return QCC_PR_StatementFlags(&pr_opcodes[OP_BITAND_I64], var_a, var_b, NULL, 0);
var_c = QCC_PR_StatementFlags(&pr_opcodes[OP_BITAND_I64], var_a, var_b, NULL, 0);
var_c = QCC_PR_StatementFlags(&pr_opcodes[OP_CONV_I64D], var_c, nullsref, NULL, 0); //grr
return var_c;
case OP_BITOR_D:
var_a = QCC_PR_StatementFlags(&pr_opcodes[OP_CONV_DI64], var_a, nullsref, NULL, flags&STFL_PRESERVEA);
var_b = QCC_PR_StatementFlags(&pr_opcodes[OP_CONV_DI64], var_b, nullsref, NULL, (flags&STFL_PRESERVEB)?STFL_PRESERVEA:0);
return QCC_PR_StatementFlags(&pr_opcodes[OP_BITOR_I64], var_a, var_b, NULL, 0);
var_c = QCC_PR_StatementFlags(&pr_opcodes[OP_BITOR_I64], var_a, var_b, NULL, 0);
var_c = QCC_PR_StatementFlags(&pr_opcodes[OP_CONV_I64D], var_c, nullsref, NULL, 0); //grr
return var_c;
case OP_LOAD_I64:
var_a.cast = type_integer;
@ -5230,7 +5312,10 @@ QCC_sref_t QCC_PR_StatementFlags ( QCC_opcode_t *op, QCC_sref_t var_a, QCC_sref_
{
QCC_sref_t fnc = QCC_PR_EmulationFunc(memgetval);
if (!fnc.cast)
QCC_PR_ParseError(0, "memgetval function not defined: cannot emulate OP_LOADP_*");
{
QCC_PR_ParseWarning(0, "memgetval function not defined: cannot emulate OP_LOADP_*");
goto badopcode;
}
var_c = QCC_PR_GenerateFunctionCall2(nullsref, fnc, var_a, type_pointer, QCC_PR_StatementFlags(&pr_opcodes[OP_CONV_ITOF], var_b, nullsref, NULL, (flags&STFL_PRESERVEB)?STFL_PRESERVEA:0), type_float);
var_c.cast = *op->type_c;
return var_c;
@ -5294,6 +5379,7 @@ QCC_sref_t QCC_PR_StatementFlags ( QCC_opcode_t *op, QCC_sref_t var_a, QCC_sref_
return var_b;
default:
badopcode:
if (QCC_OPCodeValidForTarget(QCF_FTE, QCTARGVER_FTE_DEF, op))
QCC_PR_ParseWarning(ERR_BADEXTENSION, "Opcode \"%s|%s\" not valid for target. Consider the use of: #pragma target fte", op->name, op->opname);
else if (QCC_OPCodeValidForTarget(QCF_FTE, QCTARGVER_FTE_MAX, op))
@ -9723,6 +9809,49 @@ QCC_ref_t *QCC_PR_ParseRefValue (QCC_ref_t *refbuf, QCC_type_t *assumeclass, pbo
return QCC_PR_ParseRefArrayPointer(refbuf, QCC_DefToRef(refbuf, d), allowarrayassign, makearraypointers);
}
//true if its NOT 0
QCC_sref_t QCC_PR_GenerateLogicalTruth(QCC_sref_t e, const char *errormessage)
{
etype_t t;
QCC_type_t *type = e.cast;
while(type->type == ev_accessor || type->type == ev_boolean)
type = type->parentclass;
t = type->type;
if (t == ev_float)
return QCC_PR_Statement (&pr_opcodes[OP_NE_F], e, QCC_MakeFloatConst(0), NULL);
else if (t == ev_string)
return QCC_PR_Statement (&pr_opcodes[flag_brokenifstring?OP_NE_E:OP_NE_S], e, QCC_MakeIntConst(0), NULL);
else if (t == ev_entity)
return QCC_PR_Statement (&pr_opcodes[OP_NE_E], e, QCC_MakeIntConst(0), NULL);
else if (t == ev_vector)
return QCC_PR_Statement (&pr_opcodes[OP_NE_V], e, QCC_MakeVectorConst(0,0,0), NULL);
else if (t == ev_function)
return QCC_PR_Statement (&pr_opcodes[OP_NE_FNC], e, QCC_MakeIntConst(0), NULL);
else if (t == ev_integer || t == ev_uint)
return QCC_PR_Statement (&pr_opcodes[OP_NE_I], e, QCC_MakeIntConst(0), NULL); //functions are integer values too.
else if (t == ev_pointer)
return QCC_PR_Statement (&pr_opcodes[OP_NE_I], e, QCC_MakeIntConst(0), NULL); //Pointers are too.
else if (t == ev_double)
return QCC_PR_Statement (&pr_opcodes[OP_NE_D], e, QCC_MakeDoubleConst(0), NULL);
else if (t == ev_int64)
return QCC_PR_Statement (&pr_opcodes[OP_NE_I64], e, QCC_MakeInt64Const(0), NULL);
else if (t == ev_uint64)
return QCC_PR_Statement (&pr_opcodes[OP_NE_U64], e, QCC_MakeUInt64Const(0), NULL);
else if (t == ev_void && flag_laxcasts)
{
QCC_PR_ParseWarning(WARN_LAXCAST, errormessage, "void");
return QCC_PR_Statement (&pr_opcodes[OP_NE_F], e, QCC_MakeFloatConst(0), NULL);
}
else
{
char etype[256];
TypeName(e.cast, etype, sizeof(etype));
QCC_PR_ParseError (ERR_BADNOTTYPE, errormessage, etype);
return nullsref;
}
}
QCC_sref_t QCC_PR_GenerateLogicalNot(QCC_sref_t e, const char *errormessage)
{
etype_t t;
@ -9812,12 +9941,13 @@ static QCC_sref_t QCC_TryEvaluateCast(QCC_sref_t src, QCC_type_t *cast, pbool im
QCC_type_t *tmp;
int totype;
while (src.cast->type == ev_boolean)
src.cast = src.cast->parentclass;
for (tmp = cast; tmp->type == ev_accessor || tmp->type == ev_boolean; tmp = tmp->parentclass)
for (tmp = cast; tmp->type == ev_accessor; tmp = tmp->parentclass)
;
totype = tmp->type;
while (src.cast->type == ev_boolean)
src.cast = src.cast->parentclass;
/*you may cast from a type to itself*/
if (!typecmp(src.cast, cast))
{
@ -9833,6 +9963,12 @@ static QCC_sref_t QCC_TryEvaluateCast(QCC_sref_t src, QCC_type_t *cast, pbool im
src = QCC_MakeIntConst(0);
src.cast = cast;
}
else if (totype == ev_boolean)
{
src = QCC_PR_GenerateLogicalTruth(src, "cast to boolean");
//src will often be a float(eg:NQ_F) with a bint totype. make sure we evaluate it fully.
return QCC_TryEvaluateCast(src, tmp->parentclass, implicit);
}
/*cast from int->float will convert*/
else if (totype == ev_float && (src.cast->type == ev_uint || src.cast->type == ev_integer || (src.cast->type == ev_entity && !implicit)))
{
@ -10594,6 +10730,9 @@ static void QCC_StoreToSRef(QCC_sref_t dest, QCC_sref_t source, QCC_type_t *type
case ev_field:
QCC_FreeTemp(QCC_PR_StatementFlags(&pr_opcodes[OP_STORE_FLD], source, dest, NULL, flags));
break;
case ev_boolean:
QCC_StoreToSRef(dest, source, type->parentclass, preservesource, preservedest);
return;
case ev_integer:
case ev_uint:
QCC_FreeTemp(QCC_PR_StatementFlags(&pr_opcodes[OP_STORE_I], source, dest, NULL, flags));
@ -11617,8 +11756,26 @@ QCC_sref_t QCC_StoreSRefToRef(QCC_ref_t *dest, QCC_sref_t source, pbool readable
char typeb[256];
if (source.cast->type == ev_variant || dest->cast->type == ev_variant)
QCC_PR_ParseWarning(WARN_IMPLICITVARIANTCAST, "type mismatch: %s %s to %s %s.%s", typea, QCC_GetSRefName(source), typeb, QCC_GetSRefName(dest->base), QCC_GetSRefName(dest->index));
else if ((dest->cast->type == ev_float || dest->cast->type == ev_integer) && (source.cast->type == ev_float || source.cast->type == ev_integer))
source = QCC_SupplyConversion(source, dest->cast->type, true);
else if ((dest->cast->type == ev_float ||
dest->cast->type == ev_integer ||
dest->cast->type == ev_uint ||
dest->cast->type == ev_int64 ||
dest->cast->type == ev_uint64 ||
dest->cast->type == ev_double ||
dest->cast->type == ev_boolean) && (
source.cast->type == ev_float ||
source.cast->type == ev_integer ||
source.cast->type == ev_uint ||
source.cast->type == ev_int64 ||
source.cast->type == ev_uint64 ||
source.cast->type == ev_double ||
source.cast->type == ev_boolean))
{
if (dest->cast->type == ev_boolean)
source = QCC_SupplyConversion(QCC_PR_GenerateLogicalTruth(source, "cannot convert to boolean"), dest->cast->parentclass->type, true);
else
source = QCC_SupplyConversion(source, dest->cast->type, true);
}
else
{
TypeName(source.cast, typea, sizeof(typea));
@ -11961,6 +12118,14 @@ static QCC_opcode_t *QCC_PR_ChooseOpcode(QCC_sref_t lhs, QCC_sref_t rhs, QCC_opc
}
}
if (type_a == ev_boolean)
{
lhs.cast = lhs.cast->parentclass;
type_a = lhs.cast->type;
}
if (rhs.cast->type == ev_boolean)
rhs.cast = rhs.cast->parentclass;
if (op->name[0] == '.')// field access gets type from field
{
if (rhs.cast->aux_type)
@ -13461,6 +13626,7 @@ void QCC_PR_ParseStatement (void)
(keyword_int && !STRCMP ("int", pr_token)) ||
(keyword_short && !STRCMP ("short", pr_token)) ||
(keyword_char && !STRCMP ("char", pr_token)) ||
( !STRCMP ("_Bool", pr_token)) ||
(keyword_static && !STRCMP ("static", pr_token)) ||
(keyword_class && !STRCMP ("class", pr_token)) ||
(keyword_const && !STRCMP ("const", pr_token)))
@ -17802,7 +17968,7 @@ void QCC_PR_ParseTypedef(void)
else
{
old = QCC_TypeForName(name);
if (old)
if (old && old->scope == pr_scope)
{
if (typecmp(old, type))
{
@ -17818,6 +17984,7 @@ void QCC_PR_ParseTypedef(void)
type = QCC_PR_DuplicateType(type, false);
type->name = name;
type->typedefed = true;
type->scope = pr_scope;
pHash_Add(&typedeftable, name, type, qccHunkAlloc(sizeof(bucket_t)));
}
}

View File

@ -1341,7 +1341,9 @@ static pbool QCC_PR_Precompiler(void)
{
if (!QC_strcasecmp(pr_opcodes[f].opname, qcc_token))
{
if (st)
if (f >= OP_NUMREALOPS)
QCC_PR_ParseWarning(WARN_BADPRAGMA, "opcode %s is internal", qcc_token); //these will change with later opcodes, do not allow them to be written into the output.
else if (st)
pr_opcodes[f].flags |= OPF_VALID;
else
pr_opcodes[f].flags &= ~OPF_VALID;
@ -4708,6 +4710,8 @@ QCC_type_t *QCC_PR_DuplicateType(QCC_type_t *in, pbool recurse)
out->num_parms = in->num_parms;
out->name = in->name;
out->parentclass = in->parentclass;
out->vargs = in->vargs;
out->vargcount = in->vargcount;
return out;
}
@ -4902,7 +4906,14 @@ QCC_type_t *QCC_PR_NextSubType(QCC_type_t *type, QCC_type_t *prev)
QCC_type_t *QCC_TypeForName(const char *name)
{
return pHash_Get(&typedeftable, name);
QCC_type_t *t = pHash_Get(&typedeftable, name);
while (t && t->scope)
{
if (t->scope == pr_scope)
break; //its okay after all.
t = pHash_GetNext(&typedeftable, name, t);
}
return t;
/*
int i;
@ -6465,8 +6476,14 @@ QCC_type_t *QCC_PR_ParseType (int newtype, pbool silentfail)
bits = 16, isokay = true;
else if (!bits && QCC_PR_CheckKeyword(keyword_char, "char"))
bits = 8, isokay = true;
else if (!bits && QCC_PR_CheckKeyword(keyword_int, "_Bool")) //c99
bits = 1, isokay = true;
else if (!bits && !issigned && !isunsigned && QCC_PR_CheckKeyword(true, "_Bool")) //c99
{
if (keyword_int)
type = type_bint;
else
type = type_bfloat;
goto wasctype;
}
else if (!bits && !islong && QCC_PR_CheckKeyword(keyword_float, "float"))
bits = 32, isfloat = isokay = true;

View File

@ -3614,10 +3614,10 @@ static void QCC_PR_BeginCompilation (void *memory, int memsize)
type_floatfunction = QCC_PR_NewType("__floatfunction", ev_function, false);
type_floatfunction->aux_type = type_float;
type_bfloat = QCC_PR_NewType("__bfloat", ev_boolean, false);
type_bfloat = QCC_PR_NewType("__bfloat", ev_boolean, true);
type_bfloat->parentclass = type_float;
type_bint = QCC_PR_NewType("__bint", ev_boolean, false);
type_bint->parentclass = type_integer;
type_bint = QCC_PR_NewType("__bint", ev_boolean, true);
type_bint->parentclass = type_uint;
//type_field->aux_type = type_float;