From 31c56a8ba7c10ccacfa1f3566d8eb16dddadbfd2 Mon Sep 17 00:00:00 2001 From: Fergus Henderson Date: Thu, 10 Jul 2003 08:18:53 +0000 Subject: [PATCH] Remove C language front end dependencies. * tree-convert.c: New file. * treetree.c: Don't include c-tree.h. Include target.h. (struct lang_identifier, union lang_tree_node, struct lang_type, struct lang_function): New, minimal language-specific datastructs. (tree_lang_truthvalue_conversion, tree_mark_addressable, tree_lang_type_for_size, tree_lang_type_for_mode, tree_lang_unsigned_type, tree_lang_signed_type, tree_lang_signed_or_unsigned): New functions. (LANG_HOOKS_*): Don't use C front end langhooks. Use new functions. (pushlevel, poplevel, global_bindings_p, insert_block, set_block, pushdecl, getdecls, kept_level_p, tree_push_type_decl, tree_push_atomic_type_decl): New functions. (struct resword, struct reswords): Remove. * Make-lang.in: Update. Don't depend on C front end objects. * config-lang.in: Likewise. Co-Authored-By: Steven Bosscher From-SVN: r69178 --- gcc/treelang/ChangeLog | 19 + gcc/treelang/Make-lang.in | 31 +- gcc/treelang/config-lang.in | 2 +- gcc/treelang/tree-convert.c | 108 +++++ gcc/treelang/treetree.c | 899 +++++++++++++++++++++--------------- 5 files changed, 670 insertions(+), 389 deletions(-) create mode 100644 gcc/treelang/tree-convert.c diff --git a/gcc/treelang/ChangeLog b/gcc/treelang/ChangeLog index 2569137a0e2..db873ac3097 100644 --- a/gcc/treelang/ChangeLog +++ b/gcc/treelang/ChangeLog @@ -1,3 +1,22 @@ +2003-07-10 Fergus Henderson + Steven Bosscher + + * tree-convert.c: New file. + * treetree.c: Don't include c-tree.h. Include target.h. + (struct lang_identifier, union lang_tree_node, struct lang_type, + struct lang_function): New, minimal language-specific datastructs. + (tree_lang_truthvalue_conversion, tree_mark_addressable, + tree_lang_type_for_size, tree_lang_type_for_mode, + tree_lang_unsigned_type, tree_lang_signed_type, + tree_lang_signed_or_unsigned): New functions. + (LANG_HOOKS_*): Don't use C front end langhooks. Use new functions. + (pushlevel, poplevel, global_bindings_p, insert_block, set_block, + pushdecl, getdecls, kept_level_p, tree_push_type_decl, + tree_push_atomic_type_decl): New functions. + (struct resword, struct reswords): Remove. + * Make-lang.in: Update. Don't depend on C front end objects. + * config-lang.in: Likewise. + 2003-07-07 Nathan Sidwell * treelang/treetree.c (tree_code_if_start, tree_code_if_else, diff --git a/gcc/treelang/Make-lang.in b/gcc/treelang/Make-lang.in index b6ce0fe72de..c1663945b90 100644 --- a/gcc/treelang/Make-lang.in +++ b/gcc/treelang/Make-lang.in @@ -47,7 +47,9 @@ TREELANGSED = sed TREELANGSEDFLAGS = -n # back end compiler libraries etc -TREE_BE_LIBS = $(C_TARGET_OBJS) $(BACKEND) $(LIBIBERTY) $(INTLLIBS) $(LIBS) $(LIBDEPS) +TREE_BE_LIBS = $(BACKEND) $(LIBIBERTY) $(INTLIBS) $(LIBS) $(LIBDEPS) + + GCC_EXTRAS = -B./ -B$(build_tooldir)/bin/ -isystem $(build_tooldir)/include # ./xgcc is the just built compiler. See GCC_FOR_TARGET in the GCC Makefile.in. @@ -56,10 +58,9 @@ GCC_EXTRAS = -B./ -B$(build_tooldir)/bin/ -isystem $(build_tooldir)/include # GCC_FOR_TREELANG = ./xgcc $(GCC_EXTRAS) -TREE_GENERATED = $(srcdir)/treelang/lex.c $(srcdir)/treelang/parse.c\ - $(srcdir)/treelang/parse.h $(srcdir)/treelang/parse.output $(srcdir)/treelang/TAGS - -TREE_SOURCE = ${srcdir}/treelang/parse.y ${srcdir}/treelang/lex.l ${srcdir}/treelang/tree1.c ${srcdir}/treelang/treelang.h ${srcdir}/treelang/treetree.c $(srcdir)/treelang/treetree.h ${srcdir}/treelang/opts.h +TREE_GENERATED = $(srcdir)/treelang/lex.c $(srcdir)/treelang/parse.c \ + $(srcdir)/treelang/parse.h $(srcdir)/treelang/parse.output \ + $(srcdir)/treelang/TAGS TREE_EXES = tree1$(exeext) @@ -83,13 +84,13 @@ treelang.done: tree1$(exeext) # no preprocessor # core compiler -tree1$(exeext): treelang/tree1.o treelang/treetree.o treelang/lex.o treelang/parse.o\ - $(TREE_BE_LIBS) c-convert.o c-typeck.o c-common.o c-cppbuiltin.o \ - c-decl.o attribs.o +tree1$(exeext): treelang/tree1.o treelang/treetree.o treelang/tree-convert.o \ + treelang/lex.o treelang/parse.o \ + $(TREE_BE_LIBS) attribs.o $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ \ - treelang/tree1.o treelang/treetree.o treelang/lex.o treelang/parse.o \ - c-convert.o c-typeck.o c-common.o c-cppbuiltin.o c-decl.o attribs.o \ - $(TREE_BE_LIBS) + treelang/tree1.o treelang/treetree.o treelang/tree-convert.o \ + treelang/lex.o treelang/parse.o \ + $(TREE_BE_LIBS) attribs.o # # Compiling object files from source files. @@ -106,6 +107,9 @@ treelang/treetree.o: treelang/treetree.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ varray.h $(LANGHOOKS_DEF_H) langhooks.h treelang/treelang.h input.h \ treelang/treetree.h treelang/parse.h +treelang/tree-convert.o: treelang/tree-convert.c $(CONFIG_H) $(SYSTEM_) \ + coretypes.h diagnostic.h $(TREE_H) flags.h toplev.h langhooks.h + treelang/parse.o: treelang/parse.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ $(TM_H) diagnostic.h treelang/treelang.h input.h treelang/treetree.h @@ -314,9 +318,6 @@ treelang.check.fix: force -cp testsuite/treelang/*runpgm* t -rm -f t/*nofilename -treelang.wc: force - wc ${TREE_SOURCE} - # .PHONY: treelang.html @@ -324,3 +325,5 @@ treelang.wc: force treelang.html: cd $(srcdir)/treelang && texi2html -I ../doc/include -verbose -menu -split_chapter -number treelang.texi # mv treelang*.html $(srcdir)/treelang + +config.status: treelang/config-lang.in diff --git a/gcc/treelang/config-lang.in b/gcc/treelang/config-lang.in index 4f5a82e1668..f8a52f9787f 100644 --- a/gcc/treelang/config-lang.in +++ b/gcc/treelang/config-lang.in @@ -36,4 +36,4 @@ diff_excludes="-x lex.c -x parse.c -x parse.h" headers= build_by_default="no" -gtfiles="\$(srcdir)/c-decl.c \$(srcdir)/c-common.c \$(srcdir)/c-common.h \$(srcdir)/treelang/tree1.c \$(srcdir)/treelang/treelang.h" +gtfiles="\$(srcdir)/treelang/tree1.c \$(srcdir)/treelang/treetree.c \$(srcdir)/treelang/treelang.h" diff --git a/gcc/treelang/tree-convert.c b/gcc/treelang/tree-convert.c new file mode 100644 index 00000000000..6d50ef5a76a --- /dev/null +++ b/gcc/treelang/tree-convert.c @@ -0,0 +1,108 @@ +/* Language-level data type conversion for Treelang. + This is a very slightly modified copy of c-convert.c. + Copyright (C) 1987, 1988, 1991, 1998, 2002 Free Software Foundation, Inc. + +This file is part of GCC. + +GCC is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free +Software Foundation; either version 2, or (at your option) any later +version. + +GCC is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with GCC; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA +02111-1307, USA. */ + + +/* This file contains the functions for converting C expressions + to different data types. The only entry point is `convert'. + Every language front end must have a `convert' function + but what kind of conversions it does will depend on the language. */ + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tm.h" +#include "diagnostic.h" +#include "tree.h" +#include "flags.h" +#include "convert.h" +#include "toplev.h" +#include "langhooks.h" + +/* Change of width--truncation and extension of integers or reals-- + is represented with NOP_EXPR. Proper functioning of many things + assumes that no other conversions can be NOP_EXPRs. + + Conversion between integer and pointer is represented with CONVERT_EXPR. + Converting integer to real uses FLOAT_EXPR + and real to integer uses FIX_TRUNC_EXPR. + + Here is a list of all the functions that assume that widening and + narrowing is always done with a NOP_EXPR: + In convert.c, convert_to_integer. + In c-typeck.c, build_binary_op (boolean ops), and + c_common_truthvalue_conversion. + In expr.c: expand_expr, for operands of a MULT_EXPR. + In fold-const.c: fold. + In tree.c: get_narrower and get_unwidened. */ + +/* Create an expression whose value is that of EXPR, + converted to type TYPE. The TREE_TYPE of the value + is always TYPE. This function implements all reasonable + conversions; callers should filter out those that are + not permitted by the language being compiled. */ + +tree +convert (type, expr) + tree type, expr; +{ + tree e = expr; + enum tree_code code = TREE_CODE (type); + + if (type == TREE_TYPE (expr) + || TREE_CODE (expr) == ERROR_MARK + || code == ERROR_MARK || TREE_CODE (TREE_TYPE (expr)) == ERROR_MARK) + return expr; + + if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (expr))) + return fold (build1 (NOP_EXPR, type, expr)); + if (TREE_CODE (TREE_TYPE (expr)) == ERROR_MARK) + return error_mark_node; + if (TREE_CODE (TREE_TYPE (expr)) == VOID_TYPE) + { + error ("void value not ignored as it ought to be"); + return error_mark_node; + } + if (code == VOID_TYPE) + return build1 (CONVERT_EXPR, type, e); + if (code == INTEGER_TYPE || code == ENUMERAL_TYPE) + return fold (convert_to_integer (type, e)); + if (code == BOOLEAN_TYPE) + { + tree t = (*lang_hooks.truthvalue_conversion) (expr); + /* If it returns a NOP_EXPR, we must fold it here to avoid + infinite recursion between fold () and convert (). */ + if (TREE_CODE (t) == NOP_EXPR) + return fold (build1 (NOP_EXPR, type, TREE_OPERAND (t, 0))); + else + return fold (build1 (NOP_EXPR, type, t)); + } + if (code == POINTER_TYPE || code == REFERENCE_TYPE) + return fold (convert_to_pointer (type, e)); + if (code == REAL_TYPE) + return fold (convert_to_real (type, e)); + if (code == COMPLEX_TYPE) + return fold (convert_to_complex (type, e)); + if (code == VECTOR_TYPE) + return fold (convert_to_vector (type, e)); + + error ("conversion to non-scalar type requested"); + return error_mark_node; +} diff --git a/gcc/treelang/treetree.c b/gcc/treelang/treetree.c index c752a82f1c2..2b8fd149b43 100644 --- a/gcc/treelang/treetree.c +++ b/gcc/treelang/treetree.c @@ -63,13 +63,13 @@ #include "tree.h" #include "flags.h" #include "output.h" -#include "c-tree.h" #include "rtl.h" #include "ggc.h" #include "toplev.h" #include "varray.h" #include "langhooks-def.h" #include "langhooks.h" +#include "target.h" #include "treelang.h" #include "treetree.h" @@ -78,31 +78,94 @@ extern int option_main; extern char **file_names; +/* Types expected by gcc's garbage collector. + These types exist to allow language front-ends to + add extra information in gcc's parse tree data structure. + But the treelang front end doesn't use them -- it has + its own parse tree data structure. + We define them here only to satisfy gcc's garbage collector. */ + +/* Language-specific identifier information. */ + +struct lang_identifier GTY(()) +{ + struct tree_identifier common; +}; + +/* Language-specific tree node information. */ + +union lang_tree_node + GTY((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"))) +{ + union tree_node GTY ((tag ("0"), + desc ("tree_node_structure (&%h)"))) + generic; + struct lang_identifier GTY ((tag ("1"))) identifier; +}; + +/* Language-specific type information. */ + +struct lang_type GTY(()) +{ + char junk; /* dummy field to ensure struct is not empty */ +}; + +/* Language-specific declaration information. */ + +struct lang_decl GTY(()) +{ + char junk; /* dummy field to ensure struct is not empty */ +}; + +struct language_function GTY(()) +{ + char junk; /* dummy field to ensure struct is not empty */ +}; + +static tree tree_lang_truthvalue_conversion PARAMS((tree expr)); +static bool tree_mark_addressable PARAMS((tree exp)); +static tree tree_lang_type_for_size PARAMS((unsigned precision, + int unsignedp)); +static tree tree_lang_type_for_mode PARAMS((enum machine_mode mode, + int unsignedp)); +static tree tree_lang_unsigned_type PARAMS((tree type_node)); +static tree tree_lang_signed_type PARAMS((tree type_node)); +static tree tree_lang_signed_or_unsigned_type PARAMS((int unsignedp, + tree type)); + +/* XXX these should be static */ +void pushlevel PARAMS((int ignore)); +tree poplevel PARAMS((int keep, int reverse, int functionbody)); +int global_bindings_p PARAMS((void)); +void insert_block PARAMS((tree block)); +void set_block PARAMS((tree block)); +tree pushdecl PARAMS((tree decl)); +tree getdecls PARAMS((void)); +int kept_level_p PARAMS((void)); + +static void tree_push_type_decl PARAMS((tree id, tree type_node)); +static void tree_push_atomic_type_decl PARAMS((tree id, tree type_node)); + /* The front end language hooks (addresses of code for this front - end). Mostly just use the C routines. */ + end). These are not really very language-dependent, i.e. + treelang, C, Mercury, etc. can all use almost the same definitions. */ #undef LANG_HOOKS_TRUTHVALUE_CONVERSION -#define LANG_HOOKS_TRUTHVALUE_CONVERSION c_common_truthvalue_conversion +#define LANG_HOOKS_TRUTHVALUE_CONVERSION tree_lang_truthvalue_conversion #undef LANG_HOOKS_MARK_ADDRESSABLE -#define LANG_HOOKS_MARK_ADDRESSABLE c_mark_addressable +#define LANG_HOOKS_MARK_ADDRESSABLE tree_mark_addressable #undef LANG_HOOKS_SIGNED_TYPE -#define LANG_HOOKS_SIGNED_TYPE c_common_signed_type +#define LANG_HOOKS_SIGNED_TYPE tree_lang_signed_type #undef LANG_HOOKS_UNSIGNED_TYPE -#define LANG_HOOKS_UNSIGNED_TYPE c_common_unsigned_type +#define LANG_HOOKS_UNSIGNED_TYPE tree_lang_unsigned_type #undef LANG_HOOKS_SIGNED_OR_UNSIGNED_TYPE -#define LANG_HOOKS_SIGNED_OR_UNSIGNED_TYPE c_common_signed_or_unsigned_type +#define LANG_HOOKS_SIGNED_OR_UNSIGNED_TYPE tree_lang_signed_or_unsigned_type #undef LANG_HOOKS_TYPE_FOR_MODE -#define LANG_HOOKS_TYPE_FOR_MODE c_common_type_for_mode +#define LANG_HOOKS_TYPE_FOR_MODE tree_lang_type_for_mode #undef LANG_HOOKS_TYPE_FOR_SIZE -#define LANG_HOOKS_TYPE_FOR_SIZE c_common_type_for_size +#define LANG_HOOKS_TYPE_FOR_SIZE tree_lang_type_for_size #undef LANG_HOOKS_PARSE_FILE #define LANG_HOOKS_PARSE_FILE treelang_parse_file -#undef LANG_HOOKS_COMMON_ATTRIBUTE_TABLE -#define LANG_HOOKS_COMMON_ATTRIBUTE_TABLE c_common_attribute_table -#undef LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE -#define LANG_HOOKS_FORMAT_ATTRIBUTE_TABLE c_common_format_attribute_table -#undef LANG_HOOKS_INSERT_DEFAULT_ATTRIBUTES -#define LANG_HOOKS_INSERT_DEFAULT_ATTRIBUTES c_insert_default_attributes /* Hook routines and data unique to treelang. */ @@ -805,483 +868,571 @@ tree_code_get_numeric_type (unsigned int size1, unsigned int sign1) return ret1; } -/* Garbage Collection. */ - -/* Callback to mark storage M as used always. */ - -void -tree_ggc_storage_always_used (void * m) -{ - void **mm; /* Actually M is a pointer to a pointer to the memory. */ - mm = (void**)m; - - if (*mm) - ggc_mark (*mm); -} - -/* Following from c-lang.c. */ - -/* Used by c-typeck.c (build_external_ref), but only for objc. */ +/* Get a stringpool entry for a string S of length L. This is needed + because the GTY routines don't mark strings, forcing you to put + them into stringpool, which is never freed. */ -tree -lookup_objc_ivar (tree id ATTRIBUTE_UNUSED) +const char* +get_string (const char *s, size_t l) { - return 0; + tree t; + t = get_identifier_with_length (s, l); + return IDENTIFIER_POINTER(t); } + +/* Save typing debug_tree all the time. Dump a tree T pretty and + concise. */ -/* Dummy routines called from c code. Save copying c-decl.c, c-common.c etc. */ - -tree -objc_is_id (tree arg ATTRIBUTE_UNUSED) -{ - return 0; -} +void dt (tree t); void -check_function_format (int *status ATTRIBUTE_UNUSED, - tree attrs ATTRIBUTE_UNUSED, - tree params ATTRIBUTE_UNUSED) +dt (tree t) { - return; + debug_tree (t); } -/* Tell the c code we are not objective C. */ +/* Routines Expected by gcc: */ -int -objc_comptypes (tree lhs ATTRIBUTE_UNUSED, - tree rhs ATTRIBUTE_UNUSED, - int reflexive ATTRIBUTE_UNUSED) -{ - return 0; -} +/* These are used to build types for various sizes. The code below + is a simplified version of that of GNAT. */ -/* Should not be called for treelang. Needed by RS6000 backend. */ +#ifndef MAX_BITS_PER_WORD +#define MAX_BITS_PER_WORD BITS_PER_WORD +#endif -int c_lex (tree *value); +/* This variable keeps a table for types for each precision so that we only + allocate each of them once. Signed and unsigned types are kept separate. */ +static GTY(()) tree signed_and_unsigned_types[MAX_BITS_PER_WORD + 1][2]; -int -c_lex (tree *value ATTRIBUTE_UNUSED) +/* XXX is this definition OK? */ +static tree +tree_lang_truthvalue_conversion (expr) + tree expr; { - abort (); + return expr; } -/* Should not be called for treelang. */ +/* Mark EXP saying that we need to be able to take the + address of it; it should not be allocated in a register. + Value is 1 if successful. + + This implementation was copied from c-decl.c. */ -tree -build_stmt (enum tree_code code ATTRIBUTE_UNUSED, ...) +static bool +tree_mark_addressable (exp) + tree exp; { - abort (); + register tree x = exp; + while (1) + switch (TREE_CODE (x)) + { + case COMPONENT_REF: + case ADDR_EXPR: + case ARRAY_REF: + case REALPART_EXPR: + case IMAGPART_EXPR: + x = TREE_OPERAND (x, 0); + break; + + case CONSTRUCTOR: + TREE_ADDRESSABLE (x) = 1; + return 1; + + case VAR_DECL: + case CONST_DECL: + case PARM_DECL: + case RESULT_DECL: + if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x) + && DECL_NONLOCAL (x)) + { + if (TREE_PUBLIC (x)) + { + error ("global register variable `%s' used in nested function", + IDENTIFIER_POINTER (DECL_NAME (x))); + return 0; + } + pedwarn ("register variable `%s' used in nested function", + IDENTIFIER_POINTER (DECL_NAME (x))); + } + else if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x)) + { + if (TREE_PUBLIC (x)) + { + error ("address of global register variable `%s' requested", + IDENTIFIER_POINTER (DECL_NAME (x))); + return 0; + } + + pedwarn ("address of register variable `%s' requested", + IDENTIFIER_POINTER (DECL_NAME (x))); + } + put_var_into_stack (x, /*rescan=*/ true); + + /* drops in */ + case FUNCTION_DECL: + TREE_ADDRESSABLE (x) = 1; + + default: + return 1; + } } - -/* Should not be called for treelang. */ - -tree -add_stmt (tree t ATTRIBUTE_UNUSED) + +/* Return an integer type with the number of bits of precision given by + PRECISION. UNSIGNEDP is nonzero if the type is unsigned; otherwise + it is a signed type. */ + +static tree +tree_lang_type_for_size (precision, unsignedp) + unsigned precision; + int unsignedp; { - abort (); -} + tree t; -/* Should not be called for treelang. */ + if (precision <= MAX_BITS_PER_WORD + && signed_and_unsigned_types[precision][unsignedp] != 0) + return signed_and_unsigned_types[precision][unsignedp]; -tree -build_return_stmt (tree expr ATTRIBUTE_UNUSED) -{ - abort (); + if (unsignedp) + t = signed_and_unsigned_types[precision][1] + = make_unsigned_type (precision); + else + t = signed_and_unsigned_types[precision][0] + = make_signed_type (precision); + + return t; } -/* C warning, ignore. */ +/* Return a data type that has machine mode MODE. UNSIGNEDP selects + an unsigned type; otherwise a signed type is returned. */ -void -pedwarn_c99 (const char *msgid ATTRIBUTE_UNUSED, ...) +static tree +tree_lang_type_for_mode (mode, unsignedp) + enum machine_mode mode; + int unsignedp; { - return; + return tree_lang_type_for_size (GET_MODE_BITSIZE (mode), unsignedp); } -/* Should not be called for treelang. */ +/* Return the unsigned version of a TYPE_NODE, a scalar type. */ -tree -build_case_label (tree low_value ATTRIBUTE_UNUSED, - tree high_value ATTRIBUTE_UNUSED, - tree label_decl ATTRIBUTE_UNUSED) +static tree +tree_lang_unsigned_type (type_node) + tree type_node; { - abort (); + return tree_lang_type_for_size (TYPE_PRECISION (type_node), 1); } -/* Should not be called for treelang. */ +/* Return the signed version of a TYPE_NODE, a scalar type. */ -void -emit_local_var (tree decl ATTRIBUTE_UNUSED) +static tree +tree_lang_signed_type (type_node) + tree type_node; { - abort (); + return tree_lang_type_for_size (TYPE_PRECISION (type_node), 0); } -/* Should not be called for treelang. */ +/* Return a type the same as TYPE except unsigned or signed according to + UNSIGNEDP. */ -void -expand_stmt (tree t ATTRIBUTE_UNUSED) +static tree +tree_lang_signed_or_unsigned_type (unsignedp, type) + int unsignedp; + tree type; { - abort (); + if (! INTEGRAL_TYPE_P (type) || TREE_UNSIGNED (type) == unsignedp) + return type; + else + return tree_lang_type_for_size (TYPE_PRECISION (type), unsignedp); } + +/* These functions and variables deal with binding contours. We only + need these functions for the list of PARM_DECLs, but we leave the + functions more general; these are a simplified version of the + functions from GNAT. */ -/* Should not be called for treelang. */ +/* For each binding contour we allocate a binding_level structure which records + the entities defined or declared in that contour. Contours include: -cpp_reader * -cpp_create_reader (enum c_lang lang ATTRIBUTE_UNUSED, - struct ht *table ATTRIBUTE_UNUSED) -{ - abort (); -} + the global one + one for each subprogram definition + one for each compound statement (declare block) -/* Should not be called for treelang. */ + Binding contours are used to create GCC tree BLOCK nodes. */ -void -init_c_lex (void) +struct binding_level { - abort (); -} + /* A chain of ..._DECL nodes for all variables, constants, functions, + parameters and type declarations. These ..._DECL nodes are chained + through the TREE_CHAIN field. Note that these ..._DECL nodes are stored + in the reverse of the order supplied to be compatible with the + back-end. */ + tree names; + /* For each level (except the global one), a chain of BLOCK nodes for all + the levels that were entered and exited one level down from this one. */ + tree blocks; + /* The back end may need, for its own internal processing, to create a BLOCK + node. This field is set aside for this purpose. If this field is non-null + when the level is popped, i.e. when poplevel is invoked, we will use such + block instead of creating a new one from the 'names' field, that is the + ..._DECL nodes accumulated so far. Typically the routine 'pushlevel' + will be called before setting this field, so that if the front-end had + inserted ..._DECL nodes in the current block they will not be lost. */ + tree block_created_by_back_end; + /* The binding level containing this one (the enclosing binding level). */ + struct binding_level *level_chain; +}; -/* Should not be called for treelang. */ +/* The binding level currently in effect. */ +static struct binding_level *current_binding_level = NULL; -void init_pragma (void); +/* The outermost binding level. This binding level is created when the + compiler is started and it will exist through the entire compilation. */ +static struct binding_level *global_binding_level; -void -init_pragma () -{ - abort (); -} - -/* Should not be called for treelang. */ +/* Binding level structures are initialized by copying this one. */ +static struct binding_level clear_binding_level = {NULL, NULL, NULL, NULL}; + +/* Return non-zero if we are currently in the global binding level. */ int -cpp_finish (cpp_reader *pfile ATTRIBUTE_UNUSED, FILE *f ATTRIBUTE_UNUSED) -{ - abort (); -} - -/* Should not be called for treelang. */ - -unsigned int -cpp_errors (cpp_reader *pfile ATTRIBUTE_UNUSED) +global_bindings_p () { - abort (); + return current_binding_level == global_binding_level ? -1 : 0; } -/* Dummy called by C. */ +/* Return the list of declarations in the current level. Note that this list + is in reverse order (it has to be so for back-end compatibility). */ tree -handle_format_attribute (tree *node ATTRIBUTE_UNUSED, - tree name ATTRIBUTE_UNUSED, - tree args ATTRIBUTE_UNUSED, - int flags ATTRIBUTE_UNUSED, - bool *no_add_attrs ATTRIBUTE_UNUSED) +getdecls () { - return NULL_TREE; + return current_binding_level->names; } -/* Should not be called for treelang. */ +/* Nonzero if the current level needs to have a BLOCK made. */ -tree -handle_format_arg_attribute (tree *node ATTRIBUTE_UNUSED, - tree name ATTRIBUTE_UNUSED, - tree args ATTRIBUTE_UNUSED, - int flags ATTRIBUTE_UNUSED, - bool *no_add_attrs ATTRIBUTE_UNUSED) +int +kept_level_p () { - abort (); + return (current_binding_level->names != 0); } -/* Should not be called for treelang. */ +/* Enter a new binding level. The input parameter is ignored, but has to be + specified for back-end compatibility. */ void -cpp_assert (cpp_reader * cr ATTRIBUTE_UNUSED, - const char *s ATTRIBUTE_UNUSED) +pushlevel (ignore) + int ignore ATTRIBUTE_UNUSED; { - abort (); -} + struct binding_level *newlevel + = (struct binding_level *) xmalloc (sizeof (struct binding_level)); -/* Should not be called for treelang. */ + *newlevel = clear_binding_level; -void -set_Wformat (int setting ATTRIBUTE_UNUSED) -{ - abort (); + /* Add this level to the front of the chain (stack) of levels that are + active. */ + newlevel->level_chain = current_binding_level; + current_binding_level = newlevel; } -/* Used for objective C. */ +/* Exit a binding level. + Pop the level off, and restore the state of the identifier-decl mappings + that were in effect when this level was entered. -void -objc_check_decl (tree decl ATTRIBUTE_UNUSED); + If KEEP is nonzero, this level had explicit declarations, so + and create a "block" (a BLOCK node) for the level + to record its declarations and subblocks for symbol table output. -void -objc_check_decl (tree decl ATTRIBUTE_UNUSED) -{ - abort (); -} + If FUNCTIONBODY is nonzero, this level is the body of a function, + so create a block as if KEEP were set and also clear out all + label names. -/* Tell the c code we are not objective C. */ + If REVERSE is nonzero, reverse the order of decls before putting + them into the BLOCK. */ tree -objc_message_selector (void); - -tree -objc_message_selector () +poplevel (keep, reverse, functionbody) + int keep; + int reverse; + int functionbody; { - return 0; -} - -/* Should not be called for treelang. */ - -void -gen_aux_info_record (tree fndecl ATTRIBUTE_UNUSED, - int is_definition ATTRIBUTE_UNUSED, - int is_implicit ATTRIBUTE_UNUSED, - int is_prototyped ATTRIBUTE_UNUSED) -{ - abort (); -} + /* Points to a BLOCK tree node. This is the BLOCK node construted for the + binding level that we are about to exit and which is returned by this + routine. */ + tree block_node = NULL_TREE; + tree decl_chain; + tree subblock_chain = current_binding_level->blocks; + tree subblock_node; + tree block_created_by_back_end; + + /* Reverse the list of *_DECL nodes if desired. Note that the ..._DECL + nodes chained through the `names' field of current_binding_level are in + reverse order except for PARM_DECL node, which are explicitely stored in + the right order. */ + decl_chain = (reverse) ? nreverse (current_binding_level->names) + : current_binding_level->names; + + block_created_by_back_end = current_binding_level->block_created_by_back_end; + if (block_created_by_back_end != 0) + { + block_node = block_created_by_back_end; + + /* Check if we are about to discard some information that was gathered + by the front-end. Nameley check if the back-end created a new block + without calling pushlevel first. To understand why things are lost + just look at the next case (i.e. no block created by back-end. */ + if ((keep || functionbody) && (decl_chain || subblock_chain)) + abort (); + } -/* Should not be called for treelang, but it is. */ + /* If there were any declarations in the current binding level, or if this + binding level is a function body, or if there are any nested blocks then + create a BLOCK node to record them for the life of this function. */ + else if (keep || functionbody) + block_node = build_block (keep ? decl_chain : 0, 0, subblock_chain, 0, 0); + + /* Record the BLOCK node just built as the subblock its enclosing scope. */ + for (subblock_node = subblock_chain; subblock_node; + subblock_node = TREE_CHAIN (subblock_node)) + BLOCK_SUPERCONTEXT (subblock_node) = block_node; + + /* Clear out the meanings of the local variables of this level. */ + + for (subblock_node = decl_chain; subblock_node; + subblock_node = TREE_CHAIN (subblock_node)) + if (DECL_NAME (subblock_node) != 0) + /* If the identifier was used or addressed via a local extern decl, + don't forget that fact. */ + if (DECL_EXTERNAL (subblock_node)) + { + if (TREE_USED (subblock_node)) + TREE_USED (DECL_NAME (subblock_node)) = 1; + if (TREE_ADDRESSABLE (subblock_node)) + TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (subblock_node)) = 1; + } + + /* Pop the current level. */ + current_binding_level = current_binding_level->level_chain; + + if (functionbody) + { + /* This is the top level block of a function. The ..._DECL chain stored + in BLOCK_VARS are the function's parameters (PARM_DECL nodes). Don't + leave them in the BLOCK because they are found in the FUNCTION_DECL + instead. */ + DECL_INITIAL (current_function_decl) = block_node; + BLOCK_VARS (block_node) = 0; + } + else if (block_node) + { + if (block_created_by_back_end == NULL) + current_binding_level->blocks + = chainon (current_binding_level->blocks, block_node); + } -void -c_parse_init () -{ - return; + /* If we did not make a block for the level just exited, any blocks made for + inner levels (since they cannot be recorded as subblocks in that level) + must be carried forward so they will later become subblocks of something + else. */ + else if (subblock_chain) + current_binding_level->blocks + = chainon (current_binding_level->blocks, subblock_chain); + if (block_node) + TREE_USED (block_node) = 1; + + return block_node; } - -/* Should not be called for treelang. */ - -void maybe_apply_pragma_weak (tree decl); + +/* Insert BLOCK at the end of the list of subblocks of the + current binding level. This is used when a BIND_EXPR is expanded, + to handle the BLOCK node inside the BIND_EXPR. */ void -maybe_apply_pragma_weak (tree decl ATTRIBUTE_UNUSED) +insert_block (block) + tree block; { - abort (); + TREE_USED (block) = 1; + current_binding_level->blocks + = chainon (current_binding_level->blocks, block); } -/* Should not be called for treelang. */ +/* Set the BLOCK node for the innermost scope + (the one we are currently in). */ void -add_decl_stmt (tree decl ATTRIBUTE_UNUSED) +set_block (block) + tree block; { - abort (); + current_binding_level->block_created_by_back_end = block; } -/* Should not be called for treelang. */ - -tree -maybe_apply_renaming_pragma (tree decl, tree asmname); - -/* Should not be called for treelang. */ +/* Records a ..._DECL node DECL as belonging to the current lexical scope. + Returns the ..._DECL node. */ tree -maybe_apply_renaming_pragma (tree decl ATTRIBUTE_UNUSED, tree asmname ATTRIBUTE_UNUSED) +pushdecl (decl) + tree decl; { - abort (); -} + /* External objects aren't nested, other objects may be. */ + + if ((DECL_EXTERNAL (decl)) || (decl==current_function_decl)) + DECL_CONTEXT (decl) = 0; + else + DECL_CONTEXT (decl) = current_function_decl; -/* Should not be called for treelang. */ + /* Put the declaration on the list. The list of declarations is in reverse + order. The list will be reversed later if necessary. This needs to be + this way for compatibility with the back-end. */ -void -begin_stmt_tree (tree *t ATTRIBUTE_UNUSED) -{ - abort (); -} + TREE_CHAIN (decl) = current_binding_level->names; + current_binding_level->names = decl; -/* Should not be called for treelang. */ + /* For the declartion of a type, set its name if it is not already set. */ -void -finish_stmt_tree (tree *t ATTRIBUTE_UNUSED) -{ - abort (); -} + if (TREE_CODE (decl) == TYPE_DECL + && TYPE_NAME (TREE_TYPE (decl)) == 0) + TYPE_NAME (TREE_TYPE (decl)) = DECL_NAME (decl); -/* Should not be called for treelang. */ - -int -defer_fn (tree fn ATTRIBUTE_UNUSED) -{ - abort (); + return decl; } + -/* Should not be called for treelang. */ - -cpp_options -*cpp_get_options (cpp_reader * cr ATTRIBUTE_UNUSED) +static void +tree_push_type_decl(id, type_node) + tree id; + tree type_node; { - abort (); + tree decl = build_decl (TYPE_DECL, id, type_node); + TYPE_NAME (type_node) = decl; + TYPE_STUB_DECL (type_node) = decl; + pushdecl (decl); } -/* Should not be called for treelang. */ +/* push_atomic_type_decl() ensures that the type's type is itself. + Needed for DBX. Must only be used for atomic types, + not for e.g. pointer or array types. */ -void -cpp_define (cpp_reader * cr ATTRIBUTE_UNUSED, const char * c ATTRIBUTE_UNUSED) +static void +tree_push_atomic_type_decl(id, type_node) + tree id; + tree type_node; { - abort (); + TREE_TYPE (type_node) = type_node; + tree_push_type_decl (id, type_node); } -/* Should not be called for treelang. */ - -cpp_callbacks * -cpp_get_callbacks (cpp_reader * cr ATTRIBUTE_UNUSED) -{ - abort (); -} +#define NULL_BINDING_LEVEL (struct binding_level *) NULL /* Create the predefined scalar types of C, and some nodes representing standard constants (0, 1, (void *) 0). Initialize the global binding level. Make definitions for built-in primitive functions. */ - /* `unsigned long' is the standard type for sizeof. - Note that stddef.h uses `unsigned long', - and this must agree, even if long and int are the same size. */ - -/* The reserved keyword table. */ -struct resword -{ - const char *word; - ENUM_BITFIELD(rid) rid : 16; - unsigned int disable : 16; -}; - -static const struct resword reswords[] = -{ - { "_Bool", RID_BOOL, 0 }, - { "_Complex", RID_COMPLEX, 0 }, - { "__FUNCTION__", RID_FUNCTION_NAME, 0 }, - { "__PRETTY_FUNCTION__", RID_PRETTY_FUNCTION_NAME, 0 }, - { "__alignof", RID_ALIGNOF, 0 }, - { "__alignof__", RID_ALIGNOF, 0 }, - { "__asm", RID_ASM, 0 }, - { "__asm__", RID_ASM, 0 }, - { "__attribute", RID_ATTRIBUTE, 0 }, - { "__attribute__", RID_ATTRIBUTE, 0 }, - { "__builtin_choose_expr", RID_CHOOSE_EXPR, 0 }, - { "__builtin_types_compatible_p", RID_TYPES_COMPATIBLE_P, 0 }, - { "__builtin_va_arg", RID_VA_ARG, 0 }, - { "__complex", RID_COMPLEX, 0 }, - { "__complex__", RID_COMPLEX, 0 }, - { "__const", RID_CONST, 0 }, - { "__const__", RID_CONST, 0 }, - { "__extension__", RID_EXTENSION, 0 }, - { "__func__", RID_C99_FUNCTION_NAME, 0 }, - { "__imag", RID_IMAGPART, 0 }, - { "__imag__", RID_IMAGPART, 0 }, - { "__inline", RID_INLINE, 0 }, - { "__inline__", RID_INLINE, 0 }, - { "__label__", RID_LABEL, 0 }, - { "__ptrbase", RID_PTRBASE, 0 }, - { "__ptrbase__", RID_PTRBASE, 0 }, - { "__ptrextent", RID_PTREXTENT, 0 }, - { "__ptrextent__", RID_PTREXTENT, 0 }, - { "__ptrvalue", RID_PTRVALUE, 0 }, - { "__ptrvalue__", RID_PTRVALUE, 0 }, - { "__real", RID_REALPART, 0 }, - { "__real__", RID_REALPART, 0 }, - { "__restrict", RID_RESTRICT, 0 }, - { "__restrict__", RID_RESTRICT, 0 }, - { "__signed", RID_SIGNED, 0 }, - { "__signed__", RID_SIGNED, 0 }, - { "__typeof", RID_TYPEOF, 0 }, - { "__typeof__", RID_TYPEOF, 0 }, - { "__volatile", RID_VOLATILE, 0 }, - { "__volatile__", RID_VOLATILE, 0 }, - { "asm", RID_ASM, 0 }, - { "auto", RID_AUTO, 0 }, - { "break", RID_BREAK, 0 }, - { "case", RID_CASE, 0 }, - { "char", RID_CHAR, 0 }, - { "const", RID_CONST, 0 }, - { "continue", RID_CONTINUE, 0 }, - { "default", RID_DEFAULT, 0 }, - { "do", RID_DO, 0 }, - { "double", RID_DOUBLE, 0 }, - { "else", RID_ELSE, 0 }, - { "enum", RID_ENUM, 0 }, - { "extern", RID_EXTERN, 0 }, - { "float", RID_FLOAT, 0 }, - { "for", RID_FOR, 0 }, - { "goto", RID_GOTO, 0 }, - { "if", RID_IF, 0 }, - { "inline", RID_INLINE, 0 }, - { "int", RID_INT, 0 }, - { "long", RID_LONG, 0 }, - { "register", RID_REGISTER, 0 }, - { "restrict", RID_RESTRICT, 0 }, - { "return", RID_RETURN, 0 }, - { "short", RID_SHORT, 0 }, - { "signed", RID_SIGNED, 0 }, - { "sizeof", RID_SIZEOF, 0 }, - { "static", RID_STATIC, 0 }, - { "struct", RID_STRUCT, 0 }, - { "switch", RID_SWITCH, 0 }, - { "typedef", RID_TYPEDEF, 0 }, - { "typeof", RID_TYPEOF, 0 }, - { "union", RID_UNION, 0 }, - { "unsigned", RID_UNSIGNED, 0 }, - { "void", RID_VOID, 0 }, - { "volatile", RID_VOLATILE, 0 }, - { "while", RID_WHILE, 0 }, -}; -#define N_reswords (sizeof reswords / sizeof (struct resword)) - -/* Init enough to allow the C decl code to work, then clean up - afterwards. */ - void treelang_init_decl_processing () { - unsigned int i; - tree id; - - ridpointers = (tree *) ggc_calloc ((int) RID_MAX, sizeof (tree)); - - for (i = 0; i < N_reswords; i++) - { - id = get_identifier (reswords[i].word); - C_RID_CODE (id) = reswords[i].rid; - C_IS_RESERVED_WORD (id) = 1; - ridpointers [(int) reswords[i].rid] = id; - } - - c_init_decl_processing (); - - /* ix86_return_pops_args takes the type of these so need to patch - their own type as themselves. */ - - for (i = 0; i < itk_none; i++) - { - if (integer_types[i]) - TREE_TYPE (integer_types [i]) = integer_types[i]; - } - - /* Probably these ones too. */ - TREE_TYPE (float_type_node) = float_type_node; - TREE_TYPE (double_type_node) = double_type_node; - TREE_TYPE (long_double_type_node) = long_double_type_node; - + current_function_decl = NULL; + current_binding_level = NULL_BINDING_LEVEL; + pushlevel (0); /* make the binding_level structure for global names */ + global_binding_level = current_binding_level; + + build_common_tree_nodes (flag_signed_char); + + /* set standard type names */ + + /* Define `int' and `char' first so that dbx will output them first. */ + + tree_push_atomic_type_decl (get_identifier ("int"), integer_type_node); + tree_push_atomic_type_decl (get_identifier ("char"), char_type_node); + tree_push_atomic_type_decl (get_identifier ("long int"), + long_integer_type_node); + tree_push_atomic_type_decl (get_identifier ("unsigned int"), + unsigned_type_node); + tree_push_atomic_type_decl (get_identifier ("long unsigned int"), + long_unsigned_type_node); + tree_push_atomic_type_decl (get_identifier ("long long int"), + long_long_integer_type_node); + tree_push_atomic_type_decl (get_identifier ("long long unsigned int"), + long_long_unsigned_type_node); + tree_push_atomic_type_decl (get_identifier ("short int"), + short_integer_type_node); + tree_push_atomic_type_decl (get_identifier ("short unsigned int"), + short_unsigned_type_node); + tree_push_atomic_type_decl (get_identifier ("signed char"), + signed_char_type_node); + tree_push_atomic_type_decl (get_identifier ("unsigned char"), + unsigned_char_type_node); + tree_push_atomic_type_decl (NULL_TREE, intQI_type_node); + tree_push_atomic_type_decl (NULL_TREE, intHI_type_node); + tree_push_atomic_type_decl (NULL_TREE, intSI_type_node); + tree_push_atomic_type_decl (NULL_TREE, intDI_type_node); +#if HOST_BITS_PER_WIDE_INT >= 64 + tree_push_atomic_type_decl (NULL_TREE, intTI_type_node); +#endif + tree_push_atomic_type_decl (NULL_TREE, unsigned_intQI_type_node); + tree_push_atomic_type_decl (NULL_TREE, unsigned_intHI_type_node); + tree_push_atomic_type_decl (NULL_TREE, unsigned_intSI_type_node); + tree_push_atomic_type_decl (NULL_TREE, unsigned_intDI_type_node); +#if HOST_BITS_PER_WIDE_INT >= 64 + tree_push_atomic_type_decl (NULL_TREE, unsigned_intTI_type_node); +#endif + + size_type_node = make_unsigned_type (POINTER_SIZE); + tree_push_atomic_type_decl (get_identifier ("size_t"), size_type_node); + set_sizetype (size_type_node); + + build_common_tree_nodes_2 (/* short_double= */ 0); + + tree_push_atomic_type_decl (get_identifier ("float"), float_type_node); + tree_push_atomic_type_decl (get_identifier ("double"), double_type_node); + tree_push_atomic_type_decl (get_identifier ("long double"), long_double_type_node); + tree_push_atomic_type_decl (get_identifier ("void"), void_type_node); + + /* Add any target-specific builtin functions. */ + (*targetm.init_builtins) (); + + pedantic_lvalues = pedantic; } -/* Save typing debug_tree all the time. Dump a tree T pretty and - concise. */ +/* Return a definition for a builtin function named NAME and whose data type + is TYPE. TYPE should be a function type with argument types. + FUNCTION_CODE tells later passes how to compile calls to this function. + See tree.h for its possible values. -void dt (tree t); + If LIBRARY_NAME is nonzero, use that for DECL_ASSEMBLER_NAME, + the name to be called if we can't opencode the function. If + ATTRS is nonzero, use that for the function's attribute list. -void -dt (tree t) -{ - debug_tree (t); -} - -/* Get a stringpool entry for a string S of length L. This is needed - because the GTY routines don't mark strings, forcing you to put - them into stringpool, which is never freed. */ + copied from gcc/c-decl.c +*/ -const char* -get_string (const char *s, size_t l) +tree +builtin_function (name, type, function_code, class, library_name, attrs) + const char *name; + tree type; + int function_code; + enum built_in_class class; + const char *library_name; + tree attrs; { - tree t; - t = get_identifier_with_length (s, l); - return IDENTIFIER_POINTER(t); + tree decl = build_decl (FUNCTION_DECL, get_identifier (name), type); + DECL_EXTERNAL (decl) = 1; + TREE_PUBLIC (decl) = 1; + if (library_name) + SET_DECL_ASSEMBLER_NAME (decl, get_identifier (library_name)); + make_decl_rtl (decl, NULL); + pushdecl (decl); + DECL_BUILT_IN_CLASS (decl) = class; + DECL_FUNCTION_CODE (decl) = function_code; + + /* Possibly apply some default attributes to this built-in function. */ + if (attrs) + decl_attributes (&decl, attrs, ATTR_FLAG_BUILT_IN); + else + decl_attributes (&decl, NULL_TREE, 0); + + return decl; } +#include "debug.h" /* for debug_hooks, needed by gt-treelang-treetree.h */ +#include "gt-treelang-treetree.h" -- 2.30.2