From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 19545 invoked by alias); 6 Oct 2011 22:46:54 -0000 Received: (qmail 19484 invoked by uid 22791); 6 Oct 2011 22:46:50 -0000 X-SWARE-Spam-Status: No, hits=-0.5 required=5.0 tests=AWL,BAYES_50,TW_FP,TW_TM X-Spam-Check-By: sourceware.org Received: from gw.haerkules.de (HELO mail.lxgcc.net) (188.40.77.251) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Thu, 06 Oct 2011 22:46:34 +0000 Received: from localhost (localhost [127.0.0.1]) by mail.lxgcc.net (Postfix) with ESMTP id B51D11031D2; Fri, 7 Oct 2011 00:48:43 +0200 (CEST) Received: from mail.lxgcc.net ([127.0.0.1]) by localhost (mail.lxgcc.net [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id CvVIfZ04Hpkg; Fri, 7 Oct 2011 00:48:42 +0200 (CEST) Received: from [192.168.2.106] (p3E9EB204.dip.t-dialin.net [62.158.178.4]) by mail.lxgcc.net (Postfix) with ESMTPSA id DFDD61031D1; Fri, 7 Oct 2011 00:48:41 +0200 (CEST) Message-ID: <4E8E2FC5.6050801@mail.lxgcc.net> Date: Fri, 07 Oct 2011 02:06:00 -0000 From: Andi Hellmund User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.11pre) Gecko/20100623 Spicebird/0.8 MIME-Version: 1.0 To: niXman CC: "gcc@gcc.gnu.org" Subject: Re: The AST tree modification. Edited. References: <2950715866004049A240A2F9BB410E7315F416F5E7@azsmsx502.amr.corp.intel.com> In-Reply-To: <2950715866004049A240A2F9BB410E7315F416F5E7@azsmsx502.amr.corp.intel.com> Content-Type: multipart/mixed; boundary="------------050108090101010304060805" X-IsSubscribed: yes Mailing-List: contact gcc-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-owner@gcc.gnu.org X-SW-Source: 2011-10/txt/msg00100.txt.bz2 This is a multi-part message in MIME format. --------------050108090101010304060805 Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit Content-length: 2681 Hi, as an addition to Balaji's answer. Please find attached an extract of a sample front-end generating various types of tree nodes (e.g. arrays, structs, ...). This used to work with an older version of GCC, but I'm not sure if this still works with the most recent version. Anyway, it should give you some pointers for further investigations ... Best regards, Andi > Hello, > For most of the things you are looking for, please look for a function called build_decl. It is used in several places inside GCC. Let me give you a small example, > > If you do the following: > > tree x = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifer("ii"), integer_type_node) > > you will declare a variable called "ii" of type "integer." > > Similarly, to create a new internal structure, if do something like this: > > tree struct_frame = lang_hooks.make_type (RECORD_TYPE); > tree struct_field = build_decl (UNKNOWN_LOCATION, FIELD_DECL, get_identifier("variable"), integer_type_node) > TREE_CHAIN(struct_field) = struct_frame > > You will create the following internal structure > > struct { > int variable; > } > > I hope this helps you get started. > > Thanks, > > Balaji V .Iyer. > > -----Original Message----- > From: niXman [mailto:i.nixman@gmail.com] > Sent: Monday, October 03, 2011 6:51 PM > To: gcc@gcc.gnu.org > Subject: The AST tree modification. Edited. > > Hi everybody! > It is necessary to implement a plug-in for GCC designed to collect the information on types of translation unit, and generate static const array of types rtti_ex _ on its base; ////////////////////////////////////// > enum class type_ { > char_, uchar_, short_, ushort_, int_, uint_, long_, ulong_, > int64_, uint64_, array_, pointer_, double_, long_double_, float_, > class_ > }; > > struct rtti_ex_ { //<<<<<<<<<<<<<<<<<<<<<<<<< > const char* name; > const type_ type; > const size_t size; > const size_t align; > const size_t offset; > }; > > // generated from plugin. > static const rtti_ex_ rtti_ex_array_[] = { > {...}, > {...}, > {...} > }; > ///////////////////////////////////// > > There aren't any problems with information collection from AST. There is a complexity with AST modification: > 1. How to declare a variable? > 2. How to declare the typedef? > 3. How to declare a structure? > 4. How to declare an array of structures? > I suppose that there should be a function like: tree make_subtree (const char* source); which result I could insert in the corresponding node. But I haven't found it. > > Please, give me some links on this subject. It is very desirable, if you could give some links with examples. > > Thanks. > --------------050108090101010304060805 Content-Type: text/x-csrc; name="sfe_example.c" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="sfe_example.c" Content-length: 11420 #include "config.h" #include "system.h" #include "coretypes.h" #include "tm.h" #include "tree.h" #include "tree-dump.h" #include "tree-iterator.h" #include "gimple.h" #include "function.h" #include "flags.h" #include "output.h" #include "ggc.h" #include "toplev.h" #include "varray.h" #include "langhooks-def.h" #include "langhooks.h" #include "target.h" #include "cgraph.h" #include "sfe1.h" #include "opts.h" #include "input.h" /* static unsigned int global_var = 0; */ tree create_decl__global_var () { tree __glob_id = get_identifier("global_var"); tree __glob_decl = build_decl(VAR_DECL, __glob_id, unsigned_type_node); /* allocate static storage for this variable */ TREE_STATIC(__glob_decl) = true; /* static: internal linkage */ TREE_PUBLIC(__glob_decl) = false; /* the context of this declaration: file scope */ DECL_CONTEXT(__glob_decl) = NULL_TREE; /* this declaration is used in its scope */ TREE_USED(__glob_decl) = true; /* initialization to 0 */ tree __glob_init_val = build_int_cstu(unsigned_type_node, 1); DECL_INITIAL(__glob_decl) = __glob_init_val; layout_decl(__glob_decl, false); rest_of_decl_compilation(__glob_decl, 1, 0); return __glob_decl; } tree create_decl__str () { tree __str_id = get_identifier("str"); /* create a new type for const char */ tree __str_array_type = build_array_type(char_type_node, build_index_type(build_int_cst(NULL_TREE, 18))); tree __str_type = build_pointer_type(char_type_node); tree __str_array_ptr_type = build_pointer_type(__str_array_type); tree __str_decl = build_decl(VAR_DECL, __str_id, __str_type); TREE_STATIC(__str_decl) = true; /* external linkage */ TREE_PUBLIC(__str_decl) = true; DECL_CONTEXT(__str_decl) = NULL_TREE; TREE_USED(__str_decl) = true; /* initialization to constant/read-only string */ tree __str_init_val = build_string(18, "Global Value: %u\n"); TREE_TYPE(__str_init_val) = __str_array_type; TREE_CONSTANT(__str_init_val) = true; TREE_STATIC(__str_init_val) = true; TREE_READONLY(__str_init_val) = true; tree adr_expr = build1(ADDR_EXPR, __str_array_ptr_type, __str_init_val); tree nop_expr = build1(NOP_EXPR, __str_type, adr_expr); DECL_INITIAL(__str_decl) = nop_expr; layout_decl(__str_decl, false); rest_of_decl_compilation(__str_decl, 1, 0); return __str_decl; } tree create_type__fptr_t () { tree __arg0_type = build_pointer_type(signed_char_type_node); tree __arg1_type = signed_char_type_node; tree __ret_type = unsigned_type_node; return build_function_type_list(__ret_type, __arg0_type, __arg1_type, NULL_TREE); } tree create_type__function_pointer_fptr_t () { tree __fptr_type = create_type__fptr_t(); return build_pointer_type(__fptr_type); } tree create_type__struct_callback() { tree __struct_type = make_node(RECORD_TYPE); TYPE_PACKED(__struct_type) = false; TYPE_NAME(__struct_type) = get_identifier("callback"); tree __field0_type = create_type__function_pointer_fptr_t(); tree __field0 = build_decl(FIELD_DECL, get_identifier("cb_fnc"), __field0_type ); DECL_CONTEXT(__field0) = __struct_type; DECL_PACKED(__field0) = false; tree __field1_type = signed_char_type_node; tree __field1 = build_decl(FIELD_DECL, get_identifier("val"), __field1_type); DECL_CONTEXT(__field1) = __struct_type; DECL_PACKED(__field1) = false; TREE_CHAIN(__field0) = __field1; TYPE_FIELDS(__struct_type) = __field0; layout_type(__struct_type); rest_of_type_compilation(__struct_type, 1); return __struct_type; } tree create_decl__arr () { tree __arr_elements_type = create_type__struct_callback(); tree __arr_dimension = build_index_type(size_int(9)); /* max. index */ tree __arr_type = build_array_type(__arr_elements_type, __arr_dimension); layout_type(__arr_type); rest_of_type_compilation(__arr_type, 1); tree __arr_decl = build_decl(VAR_DECL, get_identifier("arr"), __arr_type); TREE_STATIC(__arr_decl) = true; TREE_PUBLIC(__arr_decl) = true; layout_decl(__arr_decl, false); rest_of_decl_compilation(__arr_decl, 1, 0); return __arr_decl; } /* Functions */ tree create_func__fptr_do1 () { tree __func_type = create_type__fptr_t(); tree __func_decl = build_decl(FUNCTION_DECL, get_identifier("fptr_do1"), __func_type); DECL_CONTEXT(__func_decl) = NULL_TREE; TREE_STATIC(__func_decl) = true; TREE_PUBLIC(__func_decl) = true; /* Function arguments */ tree __func_paramlist = NULL_TREE; /* Function arg 0 */ tree __arg0_type = build_pointer_type(signed_char_type_node); tree __arg0 = build_decl(PARM_DECL, get_identifier("val"), __arg0_type); DECL_ARG_TYPE(__arg0) = TREE_TYPE(__arg0); DECL_CONTEXT(__arg0) = __func_decl; /* Function arg 1 */ tree __arg1_type = signed_char_type_node; tree __arg1 = build_decl(PARM_DECL, get_identifier("change_val"), __arg1_type); DECL_ARG_TYPE(__arg1) = TREE_TYPE(__arg1); DECL_CONTEXT(__arg1) = __func_decl; __func_paramlist = chainon(__arg0, __func_paramlist); __func_paramlist = chainon(__arg1, __func_paramlist); DECL_ARGUMENTS(__func_decl) = (__func_paramlist = nreverse(__func_paramlist)); /* return type preparation */ /* * Each function defines one RESULT_DECL - an artificial storage * for the return value */ tree __func_result = build_decl(RESULT_DECL, NULL_TREE, TREE_TYPE(__func_type)); DECL_CONTEXT(__func_result) = __func_decl; DECL_ARTIFICIAL(__func_result) = true; DECL_IGNORED_P(__func_result) = true; DECL_RESULT(__func_decl) = __func_result; /* debugging purpose */ tree __func_art_block = build_block(NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE); DECL_INITIAL(__func_decl) = __func_art_block; /* statements */ tree __func_stmts = alloc_stmt_list(); /* no sanity checks done */ tree __add_type = TREE_TYPE(__arg0_type); tree __ind_ref = build1(INDIRECT_REF, __add_type, __arg0); tree __add = build2(PLUS_EXPR, __add_type, __ind_ref, __arg1); tree __add_assign = build2(MODIFY_EXPR, __add_type, __ind_ref, __add); append_to_statement_list(__add_assign, &__func_stmts); /* return value */ tree __ret_set = build2(MODIFY_EXPR, TREE_TYPE(__func_result), __func_result, __ind_ref); TREE_USED(__ret_set) = true; tree __ret_expr = build1(RETURN_EXPR, void_type_node, __ret_set); append_to_statement_list(__ret_expr, &__func_stmts); /* function binding */ DECL_SAVED_TREE(__func_decl) = build3(BIND_EXPR, void_type_node, NULL_TREE, __func_stmts, __func_art_block); gimplify_function_tree(__func_decl); dump_function(TDI_generic, __func_decl); cgraph_node(__func_decl); cgraph_finalize_function(__func_decl, false); return __func_decl; } void create_func__main (tree glob_var, tree func_ptr, tree array) { tree __func_type = build_function_type_list(integer_type_node, NULL_TREE); tree __func_decl = build_decl(FUNCTION_DECL, get_identifier("main"), __func_type); DECL_CONTEXT(__func_decl) = NULL_TREE; TREE_STATIC(__func_decl) = true; TREE_PUBLIC(__func_decl) = true; /* Function arguments */ tree __func_paramlist = NULL_TREE; DECL_ARGUMENTS(__func_decl) = (__func_paramlist = nreverse(__func_paramlist)); /* return type preparation */ /* * Each function defines one RESULT_DECL - an artificial storage * for the return value */ tree __func_result = build_decl(RESULT_DECL, NULL_TREE, TREE_TYPE(__func_type)); DECL_CONTEXT(__func_result) = __func_decl; DECL_ARTIFICIAL(__func_result) = true; DECL_IGNORED_P(__func_result) = true; DECL_RESULT(__func_decl) = __func_result; /* debugging purpose */ tree __func_art_block = build_block(NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE); DECL_INITIAL(__func_decl) = __func_art_block; /* statements */ tree __func_stmts = alloc_stmt_list(); //tree __label_decl = build_decl(LABEL_DECL, get_identifier(".andi_lbl"), void_type_node); //tree __label_expr = build1(LABEL_EXPR, void_type_node, __label_decl); //append_to_statement_list(__label_expr, &__func_stmts); //tree __goto_expr = build1(GOTO_EXPR, void_type_node, LABEL_EXPR_LABEL(__label_expr)); //append_to_statement_list(__goto_expr, &__func_stmts); /* avoid assigning 0 to glob_var explicitly - keeps the code smaller */ tree __exit_cond = build2(GE_EXPR, TREE_TYPE(glob_var), glob_var, build_int_cst(TREE_TYPE(glob_var), 10)); tree __exit_expr = build1(EXIT_EXPR, void_type_node, __exit_cond); tree __loop_art_block = build_block(NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE); tree __loop_stmts = alloc_stmt_list(); append_to_statement_list(__exit_expr, &__loop_stmts); tree __if_cond_1 = build2(BIT_AND_EXPR, TREE_TYPE(glob_var), glob_var, build_int_cst(TREE_TYPE(glob_var), 1)); tree __if_cond_final = build2(EQ_EXPR, TREE_TYPE(glob_var), __if_cond_1, build_int_cst(TREE_TYPE(glob_var), 0)); tree __array_el_type = TREE_TYPE(TREE_TYPE(array)); tree __array_access = build4(ARRAY_REF, __array_el_type, array, glob_var, NULL_TREE, NULL_TREE); tree __struct_field0 = TYPE_FIELDS(__array_el_type); tree __struct_field1 = TREE_CHAIN(__struct_field0); tree __struct_access_0 = build3(COMPONENT_REF, TREE_TYPE(__struct_field0), __array_access, __struct_field0, NULL_TREE); tree __struct_access_1 = build3(COMPONENT_REF, TREE_TYPE(__struct_field1), __array_access, __struct_field1, NULL_TREE); tree __assign_if = build2(MODIFY_EXPR, TREE_TYPE(__struct_field1), __struct_access_1, glob_var); tree __assign_else = build2(MODIFY_EXPR, TREE_TYPE(__struct_field1), __struct_access_1, build2(PLUS_EXPR, TREE_TYPE(glob_var), glob_var, build_int_cst(TREE_TYPE(glob_var), 1))); tree __if_stmt = build3(COND_EXPR, void_type_node, __if_cond_final, __assign_if, __assign_else); append_to_statement_list(__if_stmt, &__loop_stmts); tree __assign_func = build2(MODIFY_EXPR, TREE_TYPE(__struct_access_0), __struct_access_0, build1(ADDR_EXPR, TREE_TYPE(__struct_access_0), func_ptr)); append_to_statement_list(__assign_func, &__loop_stmts); tree __loop_inc = build2(POSTINCREMENT_EXPR, TREE_TYPE(glob_var), glob_var, build_int_cst(TREE_TYPE(glob_var), 1)); append_to_statement_list(__loop_inc, &__loop_stmts); tree __loop_body = build3(BIND_EXPR, void_type_node, NULL_TREE, __loop_stmts, __loop_art_block); tree __loop = build1(LOOP_EXPR, void_type_node, __loop_body); append_to_statement_list(__loop, &__func_stmts); __array_access = build4(ARRAY_REF, __array_el_type, array, size_int(1), NULL_TREE, NULL_TREE); __struct_access_0 = build3(COMPONENT_REF, TREE_TYPE(__struct_field0), __array_access, __struct_field0, NULL_TREE); __struct_access_1 = build3(COMPONENT_REF, TREE_TYPE(__struct_field1), __array_access, __struct_field1, NULL_TREE); tree __addr_expr = build1(ADDR_EXPR, build_pointer_type(TREE_TYPE(__struct_access_1)), __struct_access_1); tree __call_expr = build_call_nary(TREE_TYPE(TREE_TYPE(__struct_access_0)), __struct_access_0, 2, __addr_expr, build_int_cst(signed_char_type_node, 1)); append_to_statement_list(__call_expr, &__func_stmts); /* return value */ tree __ret_set = build2(MODIFY_EXPR, TREE_TYPE(__func_result), __func_result, build_int_cst(integer_type_node, 0)); TREE_USED(__ret_set) = true; tree __ret_expr = build1(RETURN_EXPR, void_type_node, __ret_set); append_to_statement_list(__ret_expr, &__func_stmts); /* function binding */ DECL_SAVED_TREE(__func_decl) = build3(BIND_EXPR, void_type_node, NULL_TREE, __func_stmts, __func_art_block); gimplify_function_tree(__func_decl); cgraph_node(__func_decl); cgraph_finalize_function(__func_decl, false); return __func_decl; } --------------050108090101010304060805--