tree parse_signature_string (const unsigned char *sig_string, int sig_length) { tree result_type; const unsigned char *str = sig_string; const unsigned char *limit = str + sig_length; if (str < limit && str[0] == '(') { tree argtype_list = NULL_TREE; str++; while (str < limit && str[0] != ')') { tree argtype = parse_signature_type (&str, limit); argtype_list = tree_cons (NULL_TREE, argtype, argtype_list); } if (str++, str >= limit) abort (); result_type = parse_signature_type (&str, limit); argtype_list = chainon (nreverse (argtype_list), end_params_node); result_type = build_function_type (result_type, argtype_list); } else result_type = parse_signature_type (&str, limit); if (str != limit) error ("junk at end of signature string"); return result_type; }
static void set_type_package_list (tree type) { int i; const char *type_string = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))); const char *ptr; int qualifications; tree list = NULL_TREE, elt; for (ptr = type_string, qualifications = 0; *ptr; ptr++) if (*ptr == '.') qualifications += 1; for (ptr = type_string, i = 0; i < qualifications; ptr++) { if (ptr [0] == '.') { tree const identifier = get_identifier_with_length (type_string, ptr - type_string); elt = build_tree_list (identifier, identifier); TREE_CHAIN (elt) = list; list = elt; type_string = ptr+1; i += 1; } } elt = build_tree_list (type, get_identifier (type_string)); TREE_CHAIN (elt) = list; list = elt; TYPE_PACKAGE_LIST (type) = nreverse (list); }
static tree ptm_initializer (tree desc, tree target) { tree init = tinfo_base_init (desc, target); tree to = TYPE_PTRMEM_POINTED_TO_TYPE (target); tree klass = TYPE_PTRMEM_CLASS_TYPE (target); int flags = qualifier_flags (to); bool incomplete = target_incomplete_p (to); if (incomplete) flags |= 0x8; if (!COMPLETE_TYPE_P (klass)) flags |= 0x10; init = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, flags), init); init = tree_cons (NULL_TREE, get_tinfo_ptr (TYPE_MAIN_VARIANT (to)), init); init = tree_cons (NULL_TREE, get_tinfo_ptr (klass), init); init = build_constructor (NULL_TREE, nreverse (init)); TREE_CONSTANT (init) = 1; TREE_INVARIANT (init) = 1; TREE_STATIC (init) = 1; return init; }
LVal mapcar1(Function1 f,LVal v) { LVal ret; for(ret=0;v;v=Next(v)) { ret=cons((void*)f(first(v)),ret); } return nreverse(ret); }
tree getdecls (void) { if (!current_binding_level->reversed) { current_binding_level->reversed = true; current_binding_level->names = nreverse (current_binding_level->names); } return current_binding_level->names; }
LVal atag_list(char* filename) { FILE* fp; LVal ret=(LVal)NULL; cond_printf(1,"open %s\n",filename); fp=fopen(filename,"r"); if(fp!=NULL) { LVal tags=parse_tags(fp,(LVal)NULL,0); tags=delete_not_tags("a",delete_not_open_tags(tags)); ret=nreverse(filter_href(tags)); tagsfree(tags); fclose (fp); } return ret; }
LISP lgetgrgid(LISP n) {gid_t gid; struct group *gr; long iflag,j; LISP result = NIL; gid = get_c_long(n); iflag = no_interrupt(1); if ((gr = getgrgid(gid))) {result = cons(strcons(strlen(gr->gr_name),gr->gr_name),result); for(j=0;gr->gr_mem[j];++j) result = cons(strcons(strlen(gr->gr_mem[j]),gr->gr_mem[j]),result); result = nreverse(result);} no_interrupt(iflag); return(result);}
LVal remove_if_not1(Function1 f,LVal v) { LVal ret; for(ret=0;v;v=Next(v)) { LVal fret=f(v); if(fret) { if(NumberP(first(v))) { ret=consi(firsti(v),ret); }else if(StringP(first(v))) { ret=conss(q(firsts(v)),ret); } } sL(fret); } return nreverse(ret); }
static void sdbout_dequeue_anonymous_types (void) { tree types, link; while (anonymous_types) { types = nreverse (anonymous_types); anonymous_types = NULL_TREE; for (link = types; link; link = TREE_CHAIN (link)) { tree type = TREE_VALUE (link); if (type && ! TREE_ASM_WRITTEN (type)) sdbout_one_type (type); } } }
void register_cmd_run(void) { char* _help; /*options*/ run_options=register_runtime_options(run_options); run_options=add_command(run_options,"",NULL,cmd_run_star,OPT_SHOW_NONE,1,NULL,NULL); /*run_options=add_command(run_options,"version",NULL,cmd_run_version,OPT_SHOW_NONE,0,NULL,NULL);*/ run_options=nreverse(run_options); /*commands*/ top_options=add_command(top_options,"" ,NULL,cmd_script_frontend,OPT_SHOW_NONE,1,"Run lisp environment then quit (default)",NULL); top_commands=add_command(top_commands,ROS_RUN_REPL ,NULL,cmd_run,OPT_SHOW_HELP,1,"Run repl",NULL); top_commands=add_command(top_commands,"*" ,NULL,cmd_script_frontend,OPT_SHOW_NONE,1,"Run lisp environment then quit (default)",NULL); _help=cat("Usage: ",argv_orig[0]," [OPTIONS] "ROS_RUN_REPL" [OPTIONS] [-- implementation-native-options...]\n\n",NULL); top_helps=add_help(top_helps,ROS_RUN_REPL,_help,run_commands,run_options,NULL,NULL,NULL); s(_help); _help=cat("Usage: ",argv_orig[0]," [OPTIONS] [--] script-file arguments...\n\n", NULL); s(_help); }
static tree ptr_initializer (tree desc, tree target) { tree init = tinfo_base_init (desc, target); tree to = TREE_TYPE (target); int flags = qualifier_flags (to); bool incomplete = target_incomplete_p (to); if (incomplete) flags |= 8; init = tree_cons (NULL_TREE, build_int_cst (NULL_TREE, flags), init); init = tree_cons (NULL_TREE, get_tinfo_ptr (TYPE_MAIN_VARIANT (to)), init); init = build_constructor (NULL_TREE, nreverse (init)); TREE_CONSTANT (init) = 1; TREE_INVARIANT (init) = 1; TREE_STATIC (init) = 1; return init; }
void write_resource_constructor (tree *list_p) { tree iter, t, register_resource_fn; if (resources == NULL) return; t = build_function_type_list (void_type_node, ptr_type_node, NULL); t = build_decl (FUNCTION_DECL, get_identifier ("_Jv_RegisterResource"), t); TREE_PUBLIC (t) = 1; DECL_EXTERNAL (t) = 1; register_resource_fn = t; /* Write out entries in the same order in which they were defined. */ for (iter = nreverse (resources); iter ; iter = TREE_CHAIN (iter)) { t = build_fold_addr_expr (TREE_VALUE (iter)); t = tree_cons (NULL, t, NULL); t = build_function_call_expr (register_resource_fn, t); append_to_statement_list (t, list_p); } }
static tree gfc_trans_omp_do (gfc_code *code, stmtblock_t *pblock, gfc_omp_clauses *do_clauses, tree par_clauses) { gfc_se se; tree dovar, stmt, from, to, step, type, init, cond, incr; tree count = NULL_TREE, cycle_label, tmp, omp_clauses; stmtblock_t block; stmtblock_t body; gfc_omp_clauses *clauses = code->ext.omp_clauses; int i, collapse = clauses->collapse; tree dovar_init = NULL_TREE; if (collapse <= 0) collapse = 1; code = code->block->next; gcc_assert (code->op == EXEC_DO); init = make_tree_vec (collapse); cond = make_tree_vec (collapse); incr = make_tree_vec (collapse); if (pblock == NULL) { gfc_start_block (&block); pblock = █ } omp_clauses = gfc_trans_omp_clauses (pblock, do_clauses, code->loc); for (i = 0; i < collapse; i++) { int simple = 0; int dovar_found = 0; tree dovar_decl; if (clauses) { gfc_namelist *n; for (n = clauses->lists[OMP_LIST_LASTPRIVATE]; n != NULL; n = n->next) if (code->ext.iterator->var->symtree->n.sym == n->sym) break; if (n != NULL) dovar_found = 1; else if (n == NULL) for (n = clauses->lists[OMP_LIST_PRIVATE]; n != NULL; n = n->next) if (code->ext.iterator->var->symtree->n.sym == n->sym) break; if (n != NULL) dovar_found++; } /* Evaluate all the expressions in the iterator. */ gfc_init_se (&se, NULL); gfc_conv_expr_lhs (&se, code->ext.iterator->var); gfc_add_block_to_block (pblock, &se.pre); dovar = se.expr; type = TREE_TYPE (dovar); gcc_assert (TREE_CODE (type) == INTEGER_TYPE); gfc_init_se (&se, NULL); gfc_conv_expr_val (&se, code->ext.iterator->start); gfc_add_block_to_block (pblock, &se.pre); from = gfc_evaluate_now (se.expr, pblock); gfc_init_se (&se, NULL); gfc_conv_expr_val (&se, code->ext.iterator->end); gfc_add_block_to_block (pblock, &se.pre); to = gfc_evaluate_now (se.expr, pblock); gfc_init_se (&se, NULL); gfc_conv_expr_val (&se, code->ext.iterator->step); gfc_add_block_to_block (pblock, &se.pre); step = gfc_evaluate_now (se.expr, pblock); dovar_decl = dovar; /* Special case simple loops. */ if (TREE_CODE (dovar) == VAR_DECL) { if (integer_onep (step)) simple = 1; else if (tree_int_cst_equal (step, integer_minus_one_node)) simple = -1; } else dovar_decl = gfc_trans_omp_variable (code->ext.iterator->var->symtree->n.sym); /* Loop body. */ if (simple) { TREE_VEC_ELT (init, i) = build2_v (MODIFY_EXPR, dovar, from); TREE_VEC_ELT (cond, i) = fold_build2 (simple > 0 ? LE_EXPR : GE_EXPR, boolean_type_node, dovar, to); TREE_VEC_ELT (incr, i) = fold_build2 (PLUS_EXPR, type, dovar, step); TREE_VEC_ELT (incr, i) = fold_build2 (MODIFY_EXPR, type, dovar, TREE_VEC_ELT (incr, i)); } else { /* STEP is not 1 or -1. Use: for (count = 0; count < (to + step - from) / step; count++) { dovar = from + count * step; body; cycle_label:; } */ tmp = fold_build2 (MINUS_EXPR, type, step, from); tmp = fold_build2 (PLUS_EXPR, type, to, tmp); tmp = fold_build2 (TRUNC_DIV_EXPR, type, tmp, step); tmp = gfc_evaluate_now (tmp, pblock); count = gfc_create_var (type, "count"); TREE_VEC_ELT (init, i) = build2_v (MODIFY_EXPR, count, build_int_cst (type, 0)); TREE_VEC_ELT (cond, i) = fold_build2 (LT_EXPR, boolean_type_node, count, tmp); TREE_VEC_ELT (incr, i) = fold_build2 (PLUS_EXPR, type, count, build_int_cst (type, 1)); TREE_VEC_ELT (incr, i) = fold_build2 (MODIFY_EXPR, type, count, TREE_VEC_ELT (incr, i)); /* Initialize DOVAR. */ tmp = fold_build2 (MULT_EXPR, type, count, step); tmp = fold_build2 (PLUS_EXPR, type, from, tmp); dovar_init = tree_cons (dovar, tmp, dovar_init); } if (!dovar_found) { tmp = build_omp_clause (input_location, OMP_CLAUSE_PRIVATE); OMP_CLAUSE_DECL (tmp) = dovar_decl; omp_clauses = gfc_trans_add_clause (tmp, omp_clauses); } else if (dovar_found == 2) { tree c = NULL; tmp = NULL; if (!simple) { /* If dovar is lastprivate, but different counter is used, dovar += step needs to be added to OMP_CLAUSE_LASTPRIVATE_STMT, otherwise the copied dovar will have the value on entry of the last loop, rather than value after iterator increment. */ tmp = gfc_evaluate_now (step, pblock); tmp = fold_build2 (PLUS_EXPR, type, dovar, tmp); tmp = fold_build2 (MODIFY_EXPR, type, dovar, tmp); for (c = omp_clauses; c ; c = OMP_CLAUSE_CHAIN (c)) if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE && OMP_CLAUSE_DECL (c) == dovar_decl) { OMP_CLAUSE_LASTPRIVATE_STMT (c) = tmp; break; } } if (c == NULL && par_clauses != NULL) { for (c = par_clauses; c ; c = OMP_CLAUSE_CHAIN (c)) if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE && OMP_CLAUSE_DECL (c) == dovar_decl) { tree l = build_omp_clause (input_location, OMP_CLAUSE_LASTPRIVATE); OMP_CLAUSE_DECL (l) = dovar_decl; OMP_CLAUSE_CHAIN (l) = omp_clauses; OMP_CLAUSE_LASTPRIVATE_STMT (l) = tmp; omp_clauses = l; OMP_CLAUSE_SET_CODE (c, OMP_CLAUSE_SHARED); break; } } gcc_assert (simple || c != NULL); } if (!simple) { tmp = build_omp_clause (input_location, OMP_CLAUSE_PRIVATE); OMP_CLAUSE_DECL (tmp) = count; omp_clauses = gfc_trans_add_clause (tmp, omp_clauses); } if (i + 1 < collapse) code = code->block->next; } if (pblock != &block) { pushlevel (0); gfc_start_block (&block); } gfc_start_block (&body); dovar_init = nreverse (dovar_init); while (dovar_init) { gfc_add_modify (&body, TREE_PURPOSE (dovar_init), TREE_VALUE (dovar_init)); dovar_init = TREE_CHAIN (dovar_init); } /* Cycle statement is implemented with a goto. Exit statement must not be present for this loop. */ cycle_label = gfc_build_label_decl (NULL_TREE); /* Put these labels where they can be found later. We put the labels in a TREE_LIST node (because TREE_CHAIN is already used). cycle_label goes in TREE_PURPOSE (backend_decl), exit label in TREE_VALUE (backend_decl). */ code->block->backend_decl = tree_cons (cycle_label, NULL, NULL); /* Main loop body. */ tmp = gfc_trans_omp_code (code->block->next, true); gfc_add_expr_to_block (&body, tmp); /* Label for cycle statements (if needed). */ if (TREE_USED (cycle_label)) { tmp = build1_v (LABEL_EXPR, cycle_label); gfc_add_expr_to_block (&body, tmp); } /* End of loop body. */ stmt = make_node (OMP_FOR); TREE_TYPE (stmt) = void_type_node; OMP_FOR_BODY (stmt) = gfc_finish_block (&body); OMP_FOR_CLAUSES (stmt) = omp_clauses; OMP_FOR_INIT (stmt) = init; OMP_FOR_COND (stmt) = cond; OMP_FOR_INCR (stmt) = incr; gfc_add_expr_to_block (&block, stmt); return gfc_finish_block (&block); }
static tree tinfo_base_init (tree desc, tree target) { tree init = NULL_TREE; tree name_decl; tree vtable_ptr; { tree name_name; /* Generate the NTBS array variable. */ tree name_type = build_cplus_array_type (build_qualified_type (char_type_node, TYPE_QUAL_CONST), NULL_TREE); tree name_string = tinfo_name (target); /* Determine the name of the variable -- and remember with which type it is associated. */ name_name = mangle_typeinfo_string_for_type (target); TREE_TYPE (name_name) = target; name_decl = build_lang_decl (VAR_DECL, name_name, name_type); SET_DECL_ASSEMBLER_NAME (name_decl, name_name); DECL_ARTIFICIAL (name_decl) = 1; DECL_IGNORED_P (name_decl) = 1; TREE_READONLY (name_decl) = 1; TREE_STATIC (name_decl) = 1; DECL_EXTERNAL (name_decl) = 0; DECL_TINFO_P (name_decl) = 1; if (involves_incomplete_p (target)) { TREE_PUBLIC (name_decl) = 0; DECL_INTERFACE_KNOWN (name_decl) = 1; } else set_linkage_according_to_type (target, name_decl); import_export_decl (name_decl); DECL_INITIAL (name_decl) = name_string; mark_used (name_decl); pushdecl_top_level_and_finish (name_decl, name_string); } vtable_ptr = TINFO_VTABLE_DECL (desc); if (!vtable_ptr) { tree real_type; push_nested_namespace (abi_node); real_type = xref_tag (class_type, TINFO_REAL_NAME (desc), /* APPLE LOCAL 4184203 */ /*tag_scope=*/ts_global, false); pop_nested_namespace (abi_node); if (!COMPLETE_TYPE_P (real_type)) { /* We never saw a definition of this type, so we need to tell the compiler that this is an exported class, as indeed all of the __*_type_info classes are. */ SET_CLASSTYPE_INTERFACE_KNOWN (real_type); CLASSTYPE_INTERFACE_ONLY (real_type) = 1; } vtable_ptr = get_vtable_decl (real_type, /*complete=*/1); vtable_ptr = build_unary_op (ADDR_EXPR, vtable_ptr, 0); /* We need to point into the middle of the vtable. */ vtable_ptr = build2 (PLUS_EXPR, TREE_TYPE (vtable_ptr), vtable_ptr, size_binop (MULT_EXPR, size_int (2 * TARGET_VTABLE_DATA_ENTRY_DISTANCE), TYPE_SIZE_UNIT (vtable_entry_type))); TINFO_VTABLE_DECL (desc) = vtable_ptr; } init = tree_cons (NULL_TREE, vtable_ptr, init); init = tree_cons (NULL_TREE, decay_conversion (name_decl), init); init = build_constructor (NULL_TREE, nreverse (init)); TREE_CONSTANT (init) = 1; TREE_INVARIANT (init) = 1; TREE_STATIC (init) = 1; init = tree_cons (NULL_TREE, init, NULL_TREE); return init; }
void use_thunk (tree thunk_fndecl, bool emit_p) { tree a, t, function, alias; tree virtual_offset; HOST_WIDE_INT fixed_offset, virtual_value; bool this_adjusting = DECL_THIS_THUNK_P (thunk_fndecl); /* We should have called finish_thunk to give it a name. */ gcc_assert (DECL_NAME (thunk_fndecl)); /* We should never be using an alias, always refer to the aliased thunk. */ gcc_assert (!THUNK_ALIAS (thunk_fndecl)); if (TREE_ASM_WRITTEN (thunk_fndecl)) return; function = THUNK_TARGET (thunk_fndecl); if (DECL_RESULT (thunk_fndecl)) /* We already turned this thunk into an ordinary function. There's no need to process this thunk again. */ return; if (DECL_THUNK_P (function)) /* The target is itself a thunk, process it now. */ use_thunk (function, emit_p); /* Thunks are always addressable; they only appear in vtables. */ TREE_ADDRESSABLE (thunk_fndecl) = 1; /* Figure out what function is being thunked to. It's referenced in this translation unit. */ TREE_ADDRESSABLE (function) = 1; mark_used (function); if (!emit_p) return; if (TARGET_USE_LOCAL_THUNK_ALIAS_P (function)) alias = make_alias_for_thunk (function); else alias = function; fixed_offset = THUNK_FIXED_OFFSET (thunk_fndecl); virtual_offset = THUNK_VIRTUAL_OFFSET (thunk_fndecl); if (virtual_offset) { if (!this_adjusting) virtual_offset = BINFO_VPTR_FIELD (virtual_offset); virtual_value = tree_low_cst (virtual_offset, /*pos=*/0); gcc_assert (virtual_value); } else virtual_value = 0; /* And, if we need to emit the thunk, it's used. */ mark_used (thunk_fndecl); /* This thunk is actually defined. */ DECL_EXTERNAL (thunk_fndecl) = 0; /* The linkage of the function may have changed. FIXME in linkage rewrite. */ TREE_PUBLIC (thunk_fndecl) = TREE_PUBLIC (function); DECL_VISIBILITY (thunk_fndecl) = DECL_VISIBILITY (function); DECL_VISIBILITY_SPECIFIED (thunk_fndecl) = DECL_VISIBILITY_SPECIFIED (function); if (DECL_ONE_ONLY (function)) make_decl_one_only (thunk_fndecl); if (flag_syntax_only) { TREE_ASM_WRITTEN (thunk_fndecl) = 1; return; } push_to_top_level (); if (TARGET_USE_LOCAL_THUNK_ALIAS_P (function) && targetm.have_named_sections) { resolve_unique_section (function, 0, flag_function_sections); if (DECL_SECTION_NAME (function) != NULL && DECL_ONE_ONLY (function)) { resolve_unique_section (thunk_fndecl, 0, flag_function_sections); /* Output the thunk into the same section as function. */ DECL_SECTION_NAME (thunk_fndecl) = DECL_SECTION_NAME (function); } } /* The back-end expects DECL_INITIAL to contain a BLOCK, so we create one. */ DECL_INITIAL (thunk_fndecl) = make_node (BLOCK); /* Set up cloned argument trees for the thunk. */ t = NULL_TREE; for (a = DECL_ARGUMENTS (function); a; a = TREE_CHAIN (a)) { tree x = copy_node (a); TREE_CHAIN (x) = t; DECL_CONTEXT (x) = thunk_fndecl; SET_DECL_RTL (x, NULL_RTX); DECL_HAS_VALUE_EXPR_P (x) = 0; t = x; } a = nreverse (t); DECL_ARGUMENTS (thunk_fndecl) = a; BLOCK_VARS (DECL_INITIAL (thunk_fndecl)) = a; if (this_adjusting && targetm.asm_out.can_output_mi_thunk (thunk_fndecl, fixed_offset, virtual_value, alias)) { const char *fnname; current_function_decl = thunk_fndecl; DECL_RESULT (thunk_fndecl) = build_decl (RESULT_DECL, 0, integer_type_node); fnname = XSTR (XEXP (DECL_RTL (thunk_fndecl), 0), 0); init_function_start (thunk_fndecl); current_function_is_thunk = 1; assemble_start_function (thunk_fndecl, fnname); targetm.asm_out.output_mi_thunk (asm_out_file, thunk_fndecl, fixed_offset, virtual_value, alias); assemble_end_function (thunk_fndecl, fnname); init_insn_lengths (); current_function_decl = 0; cfun = 0; TREE_ASM_WRITTEN (thunk_fndecl) = 1; } else { /* If this is a covariant thunk, or we don't have the necessary code for efficient thunks, generate a thunk function that just makes a call to the real function. Unfortunately, this doesn't work for varargs. */ if (varargs_function_p (function)) error ("generic thunk code fails for method %q#D which uses %<...%>", function); DECL_RESULT (thunk_fndecl) = NULL_TREE; start_preparsed_function (thunk_fndecl, NULL_TREE, SF_PRE_PARSED); /* We don't bother with a body block for thunks. */ /* There's no need to check accessibility inside the thunk body. */ push_deferring_access_checks (dk_no_check); t = a; if (this_adjusting) t = thunk_adjust (t, /*this_adjusting=*/1, fixed_offset, virtual_offset); /* Build up the call to the real function. */ t = tree_cons (NULL_TREE, t, NULL_TREE); for (a = TREE_CHAIN (a); a; a = TREE_CHAIN (a)) t = tree_cons (NULL_TREE, a, t); t = nreverse (t); t = build_call (alias, t); CALL_FROM_THUNK_P (t) = 1; if (VOID_TYPE_P (TREE_TYPE (t))) finish_expr_stmt (t); else { if (!this_adjusting) { tree cond = NULL_TREE; if (TREE_CODE (TREE_TYPE (t)) == POINTER_TYPE) { /* If the return type is a pointer, we need to protect against NULL. We know there will be an adjustment, because that's why we're emitting a thunk. */ t = save_expr (t); cond = cp_convert (boolean_type_node, t); } t = thunk_adjust (t, /*this_adjusting=*/0, fixed_offset, virtual_offset); if (cond) t = build3 (COND_EXPR, TREE_TYPE (t), cond, t, cp_convert (TREE_TYPE (t), integer_zero_node)); } if (IS_AGGR_TYPE (TREE_TYPE (t))) t = build_cplus_new (TREE_TYPE (t), t); finish_return_stmt (t); } /* Since we want to emit the thunk, we explicitly mark its name as referenced. */ mark_decl_referenced (thunk_fndecl); /* But we don't want debugging information about it. */ DECL_IGNORED_P (thunk_fndecl) = 1; /* Re-enable access control. */ pop_deferring_access_checks (); thunk_fndecl = finish_function (0); tree_lowering_passes (thunk_fndecl); expand_body (thunk_fndecl); } pop_from_top_level (); }
void use_thunk (tree thunk_fndecl, bool emit_p) { tree a, t, function, alias; tree virtual_offset; HOST_WIDE_INT fixed_offset, virtual_value; bool this_adjusting = DECL_THIS_THUNK_P (thunk_fndecl); /* We should have called finish_thunk to give it a name. */ gcc_assert (DECL_NAME (thunk_fndecl)); /* We should never be using an alias, always refer to the aliased thunk. */ gcc_assert (!THUNK_ALIAS (thunk_fndecl)); if (TREE_ASM_WRITTEN (thunk_fndecl)) return; function = THUNK_TARGET (thunk_fndecl); if (DECL_RESULT (thunk_fndecl)) /* We already turned this thunk into an ordinary function. There's no need to process this thunk again. */ return; if (DECL_THUNK_P (function)) /* The target is itself a thunk, process it now. */ use_thunk (function, emit_p); /* Thunks are always addressable; they only appear in vtables. */ TREE_ADDRESSABLE (thunk_fndecl) = 1; /* Figure out what function is being thunked to. It's referenced in this translation unit. */ TREE_ADDRESSABLE (function) = 1; mark_used (function); if (!emit_p) return; if (0 && TARGET_USE_LOCAL_THUNK_ALIAS_P (function)) alias = make_alias_for_thunk (function); else alias = function; fixed_offset = THUNK_FIXED_OFFSET (thunk_fndecl); virtual_offset = THUNK_VIRTUAL_OFFSET (thunk_fndecl); if (virtual_offset) { if (!this_adjusting) virtual_offset = BINFO_VPTR_FIELD (virtual_offset); virtual_value = tree_low_cst (virtual_offset, /*pos=*/0); gcc_assert (virtual_value); } else virtual_value = 0; /* And, if we need to emit the thunk, it's used. */ mark_used (thunk_fndecl); /* This thunk is actually defined. */ DECL_EXTERNAL (thunk_fndecl) = 0; /* The linkage of the function may have changed. FIXME in linkage rewrite. */ TREE_PUBLIC (thunk_fndecl) = TREE_PUBLIC (function); DECL_VISIBILITY (thunk_fndecl) = DECL_VISIBILITY (function); DECL_VISIBILITY_SPECIFIED (thunk_fndecl) = DECL_VISIBILITY_SPECIFIED (function); if (DECL_ONE_ONLY (function) || DECL_WEAK (function)) make_decl_one_only (thunk_fndecl, cxx_comdat_group (thunk_fndecl)); if (flag_syntax_only) { TREE_ASM_WRITTEN (thunk_fndecl) = 1; return; } push_to_top_level (); if (TARGET_USE_LOCAL_THUNK_ALIAS_P (function) && targetm.have_named_sections) { resolve_unique_section (function, 0, flag_function_sections); if (DECL_SECTION_NAME (function) != NULL && DECL_ONE_ONLY (function)) { resolve_unique_section (thunk_fndecl, 0, flag_function_sections); /* Output the thunk into the same section as function. */ DECL_SECTION_NAME (thunk_fndecl) = DECL_SECTION_NAME (function); } } /* Set up cloned argument trees for the thunk. */ t = NULL_TREE; for (a = DECL_ARGUMENTS (function); a; a = TREE_CHAIN (a)) { tree x = copy_node (a); TREE_CHAIN (x) = t; DECL_CONTEXT (x) = thunk_fndecl; SET_DECL_RTL (x, NULL_RTX); DECL_HAS_VALUE_EXPR_P (x) = 0; t = x; } a = nreverse (t); DECL_ARGUMENTS (thunk_fndecl) = a; TREE_ASM_WRITTEN (thunk_fndecl) = 1; cgraph_add_thunk (thunk_fndecl, function, this_adjusting, fixed_offset, virtual_value, virtual_offset, alias); if (!this_adjusting || !targetm.asm_out.can_output_mi_thunk (thunk_fndecl, fixed_offset, virtual_value, alias)) { /* If this is a covariant thunk, or we don't have the necessary code for efficient thunks, generate a thunk function that just makes a call to the real function. Unfortunately, this doesn't work for varargs. */ if (varargs_function_p (function)) error ("generic thunk code fails for method %q#D which uses %<...%>", function); } pop_from_top_level (); }
void write_resource_constructor (void) { tree init_name, init_type, init_decl; tree iter; location_t saved_loc = input_location; char *resource_ctor_name; /* Only do work if required. */ if (resources == NULL_TREE) return; resource_ctor_name = concat (IDENTIFIER_POINTER (get_file_function_name ('I')), "_resource", NULL); init_name = get_identifier (resource_ctor_name); free (resource_ctor_name); init_type = build_function_type (void_type_node, end_params_node); init_decl = build_decl (FUNCTION_DECL, init_name, init_type); DECL_SOURCE_LINE (init_decl) = 0; SET_DECL_ASSEMBLER_NAME (init_decl, init_name); TREE_STATIC (init_decl) = 1; current_function_decl = init_decl; DECL_RESULT (init_decl) = build_decl (RESULT_DECL, NULL_TREE, void_type_node); /* It can be a static function as long as collect2 does not have to scan the object file to find its ctor/dtor routine. */ TREE_PUBLIC (init_decl) = ! targetm.have_ctors_dtors; pushlevel (0); make_decl_rtl (init_decl, NULL); init_function_start (init_decl); expand_function_start (init_decl, 0); /* Write out entries in the same order in which they were defined. */ for (iter = nreverse (resources); iter != NULL_TREE; iter = TREE_CHAIN (iter)) { emit_library_call (registerResource_libfunc, 0, VOIDmode, 1, expand_expr (build_address_of (TREE_VALUE (iter)), 0, Pmode, 0), Pmode); } input_location = DECL_SOURCE_LOCATION (init_decl); expand_function_end (); poplevel (1, 0, 1); { /* Force generation, even with -O3 or deeper. Gross hack. FIXME. */ int saved_flag = flag_inline_functions; flag_inline_functions = 0; rest_of_compilation (init_decl); flag_inline_functions = saved_flag; } current_function_decl = NULL_TREE; (* targetm.asm_out.constructor) (XEXP (DECL_RTL (init_decl), 0), DEFAULT_INIT_PRIORITY); input_location = saved_loc; }
/* Return the tree for an expresssion, type EXP_TYPE (see treetree.h) with tree type TYPE and with operands1 OP1, OP2 (maybe), OP3 (maybe). */ tree tree_code_get_expression (unsigned int exp_type, tree type, tree op1, tree op2, tree op3 ATTRIBUTE_UNUSED) { tree ret1; int operator; switch (exp_type) { case EXP_ASSIGN: if (!op1 || !op2) abort (); operator = MODIFY_EXPR; ret1 = build (operator, type, op1, build1 (CONVERT_EXPR, type, op2)); break; case EXP_PLUS: operator = PLUS_EXPR; goto binary_expression; case EXP_MINUS: operator = MINUS_EXPR; goto binary_expression; case EXP_EQUALS: operator = EQ_EXPR; goto binary_expression; /* Expand a binary expression. Ensure the operands are the right type. */ binary_expression: if (!op1 || !op2) abort (); ret1 = build (operator, type, build1 (CONVERT_EXPR, type, op1), build1 (CONVERT_EXPR, type, op2)); break; /* Reference to a variable. This is dead easy, just return the decl for the variable. If the TYPE is different than the variable type, convert it. */ case EXP_REFERENCE: if (!op1) abort (); if (type == TREE_TYPE (op1)) ret1 = op1; else ret1 = build1 (CONVERT_EXPR, type, op1); break; case EXP_FUNCTION_INVOCATION: if (!op1 || !op2) abort (); { tree fun_ptr; fun_ptr = build1 (ADDR_EXPR, build_pointer_type (type), op1); ret1 = build (CALL_EXPR, type, fun_ptr, nreverse (op2)); } break; default: abort (); } return ret1; }
/* Output code for start of function; the decl of the function is in PREV_SAVED (as created by tree_code_create_function_prototype), the function is at line number LINENO in file FILENAME. The parameter details are in the lists PARMS. Returns nothing. */ void tree_code_create_function_initial (tree prev_saved, unsigned char* filename, int lineno, struct prod_token_parm_item* parms) { tree fn_decl; tree param_decl; tree next_param; tree first_param; tree parm_decl; tree parm_list; tree resultdecl; struct prod_token_parm_item* this_parm; struct prod_token_parm_item* parm; fn_decl = prev_saved; if (!fn_decl) abort (); /* Output message if not -quiet. */ announce_function (fn_decl); /* This has something to do with forcing output also. */ pushdecl (fn_decl); /* Set current function for error msgs etc. */ current_function_decl = fn_decl; DECL_INITIAL (fn_decl) = error_mark_node; DECL_SOURCE_FILE (fn_decl) = (const char *)filename; DECL_SOURCE_LINE (fn_decl) = lineno; /* Prepare creation of rtl for a new function. */ resultdecl = DECL_RESULT (fn_decl) = build_decl (RESULT_DECL, NULL_TREE, TREE_TYPE (TREE_TYPE (fn_decl))); DECL_CONTEXT (DECL_RESULT (fn_decl)) = fn_decl; DECL_SOURCE_FILE (resultdecl) = (const char *)filename; DECL_SOURCE_LINE (resultdecl) = lineno; /* Work out the size. ??? is this needed. */ layout_decl (DECL_RESULT (fn_decl), 0); /* Make the argument variable decls. */ parm_list = NULL_TREE; for (parm = parms; parm; parm = parm->tp.par.next) { parm_decl = build_decl (PARM_DECL, get_identifier ((const char*) (parm->tp.par.variable_name)), get_type_for_numeric_type (parm->type)); /* Some languages have different nominal and real types. */ DECL_ARG_TYPE (parm_decl) = TREE_TYPE (parm_decl); if (!DECL_ARG_TYPE (parm_decl)) abort (); if (!fn_decl) abort (); DECL_CONTEXT (parm_decl) = fn_decl; DECL_SOURCE_FILE (parm_decl) = (const char *)filename; DECL_SOURCE_LINE (parm_decl) = lineno; parm_list = chainon (parm_decl, parm_list); } /* Back into reverse order as the back end likes them. */ parm_list = nreverse (parm_list); DECL_ARGUMENTS (fn_decl) = parm_list; /* Save the decls for use when the args are referred to. */ for (param_decl = DECL_ARGUMENTS (fn_decl), this_parm = parms; param_decl; param_decl = TREE_CHAIN (param_decl), this_parm = this_parm->tp.par.next) { if (!this_parm) abort (); /* Too few. */ *this_parm->tp.par.where_to_put_var_tree = param_decl; } if (this_parm) abort (); /* Too many. */ /* Output the decl rtl (not the rtl for the function code). ???. If the function is not defined in this file, when should you execute this? */ make_decl_rtl (fn_decl, NULL); /* Use filename/lineno from above. */ init_function_start (fn_decl, (const char *)filename, lineno); /* Create rtl for startup code of function, such as saving registers. */ expand_function_start (fn_decl, 0); /* Function.c requires a push at the start of the function. that looks like a bug to me but let's make it happy. */ (*lang_hooks.decls.pushlevel) (0); /* Create rtl for the start of a new scope. */ expand_start_bindings (2); /* Put the parameters into the symbol table. */ for (first_param = param_decl = nreverse (DECL_ARGUMENTS (fn_decl)); param_decl; param_decl = next_param) { next_param = TREE_CHAIN (param_decl); TREE_CHAIN (param_decl) = NULL; /* layout_decl (param_decl, 0); Already done in build_decl tej 13/4/2002. */ pushdecl (param_decl); if (DECL_CONTEXT (param_decl) != current_function_decl) abort (); } /* Store back the PARM_DECL nodes. They appear in the right order. */ DECL_ARGUMENTS (fn_decl) = getdecls (); /* Force it to be output, else may be solely inlined. */ TREE_ADDRESSABLE (fn_decl) = 1; /* Stop -O3 from deleting it. */ TREE_USED (fn_decl) = 1; /* Add a new level to the debugger symbol table. */ (*lang_hooks.decls.pushlevel) (0); /* Create rtl for the start of a new scope. */ expand_start_bindings (0); emit_line_note ((const char *)filename, lineno); /* Output the line number information. */ }
tree tree_code_create_function_prototype (unsigned char* chars, unsigned int storage_class, unsigned int ret_type, struct prod_token_parm_item* parms, unsigned char* filename, int lineno) { tree id; struct prod_token_parm_item* parm; tree type_list = NULL_TREE; tree type_node; tree fn_type; tree fn_decl; /* Build the type. */ id = get_identifier ((const char*)chars); for (parm = parms; parm; parm = parm->tp.par.next) { type_node = get_type_for_numeric_type (parm->type); type_list = tree_cons (NULL_TREE, type_node, type_list); } /* Last parm if void indicates fixed length list (as opposed to printf style va_* list). */ type_list = tree_cons (NULL_TREE, void_type_node, type_list); /* The back end needs them in reverse order. */ type_list = nreverse (type_list); type_node = get_type_for_numeric_type (ret_type); fn_type = build_function_type (type_node, type_list); id = get_identifier ((const char*)chars); fn_decl = build_decl (FUNCTION_DECL, id, fn_type); DECL_CONTEXT (fn_decl) = NULL_TREE; /* Nested functions not supported here. */ DECL_SOURCE_FILE (fn_decl) = (const char *)filename; /* if (lineno > 1000000) ; */ /* Probably the line # is rubbish because someone forgot to set the line number - and unfortunately impossible line #s are used as magic flags at various times. The longest known function for example is about 550,000 lines (it was written in COBOL). */ DECL_SOURCE_LINE (fn_decl) = lineno; TREE_USED (fn_decl) = 1; /* Real name (optional). */ SET_DECL_ASSEMBLER_NAME (fn_decl, DECL_NAME (fn_decl)); TREE_PUBLIC (fn_decl) = 0; DECL_EXTERNAL (fn_decl) = 0; TREE_STATIC (fn_decl) = 0; switch (storage_class) { case STATIC_STORAGE: TREE_PUBLIC (fn_decl) = 0; break; case EXTERNAL_DEFINITION_STORAGE: TREE_PUBLIC (fn_decl) = 1; TREE_STATIC (fn_decl) = 0; DECL_EXTERNAL (fn_decl) = 0; break; case EXTERNAL_REFERENCE_STORAGE: TREE_PUBLIC (fn_decl) = 0; DECL_EXTERNAL (fn_decl) = 1; break; case AUTOMATIC_STORAGE: default: abort (); } /* Process declaration of function defined elsewhere. */ rest_of_decl_compilation (fn_decl, NULL, 1, 0); return fn_decl; }
static void create_common (gfc_common_head *com) { segment_info *s, *next_s; tree union_type; tree *field_link; record_layout_info rli; tree decl; bool is_init = false; /* Declare the variables inside the common block. */ union_type = make_node (UNION_TYPE); rli = start_record_layout (union_type); field_link = &TYPE_FIELDS (union_type); for (s = current_common; s; s = s->next) { build_field (s, union_type, rli); /* Link the field into the type. */ *field_link = s->field; field_link = &TREE_CHAIN (s->field); /* Has initial value. */ if (s->sym->value) is_init = true; } finish_record_layout (rli, true); if (com) decl = build_common_decl (com, union_type, is_init); else decl = build_equiv_decl (union_type, is_init); if (is_init) { tree list, ctor, tmp; HOST_WIDE_INT offset = 0; list = NULL_TREE; for (s = current_common; s; s = s->next) { if (s->sym->value) { if (s->offset < offset) { /* We have overlapping initializers. It could either be partially initialized arrays (legal), or the user specified multiple initial values (illegal). We don't implement this yet, so bail out. */ gfc_todo_error ("Initialization of overlapping variables"); } /* Add the initializer for this field. */ tmp = gfc_conv_initializer (s->sym->value, &s->sym->ts, TREE_TYPE (s->field), s->sym->attr.dimension, s->sym->attr.pointer || s->sym->attr.allocatable); list = tree_cons (s->field, tmp, list); offset = s->offset + s->length; } } gcc_assert (list); ctor = build1 (CONSTRUCTOR, union_type, nreverse(list)); TREE_CONSTANT (ctor) = 1; TREE_INVARIANT (ctor) = 1; TREE_STATIC (ctor) = 1; DECL_INITIAL (decl) = ctor; #ifdef ENABLE_CHECKING for (tmp = CONSTRUCTOR_ELTS (ctor); tmp; tmp = TREE_CHAIN (tmp)) gcc_assert (TREE_CODE (TREE_PURPOSE (tmp)) == FIELD_DECL); #endif } /* Build component reference for each variable. */ for (s = current_common; s; s = next_s) { s->sym->backend_decl = build3 (COMPONENT_REF, TREE_TYPE (s->field), decl, s->field, NULL_TREE); next_s = s->next; gfc_free (s); } }
/* FN is a constructor or destructor, and there are FUNCTION_DECLs cloned from it nearby. Instead of cloning this body, leave it alone and create tiny one-call bodies for the cloned FUNCTION_DECLs. These clones are sibcall candidates, and their resulting code will be very thunk-esque. */ static void thunk_body (tree clone, tree fn, tree clone_to_call) { tree bind, block, call, fn_parm, fn_parm_typelist; int parmno, vtt_parmno; tree clone_parm, parmlist; for (vtt_parmno = -1, parmno = 0, fn_parm = DECL_ARGUMENTS (fn); fn_parm; ++parmno, fn_parm = TREE_CHAIN (fn_parm)) { if (DECL_ARTIFICIAL (fn_parm) && DECL_NAME (fn_parm) == vtt_parm_identifier) { vtt_parmno = parmno; /* Compensate for removed in_charge parameter. */ break; } } /* Currently, we are not supposed to have a vtt argument. */ gcc_assert(vtt_parmno == -1); /* Walk parameter lists together, creating parameter list for call to original function. */ for (parmno = 0, parmlist = NULL, fn_parm = DECL_ARGUMENTS (fn), fn_parm_typelist = TYPE_ARG_TYPES (TREE_TYPE (fn)), clone_parm = DECL_ARGUMENTS (clone); fn_parm; ++parmno, fn_parm = TREE_CHAIN (fn_parm)) { if (parmno == vtt_parmno && ! DECL_HAS_VTT_PARM_P (clone)) { tree typed_null_pointer_node = copy_node (null_pointer_node); gcc_assert (fn_parm_typelist); /* Clobber actual parameter with formal parameter type. */ TREE_TYPE (typed_null_pointer_node) = TREE_VALUE (fn_parm_typelist); parmlist = tree_cons (NULL, typed_null_pointer_node, parmlist); } else if (parmno == 1 && DECL_HAS_IN_CHARGE_PARM_P (fn)) { /* Just skip it. */ } /* Map other parameters to their equivalents in the cloned function. */ else { gcc_assert (clone_parm); DECL_ABSTRACT_ORIGIN (clone_parm) = NULL; parmlist = tree_cons (NULL, clone_parm, parmlist); clone_parm = TREE_CHAIN (clone_parm); } if (fn_parm_typelist) fn_parm_typelist = TREE_CHAIN (fn_parm_typelist); } /* We built this list backwards; fix now. */ parmlist = nreverse (parmlist); TREE_USED (clone_to_call) = 1; call = build_cxx_call (clone_to_call, parmlist); for (parmlist = TREE_OPERAND (call, 1); parmlist; parmlist = TREE_CHAIN (parmlist)) { fn_parm = TREE_VALUE (parmlist); /* Remove the EMPTY_CLASS_EXPR because it upsets estimate_num_insns(). */ if (TREE_CODE (fn_parm) == COMPOUND_EXPR) { gcc_assert (TREE_CODE (TREE_OPERAND (fn_parm, 1)) == EMPTY_CLASS_EXPR); TREE_VALUE (parmlist) = TREE_OPERAND (fn_parm, 0); } } block = make_node (BLOCK); if (targetm.cxx.cdtor_returns_this ()) { tree clone_result = DECL_RESULT (clone); tree modify = build2 (MODIFY_EXPR, TREE_TYPE (clone_result), clone_result, call); add_stmt (modify); BLOCK_VARS (block) = clone_result; } else { add_stmt (call); } bind = c_build_bind_expr (block, cur_stmt_list); DECL_SAVED_TREE (clone) = push_stmt_list (); add_stmt (bind); }
static tree cxx_omp_clause_apply_fn (tree fn, tree arg1, tree arg2) { tree defparm, parm; int i; if (fn == NULL) return NULL; defparm = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (fn))); if (arg2) defparm = TREE_CHAIN (defparm); if (TREE_CODE (TREE_TYPE (arg1)) == ARRAY_TYPE) { tree inner_type = TREE_TYPE (arg1); tree start1, end1, p1; tree start2 = NULL, p2 = NULL; tree ret = NULL, lab, t; start1 = arg1; start2 = arg2; do { inner_type = TREE_TYPE (inner_type); start1 = build4 (ARRAY_REF, inner_type, start1, size_zero_node, NULL, NULL); if (arg2) start2 = build4 (ARRAY_REF, inner_type, start2, size_zero_node, NULL, NULL); } while (TREE_CODE (inner_type) == ARRAY_TYPE); start1 = build_fold_addr_expr (start1); if (arg2) start2 = build_fold_addr_expr (start2); end1 = TYPE_SIZE_UNIT (TREE_TYPE (arg1)); end1 = fold_convert (TREE_TYPE (start1), end1); end1 = build2 (PLUS_EXPR, TREE_TYPE (start1), start1, end1); p1 = create_tmp_var (TREE_TYPE (start1), NULL); t = build2 (MODIFY_EXPR, void_type_node, p1, start1); append_to_statement_list (t, &ret); if (arg2) { p2 = create_tmp_var (TREE_TYPE (start2), NULL); t = build2 (MODIFY_EXPR, void_type_node, p2, start2); append_to_statement_list (t, &ret); } lab = create_artificial_label (); t = build1 (LABEL_EXPR, void_type_node, lab); append_to_statement_list (t, &ret); t = tree_cons (NULL, p1, NULL); if (arg2) t = tree_cons (NULL, p2, t); /* Handle default arguments. */ i = 1 + (arg2 != NULL); for (parm = defparm; parm != void_list_node; parm = TREE_CHAIN (parm)) t = tree_cons (NULL, convert_default_arg (TREE_VALUE (parm), TREE_PURPOSE (parm), fn, i++), t); t = build_call (fn, nreverse (t)); append_to_statement_list (t, &ret); t = fold_convert (TREE_TYPE (p1), TYPE_SIZE_UNIT (inner_type)); t = build2 (PLUS_EXPR, TREE_TYPE (p1), p1, t); t = build2 (MODIFY_EXPR, void_type_node, p1, t); append_to_statement_list (t, &ret); if (arg2) { t = fold_convert (TREE_TYPE (p2), TYPE_SIZE_UNIT (inner_type)); t = build2 (PLUS_EXPR, TREE_TYPE (p2), p2, t); t = build2 (MODIFY_EXPR, void_type_node, p2, t); append_to_statement_list (t, &ret); } t = build2 (NE_EXPR, boolean_type_node, p1, end1); t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&lab), NULL); append_to_statement_list (t, &ret); return ret; } else { tree t = tree_cons (NULL, build_fold_addr_expr (arg1), NULL); if (arg2) t = tree_cons (NULL, build_fold_addr_expr (arg2), t); /* Handle default arguments. */ i = 1 + (arg2 != NULL); for (parm = defparm; parm != void_list_node; parm = TREE_CHAIN (parm)) t = tree_cons (NULL, convert_default_arg (TREE_VALUE (parm), TREE_PURPOSE (parm), fn, i++), t); return build_call (fn, nreverse (t)); } }