Commit 46fbaaf3 authored by Götz Lindenmaier's avatar Götz Lindenmaier
Browse files

implemented typecheck, called in inline_method.

[r445]
parent 167eae6f
......@@ -23,4 +23,9 @@ typedef unsigned char bool;
# define FALSE 0
# endif /* ndef TRUE */
# ifndef true
# define true 1
# define false 0
# endif /* ndef TRUE */
# endif /* _BOOL_H_ */
......@@ -432,6 +432,8 @@ void inline_method(ir_node *call, ir_graph *called_graph) {
/** Check preconditions **/
assert(get_irn_op(call) == op_Call);
/* assert(get_Call_type(call) == get_entity_type(get_irg_ent(called_graph))); */
assert(smaller_type(get_entity_type(get_irg_ent(called_graph)),
get_Call_type(call)));
assert(get_type_tpop(get_Call_type(call)) == type_method);
if (called_graph == current_ir_graph) return;
......
......@@ -508,3 +508,14 @@ mode_is_dataM (ir_mode *mode)
}
return res;
}
/* Returns true if sm can be converted to lm without loss. */
bool
smaller_mode(ir_mode *sm, ir_mode *lm) {
if ((mode_is_int(sm) && mode_is_int(lm)) &&
get_mode_modecode(sm) <= get_mode_modecode(lm))
return true;
if ((mode_is_float(sm) && mode_is_float(lm)) &&
get_mode_modecode(sm) <= get_mode_modecode(lm))
return true;
}
......@@ -20,6 +20,7 @@ reimplementation of the tarval module.
# define _IRMODE_H_
#include "ident.h"
#include "bool.h"
# define target_bits 8
......@@ -128,4 +129,8 @@ int mode_is_data (ir_mode *mode);
int mode_is_datab (ir_mode *mode);
int mode_is_dataM (ir_mode *mode);
/* Returns true if sm can be converted to lm without loss
according to firm definiton */
bool smaller_mode(ir_mode *sm, ir_mode *lm);
# endif /* _IRMODE_H_ */
......@@ -506,3 +506,7 @@ int is_compound_entity(entity *ent) {
return (is_class_type(t) || is_struct_type(t) ||
is_array_type(t) || is_union_type(t));
}
bool equal_entity(entity *ent1, entity *ent2) {
return true;
}
......@@ -277,6 +277,11 @@ int is_atomic_entity(entity *ent);
array or union type. */
int is_compound_entity(entity *ent);
/* Returns true if ent1 and ent2 have are equal except for their owner.
Two entities are equal if
- they have the same type (the same C-struct)
*/
bool equal_entity(entity *ent1, entity *ent2);
/*****/
......
......@@ -255,6 +255,251 @@ int is_type (void *thing) {
return 0;
}
bool equal_type(type *typ1, type *typ2) {
entity **m;
type **t;
int i, j;
if (typ1 == typ2) return true;
if ((get_type_tpop_code(typ1) != get_type_tpop_code(typ2)) ||
(get_type_name(typ1) != get_type_name(typ2)) ||
(get_type_mode(typ1) != get_type_mode(typ2)) ||
(get_type_state(typ1) != get_type_state(typ2)))
return false;
if ((get_type_state(typ1) == layout_fixed) &&
(get_type_size(typ1) != get_type_size(typ2)))
return false;
switch(get_type_tpop_code(typ1)) {
case tpo_class: {
if (get_class_n_members(typ1) != get_class_n_members(typ2)) return false;
if (get_class_n_subtypes(typ1) != get_class_n_subtypes(typ2)) return false;
if (get_class_n_supertypes(typ1) != get_class_n_supertypes(typ2)) return false;
if (get_class_peculiarity(typ1) != get_class_peculiarity(typ2)) return false;
/** Compare the members **/
m = alloca(sizeof(entity *) * get_class_n_members(typ1));
memset(m, 0, sizeof(entity *) * get_class_n_members(typ1));
/* First sort the members of typ2 */
for (i = 0; i < get_class_n_members(typ1); i++) {
entity *e1 = get_class_member(typ1, i);
for (j = 0; j < get_class_n_members(typ2); j++) {
entity *e2 = get_class_member(typ2, j);
if (get_entity_name(e1) == get_entity_name(e2))
m[i] = e2;
}
}
for (i = 0; i < get_class_n_members(typ1); i++) {
if (!m[i] || /* Found no counterpart */
!equal_entity(get_class_member(typ1, i), m[i]))
return false;
}
/** Compare the supertypes **/
t = alloca(sizeof(entity *) * get_class_n_supertypes(typ1));
memset(t, 0, sizeof(entity *) * get_class_n_supertypes(typ1));
/* First sort the supertypes of typ2 */
for (i = 0; i < get_class_n_supertypes(typ1); i++) {
type *t1 = get_class_supertype(typ1, i);
for (j = 0; j < get_class_n_supertypes(typ2); j++) {
type *t2 = get_class_supertype(typ2, j);
if (get_type_name(t2) == get_type_name(t1))
t[i] = t2;
}
}
for (i = 0; i < get_class_n_supertypes(typ1); i++) {
if (!t[i] || /* Found no counterpart */
get_class_supertype(typ1, i) != t[i])
return false;
}
} break;
case tpo_struct: {
if (get_struct_n_members(typ1) != get_struct_n_members(typ2)) return false;
m = alloca(sizeof(entity *) * get_struct_n_members(typ1));
memset(m, 0, sizeof(entity *) * get_struct_n_members(typ1));
/* First sort the members of lt */
for (i = 0; i < get_struct_n_members(typ1); i++) {
entity *e1 = get_struct_member(typ1, i);
for (j = 0; j < get_struct_n_members(typ2); j++) {
entity *e2 = get_struct_member(typ2, j);
if (get_entity_name(e1) == get_entity_name(e2))
m[i] = e2;
}
}
for (i = 0; i < get_struct_n_members(typ1); i++) {
if (!m[i] || /* Found no counterpart */
!equal_entity(get_struct_member(typ1, i), m[i]))
return false;
}
} break;
case tpo_method: {
if (get_method_n_params(typ1) != get_method_n_params(typ2)) return false;
if (get_method_n_ress(typ1) != get_method_n_ress(typ2)) return false;
for (i = 0; i < get_method_n_params(typ1); i++) {
if (!equal_type(get_method_param_type(typ1, i), get_method_param_type(typ2, i)))
return false;
}
for (i = 0; i < get_method_n_ress(typ1); i++) {
if (!equal_type(get_method_res_type(typ1, i), get_method_res_type(typ2, i)))
return false;
}
} break;
case tpo_union: {
if (get_union_n_members(typ1) != get_union_n_members(typ2)) return false;
m = alloca(sizeof(entity *) * get_union_n_members(typ1));
memset(m, 0, sizeof(entity *) * get_union_n_members(typ1));
/* First sort the members of lt */
for (i = 0; i < get_union_n_members(typ1); i++) {
entity *e1 = get_union_member(typ1, i);
for (j = 0; j < get_union_n_members(typ2); j++) {
entity *e2 = get_union_member(typ2, j);
if (get_entity_name(e1) == get_entity_name(e2))
m[i] = e2;
}
}
for (i = 0; i < get_union_n_members(typ1); i++) {
if (!m[i] || /* Found no counterpart */
!equal_entity(get_union_member(typ1, i), m[i]))
return false;
}
} break;
case tpo_array: {
type *set, *let; /* small/large elt. type */
if (get_array_n_dimensions(typ1) != get_array_n_dimensions(typ2))
return false;
if (!equal_type(get_array_element_type(typ1), get_array_element_type(typ2)))
return false;
for(i = 0; i < get_array_n_dimensions(typ1); i++) {
if (get_array_lower_bound(typ1, i) != get_array_lower_bound(typ2, i) ||
get_array_upper_bound(typ1, i) != get_array_upper_bound(typ2, i))
return false;
if (get_array_order(typ1, i) != get_array_order(typ2, i))
assert(0 && "type compare with different dimension orders not implemented");
}
} break;
case tpo_enumeration: {
assert(0 && "enumerations not implemented");
} break;
case tpo_pointer: {
if (get_pointer_points_to_type(typ1) != get_pointer_points_to_type(typ2))
return false;
} break;
case tpo_primitive: {
} break;
default: break;
}
return true;
}
bool smaller_type (type *st, type *lt) {
entity **m;
int i, j;
if (st == lt) return true;
if (get_type_tpop_code(st) != get_type_tpop_code(lt))
return false;
switch(get_type_tpop_code(st)) {
case tpo_class: {
return is_subclass_of(st, lt);
} break;
case tpo_struct: {
if (get_struct_n_members(st) != get_struct_n_members(lt)) return false;
m = alloca(sizeof(entity *) * get_struct_n_members(st));
memset(m, 0, sizeof(entity *) * get_struct_n_members(st));
/* First sort the members of lt */
for (i = 0; i < get_struct_n_members(st); i++) {
entity *se = get_struct_member(st, i);
for (j = 0; j < get_struct_n_members(lt); j++) {
entity *le = get_struct_member(lt, j);
if (get_entity_name(le) == get_entity_name(se))
m[i] = le;
}
}
for (i = 0; i < get_struct_n_members(st); i++) {
if (!m[i] || /* Found no counterpart */
!smaller_type(get_entity_type(get_struct_member(st, i)),
get_entity_type(m[i])))
return false;
}
} break;
case tpo_method: {
if (get_method_n_params(st) != get_method_n_params(lt)) return false;
if (get_method_n_ress(st) != get_method_n_ress(lt)) return false;
for (i = 0; i < get_method_n_params(st); i++) {
if (!smaller_type(get_method_param_type(st, i), get_method_param_type(lt, i)))
return false;
}
for (i = 0; i < get_method_n_ress(st); i++) {
if (!smaller_type(get_method_res_type(st, i), get_method_res_type(lt, i)))
return false;
}
} break;
case tpo_union: {
if (get_union_n_members(st) != get_union_n_members(lt)) return false;
m = alloca(sizeof(entity *) * get_union_n_members(st));
memset(m, 0, sizeof(entity *) * get_union_n_members(st));
/* First sort the members of lt */
for (i = 0; i < get_union_n_members(st); i++) {
entity *se = get_union_member(st, i);
for (j = 0; j < get_union_n_members(lt); j++) {
entity *le = get_union_member(lt, j);
if (get_entity_name(le) == get_entity_name(se))
m[i] = le;
}
}
for (i = 0; i < get_union_n_members(st); i++) {
if (!m[i] || /* Found no counterpart */
!smaller_type(get_entity_type(get_union_member(st, i)),
get_entity_type(m[i])))
return false;
}
} break;
case tpo_array: {
type *set, *let; /* small/large elt. type */
if (get_array_n_dimensions(st) != get_array_n_dimensions(lt))
return false;
set = get_array_element_type(st);
let = get_array_element_type(lt);
if (set != let) {
/* If the elt types are different, set must be convertible
to let, and they must have the same size so that address
computations work out. To have a size the layout must
be fixed. */
if ((get_type_state(set) != layout_fixed) ||
(get_type_state(let) != layout_fixed))
return false;
if (!smaller_type(set, let) ||
get_type_size(set) != get_type_size(let))
return false;
}
for(i = 0; i < get_array_n_dimensions(st); i++) {
if (get_array_lower_bound(lt, i))
if(get_array_lower_bound(st, i) != get_array_lower_bound(lt, i))
return false;
if (get_array_upper_bound(lt, i))
if(get_array_upper_bound(st, i) != get_array_upper_bound(lt, i))
return false;
}
} break;
case tpo_enumeration: {
assert(0 && "enumerations not implemented");
} break;
case tpo_pointer: {
if (!smaller_type(get_pointer_points_to_type(st),
get_pointer_points_to_type(lt)))
return false;
} break;
case tpo_primitive: {
if (!smaller_mode(get_type_mode(st), get_type_mode(lt)))
return false;
} break;
default: break;
}
return true;
}
/*******************************************************************/
/** TYPE_CLASS **/
/*******************************************************************/
......@@ -420,6 +665,20 @@ bool is_class_type(type *clss) {
if (clss->type_op == type_class) return 1; else return 0;
}
bool is_subclass_of(type *low, type *high) {
int i;
assert(is_class_type(low) && is_class_type(high));
if (low == high) return true;
/* depth first search from high downwards. */
for (i = 0; i < get_class_n_subtypes(high); i++) {
if (low == get_class_subtype(high, i))
return true;
if (is_subclass_of(low, get_class_subtype(high, i)))
return true;
}
return false;
}
/*******************************************************************/
/** TYPE_STRUCT **/
/*******************************************************************/
......
......@@ -189,6 +189,86 @@ extern unsigned long type_visited;
*/
int is_type (void *thing);
/****f* type/equal_types
*
* NAME
* equal_type - Checks whether two types are structural equal.
* SYNOPSIS
* bool equal_types (type *typ1, type *typ2);
* INPUTS
* two pointer types
* RESULT
* true if the types are equal, else false.
* Types are equal if
* - they are the same type kind
* - they have the same name
* - they have the same mode (if applicable)
* - they have the same type_state and, ev., the same size
* - they are class types and have
* - the same members (see same_entity in entity.h)
* - the same supertypes -- the C-pointers are compared --> no recursive call.
* - the same number of subtypes. Subtypes are not compared,
* as this could cause a cyclic test.
* - the same peculiarity
* - they are structure types and have the same members
* - they are method types and have
* - the same parameter types
* - the same result types
* - they are union types and have the same members
* - they are array types and have
* - the same number of dimensions
* - the same dimension bounds
* - the same dimension order
* - the same element type
* - they are enumeration types and have the same enumerator names
* - they are pointer types and have the identical points_to type
* (i.e., the same C-struct to represent the type, type_id is skipped.
* This is to avoid endless recursions; with pointer types circlic
* type graphs are possible.)
*
***
*/
bool equal_type(type *tpy1, type *typ2);
/****f* type/smaller_type
*
* NAME
* smaller_type - Checks whether two types are structural comparable.
* SYNOPSIS
* bool smaller_type (type *st, type *lt);
* INPUTS
* two pointer type
* RESULT
* true if type st is smaller than type lt, i.e. whenever
* lt is expected a st can be used.
* This is true if
* - they are the same type kind
* - mode(st) < mode (lt) (if applicable)
* - they are class types and st is (transitive) subtype of lt,
* - they are structure types and
* - the members of st have exactly one counterpart in lt with the same name,
* - the counterpart has a bigger type.
* - they are method types and have
* - the same number of parameter and result types,
* - the parameter types of st are smaller than those of lt,
* - the result types of st are smaller than those of lt
* - they are union types and have the members of st have exactly one
* counterpart in lt and the type is smaller
* - they are array types and have
* - the same number of dimensions
* - all bounds of lt are bound of st
* - the same dimension order
* - the same element type
* or
* - the element type of st is smaller than that of lt
* - the element types have the same size and fixed layout.
* - they are enumeration types and have the same enumerator names
* - they are pointer types and have the points_to type of st is
* smaller than the points_to type of lt.
***
*/
bool smaller_type (type *st, type *lt);
/****** type/class
* NAME
* Representation of a class type.
......@@ -301,7 +381,9 @@ void set_class_dfn (type*, int);
int get_class_dfn (type*);
/* typecheck */
bool is_class_type(type *clss);
bool is_class_type(type *clss);
/* Returns true if low is subclass of high. */
bool is_subclass_of(type *low, type *high);
/*****/
/****** type/struct
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment