diff --git a/tools/qfcc/include/expr.h b/tools/qfcc/include/expr.h index d23bf3ea6..200d4efee 100644 --- a/tools/qfcc/include/expr.h +++ b/tools/qfcc/include/expr.h @@ -131,7 +131,6 @@ typedef struct expr_s { float float_val; float vector_val[3]; int entity_val; - int field_val; int func_val; ex_pointer_t pointer; float quaternion_val[4]; @@ -171,7 +170,7 @@ expr_t *new_string_expr (const char *string_val); expr_t *new_float_expr (float float_val); expr_t *new_vector_expr (float *vector_val); expr_t *new_entity_expr (int entity_val); -expr_t *new_field_expr (int field_val); +expr_t *new_field_expr (int field_val, struct type_s *type, struct def_s *def); expr_t *new_func_expr (int func_val); expr_t *new_pointer_expr (int val, struct type_s *type, struct def_s *def); expr_t *new_quaternion_expr (float *quaternion_val); diff --git a/tools/qfcc/include/reloc.h b/tools/qfcc/include/reloc.h index f3d5c180b..6691e56be 100644 --- a/tools/qfcc/include/reloc.h +++ b/tools/qfcc/include/reloc.h @@ -49,6 +49,7 @@ typedef enum { rel_op_b_def_ofs, rel_op_c_def_ofs, rel_def_def_ofs, + rel_def_field_ofs, } reloc_type; typedef struct reloc_s { @@ -73,6 +74,7 @@ void reloc_def_def_ofs (struct def_s *def, int ofs); void reloc_def_func (struct function_s *func, int ofs); void reloc_def_string (int ofs); void reloc_def_field (struct def_s *def, int ofs); +void reloc_def_field_ofs (struct def_s *def, int ofs); void reloc_def_op (struct ex_label_s *label, int ofs); #endif//__reloc_h diff --git a/tools/qfcc/source/expr.c b/tools/qfcc/source/expr.c index c75216a26..3099a3a64 100644 --- a/tools/qfcc/source/expr.c +++ b/tools/qfcc/source/expr.c @@ -520,11 +520,13 @@ new_entity_expr (int entity_val) } expr_t * -new_field_expr (int field_val) +new_field_expr (int field_val, type_t *type, def_t *def) { expr_t *e = new_expr (); e->type = ex_field; - e->e.field_val = field_val; + e->e.pointer.val = field_val; + e->e.pointer.type = type; + e->e.pointer.def = def; return e; } @@ -606,7 +608,8 @@ constant_expr (expr_t *var) case ev_vector: return new_vector_expr (G_VECTOR (var->e.def->ofs)); case ev_field: - return new_field_expr (G_INT (var->e.def->ofs)); + return new_field_expr (G_INT (var->e.def->ofs), var->e.def->type, + var->e.def); case ev_integer: return new_integer_expr (G_INT (var->e.def->ofs)); case ev_uinteger: @@ -820,8 +823,10 @@ print_expr (expr_t *e) printf ("(%s)[%d]", pr_type_name[e->e.pointer.type->type], e->e.pointer.val); break; - case ex_entity: case ex_field: + printf ("%d", e->e.pointer.val); + break; + case ex_entity: case ex_func: case ex_integer: printf ("%d", e->e.integer_val); @@ -967,15 +972,22 @@ field_expr (expr_t *e1, expr_t *e2) if (e1->e.expr.op == '.' && extract_type (e1->e.expr.e1) == ev_entity) { int ofs; + def_t *def; + type_t *type; - if (e1->e.expr.e2->type == ex_def) - ofs = G_INT (e1->e.expr.e2->e.def->ofs); - else if (e1->e.expr.e2->type == ex_field) - ofs = e1->e.expr.e2->e.field_val; - else + if (e1->e.expr.e2->type == ex_def) { + ofs = 0; + def = e1->e.expr.e2->e.def; + type = def->type; + } else if (e1->e.expr.e2->type == ex_field) { + ofs = e1->e.expr.e2->e.pointer.val; + def = e1->e.expr.e2->e.pointer.def; + type = e1->e.expr.e2->e.pointer.type; + } else break; if (field->offset) { - e = new_field_expr (ofs + field->offset); + e = new_field_expr (ofs + field->offset, + type, def); e = new_binary_expr ('.', e1->e.expr.e1, e); } else { e = e1; @@ -1094,7 +1106,7 @@ test_expr (expr_t *e, int test) new = new_entity_expr (0); break; case ev_field: - new = new_field_expr (0); + new = new_field_expr (0, 0, 0); break; case ev_func: new = new_func_expr (0); diff --git a/tools/qfcc/source/immediate.c b/tools/qfcc/source/immediate.c index a62d44130..ce0f8522d 100644 --- a/tools/qfcc/source/immediate.c +++ b/tools/qfcc/source/immediate.c @@ -272,6 +272,10 @@ ReuseConstant (expr_t *expr, def_t *def) if (e.e.func_val) reloc = new_reloc (cn->ofs, rel_def_func); break; + case ex_field: + if (e.e.pointer.def) + reloc_def_field_ofs (e.e.pointer.def, cn->ofs); + break; case ex_pointer: if (e.e.pointer.def) EMIT_DEF_OFS (G_INT (cn->ofs), e.e.pointer.def); diff --git a/tools/qfcc/source/linker.c b/tools/qfcc/source/linker.c index 5d67a5cf5..5c404ded1 100644 --- a/tools/qfcc/source/linker.c +++ b/tools/qfcc/source/linker.c @@ -243,6 +243,7 @@ add_relocs (qfo_t *qfo) qfo->strings + DATA (reloc->ofs)->string_var); break; case rel_def_field: + case rel_def_field_ofs: //FIXME more? reloc->ofs += data_base; break; @@ -478,6 +479,7 @@ fixup_relocs (void) case rel_op_b_def_ofs: case rel_op_c_def_ofs: case rel_def_def_ofs: + case rel_def_field_ofs: def = defs.defs + reloc->def; if (def->flags & (QFOD_EXTERNAL | QFOD_LOCAL | QFOD_ABSOLUTE)) continue; @@ -510,6 +512,7 @@ fixup_relocs (void) case rel_op_b_def_ofs: case rel_op_c_def_ofs: case rel_def_def_ofs: + case rel_def_field_ofs: break; case rel_def_op: DATA (reloc->ofs)->integer_var = reloc->def; diff --git a/tools/qfcc/source/qfcc.c b/tools/qfcc/source/qfcc.c index 216d03801..259f9098c 100644 --- a/tools/qfcc/source/qfcc.c +++ b/tools/qfcc/source/qfcc.c @@ -184,7 +184,8 @@ WriteData (int crc) && strcmp (def->name, ".debug_file") != 0) continue; if (def->type->type == ev_func) { - } else if (def->type->type == ev_field) { + } else if (def->type->type == ev_field + && strcmp (def->name, ".imm") != 0) { dd = &fields[numfielddefs++]; def_to_ddef (def, dd, 1); dd->ofs = G_INT (def->ofs); diff --git a/tools/qfcc/source/qfprogs.c b/tools/qfcc/source/qfprogs.c index 309bd277c..c9eecdb76 100644 --- a/tools/qfcc/source/qfprogs.c +++ b/tools/qfcc/source/qfprogs.c @@ -407,6 +407,7 @@ convert_qfo (void) case rel_def_op: case rel_def_string: case rel_def_field: + case rel_def_field_ofs: break; } } diff --git a/tools/qfcc/source/reloc.c b/tools/qfcc/source/reloc.c index ad69fe443..f5f003eca 100644 --- a/tools/qfcc/source/reloc.c +++ b/tools/qfcc/source/reloc.c @@ -138,6 +138,9 @@ relocate_refs (reloc_t *refs, int ofs) case rel_def_def_ofs: G_INT (refs->ofs) += ofs; break; + case rel_def_field_ofs: + G_INT (refs->ofs) += G_INT (ofs); + break; } refs = refs->next; } @@ -212,6 +215,14 @@ reloc_def_field (def_t *def, int ofs) def->refs = ref; } +void +reloc_def_field_ofs (def_t *def, int ofs) +{ + reloc_t *ref = new_reloc (ofs, rel_def_field_ofs); + ref->next = def->refs; + def->refs = ref; +} + void reloc_def_op (ex_label_t *label, int ofs) {