mirror of
https://github.com/DarkPlacesEngine/gmqcc.git
synced 2025-03-22 18:51:24 +00:00
Implement [[eraseable]] attribute. When used with a function it instructs the AST (which than transfers logic to the IR) that the function (or variable) is potentially unused (verified by checking the read count). This than propogates through the IR and prevents the IR from generating both the definition and global/function. The intrinsics system uses this as well to prevent intrinsic functions from being generated unless they're used.
This commit is contained in:
parent
ceb79f1897
commit
a7c1f6f021
6 changed files with 43 additions and 2 deletions
14
ast.c
14
ast.c
|
@ -1385,6 +1385,8 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield)
|
|||
self->ir_v = func->value;
|
||||
if (self->expression.flags & AST_FLAG_INCLUDE_DEF)
|
||||
self->ir_v->flags |= IR_FLAG_INCLUDE_DEF;
|
||||
if (self->expression.flags & AST_FLAG_ERASEABLE)
|
||||
self->ir_v->flags |= IR_FLAG_ERASEABLE;
|
||||
/* The function is filled later on ast_function_codegen... */
|
||||
return true;
|
||||
}
|
||||
|
@ -1426,8 +1428,11 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield)
|
|||
v->unique_life = true;
|
||||
v->locked = true;
|
||||
array->ir_v = self->ir_v = v;
|
||||
|
||||
if (self->expression.flags & AST_FLAG_INCLUDE_DEF)
|
||||
self->ir_v->flags |= IR_FLAG_INCLUDE_DEF;
|
||||
if (self->expression.flags & AST_FLAG_ERASEABLE)
|
||||
self->ir_v->flags |= IR_FLAG_ERASEABLE;
|
||||
|
||||
namelen = strlen(self->name);
|
||||
name = (char*)mem_a(namelen + 16);
|
||||
|
@ -1460,6 +1465,9 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield)
|
|||
self->ir_v = v;
|
||||
if (self->expression.flags & AST_FLAG_INCLUDE_DEF)
|
||||
self->ir_v->flags |= IR_FLAG_INCLUDE_DEF;
|
||||
|
||||
if (self->expression.flags & AST_FLAG_ERASEABLE)
|
||||
self->ir_v->flags |= IR_FLAG_ERASEABLE;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -1489,8 +1497,11 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield)
|
|||
v->context = ast_ctx(self);
|
||||
v->unique_life = true;
|
||||
v->locked = true;
|
||||
|
||||
if (self->expression.flags & AST_FLAG_INCLUDE_DEF)
|
||||
v->flags |= IR_FLAG_INCLUDE_DEF;
|
||||
if (self->expression.flags & AST_FLAG_ERASEABLE)
|
||||
self->ir_v->flags |= IR_FLAG_ERASEABLE;
|
||||
|
||||
namelen = strlen(self->name);
|
||||
name = (char*)mem_a(namelen + 16);
|
||||
|
@ -1531,8 +1542,11 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield)
|
|||
/* link us to the ir_value */
|
||||
v->cvq = self->cvq;
|
||||
self->ir_v = v;
|
||||
|
||||
if (self->expression.flags & AST_FLAG_INCLUDE_DEF)
|
||||
self->ir_v->flags |= IR_FLAG_INCLUDE_DEF;
|
||||
if (self->expression.flags & AST_FLAG_ERASEABLE)
|
||||
self->ir_v->flags |= IR_FLAG_ERASEABLE;
|
||||
|
||||
/* initialize */
|
||||
if (self->hasvalue) {
|
||||
|
|
3
ast.h
3
ast.h
|
@ -155,9 +155,10 @@ struct ast_expression_common
|
|||
#define AST_FLAG_INCLUDE_DEF (1<<5)
|
||||
#define AST_FLAG_IS_VARARG (1<<6)
|
||||
#define AST_FLAG_ALIAS (1<<7)
|
||||
#define AST_FLAG_ERASEABLE (1<<8)
|
||||
/* An array declared as []
|
||||
* so that the size is taken from the initializer */
|
||||
#define AST_FLAG_ARRAY_INIT (1<<8)
|
||||
#define AST_FLAG_ARRAY_INIT (1<<9)
|
||||
#define AST_FLAG_TYPE_MASK (AST_FLAG_VARIADIC | AST_FLAG_NORETURN)
|
||||
|
||||
/* Value
|
||||
|
|
1
intrin.c
1
intrin.c
|
@ -50,6 +50,7 @@
|
|||
"__builtin_" NAME, \
|
||||
(VALUE) \
|
||||
); \
|
||||
(VALUE)->expression.flags |= AST_FLAG_ERASEABLE; \
|
||||
} while (0)
|
||||
|
||||
#define INTRIN_REG(FUNC, VALUE) \
|
||||
|
|
16
ir.c
16
ir.c
|
@ -3464,6 +3464,14 @@ static bool gen_global_function_code(ir_builder *ir, ir_value *global)
|
|||
if (irfun->builtin)
|
||||
return true;
|
||||
|
||||
/*
|
||||
* If there is no definition and the thing is eraseable, we can ignore
|
||||
* outputting the function to begin with.
|
||||
*/
|
||||
if (global->flags & IR_FLAG_ERASEABLE && irfun->code_function_def < 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (irfun->code_function_def < 0) {
|
||||
irerror(irfun->context, "`%s`: IR global wasn't generated, failed to access function-def", irfun->name);
|
||||
return false;
|
||||
|
@ -3564,6 +3572,14 @@ static bool ir_builder_gen_global(ir_builder *self, ir_value *global, bool isloc
|
|||
{
|
||||
pushdef = true;
|
||||
|
||||
/*
|
||||
* if we're eraseable and the function isn't referenced ignore outputting
|
||||
* the function.
|
||||
*/
|
||||
if (global->flags & IR_FLAG_ERASEABLE && vec_size(global->reads) == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (OPTS_OPTIMIZATION(OPTIM_STRIP_CONSTANT_NAMES) &&
|
||||
!(global->flags & IR_FLAG_INCLUDE_DEF) &&
|
||||
(global->name[0] == '#' || global->cvq == CV_CONST))
|
||||
|
|
1
ir.h
1
ir.h
|
@ -231,6 +231,7 @@ typedef struct ir_function_s
|
|||
#define IR_FLAG_HAS_UNINITIALIZED (1<<2)
|
||||
#define IR_FLAG_HAS_GOTO (1<<3)
|
||||
#define IR_FLAG_INCLUDE_DEF (1<<4)
|
||||
#define IR_FLAG_ERASEABLE (1<<5)
|
||||
#define IR_FLAG_MASK_NO_OVERLAP (IR_FLAG_HAS_ARRAYS | IR_FLAG_HAS_UNINITIALIZED)
|
||||
#define IR_FLAG_MASK_NO_LOCAL_TEMPS (IR_FLAG_HAS_ARRAYS | IR_FLAG_HAS_UNINITIALIZED)
|
||||
|
||||
|
|
10
parser.c
10
parser.c
|
@ -2738,7 +2738,15 @@ static bool parse_qualifiers(parser_t *parser, bool with_local, int *cvq, bool *
|
|||
else if (!strcmp(parser_tokval(parser), "inline")) {
|
||||
flags |= AST_FLAG_INLINE;
|
||||
if (!parser_next(parser) || parser->tok != TOKEN_ATTRIBUTE_CLOSE) {
|
||||
parseerror(parser, "`noref` attribute has no parameters, expected `]]`");
|
||||
parseerror(parser, "`inline` attribute has no parameters, expected `]]`");
|
||||
*cvq = CV_WRONG;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (!strcmp(parser_tokval(parser), "eraseable")) {
|
||||
flags |= AST_FLAG_ERASEABLE;
|
||||
if (!parser_next(parser) || parser->tok != TOKEN_ATTRIBUTE_CLOSE) {
|
||||
parseerror(parser, "`eraseable` attribute has no parameters, expected `]]`");
|
||||
*cvq = CV_WRONG;
|
||||
return false;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue