mirror of
https://github.com/DarkPlacesEngine/gmqcc.git
synced 2025-03-21 18:30:52 +00:00
-fcorrect-logic now handles only vectors
This commit is contained in:
parent
7efc3a4c21
commit
0fe71af4ce
2 changed files with 22 additions and 68 deletions
57
ast.c
57
ast.c
|
@ -1707,64 +1707,42 @@ bool ast_binary_codegen(ast_binary *self, ast_function *func, bool lvalue, ir_va
|
|||
ir_block *from_left, *from_right;
|
||||
ir_instr *phi;
|
||||
size_t merge_id;
|
||||
uint16_t notop;
|
||||
|
||||
/* Note about casting to true boolean values:
|
||||
* We use a single NOT for sub expressions, and an
|
||||
* overall NOT at the end, and for that purpose swap
|
||||
* all the jump conditions in order for the NOT to get
|
||||
* doubled.
|
||||
* ie: (a && b) usually becomes (!!a ? !!b : !!a)
|
||||
* but we translate this to (!(!a ? !a : !b))
|
||||
*/
|
||||
|
||||
/* prepare end-block */
|
||||
merge_id = vec_size(func->ir_func->blocks);
|
||||
merge = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "sce_merge"));
|
||||
merge = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "sce_merge"));
|
||||
|
||||
/* generate the left expression */
|
||||
cgen = self->left->expression.codegen;
|
||||
if (!(*cgen)((ast_expression*)(self->left), func, false, &left))
|
||||
return false;
|
||||
if (!OPTS_FLAG(PERL_LOGIC)) {
|
||||
notop = type_not_instr[left->vtype];
|
||||
if (notop == AINSTR_END) {
|
||||
compile_error(ast_ctx(self), "don't know how to cast to bool...");
|
||||
return false;
|
||||
}
|
||||
left = ir_block_create_unary(func->curblock, ast_ctx(self),
|
||||
ast_function_label(func, "sce_not"),
|
||||
notop,
|
||||
left);
|
||||
}
|
||||
/* remember the block */
|
||||
from_left = func->curblock;
|
||||
|
||||
/* create a new block for the right expression */
|
||||
other = ir_function_create_block(ast_ctx(self), func->ir_func, ast_function_label(func, "sce_other"));
|
||||
if ( !(self->op == INSTR_OR) != !OPTS_FLAG(PERL_LOGIC) ) {
|
||||
if (self->op == INSTR_AND) {
|
||||
/* on AND: left==true -> other */
|
||||
if (!ir_block_create_if(func->curblock, ast_ctx(self), left, other, merge))
|
||||
return false;
|
||||
} else {
|
||||
/* on OR: left==false -> other */
|
||||
if (!ir_block_create_if(func->curblock, ast_ctx(self), left, merge, other))
|
||||
return false;
|
||||
}
|
||||
/* use the likely flag */
|
||||
vec_last(func->curblock->instr)->likely = true;
|
||||
|
||||
/* enter the right-expression's block */
|
||||
func->curblock = other;
|
||||
/* generate */
|
||||
cgen = self->right->expression.codegen;
|
||||
if (!(*cgen)((ast_expression*)(self->right), func, false, &right))
|
||||
return false;
|
||||
if (!OPTS_FLAG(PERL_LOGIC)) {
|
||||
notop = type_not_instr[right->vtype];
|
||||
if (notop == AINSTR_END) {
|
||||
compile_error(ast_ctx(self), "don't know how to cast to bool...");
|
||||
return false;
|
||||
}
|
||||
right = ir_block_create_unary(func->curblock, ast_ctx(self),
|
||||
ast_function_label(func, "sce_not"),
|
||||
notop,
|
||||
right);
|
||||
}
|
||||
/* remember block */
|
||||
from_right = func->curblock;
|
||||
|
||||
/* jump to the merge block */
|
||||
if (!ir_block_create_jump(func->curblock, ast_ctx(self), merge))
|
||||
return false;
|
||||
|
||||
|
@ -1776,17 +1754,6 @@ bool ast_binary_codegen(ast_binary *self, ast_function *func, bool lvalue, ir_va
|
|||
ir_phi_add(phi, from_left, left);
|
||||
ir_phi_add(phi, from_right, right);
|
||||
*out = ir_phi_value(phi);
|
||||
if (!OPTS_FLAG(PERL_LOGIC)) {
|
||||
notop = type_not_instr[(*out)->vtype];
|
||||
if (notop == AINSTR_END) {
|
||||
compile_error(ast_ctx(self), "don't know how to cast to bool...");
|
||||
return false;
|
||||
}
|
||||
*out = ir_block_create_unary(func->curblock, ast_ctx(self),
|
||||
ast_function_label(func, "sce_final_not"),
|
||||
notop,
|
||||
*out);
|
||||
}
|
||||
if (!*out)
|
||||
return false;
|
||||
self->expression.outr = *out;
|
||||
|
|
33
parser.c
33
parser.c
|
@ -893,14 +893,8 @@ static bool parser_sy_apply_operator(parser_t *parser, shunt *sy)
|
|||
if (OPTS_FLAG(CORRECT_LOGIC)) {
|
||||
/* non-floats need to be NOTed */
|
||||
for (i = 0; i < 2; ++i) {
|
||||
if (exprs[i]->expression.vtype != TYPE_FLOAT) {
|
||||
if (type_not_instr[exprs[i]->expression.vtype] == AINSTR_END) {
|
||||
ast_type_to_string(exprs[0], ty1, sizeof(ty1));
|
||||
ast_type_to_string(exprs[1], ty2, sizeof(ty2));
|
||||
parseerror(parser, "invalid types for logical operation with -fcorrect-logic: %s and %s", ty1, ty2);
|
||||
return false;
|
||||
}
|
||||
out = (ast_expression*)ast_unary_new(ctx, type_not_instr[exprs[i]->expression.vtype], exprs[i]);
|
||||
if (exprs[i]->expression.vtype == TYPE_VECTOR) {
|
||||
out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_V, exprs[i]);
|
||||
if (!out) break;
|
||||
out = (ast_expression*)ast_unary_new(ctx, INSTR_NOT_F, out);
|
||||
if (!out) break;
|
||||
|
@ -1901,7 +1895,8 @@ static ast_expression* process_condition(parser_t *parser, ast_expression *cond,
|
|||
ast_unary *unary;
|
||||
ast_expression *prev;
|
||||
|
||||
if (OPTS_FLAG(FALSE_EMPTY_STRINGS) && cond->expression.vtype == TYPE_STRING) {
|
||||
if (OPTS_FLAG(FALSE_EMPTY_STRINGS) && cond->expression.vtype == TYPE_STRING)
|
||||
{
|
||||
prev = cond;
|
||||
cond = (ast_expression*)ast_unary_new(ast_ctx(cond), INSTR_NOT_S, cond);
|
||||
if (!cond) {
|
||||
|
@ -1911,22 +1906,15 @@ static ast_expression* process_condition(parser_t *parser, ast_expression *cond,
|
|||
}
|
||||
ifnot = !ifnot;
|
||||
}
|
||||
if (OPTS_FLAG(CORRECT_LOGIC) &&
|
||||
!(cond->expression.vtype == TYPE_STRING && OPTS_FLAG(TRUE_EMPTY_STRINGS)))
|
||||
else if (OPTS_FLAG(CORRECT_LOGIC) && cond->expression.vtype == TYPE_VECTOR)
|
||||
{
|
||||
/* non-floats need to use NOT; except for strings on -ftrue-empty-strings */
|
||||
unary = (ast_unary*)cond;
|
||||
if (!ast_istype(cond, ast_unary) || unary->op < INSTR_NOT_F || unary->op > INSTR_NOT_FNC)
|
||||
/* vector types need to be cast to true booleans */
|
||||
ast_binary *bin = (ast_binary*)cond;
|
||||
if (!OPTS_FLAG(PERL_LOGIC) || !ast_istype(cond, ast_binary) || !(bin->op == INSTR_AND || bin->op == INSTR_OR))
|
||||
{
|
||||
/* use the right NOT_ */
|
||||
/* in perl-logic, AND and OR take care of the -fcorrect-logic */
|
||||
prev = cond;
|
||||
cond = (ast_expression*)ast_unary_new(ast_ctx(cond), type_not_instr[cond->expression.vtype], cond);
|
||||
|
||||
/*
|
||||
* cppcheck: it thinks there is a possible null pointer dereference
|
||||
* otherwise it would be "redundant" to check it ast_unary_new returned
|
||||
* null, it's wrong.
|
||||
*/
|
||||
cond = (ast_expression*)ast_unary_new(ast_ctx(cond), INSTR_NOT_V, cond);
|
||||
if (!cond) {
|
||||
ast_unref(prev);
|
||||
parseerror(parser, "internal error: failed to process condition");
|
||||
|
@ -1938,7 +1926,6 @@ static ast_expression* process_condition(parser_t *parser, ast_expression *cond,
|
|||
|
||||
unary = (ast_unary*)cond;
|
||||
while (ast_istype(cond, ast_unary) && unary->op == INSTR_NOT_F)
|
||||
/*&& unary->operand->expression.vtype != TYPE_STRING) */
|
||||
{
|
||||
cond = unary->operand;
|
||||
unary->operand = NULL;
|
||||
|
|
Loading…
Reference in a new issue