📄 expr.c
字号:
TREE_SIDE_EFFECTS (check) = 1; expand_expr_stmt (check); } expand_assignment (build_java_arrayaccess (array, rhs_type_node, index), rhs_node, 0, 0);}/* Expand the evaluation of ARRAY[INDEX]. build_java_check_indexed_type makes sure that LHS is an array type. May expand some bound checking and NULL pointer checking. LHS_TYPE_NODE is the type of ARRAY[INDEX]. But in the case of CHAR/BYTE/ BOOLEAN/SHORT, we push a promoted type back to the stack.*/static voidexpand_java_arrayload (lhs_type_node ) tree lhs_type_node;{ tree load_node; tree index_node = pop_value (int_type_node); tree array_node = pop_value (ptr_type_node); index_node = save_expr (index_node); array_node = save_expr (array_node); lhs_type_node = build_java_check_indexed_type (array_node, lhs_type_node); load_node = build_java_arrayaccess (array_node, lhs_type_node, index_node); if (INTEGRAL_TYPE_P (lhs_type_node) && TYPE_PRECISION (lhs_type_node) <= 32) load_node = fold (build1 (NOP_EXPR, int_type_node, load_node)); push_value (load_node);}/* Expands .length. Makes sure that we deal with and array and may expand a NULL check on the array object. */static voidexpand_java_array_length (){ tree array = pop_value (ptr_type_node); tree length = build_java_array_length_access (array); push_value (build_java_arraynull_check (array, length, int_type_node));}/* Emit code for the call to _Jv_Monitor{Enter,Exit}. CALL can be either soft_monitorenter_node or soft_monitorexit_node. */static treebuild_java_monitor (call, object) tree call; tree object;{ return (build (CALL_EXPR, void_type_node, build_address_of (call), build_tree_list (NULL_TREE, object), NULL_TREE));}/* Emit code for one of the PUSHC instructions. */static voidexpand_java_pushc (ival, type) int ival; tree type;{ tree value; if (type == ptr_type_node && ival == 0) value = null_pointer_node; else if (type == int_type_node || type == long_type_node) { value = build_int_2 (ival, ival < 0 ? -1 : 0); TREE_TYPE (value) = type; } else if (type == float_type_node || type == double_type_node) { REAL_VALUE_TYPE x;#ifdef REAL_ARITHMETIC REAL_VALUE_FROM_INT (x, ival, 0, TYPE_MODE (type));#else x = ival;#endif value = build_real (type, x); } else fatal ("internal error in expand_java_pushc"); push_value (value);}static voidexpand_java_return (type) tree type;{ if (type == void_type_node) expand_null_return (); else { tree retval = pop_value (type); tree res = DECL_RESULT (current_function_decl); retval = build (MODIFY_EXPR, TREE_TYPE (res), res, retval); TREE_SIDE_EFFECTS (retval) = 1; expand_return (retval); }}treebuild_address_of (value) tree value;{ return build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (value)), value);}static voidexpand_java_NEW (type) tree type;{ if (! CLASS_LOADED_P (type)) load_class (type, 1); layout_class_methods (type); push_value (build (CALL_EXPR, promote_type (type), build_address_of (alloc_object_node), tree_cons (NULL_TREE, build_class_ref (type), build_tree_list (NULL_TREE, size_in_bytes (type))), NULL_TREE));}static voidexpand_java_INSTANCEOF (type) tree type;{ tree value = pop_value (object_ptr_type_node); value = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (soft_instanceof_node)), build_address_of (soft_instanceof_node), tree_cons (NULL_TREE, value, build_tree_list (NULL_TREE, build_class_ref (type))), NULL_TREE); push_value (value);}static voidexpand_java_CHECKCAST (type) tree type;{ tree value = pop_value (ptr_type_node); value = build (CALL_EXPR, promote_type (type), build_address_of (soft_checkcast_node), tree_cons (NULL_TREE, build_class_ref (type), build_tree_list (NULL_TREE, value)), NULL_TREE); push_value (value);}static voidexpand_iinc (local_var_index, ival, pc) unsigned int local_var_index; int ival; int pc;{ tree local_var, res; tree constant_value; flush_quick_stack (); local_var = find_local_variable (local_var_index, int_type_node, pc); constant_value = build_int_2 (ival, ival < 0 ? -1 : 0); res = fold (build (PLUS_EXPR, int_type_node, local_var, constant_value)); expand_assignment (local_var, res, 0, 0);}treebuild_java_binop (op, type, arg1, arg2) enum tree_code op; tree type, arg1, arg2;{ tree mask; switch (op) { case URSHIFT_EXPR: { tree u_type = unsigned_type (type); arg1 = convert (u_type, arg1); arg1 = build_java_binop (RSHIFT_EXPR, u_type, arg1, arg2); return convert (type, arg1); } case LSHIFT_EXPR: case RSHIFT_EXPR: mask = build_int_2 (TYPE_PRECISION (TREE_TYPE (arg1)) - 1, 0); arg2 = fold (build (BIT_AND_EXPR, int_type_node, arg2, mask)); break; case COMPARE_L_EXPR: /* arg1 > arg2 ? 1 : arg1 == arg2 ? 0 : -1 */ case COMPARE_G_EXPR: /* arg1 < arg2 ? -1 : arg1 == arg2 ? 0 : 1 */ arg1 = save_expr (arg1); arg2 = save_expr (arg2); { tree ifexp1 = fold ( build (op == COMPARE_L_EXPR ? GT_EXPR : LT_EXPR, boolean_type_node, arg1, arg2)); tree ifexp2 = fold ( build (EQ_EXPR, boolean_type_node, arg1, arg2)); tree second_compare = fold (build (COND_EXPR, int_type_node, ifexp2, integer_zero_node, op == COMPARE_L_EXPR ? integer_negative_one_node : integer_one_node)); return fold (build (COND_EXPR, int_type_node, ifexp1, op == COMPARE_L_EXPR ? integer_one_node : integer_negative_one_node, second_compare)); } case COMPARE_EXPR: arg1 = save_expr (arg1); arg2 = save_expr (arg2); { tree ifexp1 = fold ( build (LT_EXPR, boolean_type_node, arg1, arg2)); tree ifexp2 = fold ( build (GT_EXPR, boolean_type_node, arg1, arg2)); tree second_compare = fold ( build (COND_EXPR, int_type_node, ifexp2, integer_one_node, integer_zero_node)); return fold (build (COND_EXPR, int_type_node, ifexp1, integer_negative_one_node, second_compare)); } case TRUNC_MOD_EXPR: if (TREE_CODE (type) == REAL_TYPE) { tree call; if (type != double_type_node) { arg1 = convert (double_type_node, arg1); arg2 = convert (double_type_node, arg2); } call = build (CALL_EXPR, double_type_node, build_address_of (soft_fmod_node), tree_cons (NULL_TREE, arg1, build_tree_list (NULL_TREE, arg2)), NULL_TREE); if (type != double_type_node) call = convert (type, call); return call; } break; default: ; } return fold (build (op, type, arg1, arg2));}static voidexpand_java_binop (type, op) tree type; enum tree_code op;{ tree larg, rarg; tree ltype = type; tree rtype = type; switch (op) { case LSHIFT_EXPR: case RSHIFT_EXPR: case URSHIFT_EXPR: rtype = int_type_node; rarg = pop_value (rtype); break; default: rarg = pop_value (rtype); } larg = pop_value (ltype); push_value (build_java_binop (op, type, larg, rarg));}/* Lookup the field named NAME in *TYPEP or its super classes. If not found, return NULL_TREE. (If the *TYPEP is not found, return error_mark_node.) If found, return the FIELD_DECL, and set *TYPEP to the class containing the field. */treelookup_field (typep, name) tree *typep; tree name;{ if (CLASS_P (*typep) && !CLASS_LOADED_P (*typep)) { load_class (*typep, 1); if (!TYPE_SIZE (*typep) || TREE_CODE (TYPE_SIZE (*typep)) == ERROR_MARK) return error_mark_node; } do { tree field, basetype_vec; int n, i; for (field = TYPE_FIELDS (*typep); field; field = TREE_CHAIN (field)) if (DECL_NAME (field) == name) return field; /* Process implemented interfaces. */ basetype_vec = TYPE_BINFO_BASETYPES (*typep); n = TREE_VEC_LENGTH (basetype_vec); for (i = 0; i < n; i++) { tree t = BINFO_TYPE (TREE_VEC_ELT (basetype_vec, i)); if ((field = lookup_field (&t, name))) return field; } *typep = CLASSTYPE_SUPER (*typep); } while (*typep); return NULL_TREE;}/* Look up the field named NAME in object SELF_VALUE, which has class SELF_CLASS (a non-handle RECORD_TYPE). SELF_VALUE is NULL_TREE if looking for a static field. */treebuild_field_ref (self_value, self_class, name) tree self_value, self_class, name;{ tree base_class = self_class; tree field_decl = lookup_field (&base_class, name); if (field_decl == NULL_TREE) { error ("field `%s' not found", IDENTIFIER_POINTER (name)); return error_mark_node; } if (self_value == NULL_TREE) { return build_static_field_ref (field_decl); } else { tree base_handle_type = promote_type (base_class); if (base_handle_type != TREE_TYPE (self_value)) self_value = fold (build1 (NOP_EXPR, base_handle_type, self_value));#ifdef JAVA_USE_HANDLES self_value = unhand_expr (self_value);#endif self_value = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (self_value)), self_value); return fold (build (COMPONENT_REF, TREE_TYPE (field_decl), self_value, field_decl)); }}treelookup_label (pc) int pc;{ tree name; char buf[32]; ASM_GENERATE_INTERNAL_LABEL(buf, "LJpc=", pc); name = get_identifier (buf); if (IDENTIFIER_LOCAL_VALUE (name)) return IDENTIFIER_LOCAL_VALUE (name); else { /* The type of the address of a label is return_address_type_node. */ tree decl = create_label_decl (name); LABEL_PC (decl) = pc; label_rtx (decl); return pushdecl (decl); }}/* Generate a unique name for the purpose of loops and switches labels, and try-catch-finally blocks label or temporary variables. */treegenerate_name (){ static int l_number = 0; char buff [32]; ASM_GENERATE_INTERNAL_LABEL(buff, "LJv", l_number); l_number++; return get_identifier (buff);}treecreate_label_decl (name) tree name;{ tree decl; push_obstacks (&permanent_obstack, &permanent_obstack); decl = build_decl (LABEL_DECL, name, TREE_TYPE (return_address_type_node)); pop_obstacks (); DECL_CONTEXT (decl) = current_function_decl; DECL_IGNORED_P (decl) = 1; return decl;}/* This maps a bytecode offset (PC) to various flags. */char *instruction_bits;static voidnote_label (current_pc, target_pc) int current_pc ATTRIBUTE_UNUSED, target_pc;{ lookup_label (target_pc); instruction_bits [target_pc] |= BCODE_JUMP_TARGET;}/* Emit code to jump to TARGET_PC if VALUE1 CONDITION VALUE2, where CONDITION is one of one the compare operators. */static voidexpand_compare (condition, value1, value2, target_pc) enum tree_code condition; tree value1, value2; int target_pc;{ tree target = lookup_label (target_pc); tree cond = fold (build (condition, boolean_type_node, value1, value2)); expand_start_cond (truthvalue_conversion (cond), 0); expand_goto (target); expand_end_cond ();}/* Emit code for a TEST-type opcode. */static voidexpand_test (condition, type, target_pc) enum tree_code condition; tree type; int target_pc;{ tree value1, value2; flush_quick_stack (); value1 = pop_value (type); value2 = (type == ptr_type_node) ? null_pointer_node : integer_zero_node; expand_compare (condition, value1, value2, target_pc);}/* Emit code for a COND-type opcode. */static voidexpand_cond (condition, type, target_pc)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -