a few more warnings
[suif.git] / src / basesuif / check / checktypes.cc
blob83f82abc959d908eeaf9dd0c658b6f6abe6c4d52
1 /* Type-checking functions */
3 /* Copyright (c) 1994 Stanford University
5 All rights reserved.
7 This software is provided under the terms described in
8 the "suif_copyright.h" include file. */
10 #include <suif_copyright.h>
12 #define _MODULE_ "libcheck.a"
14 #include "check.h"
15 #include "check_internal.h"
17 /* local function declarations */
18 static void check_fields(tree_node *tn, instruction *i, type_node *tbase);
19 static void check_null_dst(instruction *i, tree_node *tn);
20 static void check_null_src(instruction *i, operand r, tree_node *tn);
24 void
25 check_type (tree_node *tn, void *)
27 tree_node *old_node = current_node;
28 current_node = tn;
29 if (tn->is_instr()) {
30 tree_instr *ti = (tree_instr *)tn;
31 ti->instr_map(&check_type_instr, (void *)tn, FALSE);
33 current_node = old_node;
37 void
38 check_type_instr (instruction *i, void *x)
40 tree_node *tn = (tree_node *)x;
42 /* check if this is a dummy copy in a tree_for node */
43 boolean is_dummy = FALSE;
44 if ((tn != NULL) && (!tn->list_e()->next())) {
45 assert(tn->is_instr());
46 tree_instr *ti = (tree_instr *)tn;
47 tree_node_list *parent_list = tn->parent();
48 tree_node *grandparent = parent_list->parent();
49 if (grandparent->is_for() && (ti->instr() == i)) {
50 tree_for *tf = (tree_for *)grandparent;
51 if ((parent_list == tf->lb_list()) ||
52 (parent_list == tf->ub_list()) ||
53 (parent_list == tf->step_list())) {
54 if (i->opcode() == io_cpy) {
55 is_dummy = TRUE;
56 } else {
57 problem("tree_for (%u) - missing dummy cpy for operand",
58 tf->number());
64 if (i->result_type() == 0) {
65 problem_instr(tn, i, "destination has NULL type");
66 return;
69 if (i->result_type()->is_modifier()) {
70 problem_instr(tn, i, "destination has qualified type");
73 /* check the destination (note: if the destination is an instruction,
74 the type will be checked when the result value is used) */
76 operand dst = i->dst_op();
77 if (is_dummy) {
78 if (!dst.is_null()) {
79 problem_instr(tn, i, "destination for dummy cpy is not NULL");
81 if (i->result_type()->unqual()->op() == TYPE_VOID) {
82 problem_instr(tn, i, "dummy cpy has VOID type");
84 } else if (dst.is_symbol()) {
85 if (!i->result_type()->compatible(dst.symbol()->type())) {
86 problem_instr(tn, i, "result type doesn't match destination");
90 if (i->result_type()->op() == TYPE_VOID) {
91 if (!dst.is_null()) {
92 problem_instr(tn, i,
93 "void return type with non-null destinaton operand");
97 /* now check the source operands and other conditions associated with
98 particular opcodes */
100 // DLH - Check for types in each operand
101 for (unsigned opn = 0;
102 opn < i->num_srcs(); opn++) {
103 if (i->src_op(opn).type() == 0) {
104 problem_instr(tn, i,
105 "instruction with NULL source_op type");
106 // Can't continue
107 return;
110 switch (i->opcode()) {
112 case io_ret: {
113 in_rrr *ri = (in_rrr *)i;
114 check_null_dst(i, tn);
115 type_node *ret_type = ri->src_op().type()->unqual();
116 if (tn != NULL) {
117 proc_sym *ps = tn->proc();
118 if (!ret_type->compatible(ps->type()->return_type())) {
119 problem_instr(tn, i, "return value type does not match "
120 "function declaration");
123 if ((ret_type->op() == TYPE_ARRAY) ||
124 (ret_type->op() == TYPE_FUNC)) {
125 problem_instr(tn, i, "invalid return type");
127 break;
130 case io_mbr: {
131 in_mbr *mbri = (in_mbr *)i;
132 check_null_dst(i, tn);
133 type_node *t = mbri->src_op().type()->unqual();
134 if ((t->op() != TYPE_INT) && (t->op() != TYPE_ENUM)) {
135 problem_instr(tn, i, "source operand must have type INT or "
136 "ENUM");
138 break;
141 case io_lab:
142 case io_nop:
143 case io_mrk: {
144 check_null_dst(i, tn);
145 for (unsigned n = 0; n < i->num_srcs(); n++) {
146 check_null_src(i, i->src_op(n), tn);
148 break;
151 case io_divfloor:
152 case io_divceil:
153 case io_rem:
154 case io_mod: {
155 in_rrr *ri = (in_rrr *)i;
156 type_node *t = i->result_type()->unqual();
157 if ((t->op() != TYPE_INT) &&
158 (t->op() != TYPE_ENUM)) {
159 problem_instr(tn, i, "invalid result type");
160 } else {
161 if (!t->compatible(ri->src1_op().type()) ||
162 !t->compatible(ri->src2_op().type())) {
163 problem_instr(tn, i, "source operand does not match "
164 "result type");
167 break;
170 case io_not:
171 case io_and:
172 case io_ior:
173 case io_xor: {
174 in_rrr *ri = (in_rrr *)i;
175 boolean bad_type = FALSE;
176 type_node *t = i->result_type()->unqual();
177 if ((t->op() == TYPE_INT) || (t->op() == TYPE_ENUM)) {
178 base_type *bt = (base_type *)t;
179 if (bt->is_signed()) {
180 bad_type = TRUE;
181 problem_instr(tn, i, "result type is not unsigned");
183 } else {
184 bad_type = TRUE;
185 problem_instr(tn, i, "invalid result type");
188 if (!bad_type) {
189 boolean bad_source = FALSE;
190 if (!t->compatible(ri->src1_op().type())) {
191 bad_source = TRUE;
193 if (i->opcode() == io_not) {
194 check_null_src(i, ri->src2_op(), tn);
195 } else if (!t->compatible(ri->src2_op().type())) {
196 bad_source = TRUE;
198 if (bad_source) {
199 problem_instr(tn, i, "source operand does not match "
200 "result type");
203 break;
206 case io_add:
207 case io_sub:
208 case io_neg:
209 case io_abs:
210 case io_min:
211 case io_max:
212 case io_mul:
213 case io_div: {
214 in_rrr *ri = (in_rrr *)i;
215 type_node *t = i->result_type()->unqual();
216 type_node *t1 = ri->src1_op().type()->unqual();
217 type_node *t2 = ri->src2_op().type()->unqual();
219 /* handle pointer addition separately */
220 if ((i->opcode() == io_add) && (t->op() == TYPE_PTR)) {
221 type_node *toff;
222 ptr_type *tptr;
223 if (t1->is_ptr()) {
224 tptr = (ptr_type *)t1;
225 toff = t2;
226 } else if (t2->is_ptr()) {
227 tptr = (ptr_type *)t2;
228 toff = t1;
229 } else {
230 problem_instr(tn, i, "source operands do not match "
231 "result type");
232 break;
234 if (((toff->op() != TYPE_INT) && (toff->op() != TYPE_ENUM)) ||
235 (toff->size() > target.size[C_ptr])) {
236 problem_instr(tn, i, "illegal pointer addition");
239 /* check the "fields" annotation (if there is one) */
240 check_fields(tn, i, tptr->ref_type()->unqual());
241 break;
244 /* check for pointer subtraction */
245 if ((i->opcode() == io_sub) && (t1->op() == TYPE_PTR)) {
246 if (t2->op() == TYPE_PTR) {
247 if (((t->op() != TYPE_INT) && (t->op() != TYPE_ENUM)) ||
248 (t->size() != target.size[target.ptr_diff_type])) {
249 problem_instr(tn, i, "invalid result type for "
250 "pointer subtraction");
252 } else if (((t2->op() == TYPE_INT) ||
253 (t2->op() == TYPE_ENUM)) &&
254 (t2->size() <= target.size[C_ptr])) {
255 if (t->op() != TYPE_PTR) {
256 problem_instr(tn, i, "invalid result type for pointer "
257 "subtraction");
259 } else {
260 problem_instr(tn, i, "invalid source operands");
262 break;
265 if ((t->op() != TYPE_INT) &&
266 (t->op() != TYPE_FLOAT) &&
267 (t->op() != TYPE_ENUM)) {
268 problem_instr(tn, i, "invalid result type");
269 } else {
270 boolean bad_source = FALSE;
271 if (!t->compatible(t1)) {
272 bad_source = TRUE;
274 if ((i->opcode() == io_neg) ||
275 (i->opcode() == io_abs)) {
276 check_null_src(i, ri->src2_op(), tn);
277 } else if (!t->compatible(t2)) {
278 bad_source = TRUE;
280 if (bad_source) {
281 problem_instr(tn, i, "source operand does not match "
282 "result type");
285 break;
288 case io_cpy: {
289 in_rrr *ri = (in_rrr *)i;
290 type_node *t = i->result_type()->unqual();
291 if ((t->op() != TYPE_INT) &&
292 (t->op() != TYPE_ENUM) &&
293 (t->op() != TYPE_FLOAT) &&
294 (t->op() != TYPE_PTR) &&
295 (t->op() != TYPE_ARRAY) &&
296 (t->op() != TYPE_GROUP) &&
297 (t->op() != TYPE_STRUCT) &&
298 (t->op() != TYPE_UNION)) {
299 problem_instr(tn, i, "invalid result type");
301 if (t->size() == 0) {
302 problem_instr(tn, i, "invalid result type");
304 type_node *srct = ri->src_op().type()->unqual();
305 if (!t->compatible(srct)) {
306 problem_instr(tn, i, "source operand does not match result "
307 "type");
309 /* check the "fields" annotation (this should really only be
310 needed for io_cvt instructions but we might as well be safe) */
311 if (srct->is_ptr()) {
312 check_fields(tn, i, ((ptr_type *)srct)->ref_type()->unqual());
314 check_null_src(i, ri->src2_op(), tn);
315 break;
318 case io_asr:
319 case io_lsl:
320 case io_lsr: {
321 in_rrr *ri = (in_rrr *)i;
323 /* must have "signed" type for asr, "unsigned" for lsr */
324 boolean bad_type = TRUE;
325 type_node *t = i->result_type()->unqual();
326 if ((t->op() == TYPE_INT) || (t->op() != TYPE_ENUM)) {
327 base_type *bt = (base_type *)t;
328 if (((i->opcode() != io_asr) || bt->is_signed()) &&
329 ((i->opcode() != io_lsr) || !bt->is_signed())) {
330 bad_type = FALSE;
333 if (bad_type) {
334 problem_instr(tn, i, "invalid result type");
335 } else if (!t->compatible(ri->src_op().type())) {
336 problem_instr(tn, i, "source operand does not match result "
337 "type");
340 t = ri->shift_cnt_op().type()->unqual();
341 if ((t->op() == TYPE_INT) || (t->op() == TYPE_ENUM)) {
342 base_type *bt = (base_type *)t;
343 if (bt->is_signed()) {
344 problem_instr(tn, i, "shift count type is not unsigned ");
346 } else {
347 problem_instr(tn, i, "invalid type for shift count");
350 break;
353 case io_rot: {
354 in_rrr *ri = (in_rrr *)i;
356 type_node *t = i->result_type()->unqual();
357 if ((t->op() != TYPE_INT) && (t->op() != TYPE_ENUM)) {
358 problem_instr(tn, i, "invalid result type");
360 if (!t->compatible(ri->src_op().type())) {
361 problem_instr(tn, i, "source operand does not match result "
362 "type");
365 t = ri->shift_cnt_op().type()->unqual();
366 if ((t->op() == TYPE_INT) || (t->op() == TYPE_ENUM)) {
367 base_type *bt = (base_type *)t;
368 if (!bt->is_signed()) {
369 problem_instr(tn, i, "rotation amount type is not signed");
371 } else {
372 problem_instr(tn, i, "invalid type for rotation amount");
374 break;
377 case io_seq:
378 case io_sne:
379 case io_sl:
380 case io_sle: {
381 in_rrr *ri = (in_rrr *)i;
382 type_node *t = i->result_type()->unqual();
383 if (!t->compatible(type_signed)) {
384 problem_instr(tn, i, "result type of comparison is not "
385 "signed INT");
387 t = ri->src1_op().type()->unqual();
388 if ((t->op() != TYPE_INT) &&
389 (t->op() != TYPE_FLOAT) &&
390 (t->op() != TYPE_PTR) &&
391 (t->op() != TYPE_ENUM)) {
392 problem_instr(tn, i, "invalid source operand type");
393 } else if (!t->compatible(ri->src1_op().type())) {
394 problem_instr(tn, i, "source operand types do not match");
396 break;
399 case io_btrue:
400 case io_bfalse:
401 case io_jmp: {
402 in_bj *bji = (in_bj *)i;
403 check_null_dst(i, tn);
404 if (i->opcode() == io_jmp) {
405 check_null_src(i, bji->src_op(), tn);
406 } else if (!type_signed->compatible(bji->src_op().type())) {
407 problem_instr(tn, i, "branch condition must be ``int''");
409 break;
412 case io_cvt: {
413 in_rrr *ri = (in_rrr *)i;
414 type_node *t = i->result_type()->unqual();
415 if ((t->op() != TYPE_INT) &&
416 (t->op() != TYPE_ENUM) &&
417 (t->op() != TYPE_FLOAT) &&
418 (t->op() != TYPE_PTR)) {
419 problem_instr(tn, i, "invalid result type");
421 if (ri->src_op().type() == 0) {
422 problem_instr(tn, i, "invalid result type == 0");
423 break;
425 t = ri->src_op().type()->unqual();
426 if ((t->op() != TYPE_INT) &&
427 (t->op() != TYPE_ENUM) &&
428 (t->op() != TYPE_FLOAT) &&
429 (t->op() != TYPE_PTR)) {
430 problem_instr(tn, i, "invalid source operand type");
432 /* check the "fields" annotation (if there is one) */
433 if (t->is_ptr()) {
434 check_fields(tn, i, ((ptr_type *)t)->ref_type()->unqual());
436 check_null_src(i, ri->src2_op(), tn);
437 break;
440 case io_ldc: {
441 in_ldc *ldci = (in_ldc *)i;
442 type_node *t = i->result_type()->unqual();
443 immed v = ldci->value();
444 boolean bad_type = FALSE;
445 switch (v.kind()) {
446 case im_int:
447 case im_extended_int: {
448 /* allow integers to be treated as pointers (e.g. NULL) */
449 if ((t->op() != TYPE_INT) &&
450 (t->op() != TYPE_ENUM) &&
451 (t->op() != TYPE_PTR)) {
452 bad_type = TRUE;
454 break;
456 case im_float:
457 case im_extended_float: {
458 if (t->op() != TYPE_FLOAT) {
459 bad_type = TRUE;
461 break;
463 case im_symbol: {
464 if (t->op() != TYPE_PTR) {
465 bad_type = TRUE;
467 break;
469 default: {
470 problem_instr(tn, i, "illegal constant value");
473 if (bad_type) {
474 problem_instr(tn, i, "value does not match result type");
476 break;
479 case io_lod: {
480 in_rrr *ri = (in_rrr *)i;
481 type_node *t = i->result_type()->unqual();
482 type_node *st = ri->src_addr_op().type()->unqual();
483 if (st->op() != TYPE_PTR) {
484 problem_instr(tn, i, "source address is not a pointer");
485 } else {
486 ptr_type *pt = (ptr_type *)st;
487 if (!t->compatible(pt->ref_type())) {
488 problem_instr(tn, i, "incorrect return type");
489 } else if ((t->op() == TYPE_VOID) ||
490 (t->op() == TYPE_FUNC) ||
491 (t->size() == 0)) {
492 problem_instr(tn, i, "illegal type");
495 check_null_src(i, ri->src2_op(), tn);
496 break;
499 case io_str: {
500 in_rrr *ri = (in_rrr *)i;
501 check_null_dst(i, tn);
502 type_node *dt = ri->dst_addr_op().type()->unqual();
503 if (dt->op() != TYPE_PTR) {
504 problem_instr(tn, i, "destination address is not a pointer");
505 } else {
506 ptr_type *pt = (ptr_type *)dt;
507 type_node *t = pt->ref_type()->unqual();
508 if (!t->compatible(ri->src_op().type())) {
509 problem_instr(tn, i, "incorrect source type");
510 } else if ((t->op() == TYPE_VOID) ||
511 (t->op() == TYPE_FUNC) ||
512 (t->op() == TYPE_ARRAY)) {
513 problem_instr(tn, i, "illegal type");
516 break;
519 case io_memcpy: {
520 in_rrr *ri = (in_rrr *)i;
521 check_null_dst(i, tn);
522 type_node *st = ri->src_addr_op().type()->unqual();
523 type_node *dt = ri->dst_addr_op().type()->unqual();
524 boolean bad_ptr = FALSE;
525 if (dt->op() != TYPE_PTR) {
526 problem_instr(tn, i, "destination address is not a pointer");
527 bad_ptr = TRUE;
529 if (st->op() != TYPE_PTR) {
530 problem_instr(tn, i, "source address is not a pointer");
531 bad_ptr = TRUE;
533 if (!bad_ptr) {
534 ptr_type *spt = (ptr_type *)st;
535 ptr_type *dpt = (ptr_type *)dt;
536 type_node *t = spt->ref_type()->unqual();
538 if (!t->compatible(dpt->ref_type())) {
539 problem_instr(tn, i, "pointer types do not match");
540 } else if ((t->op() == TYPE_VOID) ||
541 (t->op() == TYPE_FUNC) ||
542 (t->op() == TYPE_ARRAY)) {
543 problem_instr(tn, i, "illegal type");
546 break;
549 case io_cal: {
550 in_cal *cali = (in_cal *)i;
551 type_node *t = cali->addr_op().type()->unqual();
552 func_type *ft = NULL;
553 if (t->op() == TYPE_PTR) {
554 ptr_type *pt = (ptr_type *)t;
555 type_node *rt = pt->ref_type()->unqual();
556 if (rt->op() == TYPE_FUNC) {
557 ft = (func_type *)rt;
560 if (!ft) {
561 problem_instr(tn, i, "bad target address");
562 } else {
563 if (!ft->return_type()->compatible(i->result_type())) {
564 problem_instr(tn, i, "result type does not match "
565 "function declaration");
567 if (ft->return_type()->unqual()->is_array() ||
568 ft->return_type()->unqual()->is_func()) {
569 problem_instr(tn, i, "illegal return type for call");
571 if (ft->args_known()) {
572 unsigned numargs = ft->num_args();
573 if (cali->num_args() < numargs) {
574 problem_instr(tn, i, "too few arguments");
575 numargs = cali->num_args();
576 } else if ((cali->num_args() > numargs) &&
577 !ft->has_varargs()) {
578 problem_instr(tn, i, "too many arguments");
580 for (unsigned n = 0; n < numargs; n++) {
581 if (!ft->arg_type(n)->compatible
582 (cali->argument(n).type())) {
583 problem_instr(tn, i, "argument does not match "
584 "function declaration");
589 break;
592 case io_array: {
593 in_array *arri = (in_array *)i;
595 /* the result type may be a pointer of any sort */
596 if (arri->result_type()->unqual()->op() != TYPE_PTR) {
597 problem_instr(tn, i, "result type is not a pointer");
600 /* check the type of the offset operand */
601 type_node *toff = arri->offset_op().type()->unqual();
602 if ((toff->op() != TYPE_VOID) &&
603 (toff->op() != TYPE_INT) &&
604 (toff->op() != TYPE_ENUM)) {
605 problem_instr(tn, i, "invalid type for offset operand");
608 /* check the base operand type */
609 type_node *tbase = arri->base_op().type()->unqual();
610 if (tbase->op() == TYPE_PTR) {
611 ptr_type *pt = (ptr_type *)tbase;
612 tbase = pt->ref_type()->unqual();
613 } else {
614 problem_instr(tn, i, "invalid type for base operand");
615 tbase = NULL;
618 /* check each dimension */
619 for (unsigned d = 0; d < arri->dims(); d++) {
620 array_type *at = (array_type *)tbase;
621 if (at && (at->op() != TYPE_ARRAY)) {
622 problem_instr(tn, i, "array type does not match");
623 at = NULL;
625 /* check the index type */
626 type_node *tind = arri->index(d).type()->unqual();
627 if ((tind->op() != TYPE_INT) &&
628 (tind->op() != TYPE_ENUM)) {
629 problem_instr(tn, i, "incorrect type for index %u", d);
632 operand b = arri->bound(d);
633 if (b.is_null()) {
634 if (d != 0) {
635 problem_instr(tn, i, "missing bound %u", d);
637 } else {
638 /* check the bound type */
639 type_node *tbnd = b.type()->unqual();
640 if ((tbnd->op() != TYPE_INT) &&
641 (tbnd->op() != TYPE_ENUM)) {
642 problem_instr(tn, i, "incorrect type for bound %u", d);
644 if (at) {
645 /* compare values of bounds */
646 if (at->lower_bound().is_constant() &&
647 at->upper_bound().is_constant()) {
649 int bndval = 1 + at->upper_bound().constant() -
650 at->lower_bound().constant();
652 if (b.is_instr() &&
653 (b.instr()->opcode() == io_ldc)) {
654 in_ldc *ldci = (in_ldc *)b.instr();
655 if (ldci->value().is_integer() &&
656 (ldci->value().integer() != bndval)) {
657 problem_instr(tn, i, "bound %u does not "
658 "match type", d);
665 /* get the next element type */
666 if (at) {
667 tbase = at->elem_type()->unqual();
668 } else {
669 tbase = NULL;
673 /* give up now if we don't know the element type */
674 if (!tbase) break;
676 /* check that the element size is correct */
677 if (arri->elem_size() != (unsigned)tbase->size()) {
678 problem_instr(tn, i, "element size does not match array type");
681 /* check the "fields" annotation (if there is one) */
682 check_fields(tn, i, tbase);
684 break;
687 default: {
688 problem_instr(tn, i, "unexpected opcode: %s",
689 if_ops_name(i->opcode()));
695 void
696 check_fields (tree_node *tn, instruction *i, type_node *tbase)
698 /* try to figure out the field (if any) */
699 annote *flds = NULL;
700 if (i->are_annotations()) {
701 flds = i->annotes()->peek_annote(k_fields);
703 if (flds) {
704 immed_list_iter ili(flds->immeds());
705 while (!ili.is_empty()) {
706 const char *fld = ili.step().string();
707 if (!tbase->is_struct()) {
708 problem_instr(tn, i, "fields annotation doesn't match type");
709 break;
711 struct_type *stbase = (struct_type *)tbase;
712 unsigned fldnum = stbase->find_field_by_name(fld);
713 if (fldnum >= stbase->num_fields()) {
714 problem_instr(tn, i, "cannot find field '%s'", fld);
715 break;
717 tbase = stbase->field_type(fldnum)->unqual();
723 void
724 check_null_dst (instruction *i, tree_node *tn)
726 if (!i->dst_op().is_null()) {
727 problem_instr(tn, i, "unexpected destination operand");
729 if (!i->result_type()->op() == TYPE_VOID) {
730 problem_instr(tn, i, "result type should be void");
735 void
736 check_null_src (instruction *i, operand r, tree_node *tn)
738 if (!r.is_null()) {
739 problem_instr(tn, i, "unused source operand is not null");
741 if (!i->result_type()->op() == TYPE_VOID) {
742 problem_instr(tn, i, "non-void result type");