* Merged executionstate branch.
[cacao.git] / src / vm / jit / verify / typecheck-fields.inc
1 /* src/vm/jit/verify/typecheck-fields.inc - type checking for field ICMDs
2
3    Copyright (C) 1996-2005, 2006, 2008
4    CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5
6    This file is part of CACAO.
7
8    This program is free software; you can redistribute it and/or
9    modify it under the terms of the GNU General Public License as
10    published by the Free Software Foundation; either version 2, or (at
11    your option) any later version.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23 */
24
25
26 {
27         unresolved_field *uf;
28         constant_FMIref *fieldref;
29         typeinfo_t *instanceti;
30         typeinfo_t *valueti;
31 #if !defined(TYPECHECK_TYPEINFERER)
32         resolve_result_t result;
33 #endif
34
35         TYPECHECK_COUNT(stat_ins_field);
36
37         instanceti = (instance) ? &(instance->typeinfo) : NULL;
38         valueti    = (value && value->type == TYPE_ADR) ? &(value->typeinfo) : NULL;
39
40         /* get the field reference from the instruction */
41
42         if (INSTRUCTION_IS_UNRESOLVED(state->iptr)) {
43                 uf = state->iptr->sx.s23.s3.uf;
44                 fieldref = uf->fieldref;
45         }
46         else {
47                 uf = NULL;
48                 fieldref = state->iptr->sx.s23.s3.fmiref;
49         }
50
51 #if !defined(TYPECHECK_TYPEINFERER)
52         /* check the basic value type for PUT instructions */
53
54         if (value && value->type != fieldref->parseddesc.fd->type)
55                 VERIFY_ERROR("Field type mismatch");
56
57         /* try to resolve the field reference lazily */
58
59         result = resolve_field_lazy(state->m, fieldref);
60
61         if (result == resolveSucceeded) {
62                 fieldinfo *fi;
63
64                 /* perform verification checks now */
65
66                 fi  = fieldref->p.field;
67
68                 result = resolve_field_verifier_checks(
69                                 state->m, fieldref, fi->clazz, fi,
70                                 instanceti, valueti,
71                                 (instance == NULL),
72                                 (value != NULL));
73         }
74
75         if (result == resolveFailed)
76                 EXCEPTION;
77
78         /* if not resolved, yet, create an unresolved field */
79
80         if (result != resolveSucceeded) {
81                 if (!uf) {
82                         uf = resolve_create_unresolved_field(state->m->clazz, 
83                                         state->m, state->iptr);
84                         if (!uf)
85                                 EXCEPTION;
86
87                         state->iptr->sx.s23.s3.uf = uf;
88                         state->iptr->flags.bits |= INS_FLAG_UNRESOLVED;
89                 }
90
91                 /* record the subtype constraints for this field access */
92
93                 if (!resolve_constrain_unresolved_field(
94                                         uf, state->m->clazz, state->m,
95                                         instanceti, valueti))
96                         EXCEPTION; /* XXX maybe wrap exception? */
97
98                 TYPECHECK_COUNTIF(INSTRUCTION_IS_UNRESOLVED(state->iptr),stat_ins_field_unresolved);
99                 TYPECHECK_COUNTIF(INSTRUCTION_IS_RESOLVED(state->iptr) && 
100                                 !state->iptr->sx.s23.s3.fmiref->p.field->clazz->initialized,
101                                 stat_ins_field_uninitialized);
102         }
103 #endif /* !defined(TYPECHECK_TYPEINFERER) */
104                 
105         /* write the result type */
106
107         if (value == NULL) {
108 #if defined(TYPECHECK_STACKBASED)
109                 typedescriptor_t *dv;
110
111                 if (IS_2_WORD_TYPE(fieldref->parseddesc.fd->type)) {
112                         CHECK_STACK_SPACE(2);
113                         stack += 2;
114                         dv = &(stack[-1]);
115                         stack[0].type = TYPE_VOID;
116                 }
117                 else {
118                         CHECK_STACK_SPACE(1);
119                         stack += 1;
120                         dv = stack;
121                 }
122 #define DST dv
123 #else
124 #define DST VAROP(state->iptr->dst)
125 #endif
126                 DST->type = fieldref->parseddesc.fd->type;
127                 if (DST->type == TYPE_ADR) {
128                         if (!typeinfo_init_from_typedesc(fieldref->parseddesc.fd,NULL,&(DST->typeinfo)))
129                                 EXCEPTION;
130                 }
131 #undef DST
132         }
133 }
134
135 /*
136  * These are local overrides for various environment variables in Emacs.
137  * Please do not remove this and leave it at the end of the file, where
138  * Emacs will automagically detect them.
139  * ---------------------------------------------------------------------
140  * Local variables:
141  * mode: c
142  * indent-tabs-mode: t
143  * c-basic-offset: 4
144  * tab-width: 4
145  * End:
146  * vim:noexpandtab:sw=4:ts=4:filetype=c:
147  */