📄 expr.c
字号:
{ count--; if (stack_pointer == 1 || count <= 0) fatal ("stack underflow"); type = stack_type_map[stack_pointer - 2]; } val = pop_value (type); count--; }}/* Implement the 'swap' operator (to swap two top stack slots). */static voidjava_stack_swap (){ tree type1, type2; rtx temp; tree decl1, decl2; if (stack_pointer < 2 || (type1 = stack_type_map[stack_pointer - 1]) == TYPE_UNKNOWN || (type2 = stack_type_map[stack_pointer - 2]) == TYPE_UNKNOWN || type1 == TYPE_SECOND || type2 == TYPE_SECOND || TYPE_IS_WIDE (type1) || TYPE_IS_WIDE (type2)) fatal ("bad stack swap"); flush_quick_stack (); decl1 = find_stack_slot (stack_pointer - 1, type1); decl2 = find_stack_slot (stack_pointer - 2, type2); temp = copy_to_reg (DECL_RTL (decl1)); emit_move_insn (DECL_RTL (decl1), DECL_RTL (decl2)); emit_move_insn (DECL_RTL (decl2), temp); stack_type_map[stack_pointer - 1] = type2; stack_type_map[stack_pointer - 2] = type1;}static voidjava_stack_dup (size, offset) int size, offset;{ int low_index = stack_pointer - size - offset; int dst_index; if (low_index < 0) error ("stack underflow - dup* operation"); flush_quick_stack (); stack_pointer += size; dst_index = stack_pointer; for (dst_index = stack_pointer; --dst_index >= low_index; ) { tree type; int src_index = dst_index - size; if (src_index < low_index) src_index = dst_index + size + offset; type = stack_type_map [src_index]; if (type == TYPE_SECOND) { if (src_index <= low_index) fatal ("dup operation splits 64-bit number"); stack_type_map[dst_index] = type; src_index--; dst_index--; type = stack_type_map[src_index]; if (! TYPE_IS_WIDE (type)) fatal ("internal error - dup operation"); } else if (TYPE_IS_WIDE (type)) fatal ("internal error - dup operation"); if (src_index != dst_index) { tree src_decl = find_stack_slot (src_index, type); tree dst_decl = find_stack_slot (dst_index, type); emit_move_insn (DECL_RTL (dst_decl), DECL_RTL (src_decl)); stack_type_map[dst_index] = type; } }}/* Calls _Jv_Throw. Discard the contents of the value stack. */static treebuild_java_athrow (node) tree node;{ tree call; call = build (CALL_EXPR, void_type_node, build_address_of (throw_node), build_tree_list (NULL_TREE, node), NULL_TREE); TREE_SIDE_EFFECTS (call) = 1; expand_expr_stmt (call); java_stack_pop (stack_pointer);}/* Implementation for jsr/ret */static voidbuild_java_jsr (where, ret) tree where; tree ret;{ tree ret_label = fold (build1 (ADDR_EXPR, return_address_type_node, ret)); push_value (ret_label); flush_quick_stack (); expand_goto (where); expand_label (ret);}static voidbuild_java_ret (location) tree location;{ expand_computed_goto (location);} /* Implementation of operations on array: new, load, store, length *//* Array core info access macros */#define JAVA_ARRAY_LENGTH_OFFSET(A) \ size_binop (CEIL_DIV_EXPR, \ (DECL_FIELD_BITPOS \ (TREE_CHAIN (TYPE_FIELDS (TREE_TYPE (TREE_TYPE (A)))))), \ size_int (BITS_PER_UNIT))treedecode_newarray_type (atype) int atype;{ switch (atype) { case 4: return boolean_type_node; case 5: return char_type_node; case 6: return float_type_node; case 7: return double_type_node; case 8: return byte_type_node; case 9: return short_type_node; case 10: return int_type_node; case 11: return long_type_node; default: return NULL_TREE; }}/* Map primitive type to the code used by OPCODE_newarray. */intencode_newarray_type (type) tree type;{ if (type == boolean_type_node) return 4; else if (type == char_type_node) return 5; else if (type == float_type_node) return 6; else if (type == double_type_node) return 7; else if (type == byte_type_node) return 8; else if (type == short_type_node) return 9; else if (type == int_type_node) return 10; else if (type == long_type_node) return 11; else fatal ("Can't compute type code - patch_newarray");}/* Build a call to _Jv_ThrowBadArrayIndex(), the ArrayIndexOfBoundsException exception handler. */static treebuild_java_throw_out_of_bounds_exception (index) tree index;{ tree node = build (CALL_EXPR, int_type_node, build_address_of (soft_badarrayindex_node), build_tree_list (NULL_TREE, index), NULL_TREE); TREE_SIDE_EFFECTS (node) = 1; /* Allows expansion within ANDIF */ return (node);}/* Return the length of an array. Doesn't perform any checking on the nature or value of the array NODE. May be used to implement some bytecodes. */treebuild_java_array_length_access (node) tree node;{ tree type = TREE_TYPE (node); HOST_WIDE_INT length; if (!is_array_type_p (type)) fatal ("array length on a non-array reference"); length = java_array_type_length (type); if (length >= 0) return build_int_2 (length, 0); return fold (build1 (INDIRECT_REF, int_type_node, fold (build (PLUS_EXPR, ptr_type_node, node, JAVA_ARRAY_LENGTH_OFFSET(node)))));}/* Optionally checks an array against the NULL pointer, eventually throwing a NullPointerException. It could replace signal handling, but tied to NULL. ARG1: the pointer to check, ARG2: the expression to use if the pointer is non-null and ARG3 the type that should be returned. */treebuild_java_arraynull_check (node, expr, type) tree node ATTRIBUTE_UNUSED; tree expr; tree type ATTRIBUTE_UNUSED;{#if 0 static int java_array_access_throws_null_exception = 0; node = ???; if (java_array_access_throws_null_exception) return (build (COND_EXPR, type, build (EQ_EXPR, int_type_node, node, null_pointer_node), build_java_athrow (node), expr )); else#endif return (expr);}static treejava_array_data_offset (array) tree array;{ tree array_type = TREE_TYPE (TREE_TYPE (array)); tree data_fld = TREE_CHAIN (TREE_CHAIN (TYPE_FIELDS (array_type))); if (data_fld == NULL_TREE) return size_in_bytes (array_type); else return build_int_2 (TREE_INT_CST_LOW (DECL_FIELD_BITPOS (data_fld)) / BITS_PER_UNIT, 0);}/* Implement array indexing (either as l-value or r-value). Returns a tree for ARRAY[INDEX], assume TYPE is the element type. Optionally performs bounds checking and/or test to NULL. At this point, ARRAY should have been verified as an array. */treebuild_java_arrayaccess (array, type, index) tree array, type, index;{ tree arith, node, throw = NULL_TREE; arith = fold (build (PLUS_EXPR, int_type_node, java_array_data_offset (array), fold (build (MULT_EXPR, int_type_node, index, size_in_bytes(type))))); if (flag_bounds_check) { /* Generate: * (unsigned jint) INDEX >= (unsigned jint) LEN * && throw ArrayIndexOutOfBoundsException. * Note this is equivalent to and more efficient than: * INDEX < 0 || INDEX >= LEN && throw ... */ tree test; tree len = build_java_array_length_access (array); TREE_TYPE (len) = unsigned_int_type_node; test = fold (build (GE_EXPR, boolean_type_node, convert (unsigned_int_type_node, index), len)); if (! integer_zerop (test)) { throw = build (TRUTH_ANDIF_EXPR, int_type_node, test, build_java_throw_out_of_bounds_exception (index)); /* allows expansion within COMPOUND */ TREE_SIDE_EFFECTS( throw ) = 1; } } node = build1 (INDIRECT_REF, type, fold (build (PLUS_EXPR, ptr_type_node, array, (throw ? build (COMPOUND_EXPR, int_type_node, throw, arith ) : arith)))); return (fold (build_java_arraynull_check (array, node, type)));}/* Makes sure that INDEXED_TYPE is appropriate. If not, make it from ARRAY_NODE. This function is used to retrieve something less vague than a pointer type when indexing the first dimension of something like [[<t>. May return a corrected type, if necessary, otherwise INDEXED_TYPE is return unchanged. As a side effect, it also makes sure that ARRAY_NODE is an array. */static treebuild_java_check_indexed_type (array_node, indexed_type) tree array_node; tree indexed_type;{ tree elt_type; if (!is_array_type_p (TREE_TYPE (array_node))) fatal ("array indexing on a non-array reference"); elt_type = (TYPE_ARRAY_ELEMENT (TREE_TYPE (TREE_TYPE (array_node)))); if (indexed_type == ptr_type_node ) return promote_type (elt_type); /* BYTE/BOOLEAN store and load are used for both type */ if (indexed_type == byte_type_node && elt_type == boolean_type_node ) return boolean_type_node; if (indexed_type != elt_type ) fatal ("type array element mismatch"); else return indexed_type;}/* newarray triggers a call to _Jv_NewArray. This function should be called with an integer code (the type of array to create) and get from the stack the size of the dimmension. */treebuild_newarray (atype_value, length) int atype_value; tree length;{ tree type = build_java_array_type (decode_newarray_type (atype_value), TREE_CODE (length) == INTEGER_CST ? TREE_INT_CST_LOW (length) : -1); return build (CALL_EXPR, promote_type (type), build_address_of (soft_newarray_node), tree_cons (NULL_TREE, build_int_2 (atype_value, 0), build_tree_list (NULL_TREE, length)), NULL_TREE);}/* Generates anewarray from a given CLASS_TYPE. Gets from the stack the size of the dimension. */treebuild_anewarray (class_type, length) tree class_type; tree length;{ tree type = build_java_array_type (class_type, TREE_CODE (length) == INTEGER_CST ? TREE_INT_CST_LOW (length) : -1); return build (CALL_EXPR, promote_type (type), build_address_of (soft_anewarray_node), tree_cons (NULL_TREE, length, tree_cons (NULL_TREE, build_class_ref (class_type), build_tree_list (NULL_TREE, null_pointer_node))), NULL_TREE);}/* Return a node the evaluates 'new TYPE[LENGTH]'. */treebuild_new_array (type, length) tree type; tree length;{ if (JPRIMITIVE_TYPE_P (type)) return build_newarray (encode_newarray_type (type), length); else return build_anewarray (TREE_TYPE (type), length);}/* Generates a call to _Jv_NewMultiArray. multianewarray expects a class pointer, a number of dimensions and the matching number of dimensions. The argument list is NULL terminated. */static voidexpand_java_multianewarray (class_type, ndim) tree class_type; int ndim;{ int i; tree args = build_tree_list( NULL_TREE, null_pointer_node ); for( i = 0; i < ndim; i++ ) args = tree_cons (NULL_TREE, pop_value (int_type_node), args); push_value (build (CALL_EXPR, promote_type (class_type), build_address_of (soft_multianewarray_node), tree_cons (NULL_TREE, build_class_ref (class_type), tree_cons (NULL_TREE, build_int_2 (ndim, 0), args )), NULL_TREE));}/* ARRAY[INDEX] <- RHS. build_java_check_indexed_type makes sure that ARRAY is an array type. May expand some bound checking and NULL pointer checking. RHS_TYPE_NODE we are going to store. In the case of the CHAR/BYTE/BOOLEAN SHORT, the type popped of the stack is an INT. In those cases, we make the convertion. if ARRAy is a reference type, the assignment is checked at run-time to make sure that the RHS can be assigned to the array element type. It is not necessary to generate this code if ARRAY is final. */static voidexpand_java_arraystore (rhs_type_node) tree rhs_type_node;{ tree rhs_node = pop_value ((INTEGRAL_TYPE_P (rhs_type_node) && TYPE_PRECISION (rhs_type_node) <= 32) ? int_type_node : rhs_type_node); tree index = pop_value (int_type_node); tree array = pop_value (ptr_type_node); rhs_type_node = build_java_check_indexed_type (array, rhs_type_node); flush_quick_stack (); index = save_expr (index); array = save_expr (array); if (TREE_CODE (rhs_type_node) == POINTER_TYPE && !CLASS_FINAL (TYPE_NAME (TREE_TYPE (rhs_type_node)))) { tree check = build (CALL_EXPR, void_type_node, build_address_of (soft_checkarraystore_node), tree_cons (NULL_TREE, array, build_tree_list (NULL_TREE, rhs_node)), NULL_TREE);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -