Add offset pointer stores to fteqcc, for writable tempbuffers.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5715 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2020-06-27 19:32:26 +00:00
parent d40c125223
commit 3c0743f169
2 changed files with 120 additions and 96 deletions

View file

@ -656,7 +656,7 @@ QCC_opcode_t pr_opcodes[] =
{7, "<IF_F>", "IF_F", PC_NONE, ASSOC_RIGHT, &type_float, NULL, &type_void}, {7, "<IF_F>", "IF_F", PC_NONE, ASSOC_RIGHT, &type_float, NULL, &type_void},
{7, "<IFNOT_F>","IFNOT_F", PC_NONE, ASSOC_RIGHT, &type_float, NULL, &type_void}, {7, "<IFNOT_F>","IFNOT_F", PC_NONE, ASSOC_RIGHT, &type_float, NULL, &type_void},
{7, "<=>", "STOREF_V", PC_NONE, ASSOC_RIGHT, &type_entity, &type_field, &type_vector}, {7, "<=>", "STOREF_V", PC_NONE, ASSOC_RIGHT, &type_entity, &type_field, &type_vector}, //ent.fld=c
{7, "<=>", "STOREF_F", PC_NONE, ASSOC_RIGHT, &type_entity, &type_field, &type_float}, {7, "<=>", "STOREF_F", PC_NONE, ASSOC_RIGHT, &type_entity, &type_field, &type_float},
{7, "<=>", "STOREF_S", PC_NONE, ASSOC_RIGHT, &type_entity, &type_field, &type_string}, {7, "<=>", "STOREF_S", PC_NONE, ASSOC_RIGHT, &type_entity, &type_field, &type_string},
{7, "<=>", "STOREF_I", PC_NONE, ASSOC_RIGHT, &type_entity, &type_field, &type_integer}, {7, "<=>", "STOREF_I", PC_NONE, ASSOC_RIGHT, &type_entity, &type_field, &type_integer},
@ -1162,7 +1162,7 @@ void QCC_PrioritiseOpcodes(void)
qsort (&opcodeprioritized[j][0], pcount[j], sizeof(opcodeprioritized[j][0]), sort_opcodenames); qsort (&opcodeprioritized[j][0], pcount[j], sizeof(opcodeprioritized[j][0]), sort_opcodenames);
} }
static pbool QCC_OPCodeValid(QCC_opcode_t *op) static pbool QCC_OPCodeValidForTarget(qcc_targetformat_t targfmt, QCC_opcode_t *op)
{ {
int num; int num;
num = op - pr_opcodes; num = op - pr_opcodes;
@ -1171,7 +1171,7 @@ static pbool QCC_OPCodeValid(QCC_opcode_t *op)
if (num >= OP_NUMREALOPS) if (num >= OP_NUMREALOPS)
return false; return false;
switch(qcc_targetformat) switch(targfmt)
{ {
case QCF_STANDARD: case QCF_STANDARD:
case QCF_KK7: case QCF_KK7:
@ -1417,6 +1417,28 @@ static pbool QCC_OPCodeValid(QCC_opcode_t *op)
return false; return false;
} }
static pbool QCC_OPCodeValid(QCC_opcode_t *op)
{
return op->flags & OPF_VALID;
}
static pbool QCC_OPCode_StorePOffset(void)
{ //5709+
return QCC_OPCodeValid(&pr_opcodes[OP_STOREF_I]); //close enough (I didn't make any public builds between revisions)
}
void QCC_OPCodeSetTarget(qcc_targetformat_t targfmt)
{
size_t i;
qcc_targetformat = targfmt;
for (i = 0; i < OP_NUMREALOPS; i++)
{
QCC_opcode_t *op = &pr_opcodes[i];
if (QCC_OPCodeValidForTarget(targfmt, op))
op->flags |= OPF_VALID;
else
op->flags &= ~OPF_VALID;
}
}
#define EXPR_WARN_ABOVE_1 2 #define EXPR_WARN_ABOVE_1 2
#define EXPR_DISALLOW_COMMA 4 #define EXPR_DISALLOW_COMMA 4
#define EXPR_DISALLOW_ARRAYASSIGN 8 #define EXPR_DISALLOW_ARRAYASSIGN 8
@ -4146,17 +4168,10 @@ QCC_sref_t QCC_PR_StatementFlags ( QCC_opcode_t *op, QCC_sref_t var_a, QCC_sref_
return var_c; return var_c;
default: default:
{ if (QCC_OPCodeValidForTarget(QCF_FTE, op))
int oldtarg = qcc_targetformat; QCC_PR_ParseError(ERR_BADEXTENSION, "Opcode \"%s|%s\" not valid for target. Consider the use of: #pragma target fte", op->name, op->opname);
pbool shamelessadvertising; else
qcc_targetformat = QCF_FTE; QCC_PR_ParseError(ERR_BADEXTENSION, "Opcode \"%s|%s\" is not supported.", op->name, op->opname);
shamelessadvertising = QCC_OPCodeValid(op);
qcc_targetformat = oldtarg;
if (shamelessadvertising)
QCC_PR_ParseError(ERR_BADEXTENSION, "Opcode \"%s|%s\" not valid for target. Consider the use of: #pragma target fte", op->name, op->opname);
else
QCC_PR_ParseError(ERR_BADEXTENSION, "Opcode \"%s|%s\" is not supported.", op->name, op->opname);
}
break; break;
} }
} }
@ -7663,17 +7678,17 @@ fieldarrayindex:
{ {
char *swizzle = QCC_PR_ParseName(); char *swizzle = QCC_PR_ParseName();
//single-channel swizzles just result in a float. nice and easy. assignable, too. //single-channel swizzles just result in a float. nice and easy. assignable, too.
if (!strcmp(swizzle, "x") || !strcmp(swizzle, "r")) if ((!strcmp(swizzle, "x") || !strcmp(swizzle, "r")) && t->size >= 1)
{ {
tmp = QCC_MakeIntConst(0); tmp = QCC_MakeIntConst(0);
goto vectorarrayindex; goto vectorarrayindex;
} }
else if (!strcmp(swizzle, "y") || !strcmp(swizzle, "g")) else if ((!strcmp(swizzle, "y") || !strcmp(swizzle, "g")) && t->size >= 2)
{ {
tmp = QCC_MakeIntConst(1); tmp = QCC_MakeIntConst(1);
goto vectorarrayindex; goto vectorarrayindex;
} }
else if (!strcmp(swizzle, "z") || !strcmp(swizzle, "b")) else if ((!strcmp(swizzle, "z") || !strcmp(swizzle, "b")) && t->size >= 3)
{ {
tmp = QCC_MakeIntConst(2); tmp = QCC_MakeIntConst(2);
goto vectorarrayindex; goto vectorarrayindex;
@ -7690,17 +7705,17 @@ fieldarrayindex:
{ {
char *swizzle = QCC_PR_ParseName(); char *swizzle = QCC_PR_ParseName();
//single-channel swizzles just result in a float. nice and easy. assignable, too. //single-channel swizzles just result in a float. nice and easy. assignable, too.
if (!strcmp(swizzle, "x") || !strcmp(swizzle, "r")) if ((!strcmp(swizzle, "x") || !strcmp(swizzle, "r")) && t->size >= 1)
{ {
tmp = QCC_MakeIntConst(0); tmp = QCC_MakeIntConst(0);
goto fieldarrayindex; goto fieldarrayindex;
} }
else if (!strcmp(swizzle, "y") || !strcmp(swizzle, "g")) else if ((!strcmp(swizzle, "y") || !strcmp(swizzle, "g")) && t->size >= 2)
{ {
tmp = QCC_MakeIntConst(1); tmp = QCC_MakeIntConst(1);
goto fieldarrayindex; goto fieldarrayindex;
} }
else if (!strcmp(swizzle, "z") || !strcmp(swizzle, "b")) else if ((!strcmp(swizzle, "z") || !strcmp(swizzle, "b")) && t->size >= 3)
{ {
tmp = QCC_MakeIntConst(2); tmp = QCC_MakeIntConst(2);
goto fieldarrayindex; goto fieldarrayindex;
@ -8907,14 +8922,22 @@ static QCC_sref_t QCC_CollapseStore(QCC_sref_t dest, QCC_sref_t source, QCC_type
return source; return source;
return nullsref; return nullsref;
} }
static void QCC_StoreToPointer(QCC_sref_t dest, QCC_sref_t source, QCC_type_t *type) static void QCC_StoreToPointer(QCC_sref_t dest, QCC_sref_t idx, QCC_sref_t source, QCC_type_t *type)
{ {
pbool freedest = false;
if (type->type == ev_variant) if (type->type == ev_variant)
type = source.cast; type = source.cast;
while (type->type == ev_accessor) while (type->type == ev_accessor)
type = type->parentclass; type = type->parentclass;
if (idx.sym && !QCC_OPCode_StorePOffset())
{ //can't do an offset store yet... bake any index into the pointer.
freedest = true;
dest = QCC_PR_StatementFlags(&pr_opcodes[OP_ADD_PIW], dest, idx, NULL, STFL_PRESERVEA);
idx = nullsref;
}
//fixme: we should probably handle entire structs or something //fixme: we should probably handle entire structs or something
switch(type->type) switch(type->type)
{ {
@ -8924,70 +8947,75 @@ static void QCC_StoreToPointer(QCC_sref_t dest, QCC_sref_t source, QCC_type_t *t
case ev_union: case ev_union:
{ {
unsigned int i; unsigned int i;
#if 1 if (QCC_OPCode_StorePOffset())
for (i = 0; i+2 < type->size; i+=3) { //store-with-offset works.
{ for (i = 0; i+2 < type->size; i+=3)
QCC_sref_t newptr = QCC_PR_StatementFlags(&pr_opcodes[OP_ADD_PIW], dest, QCC_MakeIntConst(i), NULL, STFL_PRESERVEA); {
QCC_PR_SimpleStatement(&pr_opcodes[OP_STOREP_V], source, newptr, nullsref, false); QCC_sref_t newidx = idx.sym?QCC_PR_StatementFlags(&pr_opcodes[OP_ADD_I], idx, QCC_MakeIntConst(i), NULL, STFL_PRESERVEA):QCC_MakeIntConst(i);
QCC_FreeTemp(newptr); QCC_PR_SimpleStatement(&pr_opcodes[OP_STOREP_V], source, dest, newidx, false);
source.ofs += 3; QCC_FreeTemp(newidx);
source.ofs += 3;
}
for (; i < type->size; i++)
{
QCC_sref_t newidx = idx.sym?QCC_PR_StatementFlags(&pr_opcodes[OP_ADD_I], idx, QCC_MakeIntConst(i), NULL, STFL_PRESERVEA):QCC_MakeIntConst(i);
QCC_PR_SimpleStatement(&pr_opcodes[OP_STOREP_F], source, dest, newidx, false);
QCC_FreeTemp(newidx);
source.ofs += 1;
}
} }
for (; i < type->size; i++) else
{ { //no store-with-offset.
QCC_sref_t newptr = QCC_PR_StatementFlags(&pr_opcodes[OP_ADD_PIW], dest, QCC_MakeIntConst(i), NULL, STFL_PRESERVEA); for (i = 0; i+2 < type->size; i+=3)
QCC_PR_SimpleStatement(&pr_opcodes[OP_STOREP_F], source, newptr, nullsref, false); {
QCC_FreeTemp(newptr); QCC_sref_t newptr = QCC_PR_StatementFlags(&pr_opcodes[OP_ADD_PIW], dest, QCC_MakeIntConst(i), NULL, STFL_PRESERVEA);
source.ofs += 1; QCC_PR_SimpleStatement(&pr_opcodes[OP_STOREP_V], source, newptr, idx, false);
QCC_FreeTemp(newptr);
source.ofs += 3;
}
for (; i < type->size; i++)
{
QCC_sref_t newptr = QCC_PR_StatementFlags(&pr_opcodes[OP_ADD_PIW], dest, QCC_MakeIntConst(i), NULL, STFL_PRESERVEA);
QCC_PR_SimpleStatement(&pr_opcodes[OP_STOREP_F], source, newptr, idx, false);
QCC_FreeTemp(newptr);
source.ofs += 1;
}
} }
#else
for (i = 0; i+2 < type->size; i+=3)
{
QCC_sref_t ofs = QCC_MakeIntConst(i);
QCC_PR_SimpleStatement(&pr_opcodes[OP_STOREP_V], source, dest, ofs, false);
QCC_FreeTemp(ofs);
source.ofs += 3;
}
for (; i < type->size; i++)
{
QCC_sref_t ofs = QCC_MakeIntConst(i);
QCC_PR_SimpleStatement(&pr_opcodes[OP_STOREP_F], source, dest, ofs, false);
QCC_FreeTemp(ofs);
source.ofs += 1;
}
#endif
} }
break; break;
case ev_float: case ev_float:
QCC_PR_SimpleStatement(&pr_opcodes[OP_STOREP_F], source, dest, nullsref, false); QCC_PR_SimpleStatement(&pr_opcodes[OP_STOREP_F], source, dest, idx, false);
break; break;
case ev_vector: case ev_vector:
QCC_PR_SimpleStatement(&pr_opcodes[OP_STOREP_V], source, dest, nullsref, false); QCC_PR_SimpleStatement(&pr_opcodes[OP_STOREP_V], source, dest, idx, false);
break; break;
case ev_entity: case ev_entity:
QCC_PR_SimpleStatement(&pr_opcodes[OP_STOREP_ENT], source, dest, nullsref, false); QCC_PR_SimpleStatement(&pr_opcodes[OP_STOREP_ENT], source, dest, idx, false);
break; break;
case ev_string: case ev_string:
QCC_PR_SimpleStatement(&pr_opcodes[OP_STOREP_S], source, dest, nullsref, false); QCC_PR_SimpleStatement(&pr_opcodes[OP_STOREP_S], source, dest, idx, false);
break; break;
case ev_function: case ev_function:
QCC_PR_SimpleStatement(&pr_opcodes[OP_STOREP_FNC], source, dest, nullsref, false); QCC_PR_SimpleStatement(&pr_opcodes[OP_STOREP_FNC], source, dest, idx, false);
break; break;
case ev_field: case ev_field:
QCC_PR_SimpleStatement(&pr_opcodes[OP_STOREP_FLD], source, dest, nullsref, false); QCC_PR_SimpleStatement(&pr_opcodes[OP_STOREP_FLD], source, dest, idx, false);
break; break;
case ev_integer: case ev_integer:
if (!QCC_OPCodeValid(&pr_opcodes[OP_STOREP_I])) if (!QCC_OPCodeValid(&pr_opcodes[OP_STOREP_I]))
QCC_PR_SimpleStatement(&pr_opcodes[OP_STOREP_FLD], source, dest, nullsref, false); QCC_PR_SimpleStatement(&pr_opcodes[OP_STOREP_FLD], source, dest, idx, false);
else else
QCC_PR_SimpleStatement(&pr_opcodes[OP_STOREP_I], source, dest, nullsref, false); QCC_PR_SimpleStatement(&pr_opcodes[OP_STOREP_I], source, dest, idx, false);
break; break;
case ev_pointer: case ev_pointer:
if (!QCC_OPCodeValid(&pr_opcodes[OP_STOREP_P])) if (!QCC_OPCodeValid(&pr_opcodes[OP_STOREP_P]))
QCC_PR_SimpleStatement(&pr_opcodes[OP_STOREP_FLD], source, dest, nullsref, false); QCC_PR_SimpleStatement(&pr_opcodes[OP_STOREP_FLD], source, dest, idx, false);
else else
QCC_PR_SimpleStatement(&pr_opcodes[OP_STOREP_P], source, dest, nullsref, false); QCC_PR_SimpleStatement(&pr_opcodes[OP_STOREP_P], source, dest, idx, false);
break; break;
} }
if (freedest)
QCC_FreeTemp(dest);
} }
static QCC_sref_t QCC_LoadFromPointer(QCC_sref_t source, QCC_sref_t idx, QCC_type_t *type) static QCC_sref_t QCC_LoadFromPointer(QCC_sref_t source, QCC_sref_t idx, QCC_type_t *type)
{ {
@ -9055,7 +9083,7 @@ static void QCC_StoreToArray(QCC_sref_t base, QCC_sref_t index, QCC_sref_t sourc
//ptr = &base[index]; //ptr = &base[index];
addr = QCC_PR_Statement(&pr_opcodes[OP_GLOBALADDRESS], base, QCC_SupplyConversion(index, ev_integer, true), NULL); addr = QCC_PR_Statement(&pr_opcodes[OP_GLOBALADDRESS], base, QCC_SupplyConversion(index, ev_integer, true), NULL);
//*ptr = source //*ptr = source
QCC_StoreToPointer(addr, source, t); QCC_StoreToPointer(addr, nullsref, source, t);
source.sym->referenced = true; source.sym->referenced = true;
QCC_FreeTemp(addr); QCC_FreeTemp(addr);
QCC_FreeTemp(source); QCC_FreeTemp(source);
@ -9509,7 +9537,8 @@ QCC_sref_t QCC_RefToDef(QCC_ref_t *ref, pbool freetemps)
case REF_FIELD: case REF_FIELD:
return QCC_PR_ExpandField(ref->base, ref->index, ref->cast, freetemps?0:(STFL_PRESERVEA|STFL_PRESERVEB)); return QCC_PR_ExpandField(ref->base, ref->index, ref->cast, freetemps?0:(STFL_PRESERVEA|STFL_PRESERVEB));
case REF_STRING: case REF_STRING:
return QCC_PR_StatementFlags(&pr_opcodes[OP_LOADP_C], ref->base, ref->index, NULL, freetemps?0:(STFL_PRESERVEA|STFL_PRESERVEB)); idx = QCC_SupplyConversion(ref->index, ev_float, true);
return QCC_PR_StatementFlags(&pr_opcodes[OP_LOADP_C], ref->base, idx, NULL, freetemps?0:(STFL_PRESERVEA|STFL_PRESERVEB));
case REF_ACCESSOR: case REF_ACCESSOR:
if (ref->accessor && ref->accessor->getset_func[0].cast) if (ref->accessor && ref->accessor->getset_func[0].cast)
{ {
@ -9648,21 +9677,11 @@ QCC_sref_t QCC_StoreSRefToRef(QCC_ref_t *dest, QCC_sref_t source, pbool readable
break; break;
case REF_POINTER: case REF_POINTER:
source.sym->referenced = true; source.sym->referenced = true;
if (dest->index.cast) QCC_StoreToPointer(dest->base, dest->index.cast?QCC_SupplyConversion(dest->index, ev_integer, true):nullsref, source, dest->cast);
{ if (dest->base.sym)
QCC_sref_t addr; dest->base.sym->referenced = true;
addr = QCC_PR_StatementFlags(&pr_opcodes[OP_ADD_PIW], dest->base, QCC_SupplyConversion(dest->index, ev_integer, true), NULL, preservedest?STFL_PRESERVEA:0); if (!preservedest)
QCC_StoreToPointer(addr, source, dest->cast); QCC_FreeTemp(dest->base);
QCC_FreeTemp(addr);
}
else
{
QCC_StoreToPointer(dest->base, source, dest->cast);
if (dest->base.sym)
dest->base.sym->referenced = true;
if (!preservedest)
QCC_FreeTemp(dest->base);
}
if (!readable) if (!readable)
{ {
QCC_FreeTemp(source); QCC_FreeTemp(source);
@ -9672,17 +9691,18 @@ QCC_sref_t QCC_StoreSRefToRef(QCC_ref_t *dest, QCC_sref_t source, pbool readable
case REF_STRING: case REF_STRING:
{ {
QCC_sref_t addr; QCC_sref_t addr;
if (dest->index.cast)
{ if (dest->index.sym && !QCC_OPCode_StorePOffset())
addr = QCC_PR_Statement(&pr_opcodes[OP_ADD_I], dest->base, QCC_SupplyConversion(dest->index, ev_integer, true), NULL); { //can't do an offset store yet... bake any index into the pointer.
addr = dest->base;
if (dest->index.cast)
addr = QCC_PR_Statement(&pr_opcodes[OP_ADD_I], addr, QCC_SupplyConversion(dest->index, ev_integer, true), NULL);
QCC_PR_StatementFlags(&pr_opcodes[OP_STOREP_C], source, addr, NULL, STFL_DISCARDRESULT|(preservedest?STFL_PRESERVEB:0)|(readable?STFL_PRESERVEA:0));
} }
else else
{ {
addr = dest->base; QCC_PR_SimpleStatement(&pr_opcodes[OP_STOREP_C], source, dest->base, QCC_SupplyConversion(dest->index, ev_integer, true), false);
} }
// if (readable) //if we're returning source, make sure it can't get freed
// QCC_UnFreeTemp(source);
QCC_PR_StatementFlags(&pr_opcodes[OP_STOREP_C], source, addr, NULL, STFL_DISCARDRESULT|(preservedest?STFL_PRESERVEB:0)|(readable?STFL_PRESERVEA:0));
} }
break; break;
case REF_ACCESSOR: case REF_ACCESSOR:

View file

@ -1464,7 +1464,7 @@ static pbool QCC_WriteData (int crc)
externs->Printf("Progs should run on any QuakeC VM\n"); externs->Printf("Progs should run on any QuakeC VM\n");
break; break;
} }
qcc_targetformat = (qcc_targetformat==QCF_HEXEN2)?QCF_FTEH2:QCF_FTE; QCC_OPCodeSetTarget((qcc_targetformat==QCF_HEXEN2)?QCF_FTEH2:QCF_FTE);
//intentional fallthrough //intentional fallthrough
case QCF_FTEDEBUG: case QCF_FTEDEBUG:
case QCF_FTE: case QCF_FTE:
@ -4284,7 +4284,7 @@ static void QCC_PR_CommandLinePrecompilerOptions (void)
for (p = 0; targets[p].name; p++) for (p = 0; targets[p].name; p++)
if (!stricmp(myargv[i]+2, targets[p].name)) if (!stricmp(myargv[i]+2, targets[p].name))
{ {
qcc_targetformat = targets[p].target; QCC_OPCodeSetTarget(targets[p].target);
break; break;
} }
@ -4482,16 +4482,20 @@ static void QCC_SetDefaultProperties (void)
} }
} }
if (QCC_CheckParm ("-h2")) {
qcc_targetformat = QCF_HEXEN2; qcc_targetformat_t targ;
else if (QCC_CheckParm ("-fte")) if (QCC_CheckParm ("-h2"))
qcc_targetformat = QCF_FTE; targ = QCF_HEXEN2;
else if (QCC_CheckParm ("-fteh2")) else if (QCC_CheckParm ("-fte"))
qcc_targetformat = QCF_FTEH2; targ = QCF_FTE;
else if (QCC_CheckParm ("-dp")) else if (QCC_CheckParm ("-fteh2"))
qcc_targetformat = QCF_DARKPLACES; targ = QCF_FTEH2;
else else if (QCC_CheckParm ("-dp"))
qcc_targetformat = QCF_STANDARD; targ = QCF_DARKPLACES;
else
targ = QCF_STANDARD;
QCC_OPCodeSetTarget(targ);
}
//enable all warnings //enable all warnings