mirror of
https://github.com/DarkPlacesEngine/gmqcc.git
synced 2025-03-22 10:41:43 +00:00
casting explicitly to boolean values in early out logic
This commit is contained in:
parent
21c2fcb929
commit
ebc6954bf5
3 changed files with 53 additions and 1 deletions
31
ast.c
31
ast.c
|
@ -1521,6 +1521,16 @@ 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))
|
||||
*/
|
||||
|
||||
merge_id = vec_size(func->blocks);
|
||||
merge = ir_function_create_block(func->ir_func, ast_function_label(func, "sce_merge"));
|
||||
|
@ -1528,10 +1538,17 @@ bool ast_binary_codegen(ast_binary *self, ast_function *func, bool lvalue, ir_va
|
|||
cgen = self->left->expression.codegen;
|
||||
if (!(*cgen)((ast_expression*)(self->left), func, false, &left))
|
||||
return false;
|
||||
notop = type_not_instr[left->vtype];
|
||||
if (notop == AINSTR_END) {
|
||||
asterror(ast_ctx(self), "don't know how to cast to bool...");
|
||||
return false;
|
||||
}
|
||||
left = ir_block_create_unary(func->curblock, ast_function_label(func, "sce_not"), notop, left);
|
||||
|
||||
from_left = func->curblock;
|
||||
|
||||
other = ir_function_create_block(func->ir_func, ast_function_label(func, "sce_other"));
|
||||
if (self->op == INSTR_AND) {
|
||||
if (self->op == INSTR_OR) {
|
||||
if (!ir_block_create_if(func->curblock, left, other, merge))
|
||||
return false;
|
||||
} else {
|
||||
|
@ -1545,6 +1562,12 @@ bool ast_binary_codegen(ast_binary *self, ast_function *func, bool lvalue, ir_va
|
|||
cgen = self->right->expression.codegen;
|
||||
if (!(*cgen)((ast_expression*)(self->right), func, false, &right))
|
||||
return false;
|
||||
notop = type_not_instr[right->vtype];
|
||||
if (notop == AINSTR_END) {
|
||||
asterror(ast_ctx(self), "don't know how to cast to bool...");
|
||||
return false;
|
||||
}
|
||||
right = ir_block_create_unary(func->curblock, ast_function_label(func, "sce_not"), notop, right);
|
||||
from_right = func->curblock;
|
||||
|
||||
if (!ir_block_create_jump(func->curblock, merge))
|
||||
|
@ -1558,6 +1581,12 @@ 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);
|
||||
notop = type_not_instr[(*out)->vtype];
|
||||
if (notop == AINSTR_END) {
|
||||
asterror(ast_ctx(self), "don't know how to cast to bool...");
|
||||
return false;
|
||||
}
|
||||
*out = ir_block_create_unary(func->curblock, ast_function_label(func, "sce_final_not"), notop, *out);
|
||||
self->expression.outr = *out;
|
||||
return true;
|
||||
}
|
||||
|
|
1
gmqcc.h
1
gmqcc.h
|
@ -292,6 +292,7 @@ extern uint16_t type_storep_instr[TYPE_COUNT];
|
|||
/* other useful lists */
|
||||
extern uint16_t type_eq_instr[TYPE_COUNT];
|
||||
extern uint16_t type_ne_instr[TYPE_COUNT];
|
||||
extern uint16_t type_not_instr[TYPE_COUNT];
|
||||
|
||||
typedef struct {
|
||||
uint32_t offset; /* Offset in file of where data begins */
|
||||
|
|
22
ir.c
22
ir.c
|
@ -171,6 +171,28 @@ uint16_t type_ne_instr[TYPE_COUNT] = {
|
|||
AINSTR_END, /* array */
|
||||
};
|
||||
|
||||
uint16_t type_not_instr[TYPE_COUNT] = {
|
||||
INSTR_NOT_F, /* should use I when having integer support */
|
||||
INSTR_NOT_S,
|
||||
INSTR_NOT_F,
|
||||
INSTR_NOT_V,
|
||||
INSTR_NOT_ENT,
|
||||
INSTR_NOT_ENT,
|
||||
INSTR_NOT_FNC,
|
||||
INSTR_NOT_ENT, /* should use I */
|
||||
#if 0
|
||||
INSTR_NOT_I, /* integer type */
|
||||
#else
|
||||
INSTR_NOT_F,
|
||||
#endif
|
||||
|
||||
INSTR_NOT_V, /* variant, should never be accessed */
|
||||
|
||||
AINSTR_END, /* struct */
|
||||
AINSTR_END, /* union */
|
||||
AINSTR_END, /* array */
|
||||
};
|
||||
|
||||
static void irerror(lex_ctx ctx, const char *msg, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
|
Loading…
Reference in a new issue