📄 expr.c
字号:
0, VOIDmode, 3, XEXP (targetx, 0), Pmode, op0, GET_MODE (op0), expand_expr (tsize, NULL_RTX, MEM, EXPAND_CONST_ADDRESS), TYPE_MODE (long_unsigned_type_node)); if (targetx != target) emit_move_insn (target, targetx); return target; } case SET_DIFF_EXPR: lib_func = "__diffpowerset"; goto format_2; case SET_IOR_EXPR: lib_func = "__orpowerset"; goto format_2; case SET_XOR_EXPR: lib_func = "__xorpowerset"; goto format_2; /* void __diffpowerset (char *out, char *left, char *right, unsigned bitlength) */ case SET_AND_EXPR: lib_func = "__andpowerset"; format_2: { tree expr = TREE_OPERAND (exp, 0); tree tsize = powersetlen (expr); rtx targetx; if (TREE_CODE (TREE_TYPE (expr)) != SET_TYPE) tsize = fold (build (MULT_EXPR, long_unsigned_type_node, tsize, size_int (BITS_PER_UNIT))); /* expand 1st operand to a pointer to the set */ op0 = expand_expr (force_addr_of (expr), NULL_RTX, MEM, EXPAND_CONST_ADDRESS); /* expand 2nd operand to a pointer to the set */ op1 = expand_expr (force_addr_of (TREE_OPERAND (exp, 1)), NULL_RTX, MEM, EXPAND_CONST_ADDRESS);/* FIXME: re-examine this code - the unary operator code above has recently (93/03/12) been changed a lot. Should this code also change? */ /* build a temp for the result, target is its address */ if (target == NULL_RTX) { target = assign_stack_temp (TYPE_MODE (TREE_TYPE (exp)), int_size_in_bytes (TREE_TYPE (exp)), 0); preserve_temp_slots (target); } if (GET_CODE (target) == MEM) targetx = target; else targetx = assign_stack_temp (GET_MODE (target), GET_MODE_SIZE (GET_MODE (target)), 0); emit_library_call (gen_rtx(SYMBOL_REF, Pmode, lib_func), 0, VOIDmode, 4, XEXP (targetx, 0), Pmode, op0, GET_MODE (op0), op1, GET_MODE (op1), expand_expr (tsize, NULL_RTX, MEM, EXPAND_CONST_ADDRESS), TYPE_MODE (long_unsigned_type_node)); if (target != targetx) emit_move_insn (target, targetx); return target; } case SET_IN_EXPR: { tree set = TREE_OPERAND (exp, 1); tree pos = convert (long_unsigned_type_node, TREE_OPERAND (exp, 0)); tree set_type = TREE_TYPE (set); tree set_length = discrete_count (TYPE_DOMAIN (set_type)); tree min_val = convert (long_integer_type_node, TYPE_MIN_VALUE (TYPE_DOMAIN (set_type))); tree fcall; /* FIXME: Function-call not needed if pos and width are constant! */ if (! mark_addressable (set)) { error ("powerset is not addressable"); return const0_rtx; } /* we use different functions for bitstrings and powersets */ if (CH_BOOLS_TYPE_P (set_type)) fcall = build_chill_function_call ( lookup_name (get_identifier ("__inbitstring")), tree_cons (NULL_TREE, convert (long_unsigned_type_node, pos), tree_cons (NULL_TREE, build1 (ADDR_EXPR, build_pointer_type (set_type), set), tree_cons (NULL_TREE, convert (long_unsigned_type_node, set_length), tree_cons (NULL_TREE, min_val, tree_cons (NULL_TREE, force_addr_of (get_chill_filename ()), build_tree_list (NULL_TREE, get_chill_linenumber ()))))))); else fcall = build_chill_function_call ( lookup_name (get_identifier ("__inpowerset")), tree_cons (NULL_TREE, convert (long_unsigned_type_node, pos), tree_cons (NULL_TREE, build1 (ADDR_EXPR, build_pointer_type (set_type), set), tree_cons (NULL_TREE, convert (long_unsigned_type_node, set_length), build_tree_list (NULL_TREE, min_val))))); return expand_expr (fcall, NULL_RTX, VOIDmode, 0); } case PACKED_ARRAY_REF: { tree array = TREE_OPERAND (exp, 0); tree pos = save_expr (TREE_OPERAND (exp, 1)); tree array_type = TREE_TYPE (array); tree array_length = discrete_count (TYPE_DOMAIN (array_type)); tree min_val = convert (long_integer_type_node, TYPE_MIN_VALUE (TYPE_DOMAIN (array_type))); tree fcall; /* FIXME: Function-call not needed if pos and width are constant! */ /* TODO: make sure this makes sense. */ if (! mark_addressable (array)) { error ("array is not addressable"); return const0_rtx; } fcall = build_chill_function_call ( lookup_name (get_identifier ("__inpowerset")), tree_cons (NULL_TREE, convert (long_unsigned_type_node, pos), tree_cons (NULL_TREE, build1 (ADDR_EXPR, build_pointer_type (array_type), array), tree_cons (NULL_TREE, convert (long_unsigned_type_node, array_length), build_tree_list (NULL_TREE, min_val))))); return expand_expr (fcall, NULL_RTX, VOIDmode, 0); } case UNDEFINED_EXPR: if (target == 0) { target = assign_stack_temp (TYPE_MODE (TREE_TYPE (exp)), int_size_in_bytes (TREE_TYPE (exp)), 0); preserve_temp_slots (target); } /* We don't actually need to *do* anything ... */ return target; default: break; } /* NOTREACHED */ return NULL;}/* Check that the argument list has a length in [min_length .. max_length]. (max_length == -1 means "infinite".) If so return the actual length. Otherwise, return an error message and return -1. */static intcheck_arglist_length (args, min_length, max_length, name) tree args; int min_length; int max_length; tree name;{ int length = list_length (args); if (length < min_length) error ("Too few arguments in call to `%s'", IDENTIFIER_POINTER (name)); else if (max_length != -1 && length > max_length) error ("Too many arguments in call to `%s'", IDENTIFIER_POINTER (name)); else return length; return -1;}/* * This is the code from c-typeck.c, with the C-specific cruft * removed (possibly I just didn't understand it, but it was * apparently simply discarding part of my LIST). */static treeinternal_build_compound_expr (list, first_p) tree list; int first_p ATTRIBUTE_UNUSED;{ register tree rest; if (TREE_CHAIN (list) == 0) return TREE_VALUE (list); rest = internal_build_compound_expr (TREE_CHAIN (list), FALSE); if (! TREE_SIDE_EFFECTS (TREE_VALUE (list))) return rest; return build (COMPOUND_EXPR, TREE_TYPE (rest), TREE_VALUE (list), rest);}/* Given a list of expressions, return a compound expression that performs them all and returns the value of the last of them. *//* FIXME: this should be merged with the C version */treebuild_chill_compound_expr (list) tree list;{ return internal_build_compound_expr (list, TRUE);}/* Given an expression PTR for a pointer, return an expression for the value pointed to. do_empty_check is 0, don't perform a NULL pointer check, else do it. */treebuild_chill_indirect_ref (ptr, mode, do_empty_check) tree ptr; tree mode; int do_empty_check;{ register tree type; if (ptr == NULL_TREE || TREE_CODE (ptr) == ERROR_MARK) return ptr; if (mode != NULL_TREE && TREE_CODE (mode) == ERROR_MARK) return error_mark_node; type = TREE_TYPE (ptr); if (TREE_CODE (type) == REFERENCE_TYPE) { type = TREE_TYPE (type); ptr = convert (type, ptr); } /* check for ptr is really a POINTER */ if (TREE_CODE (type) != POINTER_TYPE) { error ("cannot dereference, not a pointer."); return error_mark_node; } if (mode && TREE_CODE (mode) == IDENTIFIER_NODE) { tree decl = lookup_name (mode); if (decl == NULL_TREE || TREE_CODE (decl) != TYPE_DECL) { if (pass == 2) error ("missing '.' operator or undefined mode name `%s'.", IDENTIFIER_POINTER (mode));#if 0 error ("You have forgotten the '.' operator which must"); error (" precede a STRUCT field reference, or `%s' is an undefined mode", IDENTIFIER_POINTER (mode));#endif return error_mark_node; } } if (mode) { mode = get_type_of (mode); ptr = convert (build_pointer_type (mode), ptr); } else if (type == ptr_type_node) { error ("Can't dereference PTR value using unary `->'."); return error_mark_node; } if (do_empty_check) ptr = check_non_null (ptr); type = TREE_TYPE (ptr); if (TREE_CODE (type) == POINTER_TYPE) { if (TREE_CODE (ptr) == ADDR_EXPR && !flag_volatile && (TREE_TYPE (TREE_OPERAND (ptr, 0)) == TREE_TYPE (type))) return TREE_OPERAND (ptr, 0); else { tree t = TREE_TYPE (type); register tree ref = build1 (INDIRECT_REF, TYPE_MAIN_VARIANT (t), ptr); if (TYPE_SIZE (t) == 0 && TREE_CODE (t) != ARRAY_TYPE) { error ("dereferencing pointer to incomplete type"); return error_mark_node; } if (TREE_CODE (t) == VOID_TYPE) warning ("dereferencing `void *' pointer"); /* We *must* set TREE_READONLY when dereferencing a pointer to const, so that we get the proper error message if the result is used to assign to. Also, &* is supposed to be a no-op. And ANSI C seems to specify that the type of the result should be the const type. */ /* A de-reference of a pointer to const is not a const. It is valid to change it via some other pointer. */ TREE_READONLY (ref) = TYPE_READONLY (t); TREE_SIDE_EFFECTS (ref) = TYPE_VOLATILE (t) || TREE_SIDE_EFFECTS (ptr) || flag_volatile; TREE_THIS_VOLATILE (ref) = TYPE_VOLATILE (t) || flag_volatile; return ref; } } else if (TREE_CODE (ptr) != ERROR_MARK) error ("invalid type argument of `->'"); return error_mark_node;}/* NODE is a COMPONENT_REF whose mode is an IDENTIFIER, which is replaced by the proper FIELD_DECL. Also do the right thing for variant records. */treeresolve_component_ref (node) tree node;{ tree datum = TREE_OPERAND (node, 0); tree field_name = TREE_OPERAND (node, 1); tree type = TREE_TYPE (datum); tree field; if (TREE_CODE (datum) == ERROR_MARK) return error_mark_node; if (TREE_CODE (type) == REFERENCE_TYPE) { type = TREE_TYPE (type); TREE_OPERAND (node, 0) = datum = convert (type, datum); } if (TREE_CODE (type) != RECORD_TYPE) { error ("operand of '.' is not a STRUCT"); return error_mark_node; } TREE_READONLY (node) = TREE_READONLY (datum); TREE_SIDE_EFFECTS (node) = TREE_SIDE_EFFECTS (datum); for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) { if (TREE_CODE (TREE_TYPE (field)) == UNION_TYPE) { tree variant; for (variant = TYPE_FIELDS (TREE_TYPE (field)); variant; variant = TREE_CHAIN (variant)) { tree vfield; for (vfield = TYPE_FIELDS (TREE_TYPE (variant)); vfield; vfield = TREE_CHAIN (vfield)) { if (DECL_NAME (vfield) == field_name) { /* Found a variant field */ datum = build (COMPONENT_REF, TREE_TYPE (field), datum, field); datum = build (COMPONENT_REF, TREE_TYPE (variant), datum, variant); TREE_OPERAND (node, 0) = datum; TREE_OPERAND (node, 1) = vfield; TREE_TYPE (node) = TREE_TYPE (vfield); TREE_READONLY (node) |= TYPE_READONLY (TREE_TYPE (node));#if 0 if (flag_testing_tags) { tree tagtest = NOT IMPLEMENTED; tree tagf = ridpointers[(int) RID_RANGEFAIL]; node = check_expression (node, tagtest, tagf); }#endif return node; } } } } if (DECL_NAME (field) == field_name) { /* Found a fixed field */ TREE_OPERAND (node, 1) = field; TREE_TYPE (node) = TREE_TYPE (field); TREE_READONLY (node) |= TYPE_READONLY (TREE_TYPE (node)); return fold (node); } } error ("No field named `%s'", IDENTIFIER_POINTER (field_name)); return error_mark_node;}treebuild_component_ref (datum, field_name) tree datum, field_name;{ tree node = build_nt (COMPONENT_REF, datum, field_name); if (pass != 1) node = resolve_component_ref (node); return node;}/* function checks (for build_chill_component_ref) if a given type is really an instance type. CH_IS_INSTANCE_MODE is not strict enough in this case, i.e. SYNMODE foo = STRUCT (a, b UINT) is compatible to INSTANCE. */static intis_really_instance (type) tree type;{ tree decl = TYPE_NAME (type); if (decl == NULL_TREE) /* this is not an instance */ return 0; if (DECL_NAME (decl) == ridpointers[(int)RID_INSTANCE]) /* this is an instance */ return 1; if (TYPE_FIELDS (type) == TYPE_FIELDS (instance_type_node)) /* we have a NEWMODE'd instance */ return 1; return 0;}/* This function is called by the parse. Here we check if the user tries to access a field in a type which is layouted as a structure but isn't like INSTANCE, BUFFER, EVENT, ASSOCIATION, ACCESS, TEXT, or VARYING array or character string. We don't do this in build_component_ref cause this function gets called from the compiler to access fields in one of the above mentioned modes. */treebuild_chill_component_ref (datum, field_name) tree datum, field_name;{ tree type = TREE_TYPE (datum); if ((type != NULL_TREE && TREE_CODE (type) == RECORD_TYPE) && ((CH_IS_INSTANCE_MODE (type) && is_really_instance (type)) || CH_IS_BUFFER_MODE (type) || CH_IS_EVENT_MODE (type) || CH_IS_ASSOCIATION_MODE (type) || CH_IS_ACCESS_MODE (type) || CH_IS_TEXT_MODE (type) || chill_varying_type_p (type))) { error ("operand of '.' is not a STRUCT"); return error_mark_node; } return build_component_ref (datum, field_name);}/* * Check for invalid binary operands & unary operands * RIGHT is 1 if checking right operand or unary operand; * it is 0 if checking left operand. * * return 1 if the given operand is NOT compatible as the * operand of the given operator *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -