X-Git-Url: https://git.xonotic.org/?p=xonotic%2Fgmqcc.git;a=blobdiff_plain;f=ast.h;h=4720b402d4b3d4a9dbe28a209a604155e56db678;hp=1c4574a57182143982355403ae03c96ab1dcb566;hb=1497191e3ce1da4de07884f6fe13be3e2faaa261;hpb=8ce331b563e413f7d1c17bbe6bccc48657cfab90 diff --git a/ast.h b/ast.h index 1c4574a..4720b40 100644 --- a/ast.h +++ b/ast.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012, 2013 + * Copyright (C) 2012, 2013, 2014 * Wolfgang Bumiller * Dale Weiler * @@ -25,6 +25,8 @@ #define GMQCC_AST_HDR #include "ir.h" +typedef uint16_t ast_flag_t; + /* Note: I will not be using a _t suffix for the * "main" ast node types for now. */ @@ -51,6 +53,41 @@ typedef struct ast_breakcont_s ast_breakcont; typedef struct ast_switch_s ast_switch; typedef struct ast_label_s ast_label; typedef struct ast_goto_s ast_goto; +typedef struct ast_argpipe_s ast_argpipe; + +enum { + AST_FLAG_VARIADIC = 1 << 0, + AST_FLAG_NORETURN = 1 << 1, + AST_FLAG_INLINE = 1 << 2, + AST_FLAG_INITIALIZED = 1 << 3, + AST_FLAG_DEPRECATED = 1 << 4, + AST_FLAG_INCLUDE_DEF = 1 << 5, + AST_FLAG_IS_VARARG = 1 << 6, + AST_FLAG_ALIAS = 1 << 7, + AST_FLAG_ERASEABLE = 1 << 8, + AST_FLAG_ACCUMULATE = 1 << 9, + + /* An array declared as [] + * so that the size is taken from the initializer + */ + AST_FLAG_ARRAY_INIT = 1 << 10, + + AST_FLAG_FINAL_DECL = 1 << 11, + + /* Several coverage options + * AST_FLAG_COVERAGE means there was an explicit [[coverage]] attribute, + * which will overwrite the default set via the commandline switches. + * BLOCK_COVERAGE inserts coverage() calls into every basic block. + * In the future there might be more options like tracking variable access + * by creating get/set wrapper functions. + */ + AST_FLAG_COVERAGE = 1 << 12, + AST_FLAG_BLOCK_COVERAGE = 1 << 13, + + AST_FLAG_LAST, + AST_FLAG_TYPE_MASK = (AST_FLAG_VARIADIC | AST_FLAG_NORETURN), + AST_FLAG_COVERAGE_MASK = (AST_FLAG_BLOCK_COVERAGE) +}; enum { TYPE_ast_node, /* 0 */ @@ -73,7 +110,8 @@ enum { TYPE_ast_breakcont, /* 17 */ TYPE_ast_switch, /* 18 */ TYPE_ast_label, /* 19 */ - TYPE_ast_goto /* 20 */ + TYPE_ast_goto, /* 20 */ + TYPE_ast_argpipe /* 21 */ }; #define ast_istype(x, t) ( ((ast_node*)x)->nodetype == (TYPE_##t) ) @@ -85,7 +123,7 @@ enum { typedef void ast_node_delete(ast_node*); struct ast_node_common { - lex_ctx context; + lex_ctx_t context; /* I don't feel comfortable using keywords like 'delete' as names... */ ast_node_delete *destroy; int nodetype; @@ -132,7 +170,7 @@ struct ast_expression_common /* arrays get a member-count */ size_t count; ast_value* *params; - uint32_t flags; + ast_flag_t flags; /* void foo(string...) gets varparam set as a restriction * for variadic parameters */ @@ -145,18 +183,6 @@ struct ast_expression_common ir_value *outl; ir_value *outr; }; -#define AST_FLAG_VARIADIC (1<<0) -#define AST_FLAG_NORETURN (1<<1) -#define AST_FLAG_INLINE (1<<2) -#define AST_FLAG_INITIALIZED (1<<3) -#define AST_FLAG_DEPRECATED (1<<4) -#define AST_FLAG_INCLUDE_DEF (1<<5) -#define AST_FLAG_IS_VARARG (1<<6) -#define AST_FLAG_ALIAS (1<<7) -/* An array declared as [] - * so that the size is taken from the initializer */ -#define AST_FLAG_ARRAY_INIT (1<<8) -#define AST_FLAG_TYPE_MASK (AST_FLAG_VARIADIC | AST_FLAG_NORETURN) /* Value * @@ -166,14 +192,15 @@ struct ast_expression_common * is like creating a 'float foo', foo serving as the type's name. */ typedef union { - double vfloat; + qcfloat_t vfloat; int vint; - vector vvec; + vec3_t vvec; const char *vstring; int ventity; ast_function *vfunc; ast_value *vfield; } basic_value_t; + struct ast_value_s { ast_expression expression; @@ -187,6 +214,7 @@ struct ast_value_s bool isfield; /* this declares a field */ bool isimm; /* an immediate, not just const */ bool hasvalue; + bool inexact; /* inexact coming from folded expression */ basic_value_t constval; /* for TYPE_ARRAY we have an optional vector * of constants when an initializer list @@ -204,9 +232,12 @@ struct ast_value_s /* ONLY for arrays in progs version up to 6 */ ast_value *setter; ast_value *getter; + + + bool intrinsic; /* true if associated with intrinsic */ }; -ast_value* ast_value_new(lex_ctx ctx, const char *name, int qctype); +ast_value* ast_value_new(lex_ctx_t ctx, const char *name, int qctype); ast_value* ast_value_copy(const ast_value *self); /* This will NOT delete an underlying ast_function */ void ast_value_delete(ast_value*); @@ -223,12 +254,13 @@ bool ast_global_codegen(ast_value *self, ir_builder *ir, bool isfield); void ast_value_params_add(ast_value*, ast_value*); bool ast_compare_type(ast_expression *a, ast_expression *b); -ast_expression* ast_type_copy(lex_ctx ctx, const ast_expression *ex); +ast_expression* ast_type_copy(lex_ctx_t ctx, const ast_expression *ex); #define ast_type_adopt(a, b) ast_type_adopt_impl((ast_expression*)(a), (ast_expression*)(b)) void ast_type_adopt_impl(ast_expression *self, const ast_expression *other); void ast_type_to_string(ast_expression *e, char *buf, size_t bufsize); typedef enum ast_binary_ref_s { + AST_REF_NONE = 0, AST_REF_LEFT = 1 << 1, AST_REF_RIGHT = 1 << 2, AST_REF_ALL = (AST_REF_LEFT | AST_REF_RIGHT) @@ -247,9 +279,9 @@ struct ast_binary_s ast_expression *left; ast_expression *right; ast_binary_ref refs; - + bool right_first; }; -ast_binary* ast_binary_new(lex_ctx ctx, +ast_binary* ast_binary_new(lex_ctx_t ctx, int op, ast_expression *left, ast_expression *right); @@ -270,7 +302,7 @@ struct ast_binstore_s /* for &~= which uses the destination in a binary in source we can use this */ bool keep_dest; }; -ast_binstore* ast_binstore_new(lex_ctx ctx, +ast_binstore* ast_binstore_new(lex_ctx_t ctx, int storeop, int op, ast_expression *left, @@ -287,7 +319,7 @@ struct ast_unary_s int op; ast_expression *operand; }; -ast_unary* ast_unary_new(lex_ctx ctx, +ast_unary* ast_unary_new(lex_ctx_t ctx, int op, ast_expression *expr); @@ -302,7 +334,7 @@ struct ast_return_s ast_expression expression; ast_expression *operand; }; -ast_return* ast_return_new(lex_ctx ctx, +ast_return* ast_return_new(lex_ctx_t ctx, ast_expression *expr); /* Entity-field @@ -326,8 +358,8 @@ struct ast_entfield_s /* As can the field, it just must result in a value of TYPE_FIELD */ ast_expression *field; }; -ast_entfield* ast_entfield_new(lex_ctx ctx, ast_expression *entity, ast_expression *field); -ast_entfield* ast_entfield_new_force(lex_ctx ctx, ast_expression *entity, ast_expression *field, const ast_expression *outtype); +ast_entfield* ast_entfield_new(lex_ctx_t ctx, ast_expression *entity, ast_expression *field); +ast_entfield* ast_entfield_new_force(lex_ctx_t ctx, ast_expression *entity, ast_expression *field, const ast_expression *outtype); /* Member access: * @@ -336,13 +368,13 @@ ast_entfield* ast_entfield_new_force(lex_ctx ctx, ast_expression *entity, ast_ex */ struct ast_member_s { - ast_expression expression; + ast_expression expression; ast_expression *owner; unsigned int field; const char *name; bool rvalue; }; -ast_member* ast_member_new(lex_ctx ctx, ast_expression *owner, unsigned int field, const char *name); +ast_member* ast_member_new(lex_ctx_t ctx, ast_expression *owner, unsigned int field, const char *name); void ast_member_delete(ast_member*); bool ast_member_set_name(ast_member*, const char *name); @@ -359,11 +391,22 @@ bool ast_member_set_name(ast_member*, const char *name); */ struct ast_array_index_s { - ast_expression expression; + ast_expression expression; ast_expression *array; ast_expression *index; }; -ast_array_index* ast_array_index_new(lex_ctx ctx, ast_expression *array, ast_expression *index); +ast_array_index* ast_array_index_new(lex_ctx_t ctx, ast_expression *array, ast_expression *index); + +/* Vararg pipe node: + * + * copy all varargs starting from a specific index + */ +struct ast_argpipe_s +{ + ast_expression expression; + ast_expression *index; +}; +ast_argpipe* ast_argpipe_new(lex_ctx_t ctx, ast_expression *index); /* Store * @@ -372,12 +415,12 @@ ast_array_index* ast_array_index_new(lex_ctx ctx, ast_expression *array, ast_exp */ struct ast_store_s { - ast_expression expression; + ast_expression expression; int op; ast_expression *dest; ast_expression *source; }; -ast_store* ast_store_new(lex_ctx ctx, int op, +ast_store* ast_store_new(lex_ctx_t ctx, int op, ast_expression *d, ast_expression *s); /* If @@ -393,13 +436,13 @@ ast_store* ast_store_new(lex_ctx ctx, int op, */ struct ast_ifthen_s { - ast_expression expression; + ast_expression expression; ast_expression *cond; /* It's all just 'expressions', since an ast_block is one too. */ ast_expression *on_true; ast_expression *on_false; }; -ast_ifthen* ast_ifthen_new(lex_ctx ctx, ast_expression *cond, ast_expression *ontrue, ast_expression *onfalse); +ast_ifthen* ast_ifthen_new(lex_ctx_t ctx, ast_expression *cond, ast_expression *ontrue, ast_expression *onfalse); /* Ternary expressions... * @@ -416,13 +459,13 @@ ast_ifthen* ast_ifthen_new(lex_ctx ctx, ast_expression *cond, ast_expression *on */ struct ast_ternary_s { - ast_expression expression; + ast_expression expression; ast_expression *cond; /* It's all just 'expressions', since an ast_block is one too. */ ast_expression *on_true; ast_expression *on_false; }; -ast_ternary* ast_ternary_new(lex_ctx ctx, ast_expression *cond, ast_expression *ontrue, ast_expression *onfalse); +ast_ternary* ast_ternary_new(lex_ctx_t ctx, ast_expression *cond, ast_expression *ontrue, ast_expression *onfalse); /* A general loop node * @@ -449,7 +492,7 @@ continue: // a 'continue' will jump here */ struct ast_loop_s { - ast_expression expression; + ast_expression expression; ast_expression *initexpr; ast_expression *precond; ast_expression *postcond; @@ -464,7 +507,7 @@ struct ast_loop_s bool pre_not; bool post_not; }; -ast_loop* ast_loop_new(lex_ctx ctx, +ast_loop* ast_loop_new(lex_ctx_t ctx, ast_expression *initexpr, ast_expression *precond, bool pre_not, ast_expression *postcond, bool post_not, @@ -475,11 +518,11 @@ ast_loop* ast_loop_new(lex_ctx ctx, */ struct ast_breakcont_s { - ast_expression expression; - bool is_continue; - unsigned int levels; + ast_expression expression; + bool is_continue; + unsigned int levels; }; -ast_breakcont* ast_breakcont_new(lex_ctx ctx, bool iscont, unsigned int levels); +ast_breakcont* ast_breakcont_new(lex_ctx_t ctx, bool iscont, unsigned int levels); /* Switch Statements * @@ -497,13 +540,13 @@ typedef struct { } ast_switch_case; struct ast_switch_s { - ast_expression expression; + ast_expression expression; ast_expression *operand; ast_switch_case *cases; }; -ast_switch* ast_switch_new(lex_ctx ctx, ast_expression *op); +ast_switch* ast_switch_new(lex_ctx_t ctx, ast_expression *op); /* Label nodes * @@ -511,15 +554,16 @@ ast_switch* ast_switch_new(lex_ctx ctx, ast_expression *op); */ struct ast_label_s { - ast_expression expression; - const char *name; - ir_block *irblock; - ast_goto **gotos; + ast_expression expression; + const char *name; + ir_block *irblock; + ast_goto **gotos; + /* means it has not yet been defined */ - bool undefined; + bool undefined; }; -ast_label* ast_label_new(lex_ctx ctx, const char *name, bool undefined); +ast_label* ast_label_new(lex_ctx_t ctx, const char *name, bool undefined); /* GOTO nodes * @@ -527,13 +571,13 @@ ast_label* ast_label_new(lex_ctx ctx, const char *name, bool undefined); */ struct ast_goto_s { - ast_expression expression; - const char *name; - ast_label *target; - ir_block *irblock_from; + ast_expression expression; + const char *name; + ast_label *target; + ir_block *irblock_from; }; -ast_goto* ast_goto_new(lex_ctx ctx, const char *name); +ast_goto* ast_goto_new(lex_ctx_t ctx, const char *name); void ast_goto_set_label(ast_goto*, ast_label*); /* CALL node @@ -548,27 +592,27 @@ void ast_goto_set_label(ast_goto*, ast_label*); */ struct ast_call_s { - ast_expression expression; + ast_expression expression; ast_expression *func; - ast_expression* *params; + ast_expression **params; ast_expression *va_count; }; -ast_call* ast_call_new(lex_ctx ctx, +ast_call* ast_call_new(lex_ctx_t ctx, ast_expression *funcexpr); -bool ast_call_check_types(ast_call*); +bool ast_call_check_types(ast_call*, ast_expression *this_func_va_type); /* Blocks * */ struct ast_block_s { - ast_expression expression; + ast_expression expression; ast_value* *locals; ast_expression* *exprs; ast_expression* *collect; }; -ast_block* ast_block_new(lex_ctx ctx); +ast_block* ast_block_new(lex_ctx_t ctx); void ast_block_delete(ast_block*); void ast_block_set_type(ast_block*, ast_expression *from); void ast_block_collect(ast_block*, ast_expression*); @@ -587,13 +631,21 @@ bool GMQCC_WARN ast_block_add_expr(ast_block*, ast_expression*); */ struct ast_function_s { - ast_node node; + ast_node node; ast_value *vtype; const char *name; int builtin; + /* list of used-up names for statics without the count suffix */ + char **static_names; + /* number of static variables, by convention this includes the + * ones without the count-suffix - remember this when dealing + * with savegames. uint instead of size_t as %zu in printf is + * C99, so no windows support. */ + unsigned int static_count; + ir_function *ir_func; ir_block *curblock; ir_block **breakblocks; @@ -622,15 +674,22 @@ struct ast_function_s ast_value *fixedparams; ast_value *return_value; }; -ast_function* ast_function_new(lex_ctx ctx, const char *name, ast_value *vtype); +ast_function* ast_function_new(lex_ctx_t ctx, const char *name, ast_value *vtype); /* This will NOT delete the underlying ast_value */ void ast_function_delete(ast_function*); /* For "optimized" builds this can just keep returning "foo"... * or whatever... */ -/*const char* ast_function_label(ast_function*, const char *prefix);*/ +const char* ast_function_label(ast_function*, const char *prefix); bool ast_function_codegen(ast_function *self, ir_builder *builder); bool ast_generate_accessors(ast_value *asvalue, ir_builder *ir); +/* + * If the condition creates a situation where this becomes -1 size it means there are + * more AST_FLAGs than the type ast_flag_t is capable of holding. So either eliminate + * the AST flag count or change the ast_flag_t typedef to a type large enough to accomodate + * all the flags. + */ +typedef int static_assert_is_ast_flag_safe [((AST_FLAG_LAST) <= (ast_flag_t)(-1)) ? 1 : -1]; #endif