diff --git a/tools/qfcc/include/type.h b/tools/qfcc/include/type.h index b8cff36e5..2062933d6 100644 --- a/tools/qfcc/include/type.h +++ b/tools/qfcc/include/type.h @@ -60,6 +60,9 @@ typedef struct type_s { etype_t type; ///< ev_invalid means structure/array etc const char *name; int alignment; ///< required alignment for instances + int width; ///< components in vector types, otherwise 1 + ///< vector and quaternion are 1 (separate from + ///< vec3 and vec4) /// function/pointer/array/struct types are more complex ty_meta_e meta; union { @@ -99,6 +102,11 @@ typedef struct { #define EV_TYPE(type) extern type_t type_##type; #include "QF/progs/pr_type_names.h" +extern type_t type_ivec3; +extern type_t type_ivec4; +extern type_t type_vec3; +extern type_t type_vec4; + extern type_t type_invalid; extern type_t type_floatfield; @@ -158,6 +166,7 @@ const char *type_get_encoding (const type_t *type); int is_enum (const type_t *type) __attribute__((pure)); int is_integral (const type_t *type) __attribute__((pure)); int is_scalar (const type_t *type) __attribute__((pure)); +int is_nonscalar (const type_t *type) __attribute__((pure)); int is_math (const type_t *type) __attribute__((pure)); int is_struct (const type_t *type) __attribute__((pure)); int is_array (const type_t *type) __attribute__((pure)); diff --git a/tools/qfcc/source/class.c b/tools/qfcc/source/class.c index ce4499fdc..d90ecc062 100644 --- a/tools/qfcc/source/class.c +++ b/tools/qfcc/source/class.c @@ -71,33 +71,114 @@ static hashtab_t *static_instances; static hashtab_t *static_instance_classes; // these will be built up further -type_t type_selector = { ev_invalid, 0, 0, ty_struct}; -type_t type_SEL = { ev_ptr, "SEL", 1, ty_basic, {{&type_selector}}}; -type_t *IMP_params[] = {&type_id, &type_SEL}; -type_t type_IMP = { ev_func, "IMP", 1, ty_basic, - {{&type_id, -3, IMP_params}}}; -type_t type_super = { ev_invalid, 0, 0 }; -type_t type_SuperPtr = { ev_ptr, 0, 1, ty_basic, {{&type_super}}}; -type_t *supermsg_params[] = {&type_SuperPtr, &type_SEL}; -type_t type_supermsg = { ev_func, ".supermsg", 1, ty_basic, - {{&type_id, -3, supermsg_params}}}; -type_t type_method = { ev_invalid, 0, 0, ty_struct }; -type_t type_method_description = { ev_invalid, 0, 0, ty_struct }; -type_t type_category = { ev_invalid, 0, 0, ty_struct}; -type_t type_ivar = { ev_invalid, 0, 0, ty_struct}; -type_t type_module = { ev_invalid, 0, 0, ty_struct}; -type_t type_moduleptr = { ev_ptr, 0, 1, ty_basic, {{&type_module}}}; -type_t *obj_exec_class_params[] = { &type_moduleptr }; -type_t type_exec_class = { ev_func, 0, 1, ty_basic, - {{&type_void, 1, obj_exec_class_params}}}; +type_t type_selector = { + .type = ev_invalid, + .meta = ty_struct, +}; +type_t type_SEL = { + .type = ev_ptr, + .name = "SEL", + .alignment = 1, + .width = 1, + .meta = ty_basic, + {{&type_selector}}, +}; +type_t *IMP_params[] = { &type_id, &type_SEL }; +type_t type_IMP = { + .type = ev_func, + .name = "IMP", + .alignment = 1, + .width = 1, + .meta = ty_basic, + {{&type_id, -3, IMP_params}}, +}; +type_t type_super = { + .type = ev_invalid, +}; +type_t type_SuperPtr = { + .type = ev_ptr, + .alignment = 1, + .width = 1, + .meta = ty_basic, + {{&type_super}}, +}; +type_t *supermsg_params[] = { &type_SuperPtr, &type_SEL }; +type_t type_supermsg = { + .type = ev_func, + .name = ".supermsg", + .alignment = 1, + .width = 1, + .meta = ty_basic, + {{&type_id, -3, supermsg_params}}, +}; +type_t type_method = { + .type = ev_invalid, + .meta = ty_struct, +}; +type_t type_method_description = { + .type = ev_invalid, + .meta = ty_struct, +}; +type_t type_category = { + .type = ev_invalid, + .meta = ty_struct, +}; +type_t type_ivar = { + .type = ev_invalid, + .meta = ty_struct, +}; +type_t type_module = { + .type = ev_invalid, + .meta = ty_struct, +}; +type_t type_moduleptr = { + .type = ev_ptr, + .alignment = 1, + .width = 1, + .meta = ty_basic, + {{&type_module}}, +}; +type_t *obj_exec_class_params[] = { + &type_moduleptr, +}; +type_t type_exec_class = { + .type = ev_func, + .alignment = 1, + .width = 1, + .meta = ty_basic, + {{&type_void, 1, obj_exec_class_params}}, +}; // the cast of 1 in the init is to ensure pointers to incomplete types // are never misidentified as id. It will be set to the correct value // when the obj system is initialized. -type_t type_object = {ev_invalid, 0, 0, ty_struct, {{(type_t *)1}}}; -type_t type_id = { ev_ptr, "id", 1, ty_basic, {{&type_object}}}; -type_t type_class = { ev_invalid, 0, 0, ty_struct}; -type_t type_Class = { ev_ptr, 0, 1, ty_basic, {{&type_class}}}; -type_t type_protocol = { ev_invalid, 0, 0, ty_struct}; +type_t type_object = { + .type = ev_invalid, + .meta = ty_struct, + {{(type_t *)1}}, +}; +type_t type_id = { + .type = ev_ptr, + .name = "id", + .alignment = 1, + .width = 1, + .meta = ty_basic, + {{&type_object}}, +}; +type_t type_class = { + .type = ev_invalid, + .meta = ty_struct, +}; +type_t type_Class = { + .type = ev_ptr, + .alignment = 1, + .width = 1, + .meta = ty_basic, + {{&type_class}}, +}; +type_t type_protocol = { + .type = ev_invalid, + .meta = ty_struct, +}; int obj_initialized = 0; diff --git a/tools/qfcc/source/function.c b/tools/qfcc/source/function.c index aa4f79134..c85b68edf 100644 --- a/tools/qfcc/source/function.c +++ b/tools/qfcc/source/function.c @@ -185,6 +185,7 @@ parse_params (type_t *type, param_t *parms) new = new_type (); new->type = ev_func; new->alignment = 1; + new->width = 1; new->t.func.type = type; new->t.func.num_params = 0; diff --git a/tools/qfcc/source/opcodes.c b/tools/qfcc/source/opcodes.c index 51c7ce26d..79cc48943 100644 --- a/tools/qfcc/source/opcodes.c +++ b/tools/qfcc/source/opcodes.c @@ -230,12 +230,32 @@ v6p_opcode_find (const char *name, operand_t *op_a, operand_t *op_b, return op; } +static etype_t +operand_type (operand_t *op) +{ + if (!op) { + return ev_invalid; + } + etype_t type = low_level_type (op->type); + if (type == ev_vector || type == ev_quaternion) { + return ev_float; + } + return type; +} + static int operand_width (operand_t *op) { if (!op) { return 0; } + etype_t type = low_level_type (op->type); + if (type == ev_vector) { + return 3; + } + if (type == ev_quaternion) { + return 4; + } return op->width; } @@ -246,9 +266,9 @@ rua_opcode_find (const char *name, operand_t *op_a, operand_t *op_b, opcode_t search_op = { .opname = name, .types = { - op_a ? low_level_type (op_a->type) : ev_invalid, - op_b ? low_level_type (op_b->type) : ev_invalid, - op_c ? low_level_type (op_c->type) : ev_invalid, + operand_type (op_a), + operand_type (op_b), + operand_type (op_c), }, .widths = { operand_width (op_a), diff --git a/tools/qfcc/source/struct.c b/tools/qfcc/source/struct.c index 798696ac3..4a9f64bce 100644 --- a/tools/qfcc/source/struct.c +++ b/tools/qfcc/source/struct.c @@ -194,6 +194,8 @@ start_enum (symbol_t *sym) sym = find_enum (0); } sym->type->t.symtab = new_symtab (current_symtab, stab_local); + sym->type->alignment = 1; + sym->type->width = 1; return sym->type->t.symtab; } @@ -207,7 +209,6 @@ finish_enum (symbol_t *sym) enum_type = sym->type = find_type (sym->type); enum_tab = enum_type->t.symtab; - enum_type->alignment = 1; for (name = enum_tab->symbols; name; name = name->next) { name->type = sym->type; diff --git a/tools/qfcc/source/type.c b/tools/qfcc/source/type.c index ceb0360a5..94bf6aed0 100644 --- a/tools/qfcc/source/type.c +++ b/tools/qfcc/source/type.c @@ -65,6 +65,8 @@ .type = ev_##t, \ .name = #t, \ .alignment = PR_ALIGNOF(t), \ + .width = __builtin_choose_expr (ev_##t == ev_short \ + || ev_##t == ev_ushort, 0, 1), \ .meta = ty_basic, \ {{ __builtin_choose_expr (ev_##t == ev_field \ || ev_##t == ev_func \ @@ -72,7 +74,23 @@ }; #include "QF/progs/pr_type_names.h" -type_t type_invalid = { ev_invalid, "invalid" }; +type_t type_invalid = { + .type = ev_invalid, + .name = "invalid", +}; + +#define VTYPE(t, b) \ + type_t type_##t = { \ + .type = ev_##b, \ + .name = #t, \ + .alignment = PR_ALIGNOF(t), \ + .width = PR_SIZEOF(t) / PR_SIZEOF (b), \ + .meta = ty_basic, \ + }; +VTYPE(ivec3, int) +VTYPE(ivec4, int) +VTYPE(vec3, float) +VTYPE(vec4, float) type_t *type_nil; type_t *type_default; @@ -80,17 +98,49 @@ type_t *type_long_int; type_t *type_ulong_uint; // these will be built up further -type_t type_va_list = { ev_invalid, 0, 0, ty_struct }; -type_t type_param = { ev_invalid, 0, 0, ty_struct }; -type_t type_zero = { ev_invalid, 0, 0, ty_struct }; -type_t type_type_encodings = { ev_invalid, "@type_encodings", 0, - ty_struct }; -type_t type_xdef = { ev_invalid, "@xdef", 0, ty_struct }; -type_t type_xdef_pointer = { ev_ptr, 0, 1, ty_basic, {{&type_xdef}} }; -type_t type_xdefs = { ev_invalid, "@xdefs", 0, ty_struct }; +type_t type_va_list = { + .type = ev_invalid, + .meta = ty_struct, +}; +type_t type_param = { + .type = ev_invalid, + .meta = ty_struct, +}; +type_t type_zero = { + .type = ev_invalid, + .meta = ty_struct, +}; +type_t type_type_encodings = { + .type = ev_invalid, + .name = "@type_encodings", + .meta = ty_struct, +}; +type_t type_xdef = { + .type = ev_invalid, + .name = "@xdef", + .meta = ty_struct, +}; +type_t type_xdef_pointer = { + .type = ev_ptr, + .alignment = 1, + .width = 1, + .meta = ty_basic, + {{&type_xdef}}, +}; +type_t type_xdefs = { + .type = ev_invalid, + .name = "@xdefs", + .meta = ty_struct, +}; -type_t type_floatfield = { ev_field, ".float", 1, ty_basic, - {{&type_float}} }; +type_t type_floatfield = { + .type = ev_field, + .name = ".float", + .alignment = 1, + .width = 1, + .meta = ty_basic, + {{&type_float}}, +}; #define EV_TYPE(type) &type_##type, type_t *ev_types[ev_type_count] = { @@ -280,10 +330,12 @@ append_type (type_t *type, type_t *new) case ev_ptr: t = &(*t)->t.fldptr.type; type->alignment = 1; + type->width = 1; break; case ev_func: t = &(*t)->t.func.type; type->alignment = 1; + type->width = 1; break; case ev_invalid: internal_error (0, "invalid basic type"); @@ -293,6 +345,7 @@ append_type (type_t *type, type_t *new) case ty_array: t = &(*t)->t.array.type; type->alignment = new->alignment; + type->width = new->width; break; case ty_struct: case ty_union: @@ -339,7 +392,7 @@ types_same (type_t *a, type_t *b) return 0; return 1; default: // other types don't have aux data - return 1; + return a->width == b->width; } break; case ty_struct: @@ -447,6 +500,7 @@ field_type (type_t *aux) new = new_type (); new->type = ev_field; new->alignment = 1; + new->width = 1; if (aux) { new = find_type (append_type (new, aux)); } @@ -465,6 +519,7 @@ pointer_type (type_t *aux) new = new_type (); new->type = ev_ptr; new->alignment = 1; + new->width = 1; if (aux) { new = find_type (append_type (new, aux)); } @@ -485,6 +540,7 @@ array_type (type_t *aux, int size) new->type = ev_invalid; if (aux) { new->alignment = aux->alignment; + new->width = aux->width; } new->t.array.size = size; if (aux) { @@ -506,6 +562,7 @@ based_array_type (type_t *aux, int base, int top) new->type = ev_invalid; if (aux) { new->alignment = aux->alignment; + new->width = aux->width; } new->meta = ty_array; new->t.array.type = aux; @@ -523,6 +580,7 @@ alias_type (type_t *type, type_t *alias_chain, const char *name) alias->meta = ty_alias; alias->type = type->type; alias->alignment = type->alignment; + alias->width = type->width; if (type == alias_chain && type->meta == ty_alias) { // typedef of a type that contains a typedef somewhere // grab the alias-free branch for type @@ -868,6 +926,23 @@ int is_scalar (const type_t *type) { type = unalias_type (type); + if (is_short (type) || is_ushort (type)) { + // shorts have width 0 + return 1; + } + if (type->width != 1) { + return 0; + } + return is_float (type) || is_integral (type) || is_double (type); +} + +int +is_nonscalar (const type_t *type) +{ + type = unalias_type (type); + if (type->width < 2) { + return 0; + } return is_float (type) || is_integral (type) || is_double (type); } @@ -875,9 +950,11 @@ int is_math (const type_t *type) { type = unalias_type (type); - etype_t t = type->type; - return t == ev_vector || t == ev_quaternion || is_scalar (type); + if (is_vector (type) || is_quaternion (type)) { + return 1; + } + return is_scalar (type) || is_nonscalar (type); } int @@ -981,7 +1058,7 @@ type_size (const type_t *type) { switch (type->meta) { case ty_basic: - return pr_type_size[type->type]; + return pr_type_size[type->type] * type->width; case ty_struct: case ty_union: if (!type->t.symtab) @@ -1015,10 +1092,13 @@ type_width (const type_t *type) { switch (type->meta) { case ty_basic: - if (type->type == ev_ushort || type->type == ev_short) { - return 0; + if (type->type == ev_vector) { + return 3; } - return 1; //FIXME vector should be 3 + if (type->type == ev_quaternion) { + return 4; + } + return type->width; case ty_struct: case ty_union: return 1; @@ -1050,11 +1130,21 @@ chain_basic_types (void) chain_type (&type_ptr); chain_type (&type_floatfield); if (!options.traditional) { + if (options.code.progsversion == PROG_VERSION) { + type_quaternion.alignment = 4; + } chain_type (&type_quaternion); chain_type (&type_int); chain_type (&type_uint); chain_type (&type_short); chain_type (&type_double); + + if (options.code.progsversion == PROG_VERSION) { + chain_type (&type_ivec3); + chain_type (&type_ivec4); + chain_type (&type_vec3); + chain_type (&type_vec4); + } } }