📄 objc-act.c
字号:
tree type = (*lang_hooks.types.make_type) (RECORD_TYPE); tree fields = build_decl (FIELD_DECL, NULL_TREE, ptr_type_node); tree field = build_decl (FIELD_DECL, NULL_TREE, ptr_type_node); TREE_CHAIN (field) = fields; fields = field; field = build_decl (FIELD_DECL, NULL_TREE, unsigned_type_node); TREE_CHAIN (field) = fields; fields = field; /* NB: The finish_builtin_struct() routine expects FIELD_DECLs in reverse order! */ finish_builtin_struct (type, "__builtin_ObjCString", fields, NULL_TREE); return type;}/* Custom build_string which sets TREE_TYPE! */static treemy_build_string (int len, const char *str){ return fix_string_type (build_string (len, str));}/* Build a string with contents STR and length LEN and convert it to a pointer. */static treemy_build_string_pointer (int len, const char *str){ tree string = my_build_string (len, str); tree ptrtype = build_pointer_type (TREE_TYPE (TREE_TYPE (string))); return build1 (ADDR_EXPR, ptrtype, string);}static hashval_tstring_hash (const void *ptr){ tree str = ((struct string_descriptor *)ptr)->literal; const unsigned char *p = (const unsigned char *) TREE_STRING_POINTER (str); int i, len = TREE_STRING_LENGTH (str); hashval_t h = len; for (i = 0; i < len; i++) h = ((h * 613) + p[i]); return h;}static intstring_eq (const void *ptr1, const void *ptr2){ tree str1 = ((struct string_descriptor *)ptr1)->literal; tree str2 = ((struct string_descriptor *)ptr2)->literal; int len1 = TREE_STRING_LENGTH (str1); return (len1 == TREE_STRING_LENGTH (str2) && !memcmp (TREE_STRING_POINTER (str1), TREE_STRING_POINTER (str2), len1));}/* Given a chain of STRING_CST's, build a static instance of NXConstantString which points at the concatenation of those strings. We place the string object in the __string_objects section of the __OBJC segment. The Objective-C runtime will initialize the isa pointers of the string objects to point at the NXConstantString class object. */treeobjc_build_string_object (tree string){ tree initlist, constructor, constant_string_class; int length; tree fields, addr; struct string_descriptor *desc, key; void **loc; /* Prep the string argument. */ string = fix_string_type (string); TREE_SET_CODE (string, STRING_CST); length = TREE_STRING_LENGTH (string) - 1; /* Check whether the string class being used actually exists and has the correct ivar layout. */ if (!string_layout_checked) { string_layout_checked = -1; constant_string_class = lookup_interface (constant_string_id); internal_const_str_type = objc_build_internal_const_str_type (); if (!constant_string_class || !(constant_string_type = CLASS_STATIC_TEMPLATE (constant_string_class))) error ("cannot find interface declaration for %qs", IDENTIFIER_POINTER (constant_string_id)); /* The NSConstantString/NXConstantString ivar layout is now known. */ else if (!check_string_class_template ()) error ("interface %qs does not have valid constant string layout", IDENTIFIER_POINTER (constant_string_id)); /* For the NeXT runtime, we can generate a literal reference to the string class, don't need to run a constructor. */ else if (flag_next_runtime && !setup_string_decl ()) error ("cannot find reference tag for class %qs", IDENTIFIER_POINTER (constant_string_id)); else { string_layout_checked = 1; /* Success! */ add_class_reference (constant_string_id); } } if (string_layout_checked == -1) return error_mark_node; /* Perhaps we already constructed a constant string just like this one? */ key.literal = string; loc = htab_find_slot (string_htab, &key, INSERT); desc = *loc; if (!desc) { tree var; *loc = desc = ggc_alloc (sizeof (*desc)); desc->literal = string; /* GNU: (NXConstantString *) & ((__builtin_ObjCString) { NULL, string, length }) */ /* NeXT: (NSConstantString *) & ((__builtin_ObjCString) { isa, string, length }) */ fields = TYPE_FIELDS (internal_const_str_type); initlist = build_tree_list (fields, flag_next_runtime ? build_unary_op (ADDR_EXPR, string_class_decl, 0) : build_int_cst (NULL_TREE, 0)); fields = TREE_CHAIN (fields); initlist = tree_cons (fields, build_unary_op (ADDR_EXPR, string, 1), initlist); fields = TREE_CHAIN (fields); initlist = tree_cons (fields, build_int_cst (NULL_TREE, length), initlist); constructor = objc_build_constructor (internal_const_str_type, nreverse (initlist)); TREE_INVARIANT (constructor) = true; if (!flag_next_runtime) constructor = objc_add_static_instance (constructor, constant_string_type); else { var = build_decl (CONST_DECL, NULL, TREE_TYPE (constructor)); DECL_INITIAL (var) = constructor; TREE_STATIC (var) = 1; pushdecl_top_level (var); constructor = var; } desc->constructor = constructor; } addr = convert (build_pointer_type (constant_string_type), build_unary_op (ADDR_EXPR, desc->constructor, 1)); return addr;}/* Declare a static instance of CLASS_DECL initialized by CONSTRUCTOR. */static GTY(()) int num_static_inst;static treeobjc_add_static_instance (tree constructor, tree class_decl){ tree *chain, decl; char buf[256]; /* Find the list of static instances for the CLASS_DECL. Create one if not found. */ for (chain = &objc_static_instances; *chain && TREE_VALUE (*chain) != class_decl; chain = &TREE_CHAIN (*chain)); if (!*chain) { *chain = tree_cons (NULL_TREE, class_decl, NULL_TREE); add_objc_string (OBJC_TYPE_NAME (class_decl), class_names); } sprintf (buf, "_OBJC_INSTANCE_%d", num_static_inst++); decl = build_decl (VAR_DECL, get_identifier (buf), class_decl); DECL_COMMON (decl) = 1; TREE_STATIC (decl) = 1; DECL_ARTIFICIAL (decl) = 1; DECL_INITIAL (decl) = constructor; /* We may be writing something else just now. Postpone till end of input. */ DECL_DEFER_OUTPUT (decl) = 1; pushdecl_top_level (decl); rest_of_decl_compilation (decl, 1, 0); /* Add the DECL to the head of this CLASS' list. */ TREE_PURPOSE (*chain) = tree_cons (NULL_TREE, decl, TREE_PURPOSE (*chain)); return decl;}/* Build a static constant CONSTRUCTOR with type TYPE and elements ELTS. */static treeobjc_build_constructor (tree type, tree elts){ tree constructor = build_constructor_from_list (type, elts); TREE_CONSTANT (constructor) = 1; TREE_STATIC (constructor) = 1; TREE_READONLY (constructor) = 1;#ifdef OBJCPLUS /* Adjust for impedance mismatch. We should figure out how to build CONSTRUCTORs that consistently please both the C and C++ gods. */ if (!TREE_PURPOSE (elts)) TREE_TYPE (constructor) = NULL_TREE; TREE_HAS_CONSTRUCTOR (constructor) = 1;#endif return constructor;}/* Take care of defining and initializing _OBJC_SYMBOLS. *//* Predefine the following data type: struct _objc_symtab { long sel_ref_cnt; SEL *refs; short cls_def_cnt; short cat_def_cnt; void *defs[cls_def_cnt + cat_def_cnt]; }; */static voidbuild_objc_symtab_template (void){ tree field_decl, field_decl_chain; objc_symtab_template = start_struct (RECORD_TYPE, get_identifier (UTAG_SYMTAB)); /* long sel_ref_cnt; */ field_decl = create_field_decl (long_integer_type_node, "sel_ref_cnt"); field_decl_chain = field_decl; /* SEL *refs; */ field_decl = create_field_decl (build_pointer_type (objc_selector_type), "refs"); chainon (field_decl_chain, field_decl); /* short cls_def_cnt; */ field_decl = create_field_decl (short_integer_type_node, "cls_def_cnt"); chainon (field_decl_chain, field_decl); /* short cat_def_cnt; */ field_decl = create_field_decl (short_integer_type_node, "cat_def_cnt"); chainon (field_decl_chain, field_decl); if (imp_count || cat_count || !flag_next_runtime) { /* void *defs[imp_count + cat_count (+ 1)]; */ /* NB: The index is one less than the size of the array. */ int index = imp_count + cat_count + (flag_next_runtime? -1: 0); field_decl = create_field_decl (build_array_type (ptr_type_node, build_index_type (build_int_cst (NULL_TREE, index))), "defs"); chainon (field_decl_chain, field_decl); } finish_struct (objc_symtab_template, field_decl_chain, NULL_TREE);}/* Create the initial value for the `defs' field of _objc_symtab. This is a CONSTRUCTOR. */static treeinit_def_list (tree type){ tree expr, initlist = NULL_TREE; struct imp_entry *impent; if (imp_count) for (impent = imp_list; impent; impent = impent->next) { if (TREE_CODE (impent->imp_context) == CLASS_IMPLEMENTATION_TYPE) { expr = build_unary_op (ADDR_EXPR, impent->class_decl, 0); initlist = tree_cons (NULL_TREE, expr, initlist); } } if (cat_count) for (impent = imp_list; impent; impent = impent->next) { if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE) { expr = build_unary_op (ADDR_EXPR, impent->class_decl, 0); initlist = tree_cons (NULL_TREE, expr, initlist); } } if (!flag_next_runtime) { /* statics = { ..., _OBJC_STATIC_INSTANCES, ... } */ tree expr; if (static_instances_decl) expr = build_unary_op (ADDR_EXPR, static_instances_decl, 0); else expr = build_int_cst (NULL_TREE, 0); initlist = tree_cons (NULL_TREE, expr, initlist); } return objc_build_constructor (type, nreverse (initlist));}/* Construct the initial value for all of _objc_symtab. */static treeinit_objc_symtab (tree type){ tree initlist; /* sel_ref_cnt = { ..., 5, ... } */ initlist = build_tree_list (NULL_TREE, build_int_cst (long_integer_type_node, 0)); /* refs = { ..., _OBJC_SELECTOR_TABLE, ... } */ if (flag_next_runtime || ! sel_ref_chain) initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, 0), initlist); else initlist = tree_cons (NULL_TREE, convert (build_pointer_type (objc_selector_type), build_unary_op (ADDR_EXPR, UOBJC_SELECTOR_TABLE_decl, 1)), initlist); /* cls_def_cnt = { ..., 5, ... } */ initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, imp_count), initlist); /* cat_def_cnt = { ..., 5, ... } */ initlist = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, cat_count), initlist); /* cls_def = { ..., { &Foo, &Bar, ...}, ... } */ if (imp_count || cat_count || !flag_next_runtime) { tree field = TYPE_FIELDS (type); field = TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (field)))); initlist = tree_cons (NULL_TREE, init_def_list (TREE_TYPE (field)), initlist); } return objc_build_constructor (type, nreverse (initlist));}/* Generate forward declarations for metadata such as 'OBJC_CLASS_...'. */static treebuild_metadata_decl (const char *name, tree type){ tree decl; /* struct TYPE NAME_<name>; */ decl = start_var_decl (type, synth_id_with_class_suffix (name, objc_implementation_context)); return decl;}/* Push forward-declarations of all the categories so that init_def_list can use them in a CONSTRUCTOR. */static voidforward_declare_categories (void){ struct imp_entry *impent; tree sav = objc_implementation_context; for (impent = imp_list; impent; impent = impent->next) { if (TREE_CODE (impent->imp_context) == CATEGORY_IMPLEMENTATION_TYPE) { /* Set an invisible arg to synth_id_with_class_suffix. */ objc_implementation_context = impent->imp_context; /* extern struct objc_category _OBJC_CATEGORY_<name>; */ impent->class_decl = build_metadata_decl ("_OBJC_CATEGORY", objc_category_template); } } objc_implementation_context = sav;}/* Create the declaration of _OBJC_SYMBOLS, with type `struct _objc_symtab' and initialized appropriately. */static voidgenerate_objc_symtab_decl (void){ /* forward declare categories */ if (cat_count) forward_declare_categories (); build_objc_symtab_template (); UOBJC_SYMBOLS_decl = start_var_decl (objc_symtab_template, "_OBJC_SYMBOLS"); finish_var_decl (UOBJC_SYMBOLS_decl, init_objc_symtab (TREE_TYPE (UOBJC_SYMBOLS_decl)));}static treeinit_module_descriptor (tree type){ tree initlist, expr; /* version = { 1, ... } */ expr = build_int_cst (long_integer_type_node, OBJC_VERSION); initlist = build_tree_list (NULL_TREE, expr); /* size = { ..., sizeof (struct _objc_module), ... } */ expr = convert (long_integer_type_node, size_in_bytes (objc_module_template)); initlist = tree_cons (NULL_TREE, expr, initlist); /* name = { ..., "foo.m", ... } */ expr = add_objc_string (get_identifier (input_filename), class_names); initlist = tree_cons (NULL_TREE, expr, initlist); /* symtab = { ..., _OBJC_SYMBOLS, ... } */ if (UOBJC_SYMBOLS_decl) expr = build_unary_op (ADDR_EXPR, UOBJC_SYMBOLS_dec
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -