X-Git-Url: https://git.xonotic.org/?p=xonotic%2Fgmqcc.git;a=blobdiff_plain;f=gmqcc.h;h=583726e4a932cde7a9dfde903dc354211a5fa34d;hp=d767b7b547c88477d98ab950a8ef62d0cbc88d63;hb=206952b920856ef53b953d3d477f00869b7191fd;hpb=422c085fbab8d98aae65f70cd2315b3c60673a26 diff --git a/gmqcc.h b/gmqcc.h index d767b7b..583726e 100644 --- a/gmqcc.h +++ b/gmqcc.h @@ -1,6 +1,6 @@ /* - * Copyright (C) 2012 - * Dale Weiler + * Copyright (C) 2012 + * Dale Weiler, Wolfgang Bumiller * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in @@ -58,6 +58,22 @@ # endif # endif /* !__cplusplus */ +/* + * Of some functions which are generated we want to make sure + * that the result isn't ignored. To find such function calls, + * we use this macro. + */ +#if defined(__GNUC__) || defined(__CLANG__) +# define GMQCC_WARN __attribute__((warn_unused_result)) +#else +# define GMQCC_WARN +#endif +/* + * This is a hack to silent clang regarding empty + * body if statements. + */ +#define GMQCC_SUPRESS_EMPTY_BODY do { } while (0) + /* * stdint.h and inttypes.h -less subset * for systems that don't have it, which we must @@ -75,7 +91,7 @@ typedef int int16_t; typedef unsigned int uint16_t; #endif -#if INT_MAX == 0x7FFFFFFF +#if INT_MAX == 0x7FFFFFFF typedef int int32_t; typedef unsigned int uint32_t; #elif LONG_MAX == 0x7FFFFFFF @@ -88,7 +104,7 @@ #else typedef unsigned int uintptr_t; typedef int intptr_t; -#endif +#endif /* Ensure type sizes are correct: */ typedef char uint8_size_is_correct [sizeof(uint8_t) == 1?1:-1]; typedef char uint16_size_if_correct [sizeof(uint16_t) == 2?1:-1]; @@ -102,18 +118,18 @@ typedef char intptr_size_is_correct [sizeof(uintptr_t)== sizeof(int*)?1:-1]; //=================================================================== //============================ lex.c ================================ //=================================================================== -struct lex_file { +typedef struct lex_file_t { FILE *file; /* file handler */ char *name; /* name of file */ - char peek [5]; + char peek [5]; char lastok[8192]; - + int last; /* last token */ int current; /* current token */ int length; /* bytes left to parse */ int size; /* never changes (size of file) */ int line; /* what line are we on? */ -}; +} lex_file; /* * It's important that this table never exceed 32 keywords, the ascii @@ -147,17 +163,18 @@ enum { * and > the last type token which is TOKEN_VOID */ enum { - LEX_COMMENT = 1128, + LEX_COMMENT = 1128, LEX_CHRLIT , LEX_STRLIT , LEX_IDENT }; -int lex_token (struct lex_file *); -void lex_reset (struct lex_file *); -void lex_close (struct lex_file *); -struct lex_file *lex_include(struct lex_file *, char *); -struct lex_file *lex_open (FILE *); +int lex_token (lex_file *); +void lex_reset (lex_file *); +void lex_close (lex_file *); +void lex_parse (lex_file *); +lex_file *lex_include(lex_file *, const char *); +void lex_init (const char *, lex_file **); //=================================================================== //========================== error.c ================================ @@ -167,12 +184,12 @@ struct lex_file *lex_open (FILE *); #define ERROR_INTERNAL (SHRT_MAX+2) #define ERROR_COMPILER (SHRT_MAX+3) #define ERROR_PREPRO (SHRT_MAX+4) -int error(struct lex_file *, int, const char *, ...); +int error(lex_file *, int, const char *, ...); //=================================================================== //========================== parse.c ================================ //=================================================================== -int parse_gen(struct lex_file *); +int parse_gen(lex_file *); //=================================================================== //========================== typedef.c ============================== @@ -184,7 +201,7 @@ typedef struct typedef_node_t { void typedef_init(); void typedef_clear(); typedef_node *typedef_find(const char *); -int typedef_add (struct lex_file *file, const char *, const char *); +int typedef_add (lex_file *file, const char *, const char *); //=================================================================== @@ -194,14 +211,18 @@ void *util_memory_a (unsigned int, unsigned int, const char *); void util_memory_d (void *, unsigned int, const char *); void util_meminfo (); +bool util_strupper (const char *); +bool util_strdigit (const char *); char *util_strdup (const char *); -char *util_strrq (char *); -char *util_strrnl (char *); +char *util_strrq (const char *); +char *util_strrnl (const char *); +char *util_strsws (const char *); +char *util_strchp (const char *, const char *); void util_debug (const char *, const char *, ...); int util_getline (char **, size_t *, FILE *); void util_endianswap (void *, int, int); -uint32_t util_crc32(const char *, int, register const short); +uint32_t util_crc32(const char *, int, register const short); #ifdef NOTRACK # define mem_a(x) malloc(x) @@ -212,6 +233,8 @@ uint32_t util_crc32(const char *, int, register const short); #endif /* Builds vector type (usefull for inside structures) */ +#define VECTOR_SNAP(X,Y) X ## Y +#define VECTOR_FILL(X,Y) VECTOR_SNAP(X,Y) #define VECTOR_TYPE(T,N) \ T* N##_data = NULL; \ long N##_elements = 0; \ @@ -242,13 +265,12 @@ uint32_t util_crc32(const char *, int, register const short); elements--; \ while (N##_add(*++elements) != -1 && len--); \ return N##_elements; \ - } + } \ + typedef char VECTOR_FILL(extra_semicolon_,__COUNTER__) /* Builds a full vector inspot */ #define VECTOR_MAKE(T,N) \ VECTOR_TYPE(T,N); \ VECTOR_CORE(T,N) -/* Builds a vector add function pointer for inside structures */ -#define VECTOR_IMPL(T,N) int (*N##_add)(T) //=================================================================== //=========================== code.c ================================ @@ -261,7 +283,9 @@ enum { TYPE_ENTITY , TYPE_FIELD , TYPE_FUNCTION , - TYPE_POINTER + TYPE_POINTER , + /* TYPE_INTEGER , */ + TYPE_VARIANT , }; /* @@ -281,23 +305,23 @@ enum { typedef struct { uint16_t opcode; - + /* operand 1 */ union { int16_t s1; /* signed */ uint16_t u1; /* unsigned */ - }; + } o1; /* operand 2 */ union { int16_t s2; /* signed */ uint16_t u2; /* unsigned */ - }; + } o2; /* operand 3 */ union { int16_t s3; /* signed */ uint16_t u3; /* unsigned */ - }; - + } o3; + /* * This is the same as the structure in darkplaces * { @@ -339,8 +363,8 @@ typedef struct { uint8_t argsize[8]; /* size of arguments (keep 8 always?) */ } prog_section_function; -/* - * Instructions +/* + * Instructions * These are the external instructions supported by the interperter * this is what things compile to (from the C code). */ @@ -410,13 +434,20 @@ enum { INSTR_AND, INSTR_OR, INSTR_BITAND, - INSTR_BITOR + INSTR_BITOR, + + /* Virtual instructions used by the IR + * Keep at the end! + */ + VINSTR_PHI, + VINSTR_JUMP, + VINSTR_COND, }; /* * The symbols below are created by the following * expanded macros: - * + * * VECTOR_MAKE(prog_section_statement, code_statements); * VECTOR_MAKE(prog_section_def, code_defs ); * VECTOR_MAKE(prog_section_field, code_fields ); @@ -455,7 +486,7 @@ void code_init (); //=================================================================== static const struct { const char *m; /* menomic */ - const size_t o; /* operands */ + const size_t o; /* operands */ const size_t l; /* menomic len */ } const asm_instr[] = { [INSTR_DONE] = { "DONE" , 1, 4 }, @@ -543,4 +574,135 @@ extern bool opts_memchk; extern bool opts_darkplaces_stringtablebug; extern bool opts_omit_nullcode; extern int opts_compiler; +//====================================================================== +//============================= ast.c ================================== +//====================================================================== +#define MEM_VECTOR_PROTO(Towner, Tmem, mem) \ + bool GMQCC_WARN Towner##_##mem##_add(Towner*, Tmem); \ + bool GMQCC_WARN Towner##_##mem##_remove(Towner*, size_t) + +#define MEM_VECTOR_PROTO_ALL(Towner, Tmem, mem) \ + MEM_VECTOR_PROTO(Towner, Tmem, mem); \ + bool GMQCC_WARN Towner##_##mem##_find(Towner*, Tmem, size_t*); \ + void Towner##_##mem##_clear(Towner*) + +#define MEM_VECTOR_MAKE(Twhat, name) \ + Twhat *name; \ + size_t name##_count; \ + size_t name##_alloc + +#define _MEM_VEC_FUN_ADD(Tself, Twhat, mem) \ +bool GMQCC_WARN Tself##_##mem##_add(Tself *self, Twhat f) \ +{ \ + Twhat *reall; \ + if (self->mem##_count == self->mem##_alloc) { \ + if (!self->mem##_alloc) { \ + self->mem##_alloc = 16; \ + } else { \ + self->mem##_alloc *= 2; \ + } \ + reall = (Twhat*)mem_a(sizeof(Twhat) * self->mem##_alloc); \ + if (!reall) { \ + return false; \ + } \ + memcpy(reall, self->mem, sizeof(Twhat) * self->mem##_count); \ + mem_d(self->mem); \ + self->mem = reall; \ + } \ + self->mem[self->mem##_count++] = f; \ + return true; \ +} + +#define _MEM_VEC_FUN_REMOVE(Tself, Twhat, mem) \ +bool GMQCC_WARN Tself##_##mem##_remove(Tself *self, size_t idx) \ +{ \ + size_t i; \ + Twhat *reall; \ + if (idx >= self->mem##_count) { \ + return true; /* huh... */ \ + } \ + for (i = idx; i < self->mem##_count-1; ++i) { \ + self->mem[i] = self->mem[i+1]; \ + } \ + self->mem##_count--; \ + if (self->mem##_count < self->mem##_count/2) { \ + self->mem##_alloc /= 2; \ + reall = (Twhat*)mem_a(sizeof(Twhat) * self->mem##_count); \ + if (!reall) { \ + return false; \ + } \ + memcpy(reall, self->mem, sizeof(Twhat) * self->mem##_count); \ + mem_d(self->mem); \ + self->mem = reall; \ + } \ + return true; \ +} + +#define _MEM_VEC_FUN_FIND(Tself, Twhat, mem) \ +bool GMQCC_WARN Tself##_##mem##_find(Tself *self, Twhat obj, size_t *idx) \ +{ \ + size_t i; \ + for (i = 0; i < self->mem##_count; ++i) { \ + if (self->mem[i] == obj) { \ + if (idx) { \ + *idx = i; \ + } \ + return true; \ + } \ + } \ + return false; \ +} + +#define _MEM_VEC_FUN_CLEAR(Tself, mem) \ +void Tself##_##mem##_clear(Tself *self) \ +{ \ + if (!self->mem) \ + return; \ + mem_d((void*) self->mem); \ + self->mem = NULL; \ + self->mem##_count = 0; \ + self->mem##_alloc = 0; \ +} + +#define MEM_VECTOR_CLEAR(owner, mem) \ + if ((owner)->mem) \ + mem_d((void*)((owner)->mem)); \ + (owner)->mem = NULL; \ + (owner)->mem##_count = 0; \ + (owner)->mem##_alloc = 0 + +#define MEM_VECTOR_INIT(owner, mem) \ +{ \ + (owner)->mem = NULL; \ + (owner)->mem##_count = 0; \ + (owner)->mem##_alloc = 0; \ +} + +#define MEM_VEC_FUNCTIONS(Tself, Twhat, mem) \ +_MEM_VEC_FUN_REMOVE(Tself, Twhat, mem) \ +_MEM_VEC_FUN_ADD(Tself, Twhat, mem) + +#define MEM_VEC_FUNCTIONS_ALL(Tself, Twhat, mem) \ +MEM_VEC_FUNCTIONS(Tself, Twhat, mem) \ +_MEM_VEC_FUN_CLEAR(Tself, mem) \ +_MEM_VEC_FUN_FIND(Tself, Twhat, mem) + +enum store_types { + store_global, + store_local, /* local, assignable for now, should get promoted later */ + store_value, /* unassignable */ +}; + +typedef struct { + float x, y, z; +} vector; + +/* + * A shallow copy of a lex_file to remember where which ast node + * came from. + */ +typedef struct { + const char *file; + size_t line; +} lex_ctx; #endif