Commit 31c56a8b by Fergus Henderson Committed by Jim Wilson

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 <steven@gcc.gnu.org>

From-SVN: r69178
parent cde63840
2003-07-10 Fergus Henderson <fjh@cs.mu.oz.au>
Steven Bosscher <steven@gcc.gnu.org>
* 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 <nathan@codesourcery.com> 2003-07-07 Nathan Sidwell <nathan@codesourcery.com>
* treelang/treetree.c (tree_code_if_start, tree_code_if_else, * treelang/treetree.c (tree_code_if_start, tree_code_if_else,
......
...@@ -47,7 +47,9 @@ TREELANGSED = sed ...@@ -47,7 +47,9 @@ TREELANGSED = sed
TREELANGSEDFLAGS = -n TREELANGSEDFLAGS = -n
# back end compiler libraries etc # 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 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. # ./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 ...@@ -56,10 +58,9 @@ GCC_EXTRAS = -B./ -B$(build_tooldir)/bin/ -isystem $(build_tooldir)/include
# GCC_FOR_TREELANG = ./xgcc $(GCC_EXTRAS) # GCC_FOR_TREELANG = ./xgcc $(GCC_EXTRAS)
TREE_GENERATED = $(srcdir)/treelang/lex.c $(srcdir)/treelang/parse.c\ TREE_GENERATED = $(srcdir)/treelang/lex.c $(srcdir)/treelang/parse.c \
$(srcdir)/treelang/parse.h $(srcdir)/treelang/parse.output $(srcdir)/treelang/TAGS $(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_EXES = tree1$(exeext) TREE_EXES = tree1$(exeext)
...@@ -83,13 +84,13 @@ treelang.done: tree1$(exeext) ...@@ -83,13 +84,13 @@ treelang.done: tree1$(exeext)
# no preprocessor # no preprocessor
# core compiler # core compiler
tree1$(exeext): treelang/tree1.o treelang/treetree.o treelang/lex.o treelang/parse.o\ tree1$(exeext): treelang/tree1.o treelang/treetree.o treelang/tree-convert.o \
$(TREE_BE_LIBS) c-convert.o c-typeck.o c-common.o c-cppbuiltin.o \ treelang/lex.o treelang/parse.o \
c-decl.o attribs.o $(TREE_BE_LIBS) attribs.o
$(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ \ $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ \
treelang/tree1.o treelang/treetree.o treelang/lex.o treelang/parse.o \ treelang/tree1.o treelang/treetree.o treelang/tree-convert.o \
c-convert.o c-typeck.o c-common.o c-cppbuiltin.o c-decl.o attribs.o \ treelang/lex.o treelang/parse.o \
$(TREE_BE_LIBS) $(TREE_BE_LIBS) attribs.o
# #
# Compiling object files from source files. # Compiling object files from source files.
...@@ -106,6 +107,9 @@ treelang/treetree.o: treelang/treetree.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ ...@@ -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 \ varray.h $(LANGHOOKS_DEF_H) langhooks.h treelang/treelang.h input.h \
treelang/treetree.h treelang/parse.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 \ treelang/parse.o: treelang/parse.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(TM_H) diagnostic.h treelang/treelang.h input.h treelang/treetree.h $(TM_H) diagnostic.h treelang/treelang.h input.h treelang/treetree.h
...@@ -314,9 +318,6 @@ treelang.check.fix: force ...@@ -314,9 +318,6 @@ treelang.check.fix: force
-cp testsuite/treelang/*runpgm* t -cp testsuite/treelang/*runpgm* t
-rm -f t/*nofilename -rm -f t/*nofilename
treelang.wc: force
wc ${TREE_SOURCE}
# #
.PHONY: treelang.html .PHONY: treelang.html
...@@ -324,3 +325,5 @@ treelang.wc: force ...@@ -324,3 +325,5 @@ treelang.wc: force
treelang.html: treelang.html:
cd $(srcdir)/treelang && texi2html -I ../doc/include -verbose -menu -split_chapter -number treelang.texi cd $(srcdir)/treelang && texi2html -I ../doc/include -verbose -menu -split_chapter -number treelang.texi
# mv treelang*.html $(srcdir)/treelang # mv treelang*.html $(srcdir)/treelang
config.status: treelang/config-lang.in
...@@ -36,4 +36,4 @@ diff_excludes="-x lex.c -x parse.c -x parse.h" ...@@ -36,4 +36,4 @@ diff_excludes="-x lex.c -x parse.c -x parse.h"
headers= headers=
build_by_default="no" 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"
/* 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;
}
...@@ -63,13 +63,13 @@ ...@@ -63,13 +63,13 @@
#include "tree.h" #include "tree.h"
#include "flags.h" #include "flags.h"
#include "output.h" #include "output.h"
#include "c-tree.h"
#include "rtl.h" #include "rtl.h"
#include "ggc.h" #include "ggc.h"
#include "toplev.h" #include "toplev.h"
#include "varray.h" #include "varray.h"
#include "langhooks-def.h" #include "langhooks-def.h"
#include "langhooks.h" #include "langhooks.h"
#include "target.h"
#include "treelang.h" #include "treelang.h"
#include "treetree.h" #include "treetree.h"
...@@ -78,31 +78,94 @@ ...@@ -78,31 +78,94 @@
extern int option_main; extern int option_main;
extern char **file_names; 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 /* 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 #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 #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 #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 #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 #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 #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 #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 #undef LANG_HOOKS_PARSE_FILE
#define LANG_HOOKS_PARSE_FILE treelang_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. */ /* Hook routines and data unique to treelang. */
...@@ -805,483 +868,571 @@ tree_code_get_numeric_type (unsigned int size1, unsigned int sign1) ...@@ -805,483 +868,571 @@ tree_code_get_numeric_type (unsigned int size1, unsigned int sign1)
return ret1; return ret1;
} }
/* Garbage Collection. */ /* 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
/* Callback to mark storage M as used always. */ them into stringpool, which is never freed. */
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. */
tree const char*
lookup_objc_ivar (tree id ATTRIBUTE_UNUSED) 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. */ void dt (tree t);
tree
objc_is_id (tree arg ATTRIBUTE_UNUSED)
{
return 0;
}
void void
check_function_format (int *status ATTRIBUTE_UNUSED, dt (tree t)
tree attrs ATTRIBUTE_UNUSED,
tree params ATTRIBUTE_UNUSED)
{ {
return; debug_tree (t);
} }
/* Tell the c code we are not objective C. */ /* Routines Expected by gcc: */
int /* These are used to build types for various sizes. The code below
objc_comptypes (tree lhs ATTRIBUTE_UNUSED, is a simplified version of that of GNAT. */
tree rhs ATTRIBUTE_UNUSED,
int reflexive ATTRIBUTE_UNUSED)
{
return 0;
}
/* 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 /* XXX is this definition OK? */
c_lex (tree *value ATTRIBUTE_UNUSED) 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 static bool
build_stmt (enum tree_code code ATTRIBUTE_UNUSED, ...) 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. */ /* Return an integer type with the number of bits of precision given by
PRECISION. UNSIGNEDP is nonzero if the type is unsigned; otherwise
tree it is a signed type. */
add_stmt (tree t ATTRIBUTE_UNUSED)
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 if (unsignedp)
build_return_stmt (tree expr ATTRIBUTE_UNUSED) t = signed_and_unsigned_types[precision][1]
{ = make_unsigned_type (precision);
abort (); 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 static tree
pedwarn_c99 (const char *msgid ATTRIBUTE_UNUSED, ...) 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 static tree
build_case_label (tree low_value ATTRIBUTE_UNUSED, tree_lang_unsigned_type (type_node)
tree high_value ATTRIBUTE_UNUSED, tree type_node;
tree label_decl ATTRIBUTE_UNUSED)
{ {
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 static tree
emit_local_var (tree decl ATTRIBUTE_UNUSED) 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 static tree
expand_stmt (tree t ATTRIBUTE_UNUSED) 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 * the global one
cpp_create_reader (enum c_lang lang ATTRIBUTE_UNUSED, one for each subprogram definition
struct ht *table ATTRIBUTE_UNUSED) one for each compound statement (declare block)
{
abort ();
}
/* Should not be called for treelang. */ Binding contours are used to create GCC tree BLOCK nodes. */
void struct binding_level
init_c_lex (void)
{ {
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 /* Binding level structures are initialized by copying this one. */
init_pragma () static struct binding_level clear_binding_level = {NULL, NULL, NULL, NULL};
{
abort (); /* Return non-zero if we are currently in the global binding level. */
}
/* Should not be called for treelang. */
int int
cpp_finish (cpp_reader *pfile ATTRIBUTE_UNUSED, FILE *f ATTRIBUTE_UNUSED) global_bindings_p ()
{
abort ();
}
/* Should not be called for treelang. */
unsigned int
cpp_errors (cpp_reader *pfile ATTRIBUTE_UNUSED)
{ {
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 tree
handle_format_attribute (tree *node ATTRIBUTE_UNUSED, getdecls ()
tree name ATTRIBUTE_UNUSED,
tree args ATTRIBUTE_UNUSED,
int flags ATTRIBUTE_UNUSED,
bool *no_add_attrs ATTRIBUTE_UNUSED)
{ {
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 int
handle_format_arg_attribute (tree *node ATTRIBUTE_UNUSED, kept_level_p ()
tree name ATTRIBUTE_UNUSED,
tree args ATTRIBUTE_UNUSED,
int flags ATTRIBUTE_UNUSED,
bool *no_add_attrs ATTRIBUTE_UNUSED)
{ {
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 void
cpp_assert (cpp_reader * cr ATTRIBUTE_UNUSED, pushlevel (ignore)
const char *s ATTRIBUTE_UNUSED) 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 /* Add this level to the front of the chain (stack) of levels that are
set_Wformat (int setting ATTRIBUTE_UNUSED) active. */
{ newlevel->level_chain = current_binding_level;
abort (); 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 If KEEP is nonzero, this level had explicit declarations, so
objc_check_decl (tree decl ATTRIBUTE_UNUSED); and create a "block" (a BLOCK node) for the level
to record its declarations and subblocks for symbol table output.
void If FUNCTIONBODY is nonzero, this level is the body of a function,
objc_check_decl (tree decl ATTRIBUTE_UNUSED) so create a block as if KEEP were set and also clear out all
{ label names.
abort ();
}
/* 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 tree
objc_message_selector (void); poplevel (keep, reverse, functionbody)
int keep;
tree int reverse;
objc_message_selector () int functionbody;
{ {
return 0; /* 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. */
/* Should not be called for treelang. */ tree block_node = NULL_TREE;
tree decl_chain;
void tree subblock_chain = current_binding_level->blocks;
gen_aux_info_record (tree fndecl ATTRIBUTE_UNUSED, tree subblock_node;
int is_definition ATTRIBUTE_UNUSED, tree block_created_by_back_end;
int is_implicit ATTRIBUTE_UNUSED,
int is_prototyped ATTRIBUTE_UNUSED) /* Reverse the list of *_DECL nodes if desired. Note that the ..._DECL
{ nodes chained through the `names' field of current_binding_level are in
abort (); 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 /* If we did not make a block for the level just exited, any blocks made for
c_parse_init () inner levels (since they cannot be recorded as subblocks in that level)
{ must be carried forward so they will later become subblocks of something
return; 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. */ /* Insert BLOCK at the end of the list of subblocks of the
current binding level. This is used when a BIND_EXPR is expanded,
void maybe_apply_pragma_weak (tree decl); to handle the BLOCK node inside the BIND_EXPR. */
void 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 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. */ /* Records a ..._DECL node DECL as belonging to the current lexical scope.
Returns the ..._DECL node. */
tree
maybe_apply_renaming_pragma (tree decl, tree asmname);
/* Should not be called for treelang. */
tree 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 TREE_CHAIN (decl) = current_binding_level->names;
begin_stmt_tree (tree *t ATTRIBUTE_UNUSED) current_binding_level->names = decl;
{
abort ();
}
/* Should not be called for treelang. */ /* For the declartion of a type, set its name if it is not already set. */
void if (TREE_CODE (decl) == TYPE_DECL
finish_stmt_tree (tree *t ATTRIBUTE_UNUSED) && TYPE_NAME (TREE_TYPE (decl)) == 0)
{ TYPE_NAME (TREE_TYPE (decl)) = DECL_NAME (decl);
abort ();
}
/* Should not be called for treelang. */ return decl;
int
defer_fn (tree fn ATTRIBUTE_UNUSED)
{
abort ();
} }
/* Should not be called for treelang. */ static void
tree_push_type_decl(id, type_node)
cpp_options tree id;
*cpp_get_options (cpp_reader * cr ATTRIBUTE_UNUSED) 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 static void
cpp_define (cpp_reader * cr ATTRIBUTE_UNUSED, const char * c ATTRIBUTE_UNUSED) 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. */ #define NULL_BINDING_LEVEL (struct binding_level *) NULL
cpp_callbacks *
cpp_get_callbacks (cpp_reader * cr ATTRIBUTE_UNUSED)
{
abort ();
}
/* Create the predefined scalar types of C, /* Create the predefined scalar types of C,
and some nodes representing standard constants (0, 1, (void *) 0). and some nodes representing standard constants (0, 1, (void *) 0).
Initialize the global binding level. Initialize the global binding level.
Make definitions for built-in primitive functions. */ 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 void
treelang_init_decl_processing () treelang_init_decl_processing ()
{ {
unsigned int i; current_function_decl = NULL;
tree id; current_binding_level = NULL_BINDING_LEVEL;
pushlevel (0); /* make the binding_level structure for global names */
ridpointers = (tree *) ggc_calloc ((int) RID_MAX, sizeof (tree)); global_binding_level = current_binding_level;
for (i = 0; i < N_reswords; i++) build_common_tree_nodes (flag_signed_char);
{
id = get_identifier (reswords[i].word); /* set standard type names */
C_RID_CODE (id) = reswords[i].rid;
C_IS_RESERVED_WORD (id) = 1; /* Define `int' and `char' first so that dbx will output them first. */
ridpointers [(int) reswords[i].rid] = id;
} tree_push_atomic_type_decl (get_identifier ("int"), integer_type_node);
tree_push_atomic_type_decl (get_identifier ("char"), char_type_node);
c_init_decl_processing (); tree_push_atomic_type_decl (get_identifier ("long int"),
long_integer_type_node);
/* ix86_return_pops_args takes the type of these so need to patch tree_push_atomic_type_decl (get_identifier ("unsigned int"),
their own type as themselves. */ unsigned_type_node);
tree_push_atomic_type_decl (get_identifier ("long unsigned int"),
for (i = 0; i < itk_none; i++) long_unsigned_type_node);
{ tree_push_atomic_type_decl (get_identifier ("long long int"),
if (integer_types[i]) long_long_integer_type_node);
TREE_TYPE (integer_types [i]) = integer_types[i]; 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"),
/* Probably these ones too. */ short_integer_type_node);
TREE_TYPE (float_type_node) = float_type_node; tree_push_atomic_type_decl (get_identifier ("short unsigned int"),
TREE_TYPE (double_type_node) = double_type_node; short_unsigned_type_node);
TREE_TYPE (long_double_type_node) = long_double_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 /* Return a definition for a builtin function named NAME and whose data type
concise. */ 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 copied from gcc/c-decl.c
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. */
const char* tree
get_string (const char *s, size_t l) 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; tree decl = build_decl (FUNCTION_DECL, get_identifier (name), type);
t = get_identifier_with_length (s, l); DECL_EXTERNAL (decl) = 1;
return IDENTIFIER_POINTER(t); 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"
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment