+const char *type_name[TYPE_COUNT] = {
+ "void",
+ "string",
+ "float",
+ "vector",
+ "entity",
+ "field",
+ "function",
+ "pointer",
+ "integer",
+ "variant",
+ "struct",
+ "union",
+ "array"
+};
+
+size_t type_sizeof[TYPE_COUNT] = {
+ 1, /* TYPE_VOID */
+ 1, /* TYPE_STRING */
+ 1, /* TYPE_FLOAT */
+ 3, /* TYPE_VECTOR */
+ 1, /* TYPE_ENTITY */
+ 1, /* TYPE_FIELD */
+ 1, /* TYPE_FUNCTION */
+ 1, /* TYPE_POINTER */
+ 1, /* TYPE_INTEGER */
+ 3, /* TYPE_VARIANT */
+ 0, /* TYPE_STRUCT */
+ 0, /* TYPE_UNION */
+ 0, /* TYPE_ARRAY */
+};
+
+uint16_t type_store_instr[TYPE_COUNT] = {
+ INSTR_STORE_F, /* should use I when having integer support */
+ INSTR_STORE_S,
+ INSTR_STORE_F,
+ INSTR_STORE_V,
+ INSTR_STORE_ENT,
+ INSTR_STORE_FLD,
+ INSTR_STORE_FNC,
+ INSTR_STORE_ENT, /* should use I */
+#if 0
+ INSTR_STORE_I, /* integer type */
+#else
+ INSTR_STORE_F,
+#endif
+
+ INSTR_STORE_V, /* variant, should never be accessed */
+
+ AINSTR_END, /* struct */
+ AINSTR_END, /* union */
+ AINSTR_END, /* array */
+};
+
+uint16_t field_store_instr[TYPE_COUNT] = {
+ INSTR_STORE_FLD,
+ INSTR_STORE_FLD,
+ INSTR_STORE_FLD,
+ INSTR_STORE_V,
+ INSTR_STORE_FLD,
+ INSTR_STORE_FLD,
+ INSTR_STORE_FLD,
+ INSTR_STORE_FLD,
+#if 0
+ INSTR_STORE_FLD, /* integer type */
+#else
+ INSTR_STORE_FLD,
+#endif
+
+ INSTR_STORE_V, /* variant, should never be accessed */
+
+ AINSTR_END, /* struct */
+ AINSTR_END, /* union */
+ AINSTR_END, /* array */
+};
+
+uint16_t type_storep_instr[TYPE_COUNT] = {
+ INSTR_STOREP_F, /* should use I when having integer support */
+ INSTR_STOREP_S,
+ INSTR_STOREP_F,
+ INSTR_STOREP_V,
+ INSTR_STOREP_ENT,
+ INSTR_STOREP_FLD,
+ INSTR_STOREP_FNC,
+ INSTR_STOREP_ENT, /* should use I */
+#if 0
+ INSTR_STOREP_ENT, /* integer type */
+#else
+ INSTR_STOREP_F,
+#endif
+
+ INSTR_STOREP_V, /* variant, should never be accessed */
+
+ AINSTR_END, /* struct */
+ AINSTR_END, /* union */
+ AINSTR_END, /* array */
+};
+
+uint16_t type_eq_instr[TYPE_COUNT] = {
+ INSTR_EQ_F, /* should use I when having integer support */
+ INSTR_EQ_S,
+ INSTR_EQ_F,
+ INSTR_EQ_V,
+ INSTR_EQ_E,
+ INSTR_EQ_E, /* FLD has no comparison */
+ INSTR_EQ_FNC,
+ INSTR_EQ_E, /* should use I */
+#if 0
+ INSTR_EQ_I,
+#else
+ INSTR_EQ_F,
+#endif
+
+ INSTR_EQ_V, /* variant, should never be accessed */
+
+ AINSTR_END, /* struct */
+ AINSTR_END, /* union */
+ AINSTR_END, /* array */
+};
+
+uint16_t type_ne_instr[TYPE_COUNT] = {
+ INSTR_NE_F, /* should use I when having integer support */
+ INSTR_NE_S,
+ INSTR_NE_F,
+ INSTR_NE_V,
+ INSTR_NE_E,
+ INSTR_NE_E, /* FLD has no comparison */
+ INSTR_NE_FNC,
+ INSTR_NE_E, /* should use I */
+#if 0
+ INSTR_NE_I,
+#else
+ INSTR_NE_F,
+#endif
+
+ INSTR_NE_V, /* variant, should never be accessed */
+
+ AINSTR_END, /* struct */
+ AINSTR_END, /* union */
+ 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;
+ va_start(ap, msg);
+ con_cvprintmsg((void*)&ctx, LVL_ERROR, "internal error", msg, ap);
+ va_end(ap);
+}
+
+static bool irwarning(lex_ctx ctx, int warntype, const char *fmt, ...)
+{
+ va_list ap;
+ int lvl = LVL_WARNING;
+
+ if (warntype && !OPTS_WARN(warntype))
+ return false;
+
+ if (opts_werror)
+ lvl = LVL_ERROR;
+
+ va_start(ap, fmt);
+ con_vprintmsg(lvl, ctx.file, ctx.line, "warning", fmt, ap);
+ va_end(ap);
+
+ return opts_werror;
+}
+
+/***********************************************************************
+ * Vector utility functions
+ */
+
+bool GMQCC_WARN vec_ir_value_find(ir_value **vec, ir_value *what, size_t *idx)
+{
+ size_t i;
+ size_t len = vec_size(vec);
+ for (i = 0; i < len; ++i) {
+ if (vec[i] == what) {
+ if (idx) *idx = i;
+ return true;
+ }
+ }
+ return false;
+}
+
+bool GMQCC_WARN vec_ir_block_find(ir_block **vec, ir_block *what, size_t *idx)
+{
+ size_t i;
+ size_t len = vec_size(vec);
+ for (i = 0; i < len; ++i) {
+ if (vec[i] == what) {
+ if (idx) *idx = i;
+ return true;
+ }
+ }
+ return false;
+}
+
+bool GMQCC_WARN vec_ir_instr_find(ir_instr **vec, ir_instr *what, size_t *idx)
+{
+ size_t i;
+ size_t len = vec_size(vec);
+ for (i = 0; i < len; ++i) {
+ if (vec[i] == what) {
+ if (idx) *idx = i;
+ return true;
+ }
+ }
+ return false;
+}
+
+/***********************************************************************
+ * IR Builder
+ */
+
+static void ir_block_delete_quick(ir_block* self);
+static void ir_instr_delete_quick(ir_instr *self);
+static void ir_function_delete_quick(ir_function *self);
+