Make-lang.in (TREE_BE_LIBS): Remove.
treelang: 2004-08-01 James A. Morrison <phython@gcc.gnu.org> * Make-lang.in (TREE_BE_LIBS): Remove. (tree1): Depend on BACKEND and LIBDEPS. Use BACKEND and LIBS instead of TREE_BE_LIBS. * parse.y: Add variable_defs_opt before statements_opt. Use tree_code_get_type instead of get_type_for_numeric_type. Reformat long lines. (parameters_opt): New rule. (function_prototype): Use parameters_opt. (return): Remove calls to print_token in error cases. Use VOID_TYPE. (check_type_match): Use VOID_TYPE. * lex.l (update_lineno_charno): Ensure INPUT_LINE starts at 1. * tree1.c: Include version.h and cgraph.h (treelang_parse_file): Call cgraph_finalize_compilation_unit and cgraph_optimize. * treelang.h (item): Remove extraneous GTY. * treetree.h (get_type_for_numeric_type): Remove. * treetree.c: Include tree-dump.h, tree-iterator.h, tree-gimple.h, function.h, and cgraph.h. Don't include rtl.h (keep_level_p): Remove. (tree_push_atomic_type_decl): Remove. (get_type_for_numeric_type): Remove. (tree_code_get_numeric_type): Remove. (global_bindings_p): Make static. (getdecls): Likewise. (insert_block): Likewise. (tree_code_if_start): Create a COND_EXPR and add it to the tree instead of creating rtl. (tree_code_if_else): Create a BIND_EXPR if any variables were created in the if statement. (tree_code_end_if): Likewise. (tree_code_create_function_prototype): Use tree_code_get_type. Don't use SET_DECL_ASSEMBLER_NAME. (tree_code_create_function_initial): Set DECL_ARTIFICIAL and DECL_IGNORING_P on RESULT_DECL. Use tree_code_get_type. Don't call layout_decl on RESULT_DECL. Don't call rtl expand functions. (tree_code_create_function_wrapup): Don't call rtl expand functions. Create a BIND_EXPR for each function. Dump original and gimplified copies of the function tree. Gimplify function. (tree_code_create_variable): Use tree_code_get_type. Don't call layout_decl or expand_decl. Fold CONVERT_EXPRs. (tree_code_generate_return): Fold CONVERT_EXPRs and MODIFY_EXPRs. Add RETURN_EXPR to the current statement list. Don't call rtl expand functions. (tree_code_output_expression_statement): Append CODE to current statement list. (tree_code_get_expression): Fold expressions. Build a pointer to a FUNCTION_TYPE intead of the called functions return type. (struct binding_level): Add statement list STMTS. (getstmtlist): New Function. (pushlevel): Make static. Allocate an empty statement list. (poplevel): Make static. Don't clear BLOCK_NODE's BLOCK_VARS. Don't use DECL_ASSEMBLER_NAME. (tree_push_type_decl): Set TYPE_NAME of TYPE_NODE to ID. (treelang_init_decl_processing): Define basic types after unused types. Don't call tree_push_atomic_type_decl. (builtin_function): Don't call make_decl_rtl. (treelang_expand_function). New Function. testsuite/treelang: * compile/vars_def.tree: New File. * compile/badreturn.tree: New File. From-SVN: r85684
This commit is contained in:
parent
c30ff96bd5
commit
352a77c8dc
|
@ -1,3 +1,8 @@
|
|||
2004-07-31 James A. Morrison <phython@gcc.gnu.org>
|
||||
|
||||
* compile/vars_def.tree: New File.
|
||||
* compile/badreturn.tree: New File.
|
||||
|
||||
2004-01-18 James A. Morrison <ja2morri@uwaterloo.ca>
|
||||
|
||||
* compile/compile.exp: New File.
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
int add(int, int);
|
||||
int subtract(int, int);
|
||||
int first_nonzero(int, int);
|
||||
extern int printf(char *template, ...);
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
// { dg-do compile }
|
||||
|
||||
external_definition void bar ();
|
||||
external_definition int gar (int arg0);
|
||||
|
||||
bar
|
||||
{
|
||||
return 0; // { dg-warning "return" }
|
||||
}
|
||||
|
||||
gar
|
||||
{
|
||||
return; // { dg-error "return" }
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
# Tests for treelang; run from gcc/treelang/Make-lang.in => gcc/Makefile
|
||||
|
||||
# Copyright (C) 2004 by The Free Software Foundation
|
||||
|
||||
# This program 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.
|
||||
#
|
||||
# This program 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 this program; if not, write to the Free Software
|
||||
# Foundation, 59 Temple Place - Suite 330,
|
||||
# Boston, MA 02111-1307, USA.
|
||||
#
|
||||
# In other words, you are welcome to use, share and improve this program.
|
||||
# You are forbidden to forbid anyone else to use, share and improve
|
||||
# what you give them. Help stamp out software-hoarding!
|
||||
|
||||
# Treelang tests that only need to compile.
|
||||
|
||||
# Load support procs.
|
||||
load_lib treelang-dg.exp
|
||||
|
||||
dg-init
|
||||
dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.tree]] "" ""
|
||||
dg-finish
|
|
@ -0,0 +1,16 @@
|
|||
// { dg-do compile }
|
||||
// { dg-options "-funit-at-a-time" }
|
||||
external_definition int add (int arga, int argb);
|
||||
external_definition char sub (char argc, char argd);
|
||||
|
||||
add
|
||||
{
|
||||
return arga + argb + +3;
|
||||
}
|
||||
|
||||
sub
|
||||
{
|
||||
return argd - argc + +2;
|
||||
}
|
||||
// { dg-final { scan-assembler "add" } }
|
||||
// { dg-final { scan-assembler "sub" } }
|
|
@ -0,0 +1,11 @@
|
|||
// { dg-do compile }
|
||||
external_definition int main(int argc);
|
||||
|
||||
main {
|
||||
automatic int v1;
|
||||
automatic int v2;
|
||||
v1 = argc;
|
||||
v2 = 3;
|
||||
|
||||
return v2;
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
// { dg-do compile }
|
||||
external_definition void boring (int arg0);
|
||||
external_definition char condition (char arg1, char arg2);
|
||||
external_definition int first_nonzero (int arg5, int arg6);
|
||||
|
||||
boring
|
||||
{
|
||||
arg0 = +5 + +3; // Force 3 and 5 to be signed numbers.
|
||||
arg0 = arg0 + +3;
|
||||
}
|
||||
|
||||
condition
|
||||
{
|
||||
if (arg1)
|
||||
{
|
||||
automatic int i;
|
||||
return arg1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
first_nonzero
|
||||
{
|
||||
if (arg5)
|
||||
{
|
||||
return arg5;
|
||||
}
|
||||
else
|
||||
{
|
||||
automatic int j;
|
||||
j = arg6;
|
||||
return j;
|
||||
}
|
||||
return arg6;
|
||||
}
|
||||
|
|
@ -1,3 +1,63 @@
|
|||
2004-07-31 James A. Morrison <phython@gcc.gnu.org>
|
||||
|
||||
* Make-lang.in (TREE_BE_LIBS): Remove.
|
||||
(tree1): Depend on BACKEND and LIBDEPS. Use BACKEND and LIBS instead
|
||||
of TREE_BE_LIBS.
|
||||
* parse.y: Add variable_defs_opt before statements_opt.
|
||||
Use tree_code_get_type instead of get_type_for_numeric_type.
|
||||
Reformat long lines.
|
||||
(parameters_opt): New rule.
|
||||
(function_prototype): Use parameters_opt.
|
||||
(return): Remove calls to print_token in error cases. Use VOID_TYPE.
|
||||
(check_type_match): Use VOID_TYPE.
|
||||
* lex.l (update_lineno_charno): Ensure INPUT_LINE starts at 1.
|
||||
* tree1.c: Include version.h and cgraph.h
|
||||
(treelang_parse_file): Call cgraph_finalize_compilation_unit and
|
||||
cgraph_optimize.
|
||||
* treelang.h (item): Remove extraneous GTY.
|
||||
* treetree.h (get_type_for_numeric_type): Remove.
|
||||
* treetree.c: Include tree-dump.h, tree-iterator.h, tree-gimple.h,
|
||||
function.h, and cgraph.h. Don't include rtl.h
|
||||
(keep_level_p): Remove.
|
||||
(tree_push_atomic_type_decl): Remove.
|
||||
(get_type_for_numeric_type): Remove.
|
||||
(tree_code_get_numeric_type): Remove.
|
||||
(global_bindings_p): Make static.
|
||||
(getdecls): Likewise.
|
||||
(insert_block): Likewise.
|
||||
(tree_code_if_start): Create a COND_EXPR and add it to the tree
|
||||
instead of creating rtl.
|
||||
(tree_code_if_else): Create a BIND_EXPR if any variables were created
|
||||
in the if statement.
|
||||
(tree_code_end_if): Likewise.
|
||||
(tree_code_create_function_prototype): Use tree_code_get_type.
|
||||
Don't use SET_DECL_ASSEMBLER_NAME.
|
||||
(tree_code_create_function_initial): Set DECL_ARTIFICIAL and
|
||||
DECL_IGNORING_P on RESULT_DECL. Use tree_code_get_type. Don't call
|
||||
layout_decl on RESULT_DECL. Don't call rtl expand functions.
|
||||
(tree_code_create_function_wrapup): Don't call rtl expand functions.
|
||||
Create a BIND_EXPR for each function. Dump original and gimplified
|
||||
copies of the function tree. Gimplify function.
|
||||
(tree_code_create_variable): Use tree_code_get_type. Don't call
|
||||
layout_decl or expand_decl. Fold CONVERT_EXPRs.
|
||||
(tree_code_generate_return): Fold CONVERT_EXPRs and MODIFY_EXPRs.
|
||||
Add RETURN_EXPR to the current statement list. Don't call rtl expand
|
||||
functions.
|
||||
(tree_code_output_expression_statement): Append CODE to current
|
||||
statement list.
|
||||
(tree_code_get_expression): Fold expressions. Build a pointer to
|
||||
a FUNCTION_TYPE intead of the called functions return type.
|
||||
(struct binding_level): Add statement list STMTS.
|
||||
(getstmtlist): New Function.
|
||||
(pushlevel): Make static. Allocate an empty statement list.
|
||||
(poplevel): Make static. Don't clear BLOCK_NODE's BLOCK_VARS.
|
||||
Don't use DECL_ASSEMBLER_NAME.
|
||||
(tree_push_type_decl): Set TYPE_NAME of TYPE_NODE to ID.
|
||||
(treelang_init_decl_processing): Define basic types after unused types.
|
||||
Don't call tree_push_atomic_type_decl.
|
||||
(builtin_function): Don't call make_decl_rtl.
|
||||
(treelang_expand_function). New Function.
|
||||
|
||||
2004-07-11 Joseph S. Myers <jsm@polyomino.org.uk>
|
||||
|
||||
* treetree.c (set_block): Remove.
|
||||
|
|
|
@ -45,10 +45,6 @@
|
|||
TREELANGSED = sed
|
||||
TREELANGSEDFLAGS = -n
|
||||
|
||||
# back end compiler libraries etc
|
||||
TREE_BE_LIBS = $(BACKEND) $(LIBIBERTY) $(INTLIBS) $(LIBS) $(LIBDEPS)
|
||||
|
||||
|
||||
GCC_EXTRAS = -B./ -B$(build_tooldir)/bin/ -isystem $(build_tooldir)/include
|
||||
|
||||
# ./xgcc is the just built compiler. See GCC_FOR_TARGET in the GCC Makefile.in.
|
||||
|
@ -83,11 +79,11 @@ treelang.done: tree1$(exeext)
|
|||
# core compiler
|
||||
tree1$(exeext): treelang/tree1.o treelang/treetree.o treelang/tree-convert.o \
|
||||
treelang/lex.o treelang/parse.o \
|
||||
$(TREE_BE_LIBS) attribs.o
|
||||
$(BACKEND) $(LIBSDEPS) attribs.o
|
||||
$(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ \
|
||||
treelang/tree1.o treelang/treetree.o treelang/tree-convert.o \
|
||||
treelang/lex.o treelang/parse.o \
|
||||
$(TREE_BE_LIBS) attribs.o
|
||||
$(BACKEND) $(LIBS) attribs.o
|
||||
|
||||
#
|
||||
# Compiling object files from source files.
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
---------------------------------------------------------------------
|
||||
|
||||
Copyright (C) 1986, 87, 89, 92-96, 1997, 1999, 2000, 2001, 2002, 2003
|
||||
Copyright (C) 1986, 87, 89, 92-96, 1997, 1999, 2000, 2001, 2002, 2003, 2004
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
|
@ -233,6 +233,9 @@ update_lineno_charno (void)
|
|||
int yyl;
|
||||
((struct prod_token_parm_item *)yylval)->tp.tok.location = input_location;
|
||||
((struct prod_token_parm_item *)yylval)->tp.tok.charno = next_tree_charno;
|
||||
if (input_line == 0)
|
||||
input_line = 1;
|
||||
|
||||
for ( yyl = 0; yyl < yyleng; ++yyl )
|
||||
{
|
||||
if ( yytext[yyl] == '\n' )
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
|
||||
---------------------------------------------------------------------
|
||||
|
||||
Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
|
||||
Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
|
@ -254,7 +255,7 @@ typename NAME {
|
|||
;
|
||||
|
||||
function_prototype:
|
||||
storage typename NAME LEFT_PARENTHESIS parameters RIGHT_PARENTHESIS SEMICOLON {
|
||||
storage typename NAME LEFT_PARENTHESIS parameters_opt RIGHT_PARENTHESIS SEMICOLON {
|
||||
struct prod_token_parm_item* tok;
|
||||
struct prod_token_parm_item *prod;
|
||||
struct prod_token_parm_item *type;
|
||||
|
@ -450,6 +451,14 @@ INT {
|
|||
}
|
||||
;
|
||||
|
||||
parameters_opt:
|
||||
/* Nothing to do. */ {
|
||||
$$ = 0;
|
||||
}
|
||||
| parameters {
|
||||
$$ = $1;
|
||||
}
|
||||
|
||||
parameters:
|
||||
parameter {
|
||||
/* Nothing to do. */
|
||||
|
@ -496,7 +505,7 @@ IF LEFT_PARENTHESIS expression RIGHT_PARENTHESIS {
|
|||
ensure_not_void (NUMERIC_TYPE (exp), exp->tp.pro.main_token);
|
||||
tree_code_if_start (exp->tp.pro.code, tok->tp.tok.location);
|
||||
}
|
||||
LEFT_BRACE statements_opt RIGHT_BRACE {
|
||||
LEFT_BRACE variable_defs_opt statements_opt RIGHT_BRACE {
|
||||
/* Just let the statements flow. */
|
||||
}
|
||||
ELSE {
|
||||
|
@ -504,7 +513,7 @@ ELSE {
|
|||
tok = $1;
|
||||
tree_code_if_else (tok->tp.tok.location);
|
||||
}
|
||||
LEFT_BRACE statements_opt RIGHT_BRACE {
|
||||
LEFT_BRACE variable_defs_opt statements_opt RIGHT_BRACE {
|
||||
struct prod_token_parm_item* tok;
|
||||
tok = $12;
|
||||
tree_code_if_end (tok->tp.tok.location);
|
||||
|
@ -518,25 +527,23 @@ tl_RETURN expression_opt {
|
|||
struct prod_token_parm_item* ret_tok;
|
||||
ret_tok = $1;
|
||||
type_prod = EXPRESSION_TYPE (current_function);
|
||||
if (NUMERIC_TYPE (type_prod) == VOID)
|
||||
if (NUMERIC_TYPE (type_prod) == VOID_TYPE)
|
||||
if ($2 == NULL)
|
||||
tree_code_generate_return (type_prod->tp.pro.code, NULL);
|
||||
else
|
||||
{
|
||||
fprintf (stderr, "%s:%i:%i: Redundant expression in return\n",
|
||||
ret_tok->tp.tok.location.file,
|
||||
ret_tok->tp.tok.location.line, ret_tok->tp.tok.charno);
|
||||
print_token (stderr, 0, ret_tok);
|
||||
ret_tok->tp.tok.location.file,
|
||||
ret_tok->tp.tok.location.line, ret_tok->tp.tok.charno);
|
||||
errorcount++;
|
||||
tree_code_generate_return (type_prod->tp.pro.code, NULL);
|
||||
}
|
||||
}
|
||||
else
|
||||
if ($2 == NULL)
|
||||
{
|
||||
fprintf (stderr, "%s:%i:%i: Expression missing in return\n",
|
||||
ret_tok->tp.tok.location.file,
|
||||
ret_tok->tp.tok.location.line, ret_tok->tp.tok.charno);
|
||||
print_token (stderr, 0, ret_tok);
|
||||
ret_tok->tp.tok.location.file,
|
||||
ret_tok->tp.tok.location.line, ret_tok->tp.tok.charno);
|
||||
errorcount++;
|
||||
}
|
||||
else
|
||||
|
@ -687,7 +694,7 @@ NAME LEFT_PARENTHESIS expressions_with_commas RIGHT_PARENTHESIS {
|
|||
abort ();
|
||||
parms = tree_code_add_parameter (parms, var->tp.pro.code, exp->tp.pro.code);
|
||||
}
|
||||
type = get_type_for_numeric_type (NUMERIC_TYPE (prod));
|
||||
type = tree_code_get_type (NUMERIC_TYPE (prod));
|
||||
prod->tp.pro.code = tree_code_get_expression
|
||||
(EXP_FUNCTION_INVOCATION, type, proto->tp.pro.code, parms, NULL);
|
||||
$$ = prod;
|
||||
|
@ -734,7 +741,7 @@ NAME {
|
|||
|
||||
prod = make_production (PROD_VARIABLE_REFERENCE_EXPRESSION, tok);
|
||||
NUMERIC_TYPE (prod) = NUMERIC_TYPE (symbol_table_entry);
|
||||
type = get_type_for_numeric_type (NUMERIC_TYPE (prod));
|
||||
type = tree_code_get_type (NUMERIC_TYPE (prod));
|
||||
if (!NUMERIC_TYPE (prod))
|
||||
YYERROR;
|
||||
OP1 (prod) = $1;
|
||||
|
@ -832,7 +839,7 @@ reverse_prod_list (struct prod_token_parm_item *old_first)
|
|||
static void
|
||||
ensure_not_void (unsigned int type, struct prod_token_parm_item* name)
|
||||
{
|
||||
if (type == VOID)
|
||||
if (type == VOID_TYPE)
|
||||
{
|
||||
fprintf (stderr, "%s:%i:%i: Type must not be void in this context\n",
|
||||
name->tp.tok.location.file,
|
||||
|
@ -877,7 +884,7 @@ check_type_match (int type_num, struct prod_token_parm_item *exp)
|
|||
case UNSIGNED_CHAR:
|
||||
return 1;
|
||||
|
||||
case VOID:
|
||||
case VOID_TYPE:
|
||||
abort ();
|
||||
|
||||
default:
|
||||
|
@ -885,7 +892,7 @@ check_type_match (int type_num, struct prod_token_parm_item *exp)
|
|||
}
|
||||
break;
|
||||
|
||||
case VOID:
|
||||
case VOID_TYPE:
|
||||
abort ();
|
||||
|
||||
default:
|
||||
|
@ -903,7 +910,8 @@ make_integer_constant (struct prod_token_parm_item* value)
|
|||
struct prod_token_parm_item *prod;
|
||||
tok = value;
|
||||
prod = make_production (PROD_INTEGER_CONSTANT, tok);
|
||||
if ((tok->tp.tok.chars[0] == (unsigned char)'-')|| (tok->tp.tok.chars[0] == (unsigned char)'+'))
|
||||
if ((tok->tp.tok.chars[0] == (unsigned char)'-')
|
||||
|| (tok->tp.tok.chars[0] == (unsigned char)'+'))
|
||||
NUMERIC_TYPE (prod) = SIGNED_INT;
|
||||
else
|
||||
NUMERIC_TYPE (prod) = UNSIGNED_INT;
|
||||
|
@ -930,7 +938,7 @@ make_plus_expression (struct prod_token_parm_item* tok,
|
|||
prod = make_production (PROD_PLUS_EXPRESSION, tok);
|
||||
|
||||
NUMERIC_TYPE (prod) = type_code;
|
||||
type = get_type_for_numeric_type (NUMERIC_TYPE (prod));
|
||||
type = tree_code_get_type (type_code);
|
||||
if (!type)
|
||||
abort ();
|
||||
OP1 (prod) = op1;
|
||||
|
|
|
@ -3,7 +3,8 @@
|
|||
TREELANG Compiler almost main (tree1)
|
||||
Called by GCC's toplev.c
|
||||
|
||||
Copyright (C) 1986, 87, 89, 92-96, 1997, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
|
||||
Copyright (C) 1986, 87, 89, 92-96, 1997, 1999, 2000, 2001, 2002, 2003, 2004
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
|
@ -37,9 +38,11 @@
|
|||
#include "tm.h"
|
||||
#include "flags.h"
|
||||
#include "toplev.h"
|
||||
#include "version.h"
|
||||
|
||||
#include "ggc.h"
|
||||
#include "tree.h"
|
||||
#include "cgraph.h"
|
||||
#include "diagnostic.h"
|
||||
|
||||
#include "treelang.h"
|
||||
|
@ -141,7 +144,7 @@ bool
|
|||
treelang_init (void)
|
||||
{
|
||||
input_filename = main_input_filename;
|
||||
input_line = 0;
|
||||
input_line = 1;
|
||||
|
||||
/* Init decls etc. */
|
||||
|
||||
|
@ -185,6 +188,8 @@ treelang_parse_file (int debug_flag ATTRIBUTE_UNUSED)
|
|||
{
|
||||
treelang_debug ();
|
||||
yyparse ();
|
||||
cgraph_finalize_compilation_unit ();
|
||||
cgraph_optimize ();
|
||||
}
|
||||
|
||||
/* Allocate SIZE bytes and clear them. Not to be used for strings
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
|
||||
TREELANG Compiler common definitions (treelang.h)
|
||||
|
||||
Copyright (C) 1986, 87, 89, 92-96, 1997, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
|
||||
Copyright (C) 1986, 87, 89, 92-96, 1997, 1999, 2000, 2001, 2002, 2003, 2004
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
|
@ -48,7 +49,7 @@ extern FILE* yyin;
|
|||
struct token_part;
|
||||
struct production_part;
|
||||
struct prod_token_parm_item;
|
||||
typedef struct GTY(()) prod_token_parm_item item;
|
||||
typedef struct prod_token_parm_item item;
|
||||
|
||||
/* A token from the input file. */
|
||||
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
/*
|
||||
|
||||
TREELANG Compiler back end interface (treetree.c)
|
||||
TREELANG Compiler interface to GCC's middle end (treetree.c)
|
||||
Called by the parser.
|
||||
|
||||
If you want a working example of how to write a front end to GCC,
|
||||
you are in the right place.
|
||||
|
||||
Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
|
||||
1999, 2000, 2001, 2002, 2003, Free Software Foundation, Inc.
|
||||
1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
|
||||
|
||||
This code is based on toy.c written by Richard Kenner.
|
||||
|
||||
|
@ -19,6 +19,8 @@
|
|||
|
||||
It was adapted to TREELANG by Tim Josling 2001.
|
||||
|
||||
Updated to function-at-a-time by James A. Morrison, 2004.
|
||||
|
||||
---------------------------------------------------------------------------
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
|
@ -51,8 +53,8 @@
|
|||
need for a *lot* of bother to ensure everything is in the mark trees
|
||||
at all times. */
|
||||
|
||||
/* Note it is OK to use GCC extensions such as long long in a compiler front end.
|
||||
This is because the GCC front ends are built using GCC. */
|
||||
/* Note, it is OK to use GCC extensions such as long long in a compiler front
|
||||
end. This is because the GCC front ends are built using GCC. */
|
||||
|
||||
/* GCC headers. */
|
||||
|
||||
|
@ -61,9 +63,12 @@
|
|||
#include "coretypes.h"
|
||||
#include "tm.h"
|
||||
#include "tree.h"
|
||||
#include "tree-dump.h"
|
||||
#include "tree-iterator.h"
|
||||
#include "tree-gimple.h"
|
||||
#include "function.h"
|
||||
#include "flags.h"
|
||||
#include "output.h"
|
||||
#include "rtl.h"
|
||||
#include "ggc.h"
|
||||
#include "toplev.h"
|
||||
#include "varray.h"
|
||||
|
@ -71,6 +76,8 @@
|
|||
#include "langhooks.h"
|
||||
#include "target.h"
|
||||
|
||||
#include "cgraph.h"
|
||||
|
||||
#include "treelang.h"
|
||||
#include "treetree.h"
|
||||
#include "opts.h"
|
||||
|
@ -130,17 +137,22 @@ static tree tree_lang_unsigned_type (tree type_node);
|
|||
static tree tree_lang_signed_type (tree type_node);
|
||||
static tree tree_lang_signed_or_unsigned_type (int unsignedp, tree type);
|
||||
|
||||
/* XXX these should be static */
|
||||
void pushlevel (int ignore);
|
||||
tree poplevel (int keep, int reverse, int functionbody);
|
||||
int global_bindings_p (void);
|
||||
void insert_block (tree block);
|
||||
tree pushdecl (tree decl);
|
||||
tree getdecls (void);
|
||||
int kept_level_p (void);
|
||||
/* Functions to keep track of the current scope. */
|
||||
static void pushlevel (int ignore);
|
||||
static tree poplevel (int keep, int reverse, int functionbody);
|
||||
static tree pushdecl (tree decl);
|
||||
static tree* getstmtlist (void);
|
||||
|
||||
/* Langhooks. */
|
||||
static tree builtin_function (const char *name, tree type, int function_code,
|
||||
enum built_in_class class, const char *library_name,
|
||||
tree attrs);
|
||||
static tree getdecls (void);
|
||||
static int global_bindings_p (void);
|
||||
static void insert_block (tree);
|
||||
|
||||
static void tree_push_type_decl (tree id, tree type_node);
|
||||
static void tree_push_atomic_type_decl (tree id, tree type_node);
|
||||
static void treelang_expand_function (tree fndecl);
|
||||
|
||||
/* The front end language hooks (addresses of code for this front
|
||||
end). These are not really very language-dependent, i.e.
|
||||
|
@ -163,6 +175,12 @@ static void tree_push_atomic_type_decl (tree id, tree type_node);
|
|||
#undef LANG_HOOKS_PARSE_FILE
|
||||
#define LANG_HOOKS_PARSE_FILE treelang_parse_file
|
||||
|
||||
#undef LANG_HOOKS_CALLGRAPH_EXPAND_FUNCTION
|
||||
#define LANG_HOOKS_CALLGRAPH_EXPAND_FUNCTION treelang_expand_function
|
||||
|
||||
/* #undef LANG_HOOKS_TYPES_COMPATIBLE_P
|
||||
#define LANG_HOOKS_TYPES_COMPATIBLE_P hook_bool_tree_tree_true
|
||||
*/
|
||||
/* Hook routines and data unique to treelang. */
|
||||
|
||||
#undef LANG_HOOKS_INIT
|
||||
|
@ -243,33 +261,54 @@ tree_code_get_type (int type_num)
|
|||
void
|
||||
tree_code_if_start (tree exp, location_t loc)
|
||||
{
|
||||
tree cond_exp;
|
||||
cond_exp = build (NE_EXPR,
|
||||
TREE_TYPE (exp),
|
||||
exp,
|
||||
build1 (CONVERT_EXPR, TREE_TYPE (exp), integer_zero_node));
|
||||
emit_line_note (loc); /* Output the line number information. */
|
||||
expand_start_cond (cond_exp, /* Exit-able if nonzero. */ 0);
|
||||
tree cond_exp, cond;
|
||||
cond_exp = fold (build2 (NE_EXPR, boolean_type_node, exp,
|
||||
fold (build1 (CONVERT_EXPR, TREE_TYPE (exp), integer_zero_node))));
|
||||
SET_EXPR_LOCATION (cond_exp, loc);
|
||||
cond = build3 (COND_EXPR, void_type_node, cond_exp, NULL_TREE,
|
||||
NULL_TREE);
|
||||
SET_EXPR_LOCATION (cond, loc);
|
||||
append_to_statement_list_force (cond, getstmtlist ());
|
||||
pushlevel (0);
|
||||
}
|
||||
|
||||
/* Output the code for the else of an if statement. The else occurred
|
||||
at line LINENO in file FILENAME. */
|
||||
|
||||
void
|
||||
tree_code_if_else (location_t loc)
|
||||
tree_code_if_else (location_t loc ATTRIBUTE_UNUSED)
|
||||
{
|
||||
emit_line_note (loc); /* Output the line number information. */
|
||||
expand_start_else ();
|
||||
tree stmts = *getstmtlist ();
|
||||
tree block = poplevel (1, 0, 0);
|
||||
if (BLOCK_VARS (block))
|
||||
{
|
||||
tree bindexpr = build3 (BIND_EXPR, void_type_node, BLOCK_VARS (block),
|
||||
stmts, block);
|
||||
stmts = alloc_stmt_list ();
|
||||
append_to_statement_list (bindexpr, &stmts);
|
||||
}
|
||||
|
||||
TREE_OPERAND (STATEMENT_LIST_TAIL (*getstmtlist ())->stmt, 1) = stmts;
|
||||
pushlevel (0);
|
||||
}
|
||||
|
||||
/* Output the code for the end_if an if statement. The end_if (final brace) occurred
|
||||
at line LINENO in file FILENAME. */
|
||||
/* Output the code for the end_if an if statement. The end_if (final brace)
|
||||
occurred at line LINENO in file FILENAME. */
|
||||
|
||||
void
|
||||
tree_code_if_end (location_t loc)
|
||||
tree_code_if_end (location_t loc ATTRIBUTE_UNUSED)
|
||||
{
|
||||
emit_line_note (loc); /* Output the line number information. */
|
||||
expand_end_cond ();
|
||||
tree stmts = *getstmtlist ();
|
||||
tree block = poplevel (1, 0, 0);
|
||||
if (BLOCK_VARS (block))
|
||||
{
|
||||
tree bindexpr = build3 (BIND_EXPR, void_type_node, BLOCK_VARS (block),
|
||||
stmts, block);
|
||||
stmts = alloc_stmt_list ();
|
||||
append_to_statement_list (bindexpr, &stmts);
|
||||
}
|
||||
|
||||
TREE_OPERAND (STATEMENT_LIST_TAIL (*getstmtlist ())->stmt, 2) = stmts;
|
||||
}
|
||||
|
||||
/* Create a function. The prototype name is NAME, storage class is
|
||||
|
@ -297,7 +336,7 @@ tree_code_create_function_prototype (unsigned char* chars,
|
|||
{
|
||||
if (parm->category != parameter_category)
|
||||
abort ();
|
||||
type_node = get_type_for_numeric_type (parm->type);
|
||||
type_node = tree_code_get_type (parm->type);
|
||||
type_list = tree_cons (NULL_TREE, type_node, type_list);
|
||||
}
|
||||
/* Last parm if void indicates fixed length list (as opposed to
|
||||
|
@ -306,20 +345,18 @@ tree_code_create_function_prototype (unsigned char* chars,
|
|||
/* The back end needs them in reverse order. */
|
||||
type_list = nreverse (type_list);
|
||||
|
||||
type_node = get_type_for_numeric_type (ret_type);
|
||||
type_node = tree_code_get_type (ret_type);
|
||||
fn_type = build_function_type (type_node, type_list);
|
||||
|
||||
id = get_identifier ((const char*)chars);
|
||||
fn_decl = build_decl (FUNCTION_DECL, id, fn_type);
|
||||
|
||||
DECL_CONTEXT (fn_decl) = NULL_TREE; /* Nested functions not supported here. */
|
||||
/* Nested functions not supported here. */
|
||||
DECL_CONTEXT (fn_decl) = NULL_TREE;
|
||||
DECL_SOURCE_LOCATION (fn_decl) = loc;
|
||||
|
||||
TREE_USED (fn_decl) = 1;
|
||||
|
||||
/* Real name (optional). */
|
||||
SET_DECL_ASSEMBLER_NAME (fn_decl, DECL_NAME (fn_decl));
|
||||
|
||||
TREE_PUBLIC (fn_decl) = 0;
|
||||
DECL_EXTERNAL (fn_decl) = 0;
|
||||
TREE_STATIC (fn_decl) = 0;
|
||||
|
@ -340,7 +377,6 @@ tree_code_create_function_prototype (unsigned char* chars,
|
|||
DECL_EXTERNAL (fn_decl) = 1;
|
||||
break;
|
||||
|
||||
|
||||
case AUTOMATIC_STORAGE:
|
||||
default:
|
||||
abort ();
|
||||
|
@ -364,8 +400,6 @@ tree_code_create_function_initial (tree prev_saved,
|
|||
{
|
||||
tree fn_decl;
|
||||
tree param_decl;
|
||||
tree next_param;
|
||||
tree first_param;
|
||||
tree parm_decl;
|
||||
tree parm_list;
|
||||
tree resultdecl;
|
||||
|
@ -388,15 +422,14 @@ tree_code_create_function_initial (tree prev_saved,
|
|||
|
||||
DECL_SOURCE_LOCATION (fn_decl) = loc;
|
||||
|
||||
/* Prepare creation of rtl for a new function. */
|
||||
|
||||
resultdecl = DECL_RESULT (fn_decl)
|
||||
= build_decl (RESULT_DECL, NULL_TREE, TREE_TYPE (TREE_TYPE (fn_decl)));
|
||||
DECL_CONTEXT (DECL_RESULT (fn_decl)) = fn_decl;
|
||||
/* Create a DECL for the functions result. */
|
||||
resultdecl =
|
||||
build_decl (RESULT_DECL, NULL_TREE, TREE_TYPE (TREE_TYPE (fn_decl)));
|
||||
DECL_CONTEXT (resultdecl) = fn_decl;
|
||||
DECL_ARTIFICIAL (resultdecl) = 1;
|
||||
DECL_IGNORED_P (resultdecl) = 1;
|
||||
DECL_SOURCE_LOCATION (resultdecl) = loc;
|
||||
|
||||
/* Work out the size. ??? is this needed. */
|
||||
layout_decl (DECL_RESULT (fn_decl), 0);
|
||||
DECL_RESULT (fn_decl) = resultdecl;
|
||||
|
||||
/* Make the argument variable decls. */
|
||||
parm_list = NULL_TREE;
|
||||
|
@ -404,7 +437,7 @@ tree_code_create_function_initial (tree prev_saved,
|
|||
{
|
||||
parm_decl = build_decl (PARM_DECL, get_identifier
|
||||
((const char*) (parm->tp.par.variable_name)),
|
||||
get_type_for_numeric_type (parm->type));
|
||||
tree_code_get_type (parm->type));
|
||||
|
||||
/* Some languages have different nominal and real types. */
|
||||
DECL_ARG_TYPE (parm_decl) = TREE_TYPE (parm_decl);
|
||||
|
@ -436,58 +469,15 @@ tree_code_create_function_initial (tree prev_saved,
|
|||
if (this_parm)
|
||||
abort (); /* Too many. */
|
||||
|
||||
/* Output the decl rtl (not the rtl for the function code). ???.
|
||||
If the function is not defined in this file, when should you
|
||||
execute this? */
|
||||
make_decl_rtl (fn_decl);
|
||||
|
||||
init_function_start (fn_decl);
|
||||
|
||||
/* Create rtl for startup code of function, such as saving registers. */
|
||||
|
||||
expand_function_start (fn_decl, 0);
|
||||
|
||||
/* Function.c requires a push at the start of the function. that
|
||||
looks like a bug to me but let's make it happy. */
|
||||
/* Create a new level at the start of the function. */
|
||||
|
||||
pushlevel (0);
|
||||
|
||||
/* Create rtl for the start of a new scope. */
|
||||
|
||||
expand_start_bindings (2);
|
||||
|
||||
/* Put the parameters into the symbol table. */
|
||||
|
||||
for (first_param = param_decl = nreverse (DECL_ARGUMENTS (fn_decl));
|
||||
param_decl;
|
||||
param_decl = next_param)
|
||||
{
|
||||
next_param = TREE_CHAIN (param_decl);
|
||||
TREE_CHAIN (param_decl) = NULL;
|
||||
/* layout_decl (param_decl, 0); Already done in build_decl tej 13/4/2002. */
|
||||
pushdecl (param_decl);
|
||||
if (DECL_CONTEXT (param_decl) != current_function_decl)
|
||||
abort ();
|
||||
}
|
||||
|
||||
/* Store back the PARM_DECL nodes. They appear in the right order. */
|
||||
DECL_ARGUMENTS (fn_decl) = getdecls ();
|
||||
|
||||
/* Force it to be output, else may be solely inlined. */
|
||||
TREE_ADDRESSABLE (fn_decl) = 1;
|
||||
|
||||
/* Stop -O3 from deleting it. */
|
||||
TREE_USED (fn_decl) = 1;
|
||||
|
||||
/* Add a new level to the debugger symbol table. */
|
||||
|
||||
pushlevel (0);
|
||||
|
||||
/* Create rtl for the start of a new scope. */
|
||||
|
||||
expand_start_bindings (0);
|
||||
|
||||
emit_line_note (loc); /* Output the line number information. */
|
||||
}
|
||||
|
||||
/* Wrapup a function contained in file FILENAME, ending at line LINENO. */
|
||||
|
@ -496,42 +486,38 @@ tree_code_create_function_wrapup (location_t loc)
|
|||
{
|
||||
tree block;
|
||||
tree fn_decl;
|
||||
tree stmts = *getstmtlist ();
|
||||
|
||||
fn_decl = current_function_decl;
|
||||
|
||||
emit_line_note (loc); /* Output the line number information. */
|
||||
|
||||
/* Get completely built level from debugger symbol table. */
|
||||
|
||||
block = poplevel (1, 0, 0);
|
||||
|
||||
/* Emit rtl for end of scope. */
|
||||
|
||||
expand_end_bindings (block, 0, 1);
|
||||
|
||||
/* Emit rtl for end of function. */
|
||||
|
||||
expand_function_end ();
|
||||
|
||||
/* Pop the level. */
|
||||
|
||||
block = poplevel (1, 0, 1);
|
||||
|
||||
/* And attach it to the function. */
|
||||
|
||||
DECL_INITIAL (fn_decl) = block;
|
||||
DECL_SAVED_TREE (fn_decl) = build3 (BIND_EXPR, void_type_node,
|
||||
BLOCK_VARS (block),
|
||||
stmts, block);
|
||||
|
||||
/* Emit rtl for end of scope. */
|
||||
allocate_struct_function (fn_decl);
|
||||
cfun->function_end_locus = loc;
|
||||
|
||||
expand_end_bindings (block, 0, 1);
|
||||
|
||||
/* Call optimization and convert optimized rtl to assembly code. */
|
||||
/* Dump the original tree to a file. */
|
||||
dump_function (TDI_original, fn_decl);
|
||||
|
||||
rest_of_compilation (fn_decl);
|
||||
/* Convert current function to GIMPLE for the middle end. */
|
||||
gimplify_function_tree (fn_decl);
|
||||
dump_function (TDI_generic, fn_decl);
|
||||
|
||||
/* We are not inside of any scope now. */
|
||||
|
||||
current_function_decl = NULL_TREE;
|
||||
cfun = NULL;
|
||||
|
||||
/* Pass the current function off to the middle end. */
|
||||
(void)cgraph_node (fn_decl);
|
||||
cgraph_finalize_function (fn_decl, false);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -556,7 +542,7 @@ tree_code_create_variable (unsigned int storage_class,
|
|||
tree var_decl;
|
||||
|
||||
/* 1. Build the type. */
|
||||
var_type = get_type_for_numeric_type (expression_type);
|
||||
var_type = tree_code_get_type (expression_type);
|
||||
|
||||
/* 2. Build the name. */
|
||||
if (chars[length] != 0)
|
||||
|
@ -569,13 +555,10 @@ tree_code_create_variable (unsigned int storage_class,
|
|||
|
||||
/* 3a. Initialization. */
|
||||
if (init)
|
||||
DECL_INITIAL (var_decl) = build1 (CONVERT_EXPR, var_type, init);
|
||||
DECL_INITIAL (var_decl) = fold (build1 (CONVERT_EXPR, var_type, init));
|
||||
else
|
||||
DECL_INITIAL (var_decl) = NULL_TREE;
|
||||
|
||||
/* 4. Compute size etc. */
|
||||
layout_decl (var_decl, 0);
|
||||
|
||||
if (TYPE_SIZE (var_type) == 0)
|
||||
abort (); /* Did not calculate size. */
|
||||
|
||||
|
@ -617,13 +600,8 @@ tree_code_create_variable (unsigned int storage_class,
|
|||
|
||||
if (TREE_STATIC (var_decl))
|
||||
rest_of_decl_compilation (var_decl, 0, 0);
|
||||
else
|
||||
{
|
||||
expand_decl (var_decl);
|
||||
if (DECL_INITIAL (var_decl))
|
||||
expand_decl_init (var_decl);
|
||||
}
|
||||
|
||||
TYPE_NAME (TREE_TYPE (var_decl)) = TYPE_NAME (var_type);
|
||||
return pushdecl (copy_node (var_decl));
|
||||
|
||||
}
|
||||
|
@ -646,28 +624,33 @@ tree_code_generate_return (tree type, tree exp)
|
|||
abort ();
|
||||
}
|
||||
|
||||
if (exp)
|
||||
if (exp && TREE_TYPE (TREE_TYPE (current_function_decl)) != void_type_node)
|
||||
{
|
||||
setret = build (MODIFY_EXPR, type, DECL_RESULT (current_function_decl),
|
||||
build1 (CONVERT_EXPR, type, exp));
|
||||
setret = fold (build2 (MODIFY_EXPR, type,
|
||||
DECL_RESULT (current_function_decl),
|
||||
fold (build1 (CONVERT_EXPR, type, exp))));
|
||||
TREE_SIDE_EFFECTS (setret) = 1;
|
||||
TREE_USED (setret) = 1;
|
||||
expand_expr_stmt (setret);
|
||||
setret = build1 (RETURN_EXPR, type, setret);
|
||||
}
|
||||
expand_return (DECL_RESULT (current_function_decl));
|
||||
else
|
||||
setret = build1 (RETURN_EXPR, type, NULL_TREE);
|
||||
|
||||
append_to_statement_list_force (setret, getstmtlist ());
|
||||
}
|
||||
|
||||
/* Output the code for this expression statement CODE. */
|
||||
|
||||
/* Output the code for this expression statement CODE. */
|
||||
|
||||
void
|
||||
tree_code_output_expression_statement (tree code, location_t loc)
|
||||
{
|
||||
/* Output the line number information. */
|
||||
emit_line_note (loc);
|
||||
SET_EXPR_LOCATION (code, loc);
|
||||
TREE_USED (code) = 1;
|
||||
TREE_SIDE_EFFECTS (code) = 1;
|
||||
expand_expr_stmt (code);
|
||||
/* put CODE into the code list. */
|
||||
append_to_statement_list_force (code, getstmtlist ());
|
||||
}
|
||||
|
||||
/* Return a tree for a constant integer value in the token TOK. No
|
||||
|
@ -716,9 +699,8 @@ tree_code_get_expression (unsigned int exp_type,
|
|||
if (!op1 || !op2)
|
||||
abort ();
|
||||
operator = MODIFY_EXPR;
|
||||
ret1 = build (operator, type,
|
||||
op1,
|
||||
build1 (CONVERT_EXPR, type, op2));
|
||||
ret1 = fold (build2 (operator, void_type_node, op1,
|
||||
fold (build1 (CONVERT_EXPR, TREE_TYPE (op1), op2))));
|
||||
|
||||
break;
|
||||
|
||||
|
@ -734,13 +716,13 @@ tree_code_get_expression (unsigned int exp_type,
|
|||
operator = EQ_EXPR;
|
||||
goto binary_expression;
|
||||
|
||||
/* Expand a binary expression. Ensure the operands are the right type. */
|
||||
/* Expand a binary expression. Ensure the operands are the right type. */
|
||||
binary_expression:
|
||||
if (!op1 || !op2)
|
||||
abort ();
|
||||
ret1 = build (operator, type,
|
||||
build1 (CONVERT_EXPR, type, op1),
|
||||
build1 (CONVERT_EXPR, type, op2));
|
||||
ret1 = fold (build2 (operator, type,
|
||||
fold (build1 (CONVERT_EXPR, type, op1)),
|
||||
fold (build1 (CONVERT_EXPR, type, op2))));
|
||||
break;
|
||||
|
||||
/* Reference to a variable. This is dead easy, just return the
|
||||
|
@ -752,16 +734,18 @@ tree_code_get_expression (unsigned int exp_type,
|
|||
if (type == TREE_TYPE (op1))
|
||||
ret1 = op1;
|
||||
else
|
||||
ret1 = build1 (CONVERT_EXPR, type, op1);
|
||||
ret1 = fold (build1 (CONVERT_EXPR, type, op1));
|
||||
break;
|
||||
|
||||
case EXP_FUNCTION_INVOCATION:
|
||||
if (!op1 || !op2)
|
||||
abort ();
|
||||
|
||||
{
|
||||
tree fun_ptr;
|
||||
fun_ptr = build1 (ADDR_EXPR, build_pointer_type (type), op1);
|
||||
ret1 = build (CALL_EXPR, type, fun_ptr, nreverse (op2));
|
||||
fun_ptr = fold (build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (op1)),
|
||||
op1));
|
||||
ret1 = build3 (CALL_EXPR, type, fun_ptr, nreverse (op2), NULL_TREE);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -788,83 +772,13 @@ tree_code_add_parameter (tree list, tree proto_exp, tree exp)
|
|||
{
|
||||
tree new_exp;
|
||||
new_exp = tree_cons (NULL_TREE,
|
||||
build1 (CONVERT_EXPR, TREE_TYPE (proto_exp), exp),
|
||||
NULL_TREE);
|
||||
fold (build1 (CONVERT_EXPR, TREE_TYPE (proto_exp), exp)),
|
||||
NULL_TREE);
|
||||
if (!list)
|
||||
return new_exp;
|
||||
return chainon (new_exp, list);
|
||||
}
|
||||
|
||||
/* Get the tree type for this type whose number is NUMERIC_TYPE. */
|
||||
|
||||
tree
|
||||
get_type_for_numeric_type (unsigned int numeric_type)
|
||||
{
|
||||
|
||||
int size1;
|
||||
int sign1;
|
||||
switch (numeric_type)
|
||||
{
|
||||
case VOID_TYPE:
|
||||
return void_type_node;
|
||||
|
||||
case SIGNED_INT:
|
||||
size1 = tree_code_int_size;
|
||||
sign1 = 1;
|
||||
break;
|
||||
|
||||
case UNSIGNED_INT:
|
||||
size1 = tree_code_int_size;
|
||||
sign1 = 0;
|
||||
break;
|
||||
|
||||
case SIGNED_CHAR:
|
||||
size1 = tree_code_char_size;
|
||||
sign1 = 1;
|
||||
break;
|
||||
|
||||
case UNSIGNED_CHAR:
|
||||
size1 = tree_code_char_size;
|
||||
sign1 = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
|
||||
return tree_code_get_numeric_type (size1, sign1);
|
||||
|
||||
}
|
||||
|
||||
/* Return tree representing a numeric type of size SIZE1 bits and
|
||||
signed if SIGN1 != 0. */
|
||||
tree
|
||||
tree_code_get_numeric_type (unsigned int size1, unsigned int sign1)
|
||||
{
|
||||
tree ret1;
|
||||
if (!size1)
|
||||
abort ();
|
||||
if (size1 == tree_code_int_size)
|
||||
{
|
||||
if (sign1)
|
||||
ret1 = integer_type_node;
|
||||
else
|
||||
ret1 = unsigned_type_node;
|
||||
}
|
||||
else
|
||||
if (size1 == tree_code_char_size)
|
||||
{
|
||||
if (sign1)
|
||||
ret1 = signed_char_type_node;
|
||||
else
|
||||
ret1 = unsigned_char_type_node;
|
||||
}
|
||||
else
|
||||
abort ();
|
||||
|
||||
return ret1;
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
|
@ -1056,6 +970,8 @@ struct binding_level
|
|||
/* 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;
|
||||
|
||||
tree stmts;
|
||||
/* The binding level containing this one (the enclosing binding level). */
|
||||
struct binding_level *level_chain;
|
||||
};
|
||||
|
@ -1068,37 +984,38 @@ static struct binding_level *current_binding_level = NULL;
|
|||
static struct binding_level *global_binding_level;
|
||||
|
||||
/* Binding level structures are initialized by copying this one. */
|
||||
static struct binding_level clear_binding_level = {NULL, NULL, NULL };
|
||||
static struct binding_level clear_binding_level = {NULL, NULL, NULL, NULL };
|
||||
|
||||
/* Return non-zero if we are currently in the global binding level. */
|
||||
|
||||
int
|
||||
static int
|
||||
global_bindings_p (void)
|
||||
{
|
||||
return current_binding_level == global_binding_level ? -1 : 0;
|
||||
}
|
||||
|
||||
|
||||
/* 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
|
||||
static tree
|
||||
getdecls (void)
|
||||
{
|
||||
return current_binding_level->names;
|
||||
}
|
||||
|
||||
/* Nonzero if the current level needs to have a BLOCK made. */
|
||||
/* Return a STATMENT_LIST for the current block. */
|
||||
|
||||
int
|
||||
kept_level_p (void)
|
||||
static tree*
|
||||
getstmtlist (void)
|
||||
{
|
||||
return (current_binding_level->names != 0);
|
||||
return ¤t_binding_level->stmts;
|
||||
}
|
||||
|
||||
/* Enter a new binding level. The input parameter is ignored, but has to be
|
||||
specified for back-end compatibility. */
|
||||
|
||||
void
|
||||
static void
|
||||
pushlevel (int ignore ATTRIBUTE_UNUSED)
|
||||
{
|
||||
struct binding_level *newlevel = xmalloc (sizeof (struct binding_level));
|
||||
|
@ -1109,6 +1026,7 @@ pushlevel (int ignore ATTRIBUTE_UNUSED)
|
|||
active. */
|
||||
newlevel->level_chain = current_binding_level;
|
||||
current_binding_level = newlevel;
|
||||
current_binding_level->stmts = alloc_stmt_list ();
|
||||
}
|
||||
|
||||
/* Exit a binding level.
|
||||
|
@ -1126,7 +1044,7 @@ pushlevel (int ignore ATTRIBUTE_UNUSED)
|
|||
If REVERSE is nonzero, reverse the order of decls before putting
|
||||
them into the BLOCK. */
|
||||
|
||||
tree
|
||||
static tree
|
||||
poplevel (int keep, int reverse, int functionbody)
|
||||
{
|
||||
/* Points to a BLOCK tree node. This is the BLOCK node construted for the
|
||||
|
@ -1166,8 +1084,6 @@ poplevel (int keep, int reverse, int functionbody)
|
|||
{
|
||||
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. */
|
||||
|
@ -1175,12 +1091,8 @@ poplevel (int keep, int reverse, int functionbody)
|
|||
|
||||
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. */
|
||||
/* This is the top level block of a function. */
|
||||
DECL_INITIAL (current_function_decl) = block_node;
|
||||
BLOCK_VARS (block_node) = 0;
|
||||
}
|
||||
else if (block_node)
|
||||
{
|
||||
|
@ -1205,7 +1117,7 @@ poplevel (int keep, int reverse, int functionbody)
|
|||
current binding level. This is used when a BIND_EXPR is expanded,
|
||||
to handle the BLOCK node inside the BIND_EXPR. */
|
||||
|
||||
void
|
||||
static void
|
||||
insert_block (tree block)
|
||||
{
|
||||
TREE_USED (block) = 1;
|
||||
|
@ -1213,6 +1125,7 @@ insert_block (tree block)
|
|||
= chainon (current_binding_level->blocks, block);
|
||||
}
|
||||
|
||||
|
||||
/* Records a ..._DECL node DECL as belonging to the current lexical scope.
|
||||
Returns the ..._DECL node. */
|
||||
|
||||
|
@ -1247,22 +1160,10 @@ static void
|
|||
tree_push_type_decl(tree id, tree type_node)
|
||||
{
|
||||
tree decl = build_decl (TYPE_DECL, id, type_node);
|
||||
TYPE_NAME (type_node) = decl;
|
||||
TYPE_STUB_DECL (type_node) = decl;
|
||||
TYPE_NAME (type_node) = id;
|
||||
pushdecl (decl);
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
|
||||
static void
|
||||
tree_push_atomic_type_decl(tree id, tree type_node)
|
||||
{
|
||||
TREE_TYPE (type_node) = type_node;
|
||||
tree_push_type_decl (id, type_node);
|
||||
}
|
||||
|
||||
#define NULL_BINDING_LEVEL (struct binding_level *) NULL
|
||||
|
||||
/* Create the predefined scalar types of C,
|
||||
|
@ -1282,53 +1183,52 @@ treelang_init_decl_processing (void)
|
|||
|
||||
/* set standard type names */
|
||||
|
||||
/* Define `int' and `char' first so that dbx will output them first. */
|
||||
/* Define `int' and `char' last so that they are not overwritten. */
|
||||
tree_push_type_decl (NULL_TREE, intQI_type_node);
|
||||
tree_push_type_decl (NULL_TREE, intHI_type_node);
|
||||
tree_push_type_decl (NULL_TREE, intSI_type_node);
|
||||
tree_push_type_decl (NULL_TREE, intDI_type_node);
|
||||
#if HOST_BITS_PER_WIDE_INT >= 64
|
||||
tree_push_type_decl (NULL_TREE, intTI_type_node);
|
||||
#endif
|
||||
tree_push_type_decl (NULL_TREE, unsigned_intQI_type_node);
|
||||
tree_push_type_decl (NULL_TREE, unsigned_intHI_type_node);
|
||||
tree_push_type_decl (NULL_TREE, unsigned_intSI_type_node);
|
||||
tree_push_type_decl (NULL_TREE, unsigned_intDI_type_node);
|
||||
#if HOST_BITS_PER_WIDE_INT >= 64
|
||||
tree_push_type_decl (NULL_TREE, unsigned_intTI_type_node);
|
||||
#endif
|
||||
|
||||
tree_push_atomic_type_decl (get_identifier ("int"), integer_type_node);
|
||||
tree_push_atomic_type_decl (get_identifier ("char"), char_type_node);
|
||||
tree_push_atomic_type_decl (get_identifier ("long int"),
|
||||
tree_push_type_decl (get_identifier ("int"), integer_type_node);
|
||||
tree_push_type_decl (get_identifier ("char"), char_type_node);
|
||||
tree_push_type_decl (get_identifier ("long int"),
|
||||
long_integer_type_node);
|
||||
tree_push_atomic_type_decl (get_identifier ("unsigned int"),
|
||||
tree_push_type_decl (get_identifier ("unsigned int"),
|
||||
unsigned_type_node);
|
||||
tree_push_atomic_type_decl (get_identifier ("long unsigned int"),
|
||||
tree_push_type_decl (get_identifier ("long unsigned int"),
|
||||
long_unsigned_type_node);
|
||||
tree_push_atomic_type_decl (get_identifier ("long long int"),
|
||||
tree_push_type_decl (get_identifier ("long long int"),
|
||||
long_long_integer_type_node);
|
||||
tree_push_atomic_type_decl (get_identifier ("long long unsigned int"),
|
||||
tree_push_type_decl (get_identifier ("long long unsigned int"),
|
||||
long_long_unsigned_type_node);
|
||||
tree_push_atomic_type_decl (get_identifier ("short int"),
|
||||
tree_push_type_decl (get_identifier ("short int"),
|
||||
short_integer_type_node);
|
||||
tree_push_atomic_type_decl (get_identifier ("short unsigned int"),
|
||||
tree_push_type_decl (get_identifier ("short unsigned int"),
|
||||
short_unsigned_type_node);
|
||||
tree_push_atomic_type_decl (get_identifier ("signed char"),
|
||||
tree_push_type_decl (get_identifier ("signed char"),
|
||||
signed_char_type_node);
|
||||
tree_push_atomic_type_decl (get_identifier ("unsigned char"),
|
||||
tree_push_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);
|
||||
tree_push_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);
|
||||
tree_push_type_decl (get_identifier ("float"), float_type_node);
|
||||
tree_push_type_decl (get_identifier ("double"), double_type_node);
|
||||
tree_push_type_decl (get_identifier ("long double"), long_double_type_node);
|
||||
tree_push_type_decl (get_identifier ("void"), void_type_node);
|
||||
|
||||
/* Add any target-specific builtin functions. */
|
||||
(*targetm.init_builtins) ();
|
||||
|
@ -1348,7 +1248,7 @@ treelang_init_decl_processing (void)
|
|||
copied from gcc/c-decl.c
|
||||
*/
|
||||
|
||||
tree
|
||||
static tree
|
||||
builtin_function (const char *name, tree type, int function_code,
|
||||
enum built_in_class class, const char *library_name,
|
||||
tree attrs)
|
||||
|
@ -1358,7 +1258,6 @@ builtin_function (const char *name, tree type, int function_code,
|
|||
TREE_PUBLIC (decl) = 1;
|
||||
if (library_name)
|
||||
SET_DECL_ASSEMBLER_NAME (decl, get_identifier (library_name));
|
||||
make_decl_rtl (decl);
|
||||
pushdecl (decl);
|
||||
DECL_BUILT_IN_CLASS (decl) = class;
|
||||
DECL_FUNCTION_CODE (decl) = function_code;
|
||||
|
@ -1372,5 +1271,14 @@ builtin_function (const char *name, tree type, int function_code,
|
|||
return decl;
|
||||
}
|
||||
|
||||
/* Treelang expand function langhook. */
|
||||
|
||||
static void
|
||||
treelang_expand_function (tree fndecl)
|
||||
{
|
||||
/* We have nothing special to do while expanding functions for treelang. */
|
||||
tree_rest_of_compilation (fndecl, 0);
|
||||
}
|
||||
|
||||
#include "debug.h" /* for debug_hooks, needed by gt-treelang-treetree.h */
|
||||
#include "gt-treelang-treetree.h"
|
||||
|
|
|
@ -3,7 +3,8 @@
|
|||
TREELANG Compiler definitions for interfacing to treetree.c
|
||||
(compiler back end interface).
|
||||
|
||||
Copyright (C) 1986, 87, 89, 92-96, 1997, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
|
||||
Copyright (C) 1986, 87, 89, 92-96, 1997, 1999, 2000, 2001, 2002, 2003, 2004
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by the
|
||||
|
@ -55,7 +56,6 @@ tree tree_code_create_variable (unsigned int storage_class,
|
|||
location_t loc);
|
||||
void tree_code_output_expression_statement (tree code,
|
||||
location_t loc);
|
||||
tree get_type_for_numeric_type (unsigned int numeric_type);
|
||||
void tree_code_if_start (tree exp, location_t loc);
|
||||
void tree_code_if_else (location_t loc);
|
||||
void tree_code_if_end (location_t loc);
|
||||
|
|
Loading…
Reference in New Issue