]> git.xonotic.org Git - xonotic/gmqcc.git/commitdiff
Merge branch 'master' into blub/bc3
authorWolfgang (Blub) Bumiller <blub@speed.at>
Wed, 8 Aug 2012 10:05:08 +0000 (12:05 +0200)
committerWolfgang (Blub) Bumiller <blub@speed.at>
Wed, 8 Aug 2012 10:05:08 +0000 (12:05 +0200)
1  2 
ast.c
ast.h
gmqcc.h
ir.c
ir.h

diff --combined ast.c
index 8182f7977cd6cbdcb8f3e94734decf7c03338f49,0b61fe0653afbf5b6b6701ff714d0ee98899656c..65c6934b000d2ce65dec16a0ffed4a0f897a7d80
--- 1/ast.c
--- 2/ast.c
+++ b/ast.c
@@@ -32,7 -32,7 +32,7 @@@
      if (!self) {                                                    \
          return NULL;                                                \
      }                                                               \
-     ast_node_init((ast_node*)self, ctx);                            \
+     ast_node_init((ast_node*)self, ctx, TYPE_##T);                  \
      ( (ast_node*)self )->node.destroy = (ast_node_delete*)destroyfn
  
  /* It must not be possible to get here. */
@@@ -43,11 -43,12 +43,12 @@@ static GMQCC_NORETURN void _ast_node_de
  }
  
  /* Initialize main ast node aprts */
- static void ast_node_init(ast_node *self, lex_ctx ctx)
+ static void ast_node_init(ast_node *self, lex_ctx ctx, int nodetype)
  {
      self->node.context = ctx;
      self->node.destroy = &_ast_node_destroy;
      self->node.keep    = false;
+     self->node.nodetype = nodetype;
  }
  
  /* General expression initialization */
@@@ -201,18 -202,6 +202,18 @@@ ast_binary* ast_binary_new(lex_ctx ctx
      self->left = left;
      self->right = right;
  
 +    if (op >= INSTR_EQ_F && op <= INSTR_GT)
 +        self->expression.vtype = TYPE_FLOAT;
 +    else if (op == INSTR_AND || op == INSTR_OR ||
 +             op == INSTR_BITAND || op == INSTR_BITOR)
 +        self->expression.vtype = TYPE_FLOAT;
 +    else if (op == INSTR_MUL_VF || op == INSTR_MUL_FV)
 +        self->expression.vtype = TYPE_VECTOR;
 +    else if (op == INSTR_MUL_V)
 +        self->expression.vtype = TYPE_FLOAT;
 +    else
 +        self->expression.vtype = left->expression.vtype;
 +
      return self;
  }
  
@@@ -602,10 -591,8 +603,10 @@@ bool ast_global_codegen(ast_value *self
      }
  
      v = ir_builder_create_global(ir, self->name, self->expression.vtype);
 -    if (!v)
 +    if (!v) {
 +        printf("ir_builder_create_global failed\n");
          return false;
 +    }
  
      if (self->isconst) {
          switch (self->expression.vtype)
diff --combined ast.h
index 61bacce6787ceaff6f5adf563a803c1bc97866a0,32b28e537e2f2a08e760df8396c0c9b2dfe2e300..c96484f66b933e24143714e5d808d26fd29dff06
--- 1/ast.h
--- 2/ast.h
+++ b/ast.h
@@@ -44,6 -44,25 +44,25 @@@ typedef struct ast_call_s       ast_cal
  typedef struct ast_unary_s      ast_unary;
  typedef struct ast_return_s     ast_return;
  
+ enum {
+     TYPE_ast_node,
+     TYPE_ast_expression,
+     TYPE_ast_value,
+     TYPE_ast_function,
+     TYPE_ast_block,
+     TYPE_ast_binary,
+     TYPE_ast_store,
+     TYPE_ast_entfield,
+     TYPE_ast_ifthen,
+     TYPE_ast_ternary,
+     TYPE_ast_loop,
+     TYPE_ast_call,
+     TYPE_ast_unary,
+     TYPE_ast_return
+ };
+ #define ast_istype(x, t) ( ((ast_node_common*)x)->nodetype == (t) )
  /* Node interface with common components
   */
  typedef void ast_node_delete(ast_node*);
@@@ -52,6 -71,7 +71,7 @@@ typedef struc
      lex_ctx          context;
      /* I don't feel comfortable using keywords like 'delete' as names... */
      ast_node_delete *destroy;
+     int              nodetype;
      /* keep: if a node contains this node, 'keep'
       * prevents its dtor from destroying this node as well.
       */
@@@ -111,8 -131,6 +131,8 @@@ struct ast_value_
          const char   *vstring;
          int           ventity;
          ast_function *vfunc;
 +        quaternion    vquat;
 +        matrix        vmat;
      } constval;
  
      ir_value *ir_v;
diff --combined gmqcc.h
index f27fc9ec38cdac2e73aed56c308d78e30812b34a,2da9d8c9c04e39bb2a8f3babd0ff094357745708..a296e16523cd02f1663433ee52ab60d0572878f4
+++ b/gmqcc.h
@@@ -179,6 -179,95 +179,6 @@@ typedef char int64_size_is_correct  [si
  typedef char uintptr_size_is_correct[sizeof(intptr_t) == sizeof(int*)?1:-1];
  typedef char intptr_size_is_correct [sizeof(uintptr_t)== sizeof(int*)?1:-1];
  
 -/*===================================================================*/
 -/*============================ lex.c ================================*/
 -/*===================================================================*/
 -typedef struct lex_file_t {
 -    FILE *file;        /* file handler */
 -    char *name;        /* name of file */
 -    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
 - * table starts at 33 (and we don't want conflicts)
 - */
 -enum {
 -    TOKEN_DO       ,
 -    TOKEN_ELSE     ,
 -    TOKEN_IF       ,
 -    TOKEN_WHILE    ,
 -    TOKEN_BREAK    ,
 -    TOKEN_CONTINUE ,
 -    TOKEN_RETURN   ,
 -    TOKEN_GOTO     ,
 -    TOKEN_FOR      ,   /* extension */
 -    TOKEN_TYPEDEF  ,   /* extension */
 -
 -    /* ensure the token types are out of the  */
 -    /* bounds of anyothers that may conflict. */
 -    TOKEN_FLOAT    = 110,
 -    TOKEN_VECTOR        ,
 -    TOKEN_STRING        ,
 -    TOKEN_ENTITY        ,
 -    TOKEN_VOID
 -};
 -
 -/*
 - * Lexer state constants, these are numbers for where exactly in
 - * the lexing the lexer is at. Or where it decided to stop if a lexer
 - * error occurs.  These numbers must be > where the ascii-table ends
 - * and > the last type token which is TOKEN_VOID
 - */
 -enum {
 -    LEX_COMMENT = 1128,
 -    LEX_CHRLIT        ,
 -    LEX_STRLIT        ,
 -    LEX_IDENT
 -};
 -
 -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 ================================*/
 -/*===================================================================*/
 -#define ERROR_LEX      (SHRT_MAX+0)
 -#define ERROR_PARSE    (SHRT_MAX+1)
 -#define ERROR_INTERNAL (SHRT_MAX+2)
 -#define ERROR_COMPILER (SHRT_MAX+3)
 -#define ERROR_PREPRO   (SHRT_MAX+4)
 -int error(lex_file *, int, const char *, ...);
 -
 -/*===================================================================*/
 -/*========================== parse.c ================================*/
 -/*===================================================================*/
 -int parse_gen(lex_file *);
 -
 -/*===================================================================*/
 -/*========================== typedef.c ==============================*/
 -/*===================================================================*/
 -typedef struct typedef_node_t {
 -    char      *name;
 -} typedef_node;
 -
 -void          typedef_init();
 -void          typedef_clear();
 -typedef_node *typedef_find(const char *);
 -int           typedef_add (lex_file *file, const char *, const char *);
 -
 -
  /*===================================================================*/
  /*=========================== util.c ================================*/
  /*===================================================================*/
@@@ -253,7 -342,7 +253,7 @@@ uint32_t util_crc32(const char *, int, 
          while (N##_add(*++elements) != -1 && len--);            \
          return N##_elements;                                    \
      }                                                           \
-     typedef char VECTOR_FILL(extra_semicolon_,__COUNTER__)
+     typedef char VECTOR_FILL(extra_semicolon_##N,__COUNTER__)
  #define VECTOR_PROT(T,N)                                        \
      extern T*     N##_data     ;                                \
      extern long   N##_elements ;                                \
@@@ -278,16 -367,12 +278,16 @@@ enum 
      TYPE_FIELD    ,
      TYPE_FUNCTION ,
      TYPE_POINTER  ,
 -    /* TYPE_INTEGER  , */
 +    TYPE_INTEGER  ,
 +    TYPE_QUATERNION  ,
 +    TYPE_MATRIX  ,
      TYPE_VARIANT  ,
  
      TYPE_COUNT
  };
  
 +extern const char *type_name[TYPE_COUNT];
 +
  extern size_t type_sizeof[TYPE_COUNT];
  extern uint16_t type_store_instr[TYPE_COUNT];
  /* could use type_store_instr + INSTR_STOREP_F - INSTR_STORE_F
@@@ -400,8 -485,8 +400,8 @@@ enum 
      INSTR_DONE,
      INSTR_MUL_F,
      INSTR_MUL_V,
 -    INSTR_MUL_FV,
      INSTR_MUL_VF,
 +    INSTR_MUL_FV,
      INSTR_DIV_F,
      INSTR_ADD_F,
      INSTR_ADD_V,
      INSTR_BITAND,
      INSTR_BITOR,
  
 +/* warning: will be reordered */
 +    INSTR_MUL_Q,
 +    INSTR_MUL_QF,
 +    INSTR_MUL_M,
 +    INSTR_MUL_MF,
 +    INSTR_EQ_Q,
 +    INSTR_EQ_M,
 +    INSTR_NE_Q,
 +    INSTR_NE_M,
 +    INSTR_LOAD_Q,
 +    INSTR_LOAD_M,
 +    INSTR_STORE_Q,
 +    INSTR_STORE_M,
 +    INSTR_STOREP_Q,
 +    INSTR_STOREP_M,
 +    INSTR_INV_Q,
 +    INSTR_INV_M,
      /*
       * Virtual instructions used by the assembler
       * keep at the end but before virtual instructions
@@@ -516,6 -584,9 +516,9 @@@ VECTOR_PROT(prog_section_function,  cod
  VECTOR_PROT(int,                    code_globals   );
  VECTOR_PROT(char,                   code_chars     );
  
+ typedef float   qcfloat;
+ typedef int32_t qcint;
  /*
   * code_write -- writes out the compiled file
   * code_init  -- prepares the code file
@@@ -524,6 -595,7 +527,7 @@@ bool     code_write       (const char *
  void     code_init        ();
  uint32_t code_genstring   (const char *string);
  uint32_t code_cachedstring(const char *string);
+ qcint    code_alloc_field (size_t qcsize);
  
  /*===================================================================*/
  /*========================= assembler.c =============================*/
@@@ -536,8 -608,8 +540,8 @@@ static const struct 
      { "DONE"      , 1, 4 },
      { "MUL_F"     , 3, 5 },
      { "MUL_V"     , 3, 5 },
 -    { "MUL_FV"    , 3, 6 },
      { "MUL_VF"    , 3, 6 },
 +    { "MUL_FV"    , 3, 6 },
      { "DIV"       , 0, 3 },
      { "ADD_F"     , 3, 5 },
      { "ADD_V"     , 3, 5 },
      { "OR"        , 0, 2 },
      { "BITAND"    , 0, 6 },
      { "BITOR"     , 0, 5 },
 +
 +    { "MUL_Q"     , 3, 5 },
 +    { "MUL_QF"    , 3, 6 },
 +    { "MUL_M"     , 3, 5 },
 +    { "MUL_MF"    , 3, 6 },
 +    { "EQ_Q"      , 0, 4 },
 +    { "EQ_M"      , 0, 4 },
 +    { "NE_Q"      , 0, 4 },
 +    { "NE_M"      , 0, 4 },
 +    { "FIELD_Q"   , 0, 7 },
 +    { "FIELD_M"   , 0, 7 },
 +    { "STORE_Q"   , 0, 7 },
 +    { "STORE_M"   , 0, 7 },
 +    { "STOREP_Q"  , 0, 8 },
 +    { "STOREP_M"  , 0, 8 },
 +    { "INV_Q"     , 0, 5 },
 +    { "INV_M"     , 0, 5 },
 +
      { "END"       , 0, 3 } /* virtual assembler instruction */
  };
  
@@@ -777,16 -831,6 +781,16 @@@ void Tself##_##mem##_clear(Tself *self
      (owner)->mem##_alloc = 0;       \
  }
  
 +#define MEM_VECTOR_MOVE(from, mem, to, tm)   \
 +{                                            \
 +    (to)->tm = (from)->mem;                  \
 +    (to)->tm##_count = (from)->mem##_count;  \
 +    (to)->tm##_alloc = (from)->mem##_alloc;  \
 +    (from)->mem = NULL;                      \
 +    (from)->mem##_count = 0;                 \
 +    (from)->mem##_alloc = 0;                 \
 +}
 +
  #define MEM_VEC_FUNCTIONS(Tself, Twhat, mem) \
  MEM_VEC_FUN_REMOVE(Tself, Twhat, mem)        \
  MEM_VEC_FUN_ADD(Tself, Twhat, mem)
@@@ -808,14 -852,6 +812,14 @@@ typedef struct 
      float x, y, z;
  } vector;
  
 +typedef float matrix[4][4]; /* OpenGL layout */
 +typedef float quaternion[4]; /* order: x, y, z, w */
 +#define MATRIX(axis, elem) ((4*(axis)) + (elem))
 +#define QUAT_X 0
 +#define QUAT_Y 1
 +#define QUAT_Z 2
 +#define QUAT_W 3
 +
  /*
   * A shallow copy of a lex_file to remember where which ast node
   * came from.
@@@ -834,9 -870,6 +838,6 @@@ typedef struct 
   * Since we may want to support that as well, let's redefine
   * float and int here.
   */
- typedef float   qcfloat;
- typedef int32_t qcint;
  typedef union {
      qcint   _int;
      qcint    string;
diff --combined ir.c
index 4e8060757ef70dd8fd276226088c615c5de9d250,35f00b262c6e607458dfdb86ef6c173d7c6b8cf7..fb6f4e90ca330bde92f830b4590abdfa0df265c1
--- 1/ir.c
--- 2/ir.c
+++ b/ir.c
   * Type sizes used at multiple points in the IR codegen
   */
  
 +const char *type_name[TYPE_COUNT] = {
 +    "void",
 +    "string",
 +    "float",
 +    "vector",
 +    "entity",
 +    "field",
 +    "function",
 +    "pointer",
 +#if 0
 +    "integer",
 +#endif
 +    "quaternion",
 +    "matrix",
 +    "variant"
 +};
 +
  size_t type_sizeof[TYPE_COUNT] = {
      1, /* TYPE_VOID     */
      1, /* TYPE_STRING   */
@@@ -58,9 -41,7 +58,9 @@@
  #if 0
      1, /* TYPE_INTEGER  */
  #endif
 -    3, /* TYPE_VARIANT  */
 +    4, /* TYPE_QUATERNION */
 +    16, /* TYPE_MATRIX */
 +    16, /* TYPE_VARIANT  */
  };
  
  uint16_t type_store_instr[TYPE_COUNT] = {
      INSTR_STORE_FNC,
      INSTR_STORE_ENT, /* should use I */
  #if 0
 -    INSTR_STORE_ENT, /* integer type */
 +    INSTR_STORE_I, /* integer type */
  #endif
 -    INSTR_STORE_V, /* variant, should never be accessed */
 +    INSTR_STORE_Q,
 +    INSTR_STORE_M,
 +
 +    INSTR_STORE_M, /* variant, should never be accessed */
  };
  
  uint16_t type_storep_instr[TYPE_COUNT] = {
  #if 0
      INSTR_STOREP_ENT, /* integer type */
  #endif
 -    INSTR_STOREP_V, /* variant, should never be accessed */
 +    INSTR_STOREP_Q,
 +    INSTR_STOREP_M,
 +
 +    INSTR_STOREP_M, /* variant, should never be accessed */
  };
  
  MEM_VEC_FUNCTIONS(ir_value_vector, ir_value*, v)
@@@ -115,6 -90,7 +115,7 @@@ ir_builder* ir_builder_new(const char *
  
      MEM_VECTOR_INIT(self, functions);
      MEM_VECTOR_INIT(self, globals);
+     MEM_VECTOR_INIT(self, fields);
      self->name = NULL;
      if (!ir_builder_set_name(self, modulename)) {
          mem_d(self);
  }
  
  MEM_VEC_FUNCTIONS(ir_builder, ir_value*, globals)
+ MEM_VEC_FUNCTIONS(ir_builder, ir_value*, fields)
  MEM_VEC_FUNCTIONS(ir_builder, ir_function*, functions)
  
  void ir_builder_delete(ir_builder* self)
      for (i = 0; i != self->globals_count; ++i) {
          ir_value_delete(self->globals[i]);
      }
-     MEM_VECTOR_CLEAR(self, globals);
+     MEM_VECTOR_CLEAR(self, fields);
+     for (i = 0; i != self->fields_count; ++i) {
+         ir_value_delete(self->fields[i]);
+     }
+     MEM_VECTOR_CLEAR(self, fields);
      mem_d(self);
  }
  
@@@ -206,14 -187,9 +212,14 @@@ ir_value* ir_builder_get_global(ir_buil
  
  ir_value* ir_builder_create_global(ir_builder *self, const char *name, int vtype)
  {
 -    ir_value *ve = ir_builder_get_global(self, name);
 -    if (ve) {
 -        return NULL;
 +    ir_value *ve;
 +
 +    if (name && name[0] != '#')
 +    {
 +        ve = ir_builder_get_global(self, name);
 +        if (ve) {
 +            return NULL;
 +        }
      }
  
      ve = ir_value_var(name, store_global, vtype);
      return ve;
  }
  
+ ir_value* ir_builder_get_field(ir_builder *self, const char *name)
+ {
+     size_t i;
+     for (i = 0; i < self->fields_count; ++i) {
+         if (!strcmp(self->fields[i]->name, name))
+             return self->fields[i];
+     }
+     return NULL;
+ }
+ ir_value* ir_builder_create_field(ir_builder *self, const char *name, int vtype)
+ {
+     ir_value *ve = ir_builder_get_field(self, name);
+     if (ve) {
+         return NULL;
+     }
+     ve = ir_value_var(name, store_global, TYPE_FIELD);
+     ve->fieldtype = vtype;
+     if (!ir_builder_fields_add(self, ve)) {
+         ir_value_delete(ve);
+         return NULL;
+     }
+     return ve;
+ }
  /***********************************************************************
   *IR Function
   */
@@@ -604,24 -607,6 +637,24 @@@ bool ir_value_set_vector(ir_value *self
      return true;
  }
  
 +bool ir_value_set_quaternion(ir_value *self, quaternion v)
 +{
 +    if (self->vtype != TYPE_QUATERNION)
 +        return false;
 +    memcpy(&self->constval.vquat, v, sizeof(self->constval.vquat));
 +    self->isconst = true;
 +    return true;
 +}
 +
 +bool ir_value_set_matrix(ir_value *self, matrix v)
 +{
 +    if (self->vtype != TYPE_MATRIX)
 +        return false;
 +    memcpy(&self->constval.vmat, v, sizeof(self->constval.vmat));
 +    self->isconst = true;
 +    return true;
 +}
 +
  bool ir_value_set_string(ir_value *self, const char *str)
  {
      if (self->vtype != TYPE_STRING)
@@@ -925,6 -910,7 +958,6 @@@ bool ir_block_create_storep(ir_block *s
      vtype = what->vtype;
  
      op = type_storep_instr[vtype];
 -
      return ir_block_create_store_op(self, op, target, what);
  }
  
@@@ -1284,6 -1270,8 +1317,8 @@@ on_error
  
  ir_value* ir_block_create_fieldaddress(ir_block *self, const char *label, ir_value *ent, ir_value *field)
  {
+     ir_value *v;
      /* Support for various pointer types todo if so desired */
      if (ent->vtype != TYPE_ENTITY)
          return NULL;
      if (field->vtype != TYPE_FIELD)
          return NULL;
  
-     return ir_block_create_general_instr(self, label, INSTR_ADDRESS, ent, field, TYPE_POINTER);
+     v = ir_block_create_general_instr(self, label, INSTR_ADDRESS, ent, field, TYPE_POINTER);
+     v->fieldtype = field->fieldtype;
+     return v;
  }
  
  ir_value* ir_block_create_load_from_ent(ir_block *self, const char *label, ir_value *ent, ir_value *field, int outype)
          case TYPE_POINTER: op = INSTR_LOAD_I;   break;
          case TYPE_INTEGER: op = INSTR_LOAD_I;   break;
  #endif
 +        case TYPE_QUATERNION: op = INSTR_LOAD_Q; break;
 +        case TYPE_MATRIX:     op = INSTR_LOAD_M; break;
          default:
              return NULL;
      }
@@@ -1420,22 -1408,12 +1457,22 @@@ ir_value* ir_block_create_mul(ir_block 
              case TYPE_VECTOR:
                  op = INSTR_MUL_V;
                  break;
 +            case TYPE_QUATERNION:
 +                op = INSTR_MUL_Q;
 +                break;
 +            case TYPE_MATRIX:
 +                op = INSTR_MUL_M;
 +                break;
          }
      } else {
          if ( (l == TYPE_VECTOR && r == TYPE_FLOAT) )
              op = INSTR_MUL_VF;
          else if ( (l == TYPE_FLOAT && r == TYPE_VECTOR) )
              op = INSTR_MUL_FV;
 +        else if ( (l == TYPE_QUATERNION && r == TYPE_FLOAT) )
 +            op = INSTR_MUL_QF;
 +        else if ( (l == TYPE_MATRIX && r == TYPE_FLOAT) )
 +            op = INSTR_MUL_MF;
  #if 0
          else if ( (l == TYPE_VECTOR && r == TYPE_INTEGER) )
              op = INSTR_MUL_VI;
@@@ -2105,21 -2083,7 +2142,7 @@@ static bool gen_global_field(ir_value *
      }
      else
      {
-         prog_section_field fld;
-         fld.name = global->code.name;
-         fld.offset = code_fields_elements;
-         fld.type = global->fieldtype;
-         if (fld.type == TYPE_VOID) {
-             printf("Field is missing a type: %s\n", global->name);
-             return false;
-         }
-         if (code_fields_add(fld) < 0)
-             return false;
-         global->code.globaladdr = code_globals_add(fld.offset);
+         global->code.globaladdr = code_globals_add(0);
      }
      if (global->code.globaladdr < 0)
          return false;
@@@ -2505,8 -2469,6 +2528,8 @@@ static bool ir_builder_gen_global(ir_bu
          return global->code.globaladdr >= 0;
      }
      case TYPE_VECTOR:
 +    case TYPE_QUATERNION:
 +    case TYPE_MATRIX:
      {
          size_t d;
          if (code_defs_add(def) < 0)
      }
  }
  
+ static bool ir_builder_gen_field(ir_builder *self, ir_value *field)
+ {
+     prog_section_def def;
+     prog_section_field fld;
+     def.type   = field->vtype;
+     def.offset = code_globals_elements;
+     def.name   = field->code.name = code_genstring(field->name);
+     if (code_defs_add(def) < 0)
+         return false;
+     fld.name = def.name;
+     fld.offset = code_fields_elements;
+     fld.type = field->fieldtype;
+     if (fld.type == TYPE_VOID) {
+         printf("field is missing a type: %s - don't know its size\n", field->name);
+         return false;
+     }
+     if (code_fields_add(fld) < 0)
+         return false;
+     if (!code_globals_add(code_alloc_field(type_sizeof[field->fieldtype])))
+         return false;
+     field->code.globaladdr = code_globals_add(fld.offset);
+     return field->code.globaladdr >= 0;
+ }
  bool ir_builder_generate(ir_builder *self, const char *filename)
  {
      size_t i;
  
      code_init();
  
+     for (i = 0; i < self->fields_count; ++i)
+     {
+         if (!ir_builder_gen_field(self, self->fields[i])) {
+             return false;
+         }
+     }
      for (i = 0; i < self->globals_count; ++i)
      {
          if (!ir_builder_gen_global(self, self->globals[i])) {
@@@ -2721,7 -2721,6 +2782,7 @@@ void ir_value_dump(ir_value* v, int (*o
  {
        if (v->isconst) {
                switch (v->vtype) {
 +                  default:
                        case TYPE_VOID:
                                oprintf("(void)");
                                break;
diff --combined ir.h
index eda1fbde866f7289a9d19b82f7cf6553d692fa34,47ff96b88b30fc279e2be9c91486c0a7133e16ac..bfba8faace49f1c4708369f56b6dd1fd431cfe1c
--- 1/ir.h
--- 2/ir.h
+++ b/ir.h
@@@ -55,8 -55,6 +55,8 @@@ typedef struct ir_value_s 
          char    *vstring;
          struct ir_value_s *vpointer;
          struct ir_function_s *vfunc;
 +        quaternion vquat;
 +        matrix     vmat;
      } constval;
  
      struct {
@@@ -91,8 -89,6 +91,8 @@@ bool GMQCC_WARN ir_value_set_string(ir_
  bool GMQCC_WARN ir_value_set_vector(ir_value*, vector v);
  /*bool   ir_value_set_pointer_v(ir_value*, ir_value* p); */
  /*bool   ir_value_set_pointer_i(ir_value*, int i);       */
 +bool GMQCC_WARN ir_value_set_quaternion(ir_value*, quaternion v);
 +bool GMQCC_WARN ir_value_set_matrix(ir_value*, matrix v);
  
  MEM_VECTOR_PROTO(ir_value, ir_life_entry_t, life);
  /* merge an instruction into the life-range */
@@@ -290,6 -286,7 +290,7 @@@ typedef struct ir_builder_
      char *name;
      MEM_VECTOR_MAKE(ir_function*, functions);
      MEM_VECTOR_MAKE(ir_value*, globals);
+     MEM_VECTOR_MAKE(ir_value*, fields);
  } ir_builder;
  
  ir_builder* ir_builder_new(const char *modulename);
@@@ -299,12 -296,15 +300,15 @@@ bool ir_builder_set_name(ir_builder *se
  
  MEM_VECTOR_PROTO(ir_builder, ir_function*, functions);
  MEM_VECTOR_PROTO(ir_builder, ir_value*, globals);
+ MEM_VECTOR_PROTO(ir_builder, ir_value*, fields);
  
  ir_function* ir_builder_get_function(ir_builder*, const char *fun);
  ir_function* ir_builder_create_function(ir_builder*, const char *name, int outtype);
  
  ir_value* ir_builder_get_global(ir_builder*, const char *fun);
  ir_value* ir_builder_create_global(ir_builder*, const char *name, int vtype);
+ ir_value* ir_builder_get_field(ir_builder*, const char *fun);
+ ir_value* ir_builder_create_field(ir_builder*, const char *name, int vtype);
  
  bool ir_builder_generate(ir_builder *self, const char *filename);