Article View: gnu.gcc.help
Article #42245Re: Writing a new front-end for the gcc code generation
From: Fergus Henderson
Date: Thu, 04 Jan 1996 00:00
Date: Thu, 04 Jan 1996 00:00
2006 lines
58403 bytes
58403 bytes
Nicora William <wnicora@is2.ulb.ac.be> writes:
>I would like to write a gcc front-end for an OO language developed at my
>university.
>
>Does anybody know where to find documentation and wich support can be
>obtained from GNU ??
There is not a lot of documentation around. Richard Kenner
<kenner@vlsi1.ultra.nyu.edu> has an example of a "toy" front-end that
you can use to start with. Here's a copy - but it may require
some tweaking to work with recent versions of gcc. You could try
asking Richard Kenner if he has a more recent version of it.
From Mon Jun 19 21:02:18 1995
Received: from VLSI1.ULTRA.NYU.EDU by mulga.cs.mu.OZ.AU with SMTP (5.83--+1.3.1+0.50); id AA28373
Mon, 19 Jun 1995 21:02:18 +1000 (from kenner@vlsi1.ultra.nyu.edu)
Return-Path: <kenner@vlsi1.ultra.nyu.edu>
Received: by vlsi1.ultra.nyu.edu (5.61/1.34)
id AA08221; Mon, 19 Jun 95 07:02:35 -0400
Date: Mon, 19 Jun 95 07:02:35 -0400
From: kenner@vlsi1.ultra.nyu.edu (Richard Kenner)
Message-Id: <9506191102.AA08221@vlsi1.ultra.nyu.edu>
#!/bin/sh
# This is a shell archive (shar 3.43)
# made 06/07/1995 14:36 UTC by kenner@vlsi1
# Source directory /g/gcc/gcc2/toy
#
# existing files will NOT be overwritten unless -c is specified
#
# This shar contains:
# length mode name
# ------ ---------- ------------------------------------------
# 2015 -rw-rw-r-- Make-lang.in
# 5373 -rw-rw-r-- Makefile.in
# 447 -rw-rw-r-- config-lang.in
# 22030 -rw-rw-r-- parse.c
# 1713 -rw-rw-r-- parse.y
# 19095 -rw-rw-r-- toy.c
#
# ============= Make-lang.in ==============
if test -f 'Make-lang.in' -a X"$1" != X"-c"; then
echo 'x - skipping Make-lang.in (File already exists)'
else
echo 'x - extracting Make-lang.in (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'Make-lang.in' &&
# Each language makefile fragment must provide the following targets:
#
# foo.all.build, foo.all.cross, foo.start.encap, foo.rest.encap,
# foo.info, foo.dvi,
# foo.install-normal, foo.install-common, foo.install-info, foo.install-man,
# foo.uninstall, foo.distdir,
# foo.mostlyclean, foo.clean, foo.distclean, foo.extraclean, foo.realclean,
# foo.stage1, foo.stage2, foo.stage3, foo.stage4
#
# where `foo' is the name of the language.
#
# It should also provide rules for:
#
# - making any compiler driver (eg: g++)
# - the compiler proper (eg: cc1plus)
# - define the names for selecting the language in LANGUAGES.
X
X
X
# Extra flags to pass to recursive makes.
TOY_FLAGS_TO_PASS = \
X "TOY_FOR_BUILD=$(TOY_FOR_BUILD)" \
X "TOYFLAGS=$(TOYFLAGS)" \
X "TOY_FOR_TARGET=$(TOY_FOR_TARGET)"
X
TOY_SRCS = $(srcdir)/toy/parse.y $(srcdir)/toy/toy.c
X
toy: cc1toy
X
cc1toy: $(LIBDEPS) stamp-objlist $(TOY_SRCS)
X cd toy; $(MAKE) $(FLAGS_TO_PASS) $(TOY_FLAGS_TO_PASS) ../cc1toy
X
X
# Build hooks:
X
toy.all.build:
toy.all.cross:
toy.start.encap:
toy.rest.encap:
toy.info:
toy.dvi:
X
X
# Install hooks:
# cc1toy is installed elsewhere as part of $(COMPILERS).
X
toy.install-normal:
toy.install-common:
toy.install-info:
toy.install-man:
X
toy.uninstall:
X
X
# Clean hooks:
# A lot of the ancillary files are deleted by the main makefile.
# We just have to delete files specific to us.
X
toy.mostlyclean:
X -rm -f toy/*.o
toy.clean:
toy.distclean:
X -rm -f toy/Makefile
toy.extraclean:
toy.realclean:
X -rm -f toy/parse.c
X
X
# Stage hooks:
# The main makefile has already created stage?/toy
X
toy.stage1:
X -mv toy/*.o stage1/toy
toy.stage2:
X -mv toy/*.o stage2/toy
toy.stage3:
X -mv toy/*.o stage3/toy
toy.stage4:
X -mv toy/*.o stage4/toy
X
X
# Maintenance hooks:
X
# This target creates the files that can be rebuilt, but go in the
# distribution anyway. It then copies the files to the distdir directory.
toy.distdir:
X mdkdir tmp/toy
X cd toy; \
X for file in *[0-9a-zA-Z+]; do \
X ln $$file ../tmp/toy >/dev/null 2>&1 || cp $$file ../tmp/toy; \
X done
SHAR_EOF
chmod 0664 Make-lang.in ||
echo 'restore of Make-lang.in failed'
Wc_c="`wc -c < 'Make-lang.in'`"
test 2015 -eq "$Wc_c" ||
echo 'Make-lang.in: original size 2015, current size' "$Wc_c"
fi
# ============= Makefile.in ==============
if test -f 'Makefile.in' -a X"$1" != X"-c"; then
echo 'x - skipping Makefile.in (File already exists)'
else
echo 'x - extracting Makefile.in (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'Makefile.in' &&
# The makefile built from this file lives in the language subdirectory.
# It's purpose is to provide support for:
#
# 1) recursion where necessary, and only then (building .o's), and
# 2) building and debugging cc1 from the language subdirectory, and
# 3) nothing else.
#
# The parent makefile handles all other chores, with help from the
# language makefile fragment, of course.
#
# The targets for external use are:
# all, TAGS, ???mostlyclean, ???clean.
X
# Suppress smart makes who think they know how to automake Yacc files
.y.c:
X
# Variables that exist for you to override.
# See below for how to change them for certain systems.
X
ALLOCA =
X
# Various ways of specifying flags for compilations:
# CFLAGS is for the user to override to, e.g., do a bootstrap with -O2.
# BOOT_CFLAGS is the value of CFLAGS to pass
# to the stage2 and stage3 compilations
# XCFLAGS is used for most compilations but not when using the GCC just built.
XXCFLAGS =
CFLAGS = -g
BOOT_CFLAGS = -O $(CFLAGS)
# These exists to be overridden by the x-* and t-* files, respectively.
XX_CFLAGS =
T_CFLAGS =
X
XX_CPPFLAGS =
T_CPPFLAGS =
X
CC = cc
BISON = bison
BISONFLAGS =
LEX = flex
LEXFLAGS =
AR = ar
AR_FLAGS = rc
SHELL = /bin/sh
MAKEINFO = makeinfo
TEXI2DVI = texi2dvi
X
# Define this as & to perform parallel make on a Sequent.
# Note that this has some bugs, and it seems currently necessary
# to compile all the gen* files first by hand to avoid erroneous results.
P =
X
# This is used in the definition of SUBDIR_USE_ALLOCA.
# ??? Perhaps it would be better if it just looked for *gcc*.
OLDCC = cc
X
# This is used instead of ALL_CFLAGS when compiling with GCC_FOR_TARGET.
# It omits XCFLAGS, and specifies -B./.
# It also specifies -B$(tooldir)/ to find as and ld for a cross compiler.
GCC_CFLAGS=$(INTERNAL_CFLAGS) $(X_CFLAGS) $(T_CFLAGS) $(CFLAGS)
X
# Tools to use when building a cross-compiler.
# These are used because `configure' appends `cross-make'
# to the makefile when making a cross-compiler.
X
target= ... `configure' substitutes actual target name here.
xmake_file= ... `configure' substitutes actual x- file name here.
tmake_file= ... `configure' substitutes actual t- file name here.
#version=`sed -e 's/.*\"\([^ \"]*\)[ \"].*/\1/' < $(srcdir)/version.c`
#mainversion=`sed -e 's/.*\"\([0-9]*\.[0-9]*\).*/\1/' < $(srcdir)/version.c`
X
# Directory where sources are, from where we are.
srcdir = .
X
# Additional system libraries to link with.
CLIB=
X
# Change this to a null string if obstacks are installed in the
# system library.
OBSTACK=obstack.o
X
# Choose the real default target.
ALL=all
X
# End of variables for you to override.
X
# Definition of `all' is here so that new rules inserted by sed
# do not specify the default target.
all: all.indirect
X
# This tells GNU Make version 3 not to put all variables in the environment.
.NOEXPORT:
X
# sed inserts variable overrides after the following line.
####target overrides
####host overrides
####cross overrides
####build overrides
X
X
# Now figure out from those variables how to compile and link.
X
all.indirect: Makefile ../cc1toy
X
# IN_GCC tells obstack.h that we are using gcc's <stddef.h> file.
INTERNAL_CFLAGS = $(CROSS) -DIN_GCC
X
# This is the variable actually used when we compile.
ALL_CFLAGS = $(INTERNAL_CFLAGS) $(X_CFLAGS) $(T_CFLAGS) $(CFLAGS) $(XCFLAGS)
X
# Likewise.
ALL_CPPFLAGS = $(CPPFLAGS) $(X_CPPFLAGS) $(T_CPPFLAGS)
X
# Even if ALLOCA is set, don't use it if compiling with GCC.
X
SUBDIR_OBSTACK = `if [ x$(OBSTACK) != x ]; then echo ../$(OBSTACK); else true; fi`
SUBDIR_USE_ALLOCA = `case "${CC}" in "${OLDCC}") if [ x$(ALLOCA) != x ]; then echo ../$(ALLOCA); else true; fi ;; esac`
SUBDIR_MALLOC = `if [ x$(MALLOC) != x ]; then echo ../$(MALLOC); else true; fi`
X
# How to link with both our special library facilities
# and the system's installed libraries.
LIBS = $(SUBDIR_OBSTACK) $(SUBDIR_USE_ALLOCA) $(SUBDIR_MALLOC) $(CLIB)
X
# Specify the directories to be searched for header files.
# Both . and srcdir are used, in that order,
# so that tm.h and config.h will be found in the compilation
# subdirectory rather than in the source directory.
INCLUDES = -I. -I.. -I$(srcdir) -I$(srcdir)/.. -I$(srcdir)/../config
X
# Always use -I$(srcdir)/config when compiling.
.c.o:
X $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
X
# This tells GNU make version 3 not to export all the variables
# defined in this file into the environment.
.NOEXPORT:
X
X
# Lists of files for various purposes.
X
# Language-specific object files for our toy compiler.
X
TOY_OBJS = parse.o toy.o
X
# Language-independent object files.
OBJS = `cat ../stamp-objlist` ../c-convert.o
OBJDEPS = ../stamp-objlist ../c-convert.o
X
compiler: ../cc1toy
../cc1toy: $(P) $(TOY_OBJS) $(OBJDEPS) $(LIBDEPS)
X $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o ../cc1toy \
X $(TOY_OBJS) $(OBJS) $(LIBS)
X
Makefile: $(srcdir)/Makefile.in $(srcdir)/../configure
X cd ..; $(SHELL) config.status
X
native: config.status ../cc1toy
X
# Compiling object files from source files.
X
# Note that dependencies on obstack.h are not written
# because that file is not part of GCC.
X
TREE_H = $(srcdir)/../tree.h $(srcdir)/../real.h $(srcdir)/../tree.def \
X $(srcdir)/../machmode.h $(srcdir)/../machmode.def
X
parse.o : parse.c $(CONFIG_H) $(TREE_H)
X
$(srcdir)/parse.c: $(srcdir)/parse.y
X cd $(srcdir); $(BISON) $(BISONFLAGS) -o parse.c parse.y
X
toy.o : toy.c $(CONFIG_H) $(TREE_H) ../flags.h
SHAR_EOF
chmod 0664 Makefile.in ||
echo 'restore of Makefile.in failed'
Wc_c="`wc -c < 'Makefile.in'`"
test 5373 -eq "$Wc_c" ||
echo 'Makefile.in: original size 5373, current size' "$Wc_c"
fi
# ============= config-lang.in ==============
if test -f 'config-lang.in' -a X"$1" != X"-c"; then
echo 'x - skipping config-lang.in (File already exists)'
else
echo 'x - extracting config-lang.in (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'config-lang.in' &&
# Configure looks for the existence of this file to auto-config each language.
# We define several parameters used by configure:
#
# language - name of language as it would appear in $(LANGUAGES)
# compilers - value to add to $(COMPILERS)
# stagestuff - files to add to $(STAGESTUFF)
# diff_excludes - files to ignore when building diffs between two versions.
X
language="toy"
X
compilers="cc1toy"
X
stagestuff="cc1toy"
X
diff_excludes="-x parse.c"
X
X
SHAR_EOF
chmod 0664 config-lang.in ||
echo 'restore of config-lang.in failed'
Wc_c="`wc -c < 'config-lang.in'`"
test 447 -eq "$Wc_c" ||
echo 'config-lang.in: original size 447, current size' "$Wc_c"
fi
# ============= parse.c ==============
if test -f 'parse.c' -a X"$1" != X"-c"; then
echo 'x - skipping parse.c (File already exists)'
else
echo 'x - extracting parse.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'parse.c' &&
X
/* A Bison parser, made from parse.y with Bison version GNU Bison version 1.22
X */
X
#define YYBISON 1 /* Identify Bison output. */
X
#define NUM 258
#define NAME 259
X
#line 3 "parse.y"
X
#include "config.h"
#include "tree.h"
X
extern void build_function PROTO((tree, tree));
extern tree build_function_decl PROTO((char, int));
extern tree get_arg_decl PROTO((int));
X
#line 12 "parse.y"
typedef union {
tree exp; /* Tree node representing value. */
int ival; /* Integer value for constant or arg */
char character; /* Name of function */
} YYSTYPE;
X
#ifndef YYLTYPE
typedef
X struct yyltype
X {
X int timestamp;
X int first_line;
X int first_column;
X int last_line;
X int last_column;
X char *text;
X }
X yyltype;
X
#define YYLTYPE yyltype
#endif
X
#include <stdio.h>
X
#ifndef __cplusplus
#ifndef __STDC__
#define const
#endif
#endif
X
X
X
#define YYFINAL 28
#define YYFLAG -32768
#define YYNTBASE 14
X
#define YYTRANSLATE(x) ((unsigned)(x) <= 259 ? yytranslate[x] : 18)
X
static const char yytranslate[] = { 0,
X 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
X 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
X 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
X 2, 2, 2, 2, 2, 13, 2, 2, 2, 11,
X 12, 7, 6, 2, 5, 2, 8, 2, 2, 2,
X 2, 2, 2, 2, 2, 2, 2, 9, 10, 2,
X 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
X 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
X 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
X 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
X 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
X 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
X 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
X 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
X 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
X 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
X 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
X 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
X 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
X 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
X 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
X 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
X 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
X 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
X 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
X 2, 2, 2, 2, 2, 1, 2, 3, 4
};
X
#if YYDEBUG != 0
static const short yyprhs[] = { 0,
X 0, 1, 4, 6, 11, 16, 18, 21, 25, 29,
X 33, 37, 41
};
X
static const short yyrhs[] = { -1,
X 14, 15, 0, 1, 0, 16, 9, 17, 10, 0,
X 4, 11, 3, 12, 0, 3, 0, 13, 3, 0,
X 17, 6, 17, 0, 17, 5, 17, 0, 17, 7,
X 17, 0, 17, 8, 17, 0, 11, 17, 12, 0,
X 1, 0
};
X
#endif
X
#if YYDEBUG != 0
static const short yyrline[] = { 0,
X 28, 29, 30, 32, 34, 36, 37, 38, 39, 40,
X 41, 42, 43
};
X
static const char * const yytname[] = { "$","error","$illegal.","NUM","NAME",
"'-'","'+'","'*'","'/'","':'","';'","'('","')'","'$'","input","function","fndef",
"exp",""
};
#endif
X
static const short yyr1[] = { 0,
X 14, 14, 14, 15, 16, 17, 17, 17, 17, 17,
X 17, 17, 17
};
X
static const short yyr2[] = { 0,
X 0, 2, 1, 4, 4, 1, 2, 3, 3, 3,
X 3, 3, 1
};
X
static const short yydefact[] = { 0,
X 3, 0, 0, 2, 0, 0, 0, 0, 13, 6,
X 0, 0, 0, 5, 0, 7, 0, 0, 0, 0,
X 4, 12, 9, 8, 10, 11, 0, 0
};
X
static const short yydefgoto[] = { 2,
X 4, 5, 13
};
X
static const short yypact[] = { 21,
-32768, 23, -10,-32768, 0, 8, -1, 14,-32768,-32768,
X -1, 25, -2,-32768, 12,-32768, -1, -1, -1, -1,
-32768,-32768, 22, 22,-32768,-32768, 31,-32768
};
X
static const short yypgoto[] = {-32768,
-32768,-32768, -4
};
X
X
#define YYLAST 31
X
X
static const short yytable[] = { 9,
X 6, 10, 17, 18, 19, 20, 15, 21, 7, 11,
X 8, 12, 23, 24, 25, 26, 17, 18, 19, 20,
X -1, 1, 27, 22, -1, 14, 3, 16, 19, 20,
X 28
};
X
static const short yycheck[] = { 1,
X 11, 3, 5, 6, 7, 8, 11, 10, 9, 11,
X 3, 13, 17, 18, 19, 20, 5, 6, 7, 8,
X 0, 1, 0, 12, 4, 12, 4, 3, 7, 8,
X 0
};
/* -*-C-*- Note some compilers choke on comments on `#line' lines. */
#line 3 "/usr/local/lib/bison.simple"
X
/* Skeleton output parser for bison,
X Copyright (C) 1984, 1989, 1990 Bob Corbett and Richard Stallman
X
X This program is free software; you can redistribute it and/or modify
X it under the terms of the GNU General Public License as published by
X the Free Software Foundation; either version 1, or (at your option)
X any later version.
X
X This program is distributed in the hope that it will be useful,
X but WITHOUT ANY WARRANTY; without even the implied warranty of
X MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
X GNU General Public License for more details.
X
X You should have received a copy of the GNU General Public License
X along with this program; if not, write to the Free Software
X Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
X
X
#ifndef alloca
#ifdef __GNUC__
#define alloca __builtin_alloca
#else /* not GNU C. */
#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__)
#include <alloca.h>
#else /* not sparc */
#if defined (MSDOS) && !defined (__TURBOC__)
#include <malloc.h>
#else /* not MSDOS, or __TURBOC__ */
#if defined(_AIX)
#include <malloc.h>
#pragma alloca
#endif /* not _AIX */
#endif /* not MSDOS, or __TURBOC__ */
#endif /* not sparc. */
#endif /* not GNU C. */
#endif /* alloca not defined. */
X
/* This is the parser code that is written into each bison parser
X when the %semantic_parser declaration is not specified in the grammar.
X It was written by Richard Stallman by simplifying the hairy parser
X used when %semantic_parser is specified. */
X
/* Note: there must be only one dollar sign in this file.
X It is replaced by the list of actions, each action
X as one case of the switch. */
X
#define yyerrok (yyerrstatus = 0)
#define yyclearin (yychar = YYEMPTY)
#define YYEMPTY -2
#define YYEOF 0
#define YYACCEPT return(0)
#define YYABORT return(1)
#define YYERROR goto yyerrlab1
/* Like YYERROR except do call yyerror.
X This remains here temporarily to ease the
X transition to the new meaning of YYERROR, for GCC.
X Once GCC version 2 has supplanted version 1, this can go. */
#define YYFAIL goto yyerrlab
#define YYRECOVERING() (!!yyerrstatus)
#define YYBACKUP(token, value) \
do \
X if (yychar == YYEMPTY && yylen == 1) \
X { yychar = (token), yylval = (value); \
X yychar1 = YYTRANSLATE (yychar); \
X YYPOPSTACK; \
X goto yybackup; \
X } \
X else \
X { yyerror ("syntax error: cannot back up"); YYERROR; } \
while (0)
X
#define YYTERROR 1
#define YYERRCODE 256
X
#ifndef YYPURE
#define YYLEX yylex()
#endif
X
#ifdef YYPURE
#ifdef YYLSP_NEEDED
#define YYLEX yylex(&yylval, &yylloc)
#else
#define YYLEX yylex(&yylval)
#endif
#endif
X
/* If nonreentrant, generate the variables here */
X
#ifndef YYPURE
X
int yychar; /* the lookahead symbol */
YYSTYPE yylval; /* the semantic value of the */
X /* lookahead symbol */
X
#ifdef YYLSP_NEEDED
YYLTYPE yylloc; /* location data for the lookahead */
X /* symbol */
#endif
X
int yynerrs; /* number of parse errors so far */
#endif /* not YYPURE */
X
#if YYDEBUG != 0
int yydebug; /* nonzero means print parse trace */
/* Since this is uninitialized, it does not stop multiple parsers
X from coexisting. */
#endif
X
/* YYINITDEPTH indicates the initial size of the parser's stacks */
X
#ifndef YYINITDEPTH
#define YYINITDEPTH 200
#endif
X
/* YYMAXDEPTH is the maximum size the stacks can grow to
X (effective only if the built-in stack extension method is used). */
X
#if YYMAXDEPTH == 0
#undef YYMAXDEPTH
#endif
X
#ifndef YYMAXDEPTH
#define YYMAXDEPTH 10000
#endif
X
#if __GNUC__ > 1 /* GNU C and GNU C++ define this. */
#define __yy_bcopy(FROM,TO,COUNT) __builtin_memcpy(TO,FROM,COUNT)
#else /* not GNU C or C++ */
#ifndef __cplusplus
X
/* This is the most reliable way to avoid incompatibilities
X in available built-in functions on various systems. */
static void
__yy_bcopy (from, to, count)
X char *from;
X char *to;
X int count;
{
X register char *f = from;
X register char *t = to;
X register int i = count;
X
X while (i-- > 0)
X *t++ = *f++;
}
X
#else /* __cplusplus */
X
/* This is the most reliable way to avoid incompatibilities
X in available built-in functions on various systems. */
static void
__yy_bcopy (char *from, char *to, int count)
{
X register char *f = from;
X register char *t = to;
X register int i = count;
X
X while (i-- > 0)
X *t++ = *f++;
}
X
#endif
#endif
X
#line 169 "/usr/local/lib/bison.simple"
int
yyparse()
{
X register int yystate;
X register int yyn;
X register short *yyssp;
X register YYSTYPE *yyvsp;
X int yyerrstatus; /* number of tokens to shift before error messages enabled */
X int yychar1; /* lookahead token as an internal (translated) token number */
X
X short yyssa[YYINITDEPTH]; /* the state stack */
X YYSTYPE yyvsa[YYINITDEPTH]; /* the semantic value stack */
X
X short *yyss = yyssa; /* refer to the stacks thru separate pointers */
X YYSTYPE *yyvs = yyvsa; /* to allow yyoverflow to reallocate them elsewhere */
X
#ifdef YYLSP_NEEDED
X YYLTYPE yylsa[YYINITDEPTH]; /* the location stack */
X YYLTYPE *yyls = yylsa;
X YYLTYPE *yylsp;
X
#define YYPOPSTACK (yyvsp--, yysp--, yylsp--)
#else
#define YYPOPSTACK (yyvsp--, yysp--)
#endif
X
X int yystacksize = YYINITDEPTH;
X
#ifdef YYPURE
X int yychar;
X YYSTYPE yylval;
X int yynerrs;
#ifdef YYLSP_NEEDED
X YYLTYPE yylloc;
#endif
#endif
X
X YYSTYPE yyval; /* the variable used to return */
X /* semantic values from the action */
X /* routines */
X
X int yylen;
X
#if YYDEBUG != 0
X if (yydebug)
X fprintf(stderr, "Starting parse\n");
#endif
X
X yystate = 0;
X yyerrstatus = 0;
X yynerrs = 0;
X yychar = YYEMPTY; /* Cause a token to be read. */
X
X /* Initialize stack pointers.
X Waste one element of value and location stack
X so that they stay on the same level as the state stack. */
X
X yyssp = yyss - 1;
X yyvsp = yyvs;
#ifdef YYLSP_NEEDED
X yylsp = yyls;
#endif
X
/* Push a new state, which is found in yystate . */
/* In all cases, when you get here, the value and location stacks
X have just been pushed. so pushing a state here evens the stacks. */
yynewstate:
X
X *++yyssp = yystate;
X
X if (yyssp >= yyss + yystacksize - 1)
X {
X /* Give user a chance to reallocate the stack */
X /* Use copies of these so that the &'s don't force the real ones into memory. */
X YYSTYPE *yyvs1 = yyvs;
X short *yyss1 = yyss;
#ifdef YYLSP_NEEDED
X YYLTYPE *yyls1 = yyls;
#endif
X
X /* Get the current used size of the three stacks, in elements. */
X int size = yyssp - yyss + 1;
X
#ifdef yyoverflow
X /* Each stack pointer address is followed by the size of
X the data in use in that stack, in bytes. */
X yyoverflow("parser stack overflow",
X &yyss1, size * sizeof (*yyssp),
X &yyvs1, size * sizeof (*yyvsp),
#ifdef YYLSP_NEEDED
X &yyls1, size * sizeof (*yylsp),
#endif
X &yystacksize);
X
X yyss = yyss1; yyvs = yyvs1;
#ifdef YYLSP_NEEDED
X yyls = yyls1;
#endif
#else /* no yyoverflow */
X /* Extend the stack our own way. */
X if (yystacksize >= YYMAXDEPTH)
X {
X yyerror("parser stack overflow");
X return 2;
X }
X yystacksize *= 2;
X if (yystacksize > YYMAXDEPTH)
X yystacksize = YYMAXDEPTH;
X yyss = (short *) alloca (yystacksize * sizeof (*yyssp));
X __yy_bcopy ((char *)yyss1, (char *)yyss, size * sizeof (*yyssp));
X yyvs = (YYSTYPE *) alloca (yystacksize * sizeof (*yyvsp));
X __yy_bcopy ((char *)yyvs1, (char *)yyvs, size * sizeof (*yyvsp));
#ifdef YYLSP_NEEDED
X yyls = (YYLTYPE *) alloca (yystacksize * sizeof (*yylsp));
X __yy_bcopy ((char *)yyls1, (char *)yyls, size * sizeof (*yylsp));
#endif
#endif /* no yyoverflow */
X
X yyssp = yyss + size - 1;
X yyvsp = yyvs + size - 1;
#ifdef YYLSP_NEEDED
X yylsp = yyls + size - 1;
#endif
X
#if YYDEBUG != 0
X if (yydebug)
X fprintf(stderr, "Stack size increased to %d\n", yystacksize);
#endif
X
X if (yyssp >= yyss + yystacksize - 1)
X YYABORT;
X }
X
#if YYDEBUG != 0
X if (yydebug)
X fprintf(stderr, "Entering state %d\n", yystate);
#endif
X
X yybackup:
X
/* Do appropriate processing given the current state. */
/* Read a lookahead token if we need one and don't already have one. */
/* yyresume: */
X
X /* First try to decide what to do without reference to lookahead token. */
X
X yyn = yypact[yystate];
X if (yyn == YYFLAG)
X goto yydefault;
X
X /* Not known => get a lookahead token if don't already have one. */
X
X /* yychar is either YYEMPTY or YYEOF
X or a valid token in external form. */
X
X if (yychar == YYEMPTY)
X {
#if YYDEBUG != 0
X if (yydebug)
X fprintf(stderr, "Reading a token: ");
#endif
X yychar = YYLEX;
X }
X
X /* Convert token to internal form (in yychar1) for indexing tables with */
X
X if (yychar <= 0) /* This means end of input. */
X {
X yychar1 = 0;
X yychar = YYEOF; /* Don't call YYLEX any more */
X
#if YYDEBUG != 0
X if (yydebug)
X fprintf(stderr, "Now at end of input.\n");
#endif
X }
X else
X {
X yychar1 = YYTRANSLATE(yychar);
X
#if YYDEBUG != 0
X if (yydebug)
X {
X fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]);
X /* Give the individual parser a way to print the precise meaning
X of a token, for further debugging info. */
#ifdef YYPRINT
X YYPRINT (stderr, yychar, yylval);
#endif
X fprintf (stderr, ")\n");
X }
#endif
X }
X
X yyn += yychar1;
X if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1)
X goto yydefault;
X
X yyn = yytable[yyn];
X
X /* yyn is what to do for this token type in this state.
X Negative => reduce, -yyn is rule number.
X Positive => shift, yyn is new state.
X New state is final state => don't bother to shift,
X just return success.
X 0, or most negative number => error. */
X
X if (yyn < 0)
X {
X if (yyn == YYFLAG)
X goto yyerrlab;
X yyn = -yyn;
X goto yyreduce;
X }
X else if (yyn == 0)
X goto yyerrlab;
X
X if (yyn == YYFINAL)
X YYACCEPT;
X
X /* Shift the lookahead token. */
X
#if YYDEBUG != 0
X if (yydebug)
X fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]);
#endif
X
X /* Discard the token being shifted unless it is eof. */
X if (yychar != YYEOF)
X yychar = YYEMPTY;
X
X *++yyvsp = yylval;
#ifdef YYLSP_NEEDED
X *++yylsp = yylloc;
#endif
X
X /* count tokens shifted since error; after three, turn off error status. */
X if (yyerrstatus) yyerrstatus--;
X
X yystate = yyn;
X goto yynewstate;
X
/* Do the default action for the current state. */
yydefault:
X
X yyn = yydefact[yystate];
X if (yyn == 0)
X goto yyerrlab;
X
/* Do a reduction. yyn is the number of a rule to reduce with. */
yyreduce:
X yylen = yyr2[yyn];
X yyval = yyvsp[1-yylen]; /* implement default value of the action */
X
#if YYDEBUG != 0
X if (yydebug)
X {
X int i;
X
X fprintf (stderr, "Reducing via rule %d (line %d), ",
X yyn, yyrline[yyn]);
X
X /* Print the symboles being reduced, and their result. */
X for (i = yyprhs[yyn]; yyrhs[i] > 0; i++)
X fprintf (stderr, "%s ", yytname[yyrhs[i]]);
X fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]);
X }
#endif
X
X
X switch (yyn) {
X
case 4:
#line 32 "parse.y"
{ build_function (yyvsp[-3].exp, yyvsp[-1].exp); ;
X break;}
case 5:
#line 34 "parse.y"
{ yyval.exp = build_function_decl (yyvsp[-3].character, yyvsp[-1].ival); ;
X break;}
case 6:
#line 36 "parse.y"
{ yyval.exp = build_int_2 (yyvsp[0].ival, yyvsp[0].ival >= 0 ? 0 : -1); ;
X break;}
case 7:
#line 37 "parse.y"
{ yyval.exp = get_arg_decl (yyvsp[0].ival); ;
X break;}
case 8:
#line 38 "parse.y"
{ yyval.exp = build (PLUS_EXPR, integer_type_node, yyvsp[-2].exp, yyvsp[0].exp); ;
X break;}
case 9:
#line 39 "parse.y"
{ yyval.exp = build (MINUS_EXPR, integer_type_node, yyvsp[-2].exp, yyvsp[0].exp); ;
X break;}
case 10:
#line 40 "parse.y"
{ yyval.exp = build (MULT_EXPR, integer_type_node, yyvsp[-2].exp, yyvsp[0].exp); ;
X break;}
case 11:
#line 41 "parse.y"
{ yyval.exp = build (TRUNC_DIV_EXPR, integer_type_node, yyvsp[-2].exp, yyvsp[0].exp); ;
X break;}
case 12:
#line 42 "parse.y"
{ yyval.exp = yyvsp[-1].exp; ;
X break;}
case 13:
#line 43 "parse.y"
{ yyval.exp = error_mark_node; ;
X break;}
}
X /* the action file gets copied in in place of this dollarsign */
#line 440 "/usr/local/lib/bison.simple"
X
X yyvsp -= yylen;
X yyssp -= yylen;
#ifdef YYLSP_NEEDED
X yylsp -= yylen;
#endif
X
#if YYDEBUG != 0
X if (yydebug)
X {
X short *ssp1 = yyss - 1;
X fprintf (stderr, "state stack now");
X while (ssp1 != yyssp)
X fprintf (stderr, " %d", *++ssp1);
X fprintf (stderr, "\n");
X }
#endif
X
X *++yyvsp = yyval;
X
#ifdef YYLSP_NEEDED
X yylsp++;
X if (yylen == 0)
X {
X yylsp->first_line = yylloc.first_line;
X yylsp->first_column = yylloc.first_column;
X yylsp->last_line = (yylsp-1)->last_line;
X yylsp->last_column = (yylsp-1)->last_column;
X yylsp->text = 0;
X }
X else
X {
X yylsp->last_line = (yylsp+yylen-1)->last_line;
X yylsp->last_column = (yylsp+yylen-1)->last_column;
X }
#endif
X
X /* Now "shift" the result of the reduction.
X Determine what state that goes to,
X based on the state we popped back to
X and the rule number reduced by. */
X
X yyn = yyr1[yyn];
X
X yystate = yypgoto[yyn - YYNTBASE] + *yyssp;
X if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp)
X yystate = yytable[yystate];
X else
X yystate = yydefgoto[yyn - YYNTBASE];
X
X goto yynewstate;
X
yyerrlab: /* here on detecting error */
X
X if (! yyerrstatus)
X /* If not already recovering from an error, report this error. */
X {
X ++yynerrs;
X
#ifdef YYERROR_VERBOSE
X yyn = yypact[yystate];
X
X if (yyn > YYFLAG && yyn < YYLAST)
X {
X int size = 0;
X char *msg;
X int x, count;
X
X count = 0;
X for (x = 0; x < (sizeof(yytname) / sizeof(char *)); x++)
X if (yycheck[x + yyn] == x)
X size += strlen(yytname[x]) + 15, count++;
X msg = (char *) xmalloc(size + 15);
X strcpy(msg, "parse error");
X
X if (count < 5)
X {
X count = 0;
X for (x = 0; x < (sizeof(yytname) / sizeof(char *)); x++)
X if (yycheck[x + yyn] == x)
X {
X strcat(msg, count == 0 ? ", expecting `" : " or `");
X strcat(msg, yytname[x]);
X strcat(msg, "'");
X count++;
X }
X }
X yyerror(msg);
X free(msg);
X }
X else
#endif /* YYERROR_VERBOSE */
X yyerror("parse error");
X }
X
yyerrlab1: /* here on error raised explicitly by an action */
X
X if (yyerrstatus == 3)
X {
X /* if just tried and failed to reuse lookahead token after an error, discard it. */
X
X /* return failure if at end of input */
X if (yychar == YYEOF)
X YYABORT;
X
#if YYDEBUG != 0
X if (yydebug)
X fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]);
#endif
X
X yychar = YYEMPTY;
X }
X
X /* Else will try to reuse lookahead token
X after shifting the error token. */
X
X yyerrstatus = 3; /* Each real token shifted decrements this */
X
X goto yyerrhandle;
X
yyerrdefault: /* current state does not do anything special for the error token. */
X
#if 0
X /* This is wrong; only states that explicitly want error tokens
X should shift them. */
X yyn = yydefact[yystate]; /* If its default is to accept any token, ok. Otherwise pop it.*/
X if (yyn) goto yydefault;
#endif
X
yyerrpop: /* pop the current state because it cannot handle the error token */
X
X if (yyssp == yyss) YYABORT;
X yyvsp--;
X yystate = *--yyssp;
#ifdef YYLSP_NEEDED
X yylsp--;
#endif
X
#if YYDEBUG != 0
X if (yydebug)
X {
X short *ssp1 = yyss - 1;
X fprintf (stderr, "Error: state stack now");
X while (ssp1 != yyssp)
X fprintf (stderr, " %d", *++ssp1);
X fprintf (stderr, "\n");
X }
#endif
X
yyerrhandle:
X
X yyn = yypact[yystate];
X if (yyn == YYFLAG)
X goto yyerrdefault;
X
X yyn += YYTERROR;
X if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR)
X goto yyerrdefault;
X
X yyn = yytable[yyn];
X if (yyn < 0)
X {
X if (yyn == YYFLAG)
X goto yyerrpop;
X yyn = -yyn;
X goto yyreduce;
X }
X else if (yyn == 0)
X goto yyerrpop;
X
X if (yyn == YYFINAL)
X YYACCEPT;
X
#if YYDEBUG != 0
X if (yydebug)
X fprintf(stderr, "Shifting error token, ");
#endif
X
X *++yyvsp = yylval;
#ifdef YYLSP_NEEDED
X *++yylsp = yylloc;
#endif
X
X yystate = yyn;
X goto yynewstate;
}
#line 45 "parse.y"
X
X
#include <stdio.h>
#include <ctype.h>
X
extern FILE *finput;
X
int
yylex ()
{
X int c;
X
X /* Ignore whitespace, get first character. */
X while (isspace (c = getc (finput)))
X ;
X
X /* If a digit, get the number. */
X if (isdigit (c))
X {
X ungetc (c, finput);
X fscanf (finput, "%i", &yylval.ival);
X return NUM;
X }
X
X /* Otherwise return the letter to use as the function name. */
X else if (isalpha (c))
X {
X yylval.character = c;
X return NAME;
X }
X
X return c;
}
SHAR_EOF
chmod 0664 parse.c ||
echo 'restore of parse.c failed'
Wc_c="`wc -c < 'parse.c'`"
test 22030 -eq "$Wc_c" ||
echo 'parse.c: original size 22030, current size' "$Wc_c"
fi
# ============= parse.y ==============
if test -f 'parse.y' -a X"$1" != X"-c"; then
echo 'x - skipping parse.y (File already exists)'
else
echo 'x - extracting parse.y (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'parse.y' &&
/* Grammer file for compiler for toy language. */
X
%{
#include "config.h"
#include "tree.h"
X
extern void build_function PROTO((tree, tree));
extern tree build_function_decl PROTO((char, int));
extern tree get_arg_decl PROTO((int));
%}
X
%union {
tree exp; /* Tree node representing value. */
int ival; /* Integer value for constant or arg */
char character; /* Name of function */
}
X
%token <ival> NUM /* Decimal constant. */
%token <character> NAME /* Function name. */
X
%left '-' '+'
%left '*' '/'
X
%type <exp> exp fndef
X
%%
X
input: /* empty */
X | input function
X | error ;
X
function: fndef ':' exp ';' { build_function ($1, $3); } ;
X
fndef: NAME '(' NUM ')' { $$ = build_function_decl ($1, $3); } ;
X
exp: NUM { $$ = build_int_2 ($1, $1 >= 0 ? 0 : -1); }
X | '$' NUM { $$ = get_arg_decl ($2); }
X | exp '+' exp { $$ = build (PLUS_EXPR, integer_type_node, $1, $3); }
X | exp '-' exp { $$ = build (MINUS_EXPR, integer_type_node, $1, $3); }
X | exp '*' exp { $$ = build (MULT_EXPR, integer_type_node, $1, $3); }
X | exp '/' exp { $$ = build (TRUNC_DIV_EXPR, integer_type_node, $1, $3); }
X | '(' exp ')' { $$ = $2; }
X | error { $$ = error_mark_node; } ;
X
%%
X
#include <stdio.h>
#include <ctype.h>
X
extern FILE *finput;
X
int
yylex ()
{
X int c;
X
X /* Ignore whitespace, get first character. */
X while (isspace (c = getc (finput)))
X ;
X
X /* If a digit, get the number. */
X if (isdigit (c))
X {
X ungetc (c, finput);
X fscanf (finput, "%i", &yylval.ival);
X return NUM;
X }
X
X /* Otherwise return the letter to use as the function name. */
X else if (isalpha (c))
X {
X yylval.character = c;
X return NAME;
X }
X
X return c;
}
SHAR_EOF
chmod 0664 parse.y ||
echo 'restore of parse.y failed'
Wc_c="`wc -c < 'parse.y'`"
test 1713 -eq "$Wc_c" ||
echo 'parse.y: original size 1713, current size' "$Wc_c"
fi
# ============= toy.c ==============
if test -f 'toy.c' -a X"$1" != X"-c"; then
echo 'x - skipping toy.c (File already exists)'
else
echo 'x - extracting toy.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'toy.c' &&
#include "config.h"
#include "tree.h"
#include "flags.h"
#include <stdio.h>
X
/* Global Variables for the various types and nodes we create. */
X
tree error_mark_node;
tree integer_type_node;
tree char_type_node;
tree void_type_node;
X
tree integer_zero_node;
tree integer_one_node;
tree current_function_decl;
X
/* Global Variables Expected by gcc: */
X
char *language_string = "Demo language";
int flag_traditional; /* Used by dwarfout.c. */
X
/* Here are the three functions needed to compile out language and the
X variables they use. */
X
/* Number of arguments to the current function and the decls for the args. */
static int num_args;
static tree *arg_decls;
X
/* Make a FUNCTION_DECL for a function whose single-character name is
X NAME, that has NARGS integer operands, and returns integer. */
X
tree
build_function_decl (name, nargs)
X char name;
X int nargs;
{
X tree param_list = NULL_TREE;
X tree param_type_list = tree_cons (NULL_TREE, void_type_node, NULL_TREE);
X tree parm_decl;
X tree fntype;
X tree fndecl;
X char *p;
X int i;
X
X /* Allocate space for our PARM_DECLS and create them. */
X
X num_args = nargs;
X arg_decls = (tree *) xmalloc (nargs * sizeof (tree));
X for (i = nargs - 1; i >= 0; i--)
X {
X p = xmalloc (2);
X p[0] = 'a' + i;
X p[1] = '\0';
X parm_decl = build_decl (PARM_DECL, get_identifier (p),
X integer_type_node);
X DECL_ARG_TYPE (parm_decl) = integer_type_node;
X arg_decls[i] = parm_decl;
X param_list = chainon (parm_decl, param_list);
X param_type_list = tree_cons (NULL_TREE, integer_type_node,
X param_type_list);
X }
X
X /* The function type depends on the return type and type of args. */
X fntype = build_function_type (integer_type_node, param_type_list);
X
X /* Now make the function decl. */
X p = xmalloc (2);
X p[0] = name;
X p[1] = '\0';
X
X fndecl = build_decl (FUNCTION_DECL, get_identifier (p), fntype);
X DECL_EXTERNAL (fndecl) = 0;
X TREE_PUBLIC (fndecl) = 1;
X TREE_STATIC (fndecl) = 1;
X DECL_ARGUMENTS (fndecl) = param_list;
X DECL_RESULT (fndecl)
X = build_decl (RESULT_DECL, NULL_TREE, integer_type_node);
X DECL_CONTEXT (DECL_RESULT (fndecl)) = fndecl;
X
X rest_of_decl_compilation (fndecl, NULL_PTR, 1, 0);
X return fndecl;
}
X
/* Get the PARM_DECL for the Nth operand. */
X
tree
get_arg_decl (n)
X int n;
{
X if (n >= num_args)
X {
X fprintf (stderr, "arg number too high\n");
X n = 0;
X }
X
X return arg_decls[n];
}
X
/* Generate code for FNDECL that returns EXP. */
X
void
build_function (fndecl, exp)
X tree fndecl;
X tree exp;
{
X tree param_decl, next_param;
X
X /* Set line number information; everything is line 1 for us. */
X DECL_SOURCE_FILE (fndecl) = input_filename;
X DECL_SOURCE_LINE (fndecl) = 1;
X
X /* Announce we are compiling this function. */
X announce_function (fndecl);
X
X /* Set up to compile the function and enter it. */
X current_function_decl = fndecl;
X DECL_INITIAL (fndecl) = error_mark_node;
X
X temporary_allocation ();
X pushlevel (0);
X make_function_rtl (fndecl);
X
X /* Push all the PARM_DECL nodes onto the current scope (i.e. the scope of the
X subprogram body) so that they can be recognized as local variables in the
X subprogram. */
X
X for (param_decl = nreverse (DECL_ARGUMENTS (fndecl));
X param_decl; param_decl = next_param)
X {
X next_param = TREE_CHAIN (param_decl);
X TREE_CHAIN (param_decl) = NULL;
X pushdecl (param_decl);
X }
X
X /* Store back the PARM_DECL nodes. They appear in the right order. */
X DECL_ARGUMENTS (fndecl) = getdecls ();
X
X init_function_start (fndecl, input_filename, 1);
X expand_function_start (fndecl, 0);
X expand_start_bindings (0);
X
X /* The only thing in this function is a single return statement, which
X we now generate. Note that EXP will have been allocated in
X permanent_obstack. To do this properly, we need to enter the function
X ontext before parsing the expression, but then error recovery is more
X complex, so we don't do that here. */
X
X expand_return (build (MODIFY_EXPR, void_type_node,
X DECL_RESULT (fndecl), exp));
X
X /* Now get back out of the function and compile it. */
X expand_end_bindings (NULL_TREE, 1, 0);
X poplevel (1, 0, 1);
X expand_function_end (fndecl, 1, 0);
X rest_of_compilation (fndecl);
X current_function_decl = 0;
X permanent_allocation (1);
}
X
/* Routines Expected by gcc: */
X
/* These are used to build types for various sizes. The code below
X is a simplified version of that of GNAT. */
X
#ifndef MAX_BITS_PER_WORD
#define MAX_BITS_PER_WORD BITS_PER_WORD
#endif
X
/* This variable keeps a table for types for each precision so that we only
X allocate each of them once. Signed and unsigned types are kept separate. */
static tree signed_and_unsigned_types[MAX_BITS_PER_WORD + 1][2];
X
/* Return an integer type with the number of bits of precision given by
X PRECISION. UNSIGNEDP is nonzero if the type is unsigned; otherwise
X it is a signed type. */
X
tree
type_for_size (precision, unsignedp)
X unsigned precision;
X int unsignedp;
{
X tree t;
X int moment;
X
X if (precision <= MAX_BITS_PER_WORD
X && signed_and_unsigned_types[precision][unsignedp] != 0)
X return signed_and_unsigned_types[precision][unsignedp];
X
X /* Since we will keep these types around, they must be permanent. */
X moment = suspend_momentary ();
X push_obstacks_nochange ();
X end_temporary_allocation ();
X
X if (unsignedp)
X t = signed_and_unsigned_types[precision][1]
X = make_unsigned_type (precision);
X else
X t = signed_and_unsigned_types[precision][0]
X = make_signed_type (precision);
X
X pop_obstacks ();
X resume_momentary (moment);
X
X return t;
}
X
/* Return a data type that has machine mode MODE. UNSIGNEDP selects
X an unsigned type; otherwise a signed type is returned. */
X
tree
type_for_mode (mode, unsignedp)
X enum machine_mode mode;
X int unsignedp;
{
X return type_for_size (GET_MODE_BITSIZE (mode), unsignedp);
}
X
/* Return the unsigned version of a TYPE_NODE, a scalar type. */
X
tree
unsigned_type (type_node)
X tree type_node;
{
X return type_for_size (TYPE_PRECISION (type_node), 1);
}
X
/* Return the signed version of a TYPE_NODE, a scalar type. */
X
tree
signed_type (type_node)
X tree type_node;
{
X return type_for_size (TYPE_PRECISION (type_node), 0);
}
X
/* Return a type the same as TYPE except unsigned or signed according to
X UNSIGNEDP. */
X
tree
signed_or_unsigned_type (unsignedp, type)
X int unsignedp;
X tree type;
{
X if (! INTEGRAL_TYPE_P (type) || TREE_UNSIGNED (type) == unsignedp)
X return type;
X else
X return type_for_size (TYPE_PRECISION (type), unsignedp);
}
X
/* These functions and variables deal with binding contours. We only
X need these functions for the list of PARM_DECLs, but we leave the
X functions more general; these are a simplified version of the
X functions from GNAT. */
X
/* For each binding contour we allocate a binding_level structure which records
X the entities defined or declared in that contour. Contours include:
X
X the global one
X one for each subprogram definition
X one for each compound statement (declare block)
X
X Binding contours are used to create GCC tree BLOCK nodes. */
X
struct binding_level
{
X /* A chain of ..._DECL nodes for all variables, constants, functions,
X parameters and type declarations. These ..._DECL nodes are chained
X through the TREE_CHAIN field. Note that these ..._DECL nodes are stored
X in the reverse of the order supplied to be compatible with the
X back-end. */
X tree names;
X /* For each level (except the global one), a chain of BLOCK nodes for all
X the levels that were entered and exited one level down from this one. */
X tree blocks;
X /* The back end may need, for its own internal processing, to create a BLOCK
X node. This field is set aside for this purpose. If this field is non-null
X when the level is popped, i.e. when poplevel is invoked, we will use such
X block instead of creating a new one from the 'names' field, that is the
X ..._DECL nodes accumulated so far. Typically the routine 'pushlevel'
X will be called before setting this field, so that if the front-end had
X inserted ..._DECL nodes in the current block they will not be lost. */
X tree block_created_by_back_end;
X /* The binding level containing this one (the enclosing binding level). */
X struct binding_level *level_chain;
};
X
/* The binding level currently in effect. */
static struct binding_level *current_binding_level = NULL;
X
/* The outermost binding level. This binding level is created when the
X compiler is started and it will exist through the entire compilation. */
static struct binding_level *global_binding_level;
X
/* Binding level structures are initialized by copying this one. */
static struct binding_level clear_binding_level = {NULL, NULL, NULL, NULL};
X
/* Return non-zero if we are currently in the global binding level. */
X
int
global_bindings_p ()
{
X return current_binding_level == global_binding_level ? -1 : 0;
}
X
/* Return the list of declarations in the current level. Note that this list
X is in reverse order (it has to be so for back-end compatibility). */
X
tree
getdecls ()
{
X return current_binding_level->names;
}
X
/* Nonzero if the current level needs to have a BLOCK made. */
X
int
kept_level_p ()
{
X return (current_binding_level->names != 0);
}
X
/* Enter a new binding level. The input parameter is ignored, but has to be
X specified for back-end compatibility. */
X
void
pushlevel (ignore)
X int ignore;
{
X struct binding_level *newlevel
X = (struct binding_level *) xmalloc (sizeof (struct binding_level));
X
X *newlevel = clear_binding_level;
X
X /* Add this level to the front of the chain (stack) of levels that are
X active. */
X newlevel->level_chain = current_binding_level;
X current_binding_level = newlevel;
}
X
/* Exit a binding level.
X Pop the level off, and restore the state of the identifier-decl mappings
X that were in effect when this level was entered.
X
X If KEEP is nonzero, this level had explicit declarations, so
X and create a "block" (a BLOCK node) for the level
X to record its declarations and subblocks for symbol table output.
X
X If FUNCTIONBODY is nonzero, this level is the body of a function,
X so create a block as if KEEP were set and also clear out all
X label names.
X
X If REVERSE is nonzero, reverse the order of decls before putting
X them into the BLOCK. */
X
tree
poplevel (keep, reverse, functionbody)
X int keep;
X int reverse;
X int functionbody;
{
X /* Points to a BLOCK tree node. This is the BLOCK node construted for the
X binding level that we are about to exit and which is returned by this
X routine. */
X tree block_node = NULL_TREE;
X tree decl_chain;
X tree decl_node;
X tree subblock_chain = current_binding_level->blocks;
X tree subblock_node;
X tree block_created_by_back_end;
X
X /* Reverse the list of XXXX_DECL nodes if desired. Note that the ..._DECL
X nodes chained through the `names' field of current_binding_level are in
X reverse order except for PARM_DECL node, which are explicitely stored in
X the right order. */
X decl_chain = (reverse) ? nreverse (current_binding_level->names)
X : current_binding_level->names;
X
X block_created_by_back_end = current_binding_level->block_created_by_back_end;
X if (block_created_by_back_end != 0)
X {
X block_node = block_created_by_back_end;
X
X /* Check if we are about to discard some information that was gathered
X by the front-end. Nameley check if the back-end created a new block
X without calling pushlevel first. To understand why things are lost
X just look at the next case (i.e. no block created by back-end. */
X if ((keep || functionbody) && (decl_chain || subblock_chain))
X abort ();
X }
X
X /* If there were any declarations in the current binding level, or if this
X binding level is a function body, or if there are any nested blocks then
X create a BLOCK node to record them for the life of this function. */
X else if (keep || functionbody)
X block_node = build_block (keep ? decl_chain : 0, 0, subblock_chain, 0, 0);
X
X /* Record the BLOCK node just built as the subblock its enclosing scope. */
X for (subblock_node = subblock_chain; subblock_node;
X subblock_node = TREE_CHAIN (subblock_node))
X BLOCK_SUPERCONTEXT (subblock_node) = block_node;
X
X /* Clear out the meanings of the local variables of this level. */
X
X for (subblock_node = decl_chain; subblock_node;
X subblock_node = TREE_CHAIN (subblock_node))
X if (DECL_NAME (subblock_node) != 0)
X /* If the identifier was used or addressed via a local extern decl,
X don't forget that fact. */
X if (DECL_EXTERNAL (subblock_node))
X {
X if (TREE_USED (subblock_node))
X TREE_USED (DECL_NAME (subblock_node)) = 1;
X if (TREE_ADDRESSABLE (subblock_node))
X TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (subblock_node)) = 1;
X }
X
X /* Pop the current level. */
X current_binding_level = current_binding_level->level_chain;
X
X if (functionbody)
X {
X /* This is the top level block of a function. The ..._DECL chain stored
X in BLOCK_VARS are the function's parameters (PARM_DECL nodes). Don't
X leave them in the BLOCK because they are found in the FUNCTION_DECL
X instead. */
X DECL_INITIAL (current_function_decl) = block_node;
X BLOCK_VARS (block_node) = 0;
X }
X else if (block_node)
X {
X if (block_created_by_back_end == NULL)
X current_binding_level->blocks
X = chainon (current_binding_level->blocks, block_node);
X }
X
X /* If we did not make a block for the level just exited, any blocks made for
X inner levels (since they cannot be recorded as subblocks in that level)
X must be carried forward so they will later become subblocks of something
X else. */
X else if (subblock_chain)
X current_binding_level->blocks
X = chainon (current_binding_level->blocks, subblock_chain);
X if (block_node)
X TREE_USED (block_node) = 1;
X
X return block_node;
}
X
/* Insert BLOCK at the end of the list of subblocks of the
X current binding level. This is used when a BIND_EXPR is expanded,
X to handle the BLOCK node inside the BIND_EXPR. */
X
void
insert_block (block)
X tree block;
{
X TREE_USED (block) = 1;
X current_binding_level->blocks
X = chainon (current_binding_level->blocks, block);
}
X
/* Set the BLOCK node for the innermost scope
X (the one we are currently in). */
X
void
set_block (block)
X tree block;
{
X current_binding_level->block_created_by_back_end = block;
}
X
/* Records a ..._DECL node DECL as belonging to the current lexical scope.
X Returns the ..._DECL node. */
X
tree
pushdecl (decl)
X tree decl;
{
X /* External objects aren't nested, other objects may be. */
X if (DECL_EXTERNAL (decl))
X DECL_CONTEXT (decl) = 0;
X else
X DECL_CONTEXT (decl) = current_function_decl;
X
X /* Put the declaration on the list. The list of declarations is in reverse
X order. The list will be reversed later if necessary. This needs to be
X this way for compatibility with the back-end. */
X
X TREE_CHAIN (decl) = current_binding_level->names;
X current_binding_level->names = decl;
X
X /* For the declartion of a type, set its name if it is not already set. */
X
X if (TREE_CODE (decl) == TYPE_DECL
X && TYPE_NAME (TREE_TYPE (decl)) == 0)
X TYPE_NAME (TREE_TYPE (decl)) = DECL_NAME (decl);
X
X return decl;
}
X
#ifndef CHAR_TYPE_SIZE
#define CHAR_TYPE_SIZE BITS_PER_UNIT
#endif
X
#ifndef INT_TYPE_SIZE
#define INT_TYPE_SIZE BITS_PER_WORD
#endif
X
#undef SIZE_TYPE
#define SIZE_TYPE "long unsigned int"
X
/* Create the predefined scalar types such as `integer_type_node' needed
X in the gcc back-end and initialize the global binding level. */
X
void
init_decl_processing ()
{
X tree endlink;
X
X /* The structure `tree_identifier' is the GCC tree data structure that holds
X IDENTIFIER_NODE nodes. We need to call `set_identifier_size' to tell GCC
X that we have not added any language specific fields to IDENTIFIER_NODE
X nodes. */
X set_identifier_size (sizeof (struct tree_identifier));
X lineno = 0;
X
X /* Make the binding_level structure for global names. */
X pushlevel (0);
X global_binding_level = current_binding_level;
X
X sizetype = type_for_size (GET_MODE_BITSIZE (Pmode), 1);
X pushdecl (build_decl (TYPE_DECL, get_identifier (SIZE_TYPE), sizetype));
X
X integer_type_node = type_for_size (INT_TYPE_SIZE, 0) ;
X pushdecl (build_decl (TYPE_DECL, get_identifier ("int"), integer_type_node));
X
X char_type_node = type_for_size (CHAR_TYPE_SIZE, 1);
X pushdecl (build_decl (TYPE_DECL, get_identifier ("unsigned char"),
X char_type_node));
X
X integer_zero_node = build_int_2 (0, 0);
X integer_one_node = build_int_2 (1, 0);
X
X size_zero_node = build_int_2 (0, 0);
X TREE_TYPE (size_zero_node) = sizetype;
X size_one_node = build_int_2 (1, 0);
X TREE_TYPE (size_one_node) = sizetype;
X
X error_mark_node = make_node (ERROR_MARK);
X TREE_TYPE (error_mark_node) = error_mark_node;
X void_type_node = make_node (VOID_TYPE);
X layout_type (void_type_node);
X TYPE_ALIGN (void_type_node) = BITS_PER_UNIT;
}
X
/* Decode all the language specific options that cannot be decoded by GCC. The
X option decoding phase of GCC calls this routine on the flags that it cannot
X decode. Return 1 if successful, otherwise return 0. */
X
int
lang_decode_option (p)
X char *p;
{ return 0; }
X
/* Perform all the initialization steps that are language-specific. */
X
void
lang_init ()
{}
X
/* Perform all the finalization steps that are language-specific. */
X
void
lang_finish ()
{}
X
/* Return a short string identifying this language to the debugger. */
X
char *
lang_identify ()
{ return "toy"; }
X
/* If DECL has a cleanup, build and return that cleanup here.
X This is a callback called by expand_expr. */
X
tree
maybe_build_cleanup (decl)
X tree decl;
{ return NULL_TREE; }
X
/* Print an error message for invalid use of an incomplete type. */
X
void
incomplete_type_error (dont_care_1, dont_care_2)
X tree dont_care_1, dont_care_2;
{ abort (); }
X
tree
truthvalue_conversion (expr)
X tree expr;
{ return expr;}
X
void
mark_addressable (expr)
X tree expr;
{}
X
/* Print any language-specific compilation statistics. */
X
void
print_lang_statistics ()
{}
X
/* Since we don't use the DECL_LANG_SPECIFIC field, this is a no-op. */
X
void
copy_lang_decl (node)
X tree node;
{}
X
/* Hooks for print-tree.c: */
X
void
print_lang_decl (file, node, indent)
X FILE *file;
X tree node;
X int indent;
{}
X
void
print_lang_type (file, node, indent)
X FILE *file;
X tree node;
X int indent;
{}
X
void
print_lang_identifier (file, node, indent)
X FILE *file;
X tree node;
X int indent;
{}
X
/* Performs whatever initialization steps are needed by the language-dependent
X lexical analyzer. */
X
void
init_lex ()
{}
X
/* Sets some debug flags for the parser. It does nothing here. */
X
void
set_yydebug (value)
X int value;
{}
X
/* Routine to print parse error message. */
X
void
yyerror (str)
X char *str;
{
X fprintf (stderr, "%s\n", str);
}
SHAR_EOF
chmod 0664 toy.c ||
echo 'restore of toy.c failed'
Wc_c="`wc -c < 'toy.c'`"
test 19095 -eq "$Wc_c" ||
echo 'toy.c: original size 19095, current size' "$Wc_c"
fi
exit 0
Technical Details
Message-ID:
<9600416.23942@mulga.cs.mu.OZ.AU>Path:
arc1-ca.pugleaf.net!unknown!not-for-mailReferences:
<4cdpm5$6gh@news.Belgium.EU.net>Show Full Headers
Complete Article Headers
X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 11318c,ff1cf4523271e6d X-Google-Attributes: gid11318c,public From: fjh@munta.cs.mu.OZ.AU (Fergus Henderson) Subject: Re: Writing a new front-end for the gcc code generation Date: 1996/01/04 Message-ID: <9600416.23942@mulga.cs.mu.OZ.AU> X-Deja-AN: 133957227 sender: news@cs.mu.OZ.AU (CS-Usenet) references: <4cdpm5$6gh@news.Belgium.EU.net> organization: Computer Science, University of Melbourne, Australia newsgroups: gnu.gcc.help