📄 objc-actions.c
字号:
static voidgenerate_ivar_lists (){ tree initlist, ivar_list_template, chain; tree cast, variable_length_type; int size; if (!objc_ivar_template) objc_ivar_template = build_ivar_template (); cast = build_tree_list (build_tree_list (NULLT, xref_tag (RECORD_TYPE, get_identifier (_TAG_IVAR_LIST))), NULLT); variable_length_type = groktypename (cast); /* only generate class variables for the root of the inheritance hierarchy since these will be the same for every class */ if (CLASS_SUPER_NAME (implementation_template) == NULLT && (chain = TYPE_FIELDS (objc_class_template))) { size = 0; initlist = build_ivar_list_initializer (chain, &size); ivar_list_template = build_ivar_list_template (objc_ivar_template, size); _OBJC_CLASS_VARIABLES_decl = generate_ivars_list (ivar_list_template, "_OBJC_CLASS_VARIABLES", size, initlist); /* cast! */ TREE_TYPE (_OBJC_CLASS_VARIABLES_decl) = variable_length_type; } else _OBJC_CLASS_VARIABLES_decl = 0; chain = CLASS_IVARS (implementation_template); if (chain) { size = 0; initlist = build_ivar_list_initializer (chain, &size); ivar_list_template = build_ivar_list_template (objc_ivar_template, size); _OBJC_INSTANCE_VARIABLES_decl = generate_ivars_list (ivar_list_template, "_OBJC_INSTANCE_VARIABLES", size, initlist); /* cast! */ TREE_TYPE (_OBJC_INSTANCE_VARIABLES_decl) = variable_length_type; } else _OBJC_INSTANCE_VARIABLES_decl = 0;}static treebuild_dispatch_table_initializer (entries, size) tree entries; int *size;{ tree initlist = NULLT; do { int offset = add_objc_string (METHOD_SEL_NAME (entries)); initlist = tree_cons (NULLT, init_selector (offset), initlist); offset = add_objc_string (METHOD_ENCODING (entries)); initlist = tree_cons (NULLT, build_msg_pool_reference (offset), initlist); initlist = tree_cons (NULLT, METHOD_DEFINITION (entries), initlist); (*size)++; entries = TREE_CHAIN (entries); } while (entries); return build_nt (CONSTRUCTOR, NULLT, nreverse (initlist));}/* * To accomplish method prototyping without generating all kinds of * inane warnings, the definition of the dispatch table entries were * changed from: * * struct objc_method { SEL _cmd; id (*_imp)(); }; * to: * struct objc_method { SEL _cmd; void *_imp; }; */static treebuild_method_template (){ tree _SLT_record; tree decl_specs, field_decl, field_decl_chain, parms; _SLT_record = start_struct (RECORD_TYPE, get_identifier (_TAG_METHOD));#ifdef OBJC_INT_SELECTORS /* unsigned int _cmd; */ decl_specs = tree_cons (NULLT, ridpointers[(int) RID_UNSIGNED], NULLT); decl_specs = tree_cons (NULLT, ridpointers[(int) RID_INT], decl_specs); field_decl = get_identifier ("_cmd");#else /* not OBJC_INT_SELECTORS */ /* struct objc_selector *_cmd; */ decl_specs = tree_cons (NULLT, xref_tag (RECORD_TYPE, get_identifier (TAG_SELECTOR)), NULLT); field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("_cmd"));#endif /* not OBJC_INT_SELECTORS */ field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT); field_decl_chain = field_decl; decl_specs = tree_cons (NULLT, ridpointers[(int) RID_CHAR], NULLT); field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("method_types")); field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT); chainon (field_decl_chain, field_decl); /* void *_imp; */ decl_specs = tree_cons (NULLT, ridpointers[(int) RID_VOID], NULLT); field_decl = build1 (INDIRECT_REF, NULLT, get_identifier ("_imp")); field_decl = grokfield (input_filename, lineno, field_decl, decl_specs, NULLT); chainon (field_decl_chain, field_decl); finish_struct (_SLT_record, field_decl_chain); return _SLT_record;}static treegenerate_dispatch_table (type, name, size, list) tree type; char *name; int size; tree list;{ tree sc_spec, decl_specs, decl, initlist; sc_spec = tree_cons (NULLT, ridpointers[(int) RID_STATIC], NULLT); decl_specs = tree_cons (NULLT, type, sc_spec); decl = start_decl (synth_id_with_class_suffix (name), decl_specs, 1); initlist = build_tree_list (NULLT, build_int_2 (0, 0)); initlist = tree_cons (NULLT, build_int_2 (size, 0), initlist); initlist = tree_cons (NULLT, list, initlist); finish_decl (decl, build_nt (CONSTRUCTOR, NULLT, nreverse (initlist)), NULLT); return decl;}static voidgenerate_dispatch_tables (){ tree initlist, chain, method_list_template; tree cast, variable_length_type; int size; if (!objc_method_template) objc_method_template = build_method_template (); cast = build_tree_list (build_tree_list (NULLT, xref_tag (RECORD_TYPE, get_identifier (_TAG_METHOD_LIST))), NULLT); variable_length_type = groktypename (cast); chain = CLASS_CLS_METHODS (implementation_context); if (chain) { size = 0; initlist = build_dispatch_table_initializer (chain, &size); method_list_template = build_method_list_template (objc_method_template, size); if (TREE_CODE (implementation_context) == IMPLEMENTATION_TYPE) _OBJC_CLASS_METHODS_decl = generate_dispatch_table (method_list_template, "_OBJC_CLASS_METHODS", size, initlist); else /* we have a category */ _OBJC_CLASS_METHODS_decl = generate_dispatch_table (method_list_template, "_OBJC_CATEGORY_CLASS_METHODS", size, initlist); /* cast! */ TREE_TYPE (_OBJC_CLASS_METHODS_decl) = variable_length_type; } else _OBJC_CLASS_METHODS_decl = 0; chain = CLASS_NST_METHODS (implementation_context); if (chain) { size = 0; initlist = build_dispatch_table_initializer (chain, &size); method_list_template = build_method_list_template (objc_method_template, size); if (TREE_CODE (implementation_context) == IMPLEMENTATION_TYPE) _OBJC_INSTANCE_METHODS_decl = generate_dispatch_table (method_list_template, "_OBJC_INSTANCE_METHODS", size, initlist); else /* we have a category */ _OBJC_INSTANCE_METHODS_decl = generate_dispatch_table (method_list_template, "_OBJC_CATEGORY_INSTANCE_METHODS", size, initlist); /* cast! */ TREE_TYPE (_OBJC_INSTANCE_METHODS_decl) = variable_length_type; } else _OBJC_INSTANCE_METHODS_decl = 0;}static treebuild_category_initializer (cat_name, class_name, instance_methods, class_methods) tree cat_name; tree class_name; tree instance_methods; tree class_methods;{ tree initlist = NULLT, expr; initlist = tree_cons (NULLT, cat_name, initlist); initlist = tree_cons (NULLT, class_name, initlist); if (!instance_methods) initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist); else { expr = build_unary_op (ADDR_EXPR, instance_methods, 0); initlist = tree_cons (NULLT, expr, initlist); } if (!class_methods) initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist); else { expr = build_unary_op (ADDR_EXPR, class_methods, 0); initlist = tree_cons (NULLT, expr, initlist); } return build_nt (CONSTRUCTOR, NULLT, nreverse (initlist));}/* * struct objc_class { * struct objc_class *isa; * struct objc_class *super_class; * char *name; * long version; * long info; * long instance_size; * struct objc_ivar_list *ivars; * struct objc_method_list *methods; * struct objc_cache *cache; * }; */static treebuild_shared_structure_initializer (isa, super, name, size, status, dispatch_table, ivar_list) tree isa; tree super; tree name; tree size; int status; tree dispatch_table; tree ivar_list;{ tree initlist = NULLT, expr; /* isa = */ initlist = tree_cons (NULLT, isa, initlist); /* super_class = */ initlist = tree_cons (NULLT, super, initlist); /* name = */ initlist = tree_cons (NULLT, name, initlist); /* version = */ initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist); /* info = */ initlist = tree_cons (NULLT, build_int_2 (status, 0), initlist); /* instance_size = */ initlist = tree_cons (NULLT, size, initlist); /* objc_ivar_list = */ if (!ivar_list) initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist); else { expr = build_unary_op (ADDR_EXPR, ivar_list, 0); initlist = tree_cons (NULLT, expr, initlist); } /* objc_method_list = */ if (!dispatch_table) initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist); else { expr = build_unary_op (ADDR_EXPR, dispatch_table, 0); initlist = tree_cons (NULLT, expr, initlist); } /* method_cache = */ initlist = tree_cons (NULLT, build_int_2 (0, 0), initlist); return build_nt (CONSTRUCTOR, NULLT, nreverse (initlist));}/* * static struct objc_category _OBJC_CATEGORY_<name> = { ... }; */static voidgenerate_category (cat) tree cat;{ tree sc_spec, decl_specs, decl; tree initlist, cat_name_expr, class_name_expr; int offset; sc_spec = tree_cons (NULLT, ridpointers[(int) RID_STATIC], NULLT); decl_specs = tree_cons (NULLT, objc_category_template, sc_spec); decl = start_decl (synth_id_with_class_suffix ("_OBJC_CATEGORY"), decl_specs, 1); offset = add_objc_string (CLASS_SUPER_NAME (cat)); cat_name_expr = build_msg_pool_reference (offset); offset = add_objc_string (CLASS_NAME (cat)); class_name_expr = build_msg_pool_reference (offset); initlist = build_category_initializer ( cat_name_expr, class_name_expr, _OBJC_INSTANCE_METHODS_decl, _OBJC_CLASS_METHODS_decl); finish_decl (decl, initlist, NULLT);}/* * static struct objc_class _OBJC_METACLASS_Foo={ ... }; * static struct objc_class _OBJC_CLASS_Foo={ ... }; */static voidgenerate_shared_structures (){ tree sc_spec, decl_specs, expr_decl, decl; tree name_expr, super_expr, root_expr; tree my_root_id = NULLT, my_super_id = NULLT; tree cast_type, initlist; int offset; my_super_id = CLASS_SUPER_NAME (implementation_template); if (my_super_id) { add_class_reference (my_super_id); /* compute "my_root_id" - this is required for code generation. * the "isa" for all meta class structures points to the root of * the inheritance hierarchy (e.g. "__Object")... */ my_root_id = my_super_id; do { tree my_root_int = lookup_interface (my_root_id); if (my_root_int && CLASS_SUPER_NAME (my_root_int)) my_root_id = CLASS_SUPER_NAME (my_root_int); else break; } while (1); } else /* no super class */ { my_root_id = CLASS_NAME (implementation_template); } cast_type = groktypename (build_tree_list (build_tree_list (NULLT, objc_class_template), build1 (INDIRECT_REF, NULLT, NULLT))); offset = add_objc_string (CLASS_NAME (implementation_template)); name_expr = build_msg_pool_reference (offset); /* install class `isa' and `super' pointers at runtime */ if (my_super_id) { offset = add_objc_string (my_super_id); super_expr = build_msg_pool_reference (offset); TREE_TYPE (super_expr) = cast_type; /* cast! */ } else super_expr = build_int_2 (0, 0); offset = add_objc_string (my_root_id); root_expr = build_msg_pool_reference (offset); TREE_TYPE (root_expr) = cast_type; /* cast! */ /* static struct objc_class _OBJC_METACLASS_Foo = { ... }; */ sc_spec = build_tree_list (NULLT, ridpointers[(int) RID_STATIC]); decl_specs = tree_cons (NULLT, objc_class_template, sc_spec); decl = start_decl (DECL_NAME (_OBJC_METACLASS_decl), decl_specs, 1); initlist = build_shared_structure_initializer ( root_expr, super_expr, name_expr, build_int_2 (TREE_INT_CST_LOW (TYPE_SIZE (objc_class_template)) / BITS_PER_UNIT, 0), 2 /*CLS_META*/, _OBJC_CLASS_METHODS_decl, _OBJC_CLASS_VARIABLES_decl); finish_decl (decl, initlist, NULLT); /* static struct objc_class _OBJC_CLASS_Foo={ ... }; */ decl = start_decl (DECL_NAME (_OBJC_CLASS_decl), decl_specs, 1); initlist = build_shared_structure_initializer ( build_unary_op (ADDR_EXPR, _OBJC_METACLASS_decl, 0), super_expr, name_expr, build_int_2 (TREE_INT_CST_LOW (TYPE_SIZE (CLASS_STATIC_TEMPLATE (implementation_template))) / BITS_PER_UNIT, 0), 1 /*CLS_FACTORY*/, _OBJC_INSTANCE_METHODS_decl, _OBJC_INSTANCE_VARIABLES_decl); finish_decl (decl, initlist, NULLT);}static treesynth_id_with_class_suffix (preamble) char *preamble;{ char *string; if (TREE_CODE (implementation_context) == IMPLEMENTATION_TYPE) { string = (char *) alloca (strlen (preamble) + strlen (IDENTIFIER_POINTER (CLASS_NAME (implementation_context))) + 3); sprintf (string, "%s_%s", preamble, IDENTIFIER_POINTER (CLASS_NAME (implementation_context))); } else { /* we have a category */ string = (char *) alloca (strlen (preamble) + strlen (IDENTIFIER_POINTER (CLASS_NAME (implementation_context))) + strlen (IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context))) + 3); sprintf (string, "%s_%s_%s", preamble, IDENTIFIER_POINTER (CLASS_NAME (implementation_context)), IDENTIFIER_POINTER (CLASS_SUPER_NAME (implementation_context))); } return get_identifier (string);}/* * usage: * keyworddecl: * selector ':' '(
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -