blob: 2809003fdab11030be550c41905938ec1f079b85 [file] [log] [blame]
/* Implement grant-file output & seize-file input for CHILL.
Copyright (C) 1992, 93, 94, 95, 1996, 1998 Free Software Foundation, Inc.
This file is part of GNU CC.
GNU CC 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.
GNU CC 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 GNU CC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include "config.h"
#include "system.h"
#include "tree.h"
#include "ch-tree.h"
#include "lex.h"
#include "flags.h"
#include "actions.h"
#include "input.h"
#include "rtl.h"
#include "tasking.h"
#include "toplev.h"
#include "output.h"
#define APPEND(X,Y) X = append (X, Y)
#define PREPEND(X,Y) X = prepend (X, Y);
#define FREE(x) strfree (x)
#define ALLOCAMOUNT 10000
/* may be we can handle this in a more exciting way,
but this also should work for the moment */
#define MAYBE_NEWLINE(X) \
do \
{ \
if (X->len && X->str[X->len - 1] != '\n') \
APPEND (X, ";\n"); \
} while (0)
extern tree process_type;
extern char *asm_file_name;
extern char *dump_base_name;
/* forward declarations */
/* variable indicates compilation at module level */
int chill_at_module_level = 0;
/* mark that a SPEC MODULE was generated */
static int spec_module_generated = 0;
/* define version strings */
extern char *gnuchill_version;
extern char *version_string;
/* define a faster string handling */
typedef struct
{
char *str;
int len;
int allocated;
} MYSTRING;
/* structure used for handling multiple grant files */
char *grant_file_name;
MYSTRING *gstring = NULL;
MYSTRING *selective_gstring = NULL;
static MYSTRING *decode_decl PROTO((tree));
static MYSTRING *decode_constant PROTO((tree));
static void grant_one_decl PROTO((tree));
static MYSTRING *get_type PROTO((tree));
static MYSTRING *decode_mode PROTO((tree));
static MYSTRING *decode_prefix_rename PROTO((tree));
static MYSTRING *decode_constant_selective PROTO((tree, tree));
static MYSTRING *decode_mode_selective PROTO((tree, tree));
static MYSTRING *get_type_selective PROTO((tree, tree));
static MYSTRING *decode_decl_selective PROTO((tree, tree));
/* list of the VAR_DECLs of the module initializer entries */
tree module_init_list = NULL_TREE;
/* handle different USE_SEIZE_FILE's in case of selective granting */
typedef struct SEIZEFILELIST
{
struct SEIZEFILELIST *next;
tree filename;
MYSTRING *seizes;
} seizefile_list;
static seizefile_list *selective_seizes = 0;
static MYSTRING *
newstring (str)
char *str;
{
MYSTRING *tmp = (MYSTRING *) xmalloc (sizeof (MYSTRING));
unsigned len = strlen (str);
tmp->allocated = len + ALLOCAMOUNT;
tmp->str = xmalloc ((unsigned)tmp->allocated);
strcpy (tmp->str, str);
tmp->len = len;
return (tmp);
}
static void
strfree (str)
MYSTRING *str;
{
free (str->str);
free (str);
}
static MYSTRING *
append (inout, in)
MYSTRING *inout;
char *in;
{
int inlen = strlen (in);
int amount = ALLOCAMOUNT;
if (inlen >= amount)
amount += inlen;
if ((inout->len + inlen) >= inout->allocated)
inout->str = xrealloc (inout->str, inout->allocated += amount);
strcpy (inout->str + inout->len, in);
inout->len += inlen;
return (inout);
}
static MYSTRING *
prepend (inout, in)
MYSTRING *inout;
char *in;
{
MYSTRING *res = inout;
if (strlen (in))
{
res = newstring (in);
res = APPEND (res, inout->str);
FREE (inout);
}
return res;
}
void
grant_use_seizefile (seize_filename)
char *seize_filename;
{
APPEND (gstring, "<> USE_SEIZE_FILE \"");
APPEND (gstring, seize_filename);
APPEND (gstring, "\" <>\n");
}
static MYSTRING *
decode_layout (layout)
tree layout;
{
tree temp;
tree stepsize = NULL_TREE;
int was_step = 0;
MYSTRING *result = newstring ("");
MYSTRING *work;
if (layout == integer_zero_node) /* NOPACK */
{
APPEND (result, " NOPACK");
return result;
}
if (layout == integer_one_node) /* PACK */
{
APPEND (result, " PACK");
return result;
}
APPEND (result, " ");
temp = layout;
if (TREE_PURPOSE (temp) == NULL_TREE)
{
APPEND (result, "STEP(");
was_step = 1;
temp = TREE_VALUE (temp);
stepsize = TREE_VALUE (temp);
}
APPEND (result, "POS(");
/* Get the starting word */
temp = TREE_PURPOSE (temp);
work = decode_constant (TREE_PURPOSE (temp));
APPEND (result, work->str);
FREE (work);
temp = TREE_VALUE (temp);
if (temp != NULL_TREE)
{
/* Get the starting bit */
APPEND (result, ", ");
work = decode_constant (TREE_PURPOSE (temp));
APPEND (result, work->str);
FREE (work);
temp = TREE_VALUE (temp);
if (temp != NULL_TREE)
{
/* Get the length or the ending bit */
tree what = TREE_PURPOSE (temp);
if (what == integer_zero_node) /* length */
{
APPEND (result, ", ");
}
else
{
APPEND (result, ":");
}
work = decode_constant (TREE_VALUE (temp));
APPEND (result, work->str);
FREE (work);
}
}
APPEND (result, ")");
if (was_step)
{
if (stepsize != NULL_TREE)
{
APPEND (result, ", ");
work = decode_constant (stepsize);
APPEND (result, work->str);
FREE (work);
}
APPEND (result, ")");
}
return result;
}
static MYSTRING *
grant_array_type (type)
tree type;
{
MYSTRING *result = newstring ("");
MYSTRING *mode_string;
tree layout;
int varying = 0;
if (chill_varying_type_p (type))
{
varying = 1;
type = CH_VARYING_ARRAY_TYPE (type);
}
if (CH_STRING_TYPE_P (type))
{
tree fields = TYPE_DOMAIN (type);
tree maxval = TYPE_MAX_VALUE (fields);
if (TREE_CODE (TREE_TYPE (type)) == CHAR_TYPE)
APPEND (result, "CHARS (");
else
APPEND (result, "BOOLS (");
if (TREE_CODE (maxval) == INTEGER_CST)
{
char wrk[20];
sprintf (wrk, HOST_WIDE_INT_PRINT_DEC,
TREE_INT_CST_LOW (maxval) + 1);
APPEND (result, wrk);
}
else if (TREE_CODE (maxval) == MINUS_EXPR
&& TREE_OPERAND (maxval, 1) == integer_one_node)
{
mode_string = decode_constant (TREE_OPERAND (maxval, 0));
APPEND (result, mode_string->str);
FREE (mode_string);
}
else
{
mode_string = decode_constant (maxval);
APPEND (result, mode_string->str);
FREE (mode_string);
APPEND (result, "+1");
}
APPEND (result, ")");
if (varying)
APPEND (result, " VARYING");
return result;
}
APPEND (result, "ARRAY (");
if (TREE_CODE (TYPE_DOMAIN (type)) == INTEGER_TYPE
&& TREE_TYPE (TYPE_DOMAIN (type)) == ridpointers[(int) RID_RANGE])
{
mode_string = decode_constant (TYPE_MIN_VALUE (TYPE_DOMAIN (type)));
APPEND (result, mode_string->str);
FREE (mode_string);
APPEND (result, ":");
mode_string = decode_constant (TYPE_MAX_VALUE (TYPE_DOMAIN (type)));
APPEND (result, mode_string->str);
FREE (mode_string);
}
else
{
mode_string = decode_mode (TYPE_DOMAIN (type));
APPEND (result, mode_string->str);
FREE (mode_string);
}
APPEND (result, ") ");
if (varying)
APPEND (result, "VARYING ");
mode_string = get_type (TREE_TYPE (type));
APPEND (result, mode_string->str);
FREE (mode_string);
layout = TYPE_ATTRIBUTES (type);
if (layout != NULL_TREE)
{
mode_string = decode_layout (layout);
APPEND (result, mode_string->str);
FREE (mode_string);
}
return result;
}
static MYSTRING *
grant_array_type_selective (type, all_decls)
tree type;
tree all_decls;
{
MYSTRING *result = newstring ("");
MYSTRING *mode_string;
int varying = 0;
if (chill_varying_type_p (type))
{
varying = 1;
type = CH_VARYING_ARRAY_TYPE (type);
}
if (CH_STRING_TYPE_P (type))
{
tree fields = TYPE_DOMAIN (type);
tree maxval = TYPE_MAX_VALUE (fields);
if (TREE_CODE (maxval) != INTEGER_CST)
{
if (TREE_CODE (maxval) == MINUS_EXPR
&& TREE_OPERAND (maxval, 1) == integer_one_node)
{
mode_string = decode_constant_selective (TREE_OPERAND (maxval, 0), all_decls);
if (mode_string->len)
APPEND (result, mode_string->str);
FREE (mode_string);
}
else
{
mode_string = decode_constant_selective (maxval, all_decls);
if (mode_string->len)
APPEND (result, mode_string->str);
FREE (mode_string);
}
}
return result;
}
if (TREE_CODE (TYPE_DOMAIN (type)) == INTEGER_TYPE
&& TREE_TYPE (TYPE_DOMAIN (type)) == ridpointers[(int) RID_RANGE])
{
mode_string = decode_constant_selective (TYPE_MIN_VALUE (TYPE_DOMAIN (type)), all_decls);
if (mode_string->len)
APPEND (result, mode_string->str);
FREE (mode_string);
mode_string = decode_constant_selective (TYPE_MAX_VALUE (TYPE_DOMAIN (type)), all_decls);
if (mode_string->len)
{
MAYBE_NEWLINE (result);
APPEND (result, mode_string->str);
}
FREE (mode_string);
}
else
{
mode_string = decode_mode_selective (TYPE_DOMAIN (type), all_decls);
if (mode_string->len)
APPEND (result, mode_string->str);
FREE (mode_string);
}
mode_string = get_type_selective (TREE_TYPE (type), all_decls);
if (mode_string->len)
{
MAYBE_NEWLINE (result);
APPEND (result, mode_string->str);
}
FREE (mode_string);
return result;
}
static MYSTRING *
get_tag_value (val)
tree val;
{
MYSTRING *result;
if (TREE_CODE (val) == CONST_DECL && DECL_NAME (val))
{
result = newstring (IDENTIFIER_POINTER (DECL_NAME (val)));
}
else if (TREE_CODE (val) == CONST_DECL)
{
/* it's a synonym -- get the value */
result = decode_constant (DECL_INITIAL (val));
}
else
{
result = decode_constant (val);
}
return (result);
}
static MYSTRING *
get_tag_value_selective (val, all_decls)
tree val;
tree all_decls;
{
MYSTRING *result;
if (TREE_CODE (val) == CONST_DECL && DECL_NAME (val))
result = newstring ("");
else if (TREE_CODE (val) == CONST_DECL)
{
/* it's a synonym -- get the value */
result = decode_constant_selective (DECL_INITIAL (val), all_decls);
}
else
{
result = decode_constant_selective (val, all_decls);
}
return (result);
}
static MYSTRING *
print_enumeral (type)
tree type;
{
MYSTRING *result = newstring ("");
tree fields;
#if 0
if (TYPE_LANG_SPECIFIC (type) == NULL)
#endif
{
APPEND (result, "SET (");
for (fields = TYPE_VALUES (type);
fields != NULL_TREE;
fields = TREE_CHAIN (fields))
{
if (TREE_PURPOSE (fields) == NULL_TREE)
APPEND (result, "*");
else
{
tree decl = TREE_VALUE (fields);
APPEND (result, IDENTIFIER_POINTER (TREE_PURPOSE (fields)));
if (TREE_CODE (decl) == CONST_DECL && DECL_INITIAL (decl))
{
MYSTRING *val_string = decode_constant (DECL_INITIAL (decl));
APPEND (result, " = ");
APPEND (result, val_string->str);
FREE (val_string);
}
}
if (TREE_CHAIN (fields) != NULL_TREE)
APPEND (result, ",\n ");
}
APPEND (result, ")");
}
return result;
}
static MYSTRING *
print_enumeral_selective (type, all_decls)
tree type;
tree all_decls;
{
MYSTRING *result = newstring ("");
tree fields;
for (fields = TYPE_VALUES (type);
fields != NULL_TREE;
fields = TREE_CHAIN (fields))
{
if (TREE_PURPOSE (fields) != NULL_TREE)
{
tree decl = TREE_VALUE (fields);
if (TREE_CODE (decl) == CONST_DECL && DECL_INITIAL (decl))
{
MYSTRING *val_string = decode_constant_selective (DECL_INITIAL (decl), all_decls);
if (val_string->len)
APPEND (result, val_string->str);
FREE (val_string);
}
}
}
return result;
}
static MYSTRING *
print_integer_type (type)
tree type;
{
MYSTRING *result = newstring ("");
MYSTRING *mode_string;
char *name_ptr;
tree base_type;
if (TREE_TYPE (type))
{
mode_string = decode_mode (TREE_TYPE (type));
APPEND (result, mode_string->str);
FREE (mode_string);
APPEND (result, "(");
mode_string = decode_constant (TYPE_MIN_VALUE (type));
APPEND (result, mode_string->str);
FREE (mode_string);
if (TREE_TYPE (type) != ridpointers[(int) RID_BIN])
{
APPEND (result, ":");
mode_string = decode_constant (TYPE_MAX_VALUE (type));
APPEND (result, mode_string->str);
FREE (mode_string);
}
APPEND (result, ")");
return result;
}
/* We test TYPE_MAIN_VARIANT because pushdecl often builds
a copy of a built-in type node, which is logically id-
entical but has a different address, and the same
TYPE_MAIN_VARIANT. */
/* FIXME this should not be needed! */
base_type = TREE_TYPE (type) ? TREE_TYPE (type) : type;
if (TREE_UNSIGNED (base_type))
{
if (base_type == chill_unsigned_type_node
|| TYPE_MAIN_VARIANT(base_type) ==
TYPE_MAIN_VARIANT (chill_unsigned_type_node))
name_ptr = "UINT";
else if (base_type == long_integer_type_node
|| TYPE_MAIN_VARIANT(base_type) ==
TYPE_MAIN_VARIANT (long_unsigned_type_node))
name_ptr = "ULONG";
else if (type == unsigned_char_type_node
|| TYPE_MAIN_VARIANT(base_type) ==
TYPE_MAIN_VARIANT (unsigned_char_type_node))
name_ptr = "UBYTE";
else if (type == duration_timing_type_node
|| TYPE_MAIN_VARIANT (base_type) ==
TYPE_MAIN_VARIANT (duration_timing_type_node))
name_ptr = "DURATION";
else if (type == abs_timing_type_node
|| TYPE_MAIN_VARIANT (base_type) ==
TYPE_MAIN_VARIANT (abs_timing_type_node))
name_ptr = "TIME";
else
name_ptr = "UINT";
}
else
{
if (base_type == chill_integer_type_node
|| TYPE_MAIN_VARIANT (base_type) ==
TYPE_MAIN_VARIANT (chill_integer_type_node))
name_ptr = "INT";
else if (base_type == long_integer_type_node
|| TYPE_MAIN_VARIANT (base_type) ==
TYPE_MAIN_VARIANT (long_integer_type_node))
name_ptr = "LONG";
else if (type == signed_char_type_node
|| TYPE_MAIN_VARIANT (base_type) ==
TYPE_MAIN_VARIANT (signed_char_type_node))
name_ptr = "BYTE";
else
name_ptr = "INT";
}
APPEND (result, name_ptr);
/* see if we have a range */
if (TREE_TYPE (type) != NULL)
{
mode_string = decode_constant (TYPE_MIN_VALUE (type));
APPEND (result, mode_string->str);
FREE (mode_string);
APPEND (result, ":");
mode_string = decode_constant (TYPE_MAX_VALUE (type));
APPEND (result, mode_string->str);
FREE (mode_string);
}
return result;
}
static tree
find_enum_parent (enumname, all_decls)
tree enumname;
tree all_decls;
{
tree wrk;
for (wrk = all_decls; wrk != NULL_TREE; wrk = TREE_CHAIN (wrk))
{
if (TREE_TYPE (wrk) != NULL_TREE && TREE_CODE (wrk) != CONST_DECL &&
TREE_CODE (TREE_TYPE (wrk)) == ENUMERAL_TYPE)
{
tree list;
for (list = TYPE_VALUES (TREE_TYPE (wrk)); list != NULL_TREE; list = TREE_CHAIN (list))
{
if (DECL_NAME (TREE_VALUE (list)) == enumname)
return wrk;
}
}
}
return NULL_TREE;
}
static MYSTRING *
print_integer_selective (type, all_decls)
tree type;
tree all_decls;
{
MYSTRING *result = newstring ("");
MYSTRING *mode_string;
if (TREE_TYPE (type))
{
mode_string = decode_mode_selective (TREE_TYPE (type), all_decls);
if (mode_string->len)
APPEND (result, mode_string->str);
FREE (mode_string);
if (TREE_TYPE (type) == ridpointers[(int)RID_RANGE] &&
TREE_CODE (TYPE_MIN_VALUE (type)) == IDENTIFIER_NODE &&
TREE_CODE (TYPE_MAX_VALUE (type)) == IDENTIFIER_NODE)
{
/* we have a range of a set. Find parant mode and write it
to SPEC MODULE. This will loose if the parent mode was SEIZED from
another file.*/
tree minparent = find_enum_parent (TYPE_MIN_VALUE (type), all_decls);
tree maxparent = find_enum_parent (TYPE_MAX_VALUE (type), all_decls);
if (minparent != NULL_TREE)
{
if (! CH_ALREADY_GRANTED (minparent))
{
mode_string = decode_decl (minparent);
if (mode_string->len)
APPEND (result, mode_string->str);
FREE (mode_string);
CH_ALREADY_GRANTED (minparent) = 1;
}
}
if (minparent != maxparent && maxparent != NULL_TREE)
{
if (!CH_ALREADY_GRANTED (maxparent))
{
mode_string = decode_decl (maxparent);
if (mode_string->len)
{
MAYBE_NEWLINE (result);
APPEND (result, mode_string->str);
}
FREE (mode_string);
CH_ALREADY_GRANTED (maxparent) = 1;
}
}
}
else
{
mode_string = decode_constant_selective (TYPE_MIN_VALUE (type), all_decls);
if (mode_string->len)
{
MAYBE_NEWLINE (result);
APPEND (result, mode_string->str);
}
FREE (mode_string);
mode_string = decode_constant_selective (TYPE_MAX_VALUE (type), all_decls);
if (mode_string->len)
{
MAYBE_NEWLINE (result);
APPEND (result, mode_string->str);
}
FREE (mode_string);
}
return result;
}
/* see if we have a range */
if (TREE_TYPE (type) != NULL)
{
mode_string = decode_constant_selective (TYPE_MIN_VALUE (type), all_decls);
if (mode_string->len)
APPEND (result, mode_string->str);
FREE (mode_string);
mode_string = decode_constant_selective (TYPE_MAX_VALUE (type), all_decls);
if (mode_string->len)
{
MAYBE_NEWLINE (result);
APPEND (result, mode_string->str);
}
FREE (mode_string);
}
return result;
}
static MYSTRING *
print_struct (type)
tree type;
{
MYSTRING *result = newstring ("");
MYSTRING *mode_string;
tree fields;
if (chill_varying_type_p (type))
{
mode_string = grant_array_type (type);
APPEND (result, mode_string->str);
FREE (mode_string);
}
else
{
fields = TYPE_FIELDS (type);
APPEND (result, "STRUCT (");
while (fields != NULL_TREE)
{
if (TREE_CODE (TREE_TYPE (fields)) == UNION_TYPE)
{
tree variants;
/* Format a tagged variant record type. */
APPEND (result, " CASE ");
if (TYPE_TAGFIELDS (TREE_TYPE (fields)) != NULL_TREE)
{
tree tag_list = TYPE_TAGFIELDS (TREE_TYPE (fields));
for (;;)
{
tree tag_name = DECL_NAME (TREE_VALUE (tag_list));
APPEND (result, IDENTIFIER_POINTER (tag_name));
tag_list = TREE_CHAIN (tag_list);
if (tag_list == NULL_TREE)
break;
APPEND (result, ", ");
}
}
APPEND (result, " OF\n");
variants = TYPE_FIELDS (TREE_TYPE (fields));
/* Each variant is a FIELD_DECL whose type is an anonymous
struct within the anonymous union. */
while (variants != NULL_TREE)
{
tree tag_list = TYPE_TAG_VALUES (TREE_TYPE (variants));
tree struct_elts = TYPE_FIELDS (TREE_TYPE (variants));
while (tag_list != NULL_TREE)
{
tree tag_values = TREE_VALUE (tag_list);
APPEND (result, " (");
while (tag_values != NULL_TREE)
{
mode_string = get_tag_value (TREE_VALUE (tag_values));
APPEND (result, mode_string->str);
FREE (mode_string);
if (TREE_CHAIN (tag_values) != NULL_TREE)
{
APPEND (result, ",\n ");
tag_values = TREE_CHAIN (tag_values);
}
else break;
}
APPEND (result, ")");
tag_list = TREE_CHAIN (tag_list);
if (tag_list)
APPEND (result, ",");
else
break;
}
APPEND (result, " : ");
while (struct_elts != NULL_TREE)
{
mode_string = decode_decl (struct_elts);
APPEND (result, mode_string->str);
FREE (mode_string);
if (TREE_CHAIN (struct_elts) != NULL_TREE)
APPEND (result, ",\n ");
struct_elts = TREE_CHAIN (struct_elts);
}
variants = TREE_CHAIN (variants);
if (variants != NULL_TREE
&& TREE_CHAIN (variants) == NULL_TREE
&& DECL_NAME (variants) == ELSE_VARIANT_NAME)
{
tree else_elts = TYPE_FIELDS (TREE_TYPE (variants));
APPEND (result, "\n ELSE ");
while (else_elts != NULL_TREE)
{
mode_string = decode_decl (else_elts);
APPEND (result, mode_string->str);
FREE (mode_string);
if (TREE_CHAIN (else_elts) != NULL_TREE)
APPEND (result, ",\n ");
else_elts = TREE_CHAIN (else_elts);
}
break;
}
if (variants != NULL_TREE)
APPEND (result, ",\n");
}
APPEND (result, "\n ESAC");
}
else
{
mode_string = decode_decl (fields);
APPEND (result, mode_string->str);
FREE (mode_string);
}
fields = TREE_CHAIN (fields);
if (fields != NULL_TREE)
APPEND (result, ",\n ");
}
APPEND (result, ")");
}
return result;
}
static MYSTRING *
print_struct_selective (type, all_decls)
tree type;
tree all_decls;
{
MYSTRING *result = newstring ("");
MYSTRING *mode_string;
tree fields;
if (chill_varying_type_p (type))
{
mode_string = grant_array_type_selective (type, all_decls);
if (mode_string->len)
APPEND (result, mode_string->str);
FREE (mode_string);
}
else
{
fields = TYPE_FIELDS (type);
while (fields != NULL_TREE)
{
if (TREE_CODE (TREE_TYPE (fields)) == UNION_TYPE)
{
tree variants;
/* Format a tagged variant record type. */
variants = TYPE_FIELDS (TREE_TYPE (fields));
/* Each variant is a FIELD_DECL whose type is an anonymous
struct within the anonymous union. */
while (variants != NULL_TREE)
{
tree tag_list = TYPE_TAG_VALUES (TREE_TYPE (variants));
tree struct_elts = TYPE_FIELDS (TREE_TYPE (variants));
while (tag_list != NULL_TREE)
{
tree tag_values = TREE_VALUE (tag_list);
while (tag_values != NULL_TREE)
{
mode_string = get_tag_value_selective (TREE_VALUE (tag_values),
all_decls);
if (mode_string->len)
{
MAYBE_NEWLINE (result);
APPEND (result, mode_string->str);
}
FREE (mode_string);
if (TREE_CHAIN (tag_values) != NULL_TREE)
tag_values = TREE_CHAIN (tag_values);
else break;
}
tag_list = TREE_CHAIN (tag_list);
if (!tag_list)
break;
}
while (struct_elts != NULL_TREE)
{
mode_string = decode_decl_selective (struct_elts, all_decls);
if (mode_string->len)
{
MAYBE_NEWLINE (result);
APPEND (result, mode_string->str);
}
FREE (mode_string);
struct_elts = TREE_CHAIN (struct_elts);
}
variants = TREE_CHAIN (variants);
if (variants != NULL_TREE
&& TREE_CHAIN (variants) == NULL_TREE
&& DECL_NAME (variants) == ELSE_VARIANT_NAME)
{
tree else_elts = TYPE_FIELDS (TREE_TYPE (variants));
while (else_elts != NULL_TREE)
{
mode_string = decode_decl_selective (else_elts, all_decls);
if (mode_string->len)
{
MAYBE_NEWLINE (result);
APPEND (result, mode_string->str);
}
FREE (mode_string);
else_elts = TREE_CHAIN (else_elts);
}
break;
}
}
}
else
{
mode_string = decode_decl_selective (fields, all_decls);
APPEND (result, mode_string->str);
FREE (mode_string);
}
fields = TREE_CHAIN (fields);
}
}
return result;
}
static MYSTRING *
print_proc_exceptions (ex)
tree ex;
{
MYSTRING *result = newstring ("");
if (ex != NULL_TREE)
{
APPEND (result, "\n EXCEPTIONS (");
for ( ; ex != NULL_TREE; ex = TREE_CHAIN (ex))
{
APPEND (result, IDENTIFIER_POINTER (TREE_VALUE (ex)));
if (TREE_CHAIN (ex) != NULL_TREE)
APPEND (result, ",\n ");
}
APPEND (result, ")");
}
return result;
}
static MYSTRING *
print_proc_tail (type, args, print_argnames)
tree type;
tree args;
int print_argnames;
{
MYSTRING *result = newstring ("");
MYSTRING *mode_string;
int count = 0;
int stopat = list_length (args) - 3;
/* do the argument modes */
for ( ; args != NULL_TREE;
args = TREE_CHAIN (args), count++)
{
char buf[20];
tree argmode = TREE_VALUE (args);
tree attribute = TREE_PURPOSE (args);
if (argmode == void_type_node)
continue;
/* if we have exceptions don't print last 2 arguments */
if (TYPE_RAISES_EXCEPTIONS (type) && count == stopat)
break;
if (count)
APPEND (result, ",\n ");
if (print_argnames)
{
sprintf(buf, "arg%d ", count);
APPEND (result, buf);
}
if (attribute == ridpointers[(int) RID_LOC])
argmode = TREE_TYPE (argmode);
mode_string = get_type (argmode);
APPEND (result, mode_string->str);
FREE (mode_string);
if (attribute != NULL_TREE)
{
sprintf (buf, " %s", IDENTIFIER_POINTER (attribute));
APPEND (result, buf);
}
}
APPEND (result, ")");
/* return type */
{
tree retn_type = TREE_TYPE (type);
if (retn_type != NULL_TREE
&& TREE_CODE (retn_type) != VOID_TYPE)
{
mode_string = get_type (retn_type);
APPEND (result, "\n RETURNS (");
APPEND (result, mode_string->str);
FREE (mode_string);
if (TREE_CODE (retn_type) == REFERENCE_TYPE)
APPEND (result, " LOC");
APPEND (result, ")");
}
}
mode_string = print_proc_exceptions (TYPE_RAISES_EXCEPTIONS (type));
APPEND (result, mode_string->str);
FREE (mode_string);
return result;
}
static MYSTRING *
print_proc_tail_selective (type, args, all_decls)
tree type;
tree args;
tree all_decls;
{
MYSTRING *result = newstring ("");
MYSTRING *mode_string;
int count = 0;
int stopat = list_length (args) - 3;
/* do the argument modes */
for ( ; args != NULL_TREE;
args = TREE_CHAIN (args), count++)
{
tree argmode = TREE_VALUE (args);
tree attribute = TREE_PURPOSE (args);
if (argmode == void_type_node)
continue;
/* if we have exceptions don't process last 2 arguments */
if (TYPE_RAISES_EXCEPTIONS (type) && count == stopat)
break;
if (attribute == ridpointers[(int) RID_LOC])
argmode = TREE_TYPE (argmode);
mode_string = get_type_selective (argmode, all_decls);
if (mode_string->len)
{
MAYBE_NEWLINE (result);
APPEND (result, mode_string->str);
}
FREE (mode_string);
}
/* return type */
{
tree retn_type = TREE_TYPE (type);
if (retn_type != NULL_TREE
&& TREE_CODE (retn_type) != VOID_TYPE)
{
mode_string = get_type_selective (retn_type, all_decls);
if (mode_string->len)
{
MAYBE_NEWLINE (result);
APPEND (result, mode_string->str);
}
FREE (mode_string);
}
}
return result;
}
/* output a mode (or type). */
static MYSTRING *
decode_mode (type)
tree type;
{
MYSTRING *result = newstring ("");
MYSTRING *mode_string;
switch ((enum chill_tree_code)TREE_CODE (type))
{
case TYPE_DECL:
if (DECL_NAME (type))
{
APPEND (result, IDENTIFIER_POINTER (DECL_NAME (type)));
return result;
}
type = TREE_TYPE (type);
break;
case IDENTIFIER_NODE:
APPEND (result, IDENTIFIER_POINTER (type));
return result;
case LANG_TYPE:
/* LANG_TYPE are only used until satisfy is done,
as place-holders for 'READ T', NEWMODE/SYNMODE modes,
parameterised modes, and old-fashioned CHAR(N). */
if (TYPE_READONLY (type))
APPEND (result, "READ ");
mode_string = get_type (TREE_TYPE (type));
APPEND (result, mode_string->str);
if (TYPE_DOMAIN (type) != NULL_TREE)
{
/* Parameterized mode,
or old-fashioned CHAR(N) string declaration.. */
APPEND (result, "(");
mode_string = decode_constant (TYPE_DOMAIN (type));
APPEND (result, mode_string->str);
APPEND (result, ")");
}
FREE (mode_string);
break;
case ARRAY_TYPE:
mode_string = grant_array_type (type);
APPEND (result, mode_string->str);
FREE (mode_string);
break;
case BOOLEAN_TYPE:
APPEND (result, "BOOL");
break;
case CHAR_TYPE:
APPEND (result, "CHAR");
break;
case ENUMERAL_TYPE:
mode_string = print_enumeral (type);
APPEND (result, mode_string->str);
FREE (mode_string);
break;
case FUNCTION_TYPE:
{
tree args = TYPE_ARG_TYPES (type);
APPEND (result, "PROC (");
mode_string = print_proc_tail (type, args, 0);
APPEND (result, mode_string->str);
FREE (mode_string);
}
break;
case INTEGER_TYPE:
mode_string = print_integer_type (type);
APPEND (result, mode_string->str);
FREE (mode_string);
break;
case RECORD_TYPE:
if (CH_IS_INSTANCE_MODE (type))
{
APPEND (result, "INSTANCE");
return result;
}
else if (CH_IS_BUFFER_MODE (type) || CH_IS_EVENT_MODE (type))
{ tree bufsize = max_queue_size (type);
APPEND (result, CH_IS_BUFFER_MODE (type) ? "BUFFER " : "EVENT ");
if (bufsize != NULL_TREE)
{
APPEND (result, "(");
mode_string = decode_constant (bufsize);
APPEND (result, mode_string->str);
APPEND (result, ") ");
FREE (mode_string);
}
if (CH_IS_BUFFER_MODE (type))
{
mode_string = decode_mode (buffer_element_mode (type));
APPEND (result, mode_string->str);
FREE (mode_string);
}
break;
}
else if (CH_IS_ACCESS_MODE (type))
{
tree indexmode, recordmode, dynamic;
APPEND (result, "ACCESS");
recordmode = access_recordmode (type);
indexmode = access_indexmode (type);
dynamic = access_dynamic (type);
if (indexmode != void_type_node)
{
mode_string = decode_mode (indexmode);
APPEND (result, " (");
APPEND (result, mode_string->str);
APPEND (result, ")");
FREE (mode_string);
}
if (recordmode != void_type_node)
{
mode_string = decode_mode (recordmode);
APPEND (result, " ");
APPEND (result, mode_string->str);
FREE (mode_string);
}
if (dynamic != integer_zero_node)
APPEND (result, " DYNAMIC");
break;
}
else if (CH_IS_TEXT_MODE (type))
{
tree indexmode, dynamic, length;
APPEND (result, "TEXT (");
length = text_length (type);
indexmode = text_indexmode (type);
dynamic = text_dynamic (type);
mode_string = decode_constant (length);
APPEND (result, mode_string->str);
FREE (mode_string);
APPEND (result, ")");
if (indexmode != void_type_node)
{
APPEND (result, " ");
mode_string = decode_mode (indexmode);
APPEND (result, mode_string->str);
FREE (mode_string);
}
if (dynamic != integer_zero_node)
APPEND (result, " DYNAMIC");
return result;
}
mode_string = print_struct (type);
APPEND (result, mode_string->str);
FREE (mode_string);
break;
case POINTER_TYPE:
if (TREE_CODE (TREE_TYPE (type)) == VOID_TYPE)
APPEND (result, "PTR");
else
{
if (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
{
mode_string = get_type (TREE_TYPE (type));
APPEND (result, mode_string->str);
FREE (mode_string);
}
else
{
APPEND (result, "REF ");
mode_string = get_type (TREE_TYPE (type));
APPEND (result, mode_string->str);
FREE (mode_string);
}
}
break;
case REAL_TYPE:
if (TREE_INT_CST_LOW (TYPE_SIZE (type)) == 32)
APPEND (result, "REAL");
else
APPEND (result, "LONG_REAL");
break;
case SET_TYPE:
if (CH_BOOLS_TYPE_P (type))
mode_string = grant_array_type (type);
else
{
APPEND (result, "POWERSET ");
mode_string = get_type (TYPE_DOMAIN (type));
}
APPEND (result, mode_string->str);
FREE (mode_string);
break;
case REFERENCE_TYPE:
mode_string = get_type (TREE_TYPE (type));
APPEND (result, mode_string->str);
FREE (mode_string);
break;
default:
APPEND (result, "/* ---- not implemented ---- */");
break;
}
return (result);
}
static tree
find_in_decls (id, all_decls)
tree id;
tree all_decls;
{
tree wrk;
for (wrk = all_decls; wrk != NULL_TREE; wrk = TREE_CHAIN (wrk))
{
if (DECL_NAME (wrk) == id || DECL_POSTFIX (wrk) == id)
return wrk;
}
return NULL_TREE;
}
static int
in_ridpointers (id)
tree id;
{
int i;
for (i = RID_UNUSED; i < RID_MAX; i++)
{
if (id == ridpointers[i])
return 1;
}
return 0;
}
static void
grant_seized_identifier (decl)
tree decl;
{
seizefile_list *wrk = selective_seizes;
MYSTRING *mode_string;
CH_ALREADY_GRANTED (decl) = 1;
/* comes from a SPEC MODULE in the module */
if (DECL_SEIZEFILE (decl) == NULL_TREE)
return;
/* search file already in process */
while (wrk != 0)
{
if (wrk->filename == DECL_SEIZEFILE (decl))
break;
wrk = wrk->next;
}
if (!wrk)
{
wrk = (seizefile_list *)xmalloc (sizeof (seizefile_list));
wrk->next = selective_seizes;
selective_seizes = wrk;
wrk->filename = DECL_SEIZEFILE (decl);
wrk->seizes = newstring ("<> USE_SEIZE_FILE \"");
APPEND (wrk->seizes, IDENTIFIER_POINTER (DECL_SEIZEFILE (decl)));
APPEND (wrk->seizes, "\" <>\n");
}
APPEND (wrk->seizes, "SEIZE ");
mode_string = decode_prefix_rename (decl);
APPEND (wrk->seizes, mode_string->str);
FREE (mode_string);
APPEND (wrk->seizes, ";\n");
}
static MYSTRING *
decode_mode_selective (type, all_decls)
tree type;
tree all_decls;
{
MYSTRING *result = newstring ("");
MYSTRING *mode_string;
tree decl;
switch ((enum chill_tree_code)TREE_CODE (type))
{
case TYPE_DECL:
/* FIXME: could this ever happen ?? */
if (DECL_NAME (type))
{
FREE (result);
result = decode_mode_selective (DECL_NAME (type), all_decls);
return result;
}
break;
case IDENTIFIER_NODE:
if (in_ridpointers (type))
/* it's a predefined, we must not search the whole list */
return result;
decl = find_in_decls (type, all_decls);
if (decl != NULL_TREE)
{
if (CH_ALREADY_GRANTED (decl))
/* already processed */
return result;
if (TREE_CODE (decl) == ALIAS_DECL && DECL_POSTFIX (decl) != NULL_TREE)
{
/* If CH_DECL_GRANTED, decl was granted into this scope, and
so wasn't in the source code. */
if (!CH_DECL_GRANTED (decl))
{
grant_seized_identifier (decl);
}
}
else
{
result = decode_decl (decl);
mode_string = decode_decl_selective (decl, all_decls);
if (mode_string->len)
{
PREPEND (result, mode_string->str);
}
FREE (mode_string);
}
}
return result;
case LANG_TYPE:
mode_string = get_type_selective (TREE_TYPE (type), all_decls);
APPEND (result, mode_string->str);
FREE (mode_string);
break;
case ARRAY_TYPE:
mode_string = grant_array_type_selective (type, all_decls);
APPEND (result, mode_string->str);
FREE (mode_string);
break;
case BOOLEAN_TYPE:
return result;
break;
case CHAR_TYPE:
return result;
break;
case ENUMERAL_TYPE:
mode_string = print_enumeral_selective (type, all_decls);
if (mode_string->len)
APPEND (result, mode_string->str);
FREE (mode_string);
break;
case FUNCTION_TYPE:
{
tree args = TYPE_ARG_TYPES (type);
mode_string = print_proc_tail_selective (type, args, all_decls);
if (mode_string->len)
APPEND (result, mode_string->str);
FREE (mode_string);
}
break;
case INTEGER_TYPE:
mode_string = print_integer_selective (type, all_decls);
if (mode_string->len)
APPEND (result, mode_string->str);
FREE (mode_string);
break;
case RECORD_TYPE:
if (CH_IS_INSTANCE_MODE (type))
{
return result;
}
else if (CH_IS_BUFFER_MODE (type) || CH_IS_EVENT_MODE (type))
{
tree bufsize = max_queue_size (type);
if (bufsize != NULL_TREE)
{
mode_string = decode_constant_selective (bufsize, all_decls);
if (mode_string->len)
APPEND (result, mode_string->str);
FREE (mode_string);
}
if (CH_IS_BUFFER_MODE (type))
{
mode_string = decode_mode_selective (buffer_element_mode (type), all_decls);
if (mode_string->len)
{
MAYBE_NEWLINE (result);
APPEND (result, mode_string->str);
}
FREE (mode_string);
}
break;
}
else if (CH_IS_ACCESS_MODE (type))
{
tree indexmode = access_indexmode (type);
tree recordmode = access_recordmode (type);
if (indexmode != void_type_node)
{
mode_string = decode_mode_selective (indexmode, all_decls);
if (mode_string->len)
{
if (result->len && result->str[result->len - 1] != '\n')
APPEND (result, ";\n");
APPEND (result, mode_string->str);
}
FREE (mode_string);
}
if (recordmode != void_type_node)
{
mode_string = decode_mode_selective (recordmode, all_decls);
if (mode_string->len)
{
if (result->len && result->str[result->len - 1] != '\n')
APPEND (result, ";\n");
APPEND (result, mode_string->str);
}
FREE (mode_string);
}
break;
}
else if (CH_IS_TEXT_MODE (type))
{
tree indexmode = text_indexmode (type);
tree length = text_length (type);
mode_string = decode_constant_selective (length, all_decls);
if (mode_string->len)
APPEND (result, mode_string->str);
FREE (mode_string);
if (indexmode != void_type_node)
{
mode_string = decode_mode_selective (indexmode, all_decls);
if (mode_string->len)
{
if (result->len && result->str[result->len - 1] != '\n')
APPEND (result, ";\n");
APPEND (result, mode_string->str);
}
FREE (mode_string);
}
break;
}
mode_string = print_struct_selective (type, all_decls);
if (mode_string->len)
{
MAYBE_NEWLINE (result);
APPEND (result, mode_string->str);
}
FREE (mode_string);
break;
case POINTER_TYPE:
if (TREE_CODE (TREE_TYPE (type)) == VOID_TYPE)
break;
else
{
if (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
{
mode_string = get_type_selective (TREE_TYPE (type), all_decls);
if (mode_string->len)
APPEND (result, mode_string->str);
FREE (mode_string);
}
else
{
mode_string = get_type_selective (TREE_TYPE (type), all_decls);
if (mode_string->len)
APPEND (result, mode_string->str);
FREE (mode_string);
}
}
break;
case REAL_TYPE:
return result;
break;
case SET_TYPE:
if (CH_BOOLS_TYPE_P (type))
mode_string = grant_array_type_selective (type, all_decls);
else
mode_string = get_type_selective (TYPE_DOMAIN (type), all_decls);
if (mode_string->len)
APPEND (result, mode_string->str);
FREE (mode_string);
break;
case REFERENCE_TYPE:
mode_string = get_type_selective (TREE_TYPE (type), all_decls);
if (mode_string->len)
APPEND (result, mode_string->str);
FREE (mode_string);
break;
default:
APPEND (result, "/* ---- not implemented ---- */");
break;
}
return (result);
}
static MYSTRING *
get_type (type)
tree type;
{
if (type == NULL_TREE || TREE_CODE (type) == ERROR_MARK)
return newstring ("");
return (decode_mode (type));
}
static MYSTRING *
get_type_selective (type, all_decls)
tree type;
tree all_decls;
{
if (type == NULL_TREE || TREE_CODE (type) == ERROR_MARK)
return newstring ("");
return (decode_mode_selective (type, all_decls));
}
#if 0
static int
is_forbidden (str, forbid)
tree str;
tree forbid;
{
if (forbid == NULL_TREE)
return (0);
if (TREE_CODE (forbid) == INTEGER_CST)
return (1);
while (forbid != NULL_TREE)
{
if (TREE_VALUE (forbid) == str)
return (1);
forbid = TREE_CHAIN (forbid);
}
/* nothing found */
return (0);
}
#endif
static MYSTRING *
decode_constant (init)
tree init;
{
MYSTRING *result = newstring ("");
MYSTRING *tmp_string;
tree type = TREE_TYPE (init);
tree val = init;
char *op;
char wrk[256];
MYSTRING *mode_string;
switch ((enum chill_tree_code)TREE_CODE (val))
{
case CALL_EXPR:
tmp_string = decode_constant (TREE_OPERAND (val, 0));
APPEND (result, tmp_string->str);
FREE (tmp_string);
val = TREE_OPERAND (val, 1); /* argument list */
if (val != NULL_TREE && TREE_CODE (val) != TREE_LIST)
{
APPEND (result, " ");
tmp_string = decode_constant (val);
APPEND (result, tmp_string->str);
FREE (tmp_string);
}
else
{
APPEND (result, " (");
if (val != NULL_TREE)
{
for (;;)
{
tmp_string = decode_constant (TREE_VALUE (val));
APPEND (result, tmp_string->str);
FREE (tmp_string);
val = TREE_CHAIN (val);
if (val == NULL_TREE)
break;
APPEND (result, ", ");
}
}
APPEND (result, ")");
}
return result;
case NOP_EXPR:
/* Generate an "expression conversion" expression (a cast). */
tmp_string = decode_mode (type);
APPEND (result, tmp_string->str);
FREE (tmp_string);
APPEND (result, "(");
val = TREE_OPERAND (val, 0);
type = TREE_TYPE (val);
/* If the coercee is a tuple, make sure it is prefixed by its mode. */
if (TREE_CODE (val) == CONSTRUCTOR
&& !CH_BOOLS_TYPE_P (type) && !chill_varying_type_p (type))
{
tmp_string = decode_mode (type);
APPEND (result, tmp_string->str);
FREE (tmp_string);
APPEND (result, " ");
}
tmp_string = decode_constant (val);
APPEND (result, tmp_string->str);
FREE (tmp_string);
APPEND (result, ")");
return result;
case IDENTIFIER_NODE:
APPEND (result, IDENTIFIER_POINTER (val));
return result;
case PAREN_EXPR:
APPEND (result, "(");
tmp_string = decode_constant (TREE_OPERAND (val, 0));
APPEND (result, tmp_string->str);
FREE (tmp_string);
APPEND (result, ")");
return result;
case UNDEFINED_EXPR:
APPEND (result, "*");
return result;
case PLUS_EXPR: op = "+"; goto binary;
case MINUS_EXPR: op = "-"; goto binary;
case MULT_EXPR: op = "*"; goto binary;
case TRUNC_DIV_EXPR: op = "/"; goto binary;
case FLOOR_MOD_EXPR: op = " MOD "; goto binary;
case TRUNC_MOD_EXPR: op = " REM "; goto binary;
case CONCAT_EXPR: op = "//"; goto binary;
case BIT_IOR_EXPR: op = " OR "; goto binary;
case BIT_XOR_EXPR: op = " XOR "; goto binary;
case TRUTH_ORIF_EXPR: op = " ORIF "; goto binary;
case BIT_AND_EXPR: op = " AND "; goto binary;
case TRUTH_ANDIF_EXPR: op = " ANDIF "; goto binary;
case GT_EXPR: op = ">"; goto binary;
case GE_EXPR: op = ">="; goto binary;
case SET_IN_EXPR: op = " IN "; goto binary;
case LT_EXPR: op = "<"; goto binary;
case LE_EXPR: op = "<="; goto binary;
case EQ_EXPR: op = "="; goto binary;
case NE_EXPR: op = "/="; goto binary;
case RANGE_EXPR:
if (TREE_OPERAND (val, 0) == NULL_TREE)
{
APPEND (result, TREE_OPERAND (val, 1) == NULL_TREE ? "*" : "ELSE");
return result;
}
op = ":"; goto binary;
binary:
tmp_string = decode_constant (TREE_OPERAND (val, 0));
APPEND (result, tmp_string->str);
FREE (tmp_string);
APPEND (result, op);
tmp_string = decode_constant (TREE_OPERAND (val, 1));
APPEND (result, tmp_string->str);
FREE (tmp_string);
return result;
case REPLICATE_EXPR:
APPEND (result, "(");
tmp_string = decode_constant (TREE_OPERAND (val, 0));
APPEND (result, tmp_string->str);
FREE (tmp_string);
APPEND (result, ")");
tmp_string = decode_constant (TREE_OPERAND (val, 1));
APPEND (result, tmp_string->str);
FREE (tmp_string);
return result;
case NEGATE_EXPR: op = "-"; goto unary;
case BIT_NOT_EXPR: op = " NOT "; goto unary;
case ADDR_EXPR: op = "->"; goto unary;
unary:
APPEND (result, op);
tmp_string = decode_constant (TREE_OPERAND (val, 0));
APPEND (result, tmp_string->str);
FREE (tmp_string);
return result;
case INTEGER_CST:
APPEND (result, display_int_cst (val));
return result;
case REAL_CST:
#ifndef REAL_IS_NOT_DOUBLE
sprintf (wrk, "%.20g", TREE_REAL_CST (val));
#else
REAL_VALUE_TO_DECIMAL (TREE_REAL_CST (val), "%.20g", wrk);
#endif
APPEND (result, wrk);
return result;
case STRING_CST:
{
char *ptr = TREE_STRING_POINTER (val);
int i = TREE_STRING_LENGTH (val);
APPEND (result, "\"");
while (--i >= 0)
{
char buf[10];
unsigned char c = *ptr++;
if (c == '^')
APPEND (result, "^^");
else if (c == '"')
APPEND (result, "\"\"");
else if (c == '\n')
APPEND (result, "^J");
else if (c < ' ' || c > '~')
{
sprintf (buf, "^(%u)", c);
APPEND (result, buf);
}
else
{
buf[0] = c;
buf[1] = 0;
APPEND (result, buf);
}
}
APPEND (result, "\"");
return result;
}
case CONSTRUCTOR:
val = TREE_OPERAND (val, 1);
if (type != NULL && TREE_CODE (type) == SET_TYPE
&& CH_BOOLS_TYPE_P (type))
{
/* It's a bitstring. */
tree domain = TYPE_DOMAIN (type);
tree domain_max = TYPE_MAX_VALUE (domain);
char *buf;
register char *ptr;
int len;
if (TREE_CODE (domain_max) != INTEGER_CST
|| (val && TREE_CODE (val) != TREE_LIST))
goto fail;
len = TREE_INT_CST_LOW (domain_max) + 1;
if (TREE_CODE (init) != CONSTRUCTOR)
goto fail;
buf = (char *) alloca (len + 10);
ptr = buf;
*ptr++ = ' ';
*ptr++ = 'B';
*ptr++ = '\'';
if (get_set_constructor_bits (init, ptr, len))
goto fail;
for (; --len >= 0; ptr++)
*ptr += '0';
*ptr++ = '\'';
*ptr = '\0';
APPEND (result, buf);
return result;
}
else
{ /* It's some kind of tuple */
if (type != NULL_TREE)
{
mode_string = get_type (type);
APPEND (result, mode_string->str);
FREE (mode_string);
APPEND (result, " ");
}
if (val == NULL_TREE
|| TREE_CODE (val) == ERROR_MARK)
APPEND (result, "[ ]");
else if (TREE_CODE (val) != TREE_LIST)
goto fail;
else
{
APPEND (result, "[");
for ( ; ; )
{
tree lo_val = TREE_PURPOSE (val);
tree hi_val = TREE_VALUE (val);
MYSTRING *val_string;
if (TUPLE_NAMED_FIELD (val))
APPEND(result, ".");
if (lo_val != NULL_TREE)
{
val_string = decode_constant (lo_val);
APPEND (result, val_string->str);
FREE (val_string);
APPEND (result, ":");
}
val_string = decode_constant (hi_val);
APPEND (result, val_string->str);
FREE (val_string);
val = TREE_CHAIN (val);
if (val == NULL_TREE)
break;
APPEND (result, ", ");
}
APPEND (result, "]");
}
}
return result;
case COMPONENT_REF:
{
tree op1;
mode_string = decode_constant (TREE_OPERAND (init, 0));
APPEND (result, mode_string->str);
FREE (mode_string);
op1 = TREE_OPERAND (init, 1);
if (TREE_CODE (op1) != IDENTIFIER_NODE)
{
error ("decode_constant: invalid component_ref");
break;
}
APPEND (result, ".");
APPEND (result, IDENTIFIER_POINTER (op1));
return result;
}
fail:
error ("decode_constant: mode and value mismatch");
break;
default:
error ("decode_constant: cannot decode this mode");
break;
}
return result;
}
static MYSTRING *
decode_constant_selective (init, all_decls)
tree init;
tree all_decls;
{
MYSTRING *result = newstring ("");
MYSTRING *tmp_string;
tree type = TREE_TYPE (init);
tree val = init;
MYSTRING *mode_string;
switch ((enum chill_tree_code)TREE_CODE (val))
{
case CALL_EXPR:
tmp_string = decode_constant_selective (TREE_OPERAND (val, 0), all_decls);
if (tmp_string->len)
APPEND (result, tmp_string->str);
FREE (tmp_string);
val = TREE_OPERAND (val, 1); /* argument list */
if (val != NULL_TREE && TREE_CODE (val) != TREE_LIST)
{
tmp_string = decode_constant_selective (val, all_decls);
if (tmp_string->len)
{
MAYBE_NEWLINE (result);
APPEND (result, tmp_string->str);
}
FREE (tmp_string);
}
else
{
if (val != NULL_TREE)
{
for (;;)
{
tmp_string = decode_constant_selective (TREE_VALUE (val), all_decls);
if (tmp_string->len)
{
MAYBE_NEWLINE (result);
APPEND (result, tmp_string->str);
}
FREE (tmp_string);
val = TREE_CHAIN (val);
if (val == NULL_TREE)
break;
}
}
}
return result;
case NOP_EXPR:
/* Generate an "expression conversion" expression (a cast). */
tmp_string = decode_mode_selective (type, all_decls);
if (tmp_string->len)
APPEND (result, tmp_string->str);
FREE (tmp_string);
val = TREE_OPERAND (val, 0);
type = TREE_TYPE (val);
/* If the coercee is a tuple, make sure it is prefixed by its mode. */
if (TREE_CODE (val) == CONSTRUCTOR
&& !CH_BOOLS_TYPE_P (type) && !chill_varying_type_p (type))
{
tmp_string = decode_mode_selective (type, all_decls);
if (tmp_string->len)
APPEND (result, tmp_string->str);
FREE (tmp_string);
}
tmp_string = decode_constant_selective (val, all_decls);
if (tmp_string->len)
APPEND (result, tmp_string->str);
FREE (tmp_string);
return result;
case IDENTIFIER_NODE:
tmp_string = decode_mode_selective (val, all_decls);
if (tmp_string->len)
APPEND (result, tmp_string->str);
FREE (tmp_string);
return result;
case PAREN_EXPR:
tmp_string = decode_constant_selective (TREE_OPERAND (val, 0), all_decls);
if (tmp_string->len)
APPEND (result, tmp_string->str);
FREE (tmp_string);
return result;
case UNDEFINED_EXPR:
return result;
case PLUS_EXPR:
case MINUS_EXPR:
case MULT_EXPR:
case TRUNC_DIV_EXPR:
case FLOOR_MOD_EXPR:
case TRUNC_MOD_EXPR:
case CONCAT_EXPR:
case BIT_IOR_EXPR:
case BIT_XOR_EXPR:
case TRUTH_ORIF_EXPR:
case BIT_AND_EXPR:
case TRUTH_ANDIF_EXPR:
case GT_EXPR:
case GE_EXPR:
case SET_IN_EXPR:
case LT_EXPR:
case LE_EXPR:
case EQ_EXPR:
case NE_EXPR:
goto binary;
case RANGE_EXPR:
if (TREE_OPERAND (val, 0) == NULL_TREE)
return result;
binary:
tmp_string = decode_constant_selective (TREE_OPERAND (val, 0), all_decls);
if (tmp_string->len)
APPEND (result, tmp_string->str);
FREE (tmp_string);
tmp_string = decode_constant_selective (TREE_OPERAND (val, 1), all_decls);
if (tmp_string->len)
{
MAYBE_NEWLINE (result);
APPEND (result, tmp_string->str);
}
FREE (tmp_string);
return result;
case REPLICATE_EXPR:
tmp_string = decode_constant_selective (TREE_OPERAND (val, 0), all_decls);
if (tmp_string->len)
APPEND (result, tmp_string->str);
FREE (tmp_string);
tmp_string = decode_constant_selective (TREE_OPERAND (val, 1), all_decls);
if (tmp_string->len)
{
MAYBE_NEWLINE (result);
APPEND (result, tmp_string->str);
}
FREE (tmp_string);
return result;
case NEGATE_EXPR:
case BIT_NOT_EXPR:
case ADDR_EXPR:
tmp_string = decode_constant_selective (TREE_OPERAND (val, 0), all_decls);
if (tmp_string->len)
APPEND (result, tmp_string->str);
FREE (tmp_string);
return result;
case INTEGER_CST:
return result;
case REAL_CST:
return result;
case STRING_CST:
return result;
case CONSTRUCTOR:
val = TREE_OPERAND (val, 1);
if (type != NULL && TREE_CODE (type) == SET_TYPE
&& CH_BOOLS_TYPE_P (type))
/* It's a bitstring. */
return result;
else
{ /* It's some kind of tuple */
if (type != NULL_TREE)
{
mode_string = get_type_selective (type, all_decls);
if (mode_string->len)
APPEND (result, mode_string->str);
FREE (mode_string);
}
if (val == NULL_TREE
|| TREE_CODE (val) == ERROR_MARK)
return result;
else if (TREE_CODE (val) != TREE_LIST)
goto fail;
else
{
for ( ; ; )
{
tree lo_val = TREE_PURPOSE (val);
tree hi_val = TREE_VALUE (val);
MYSTRING *val_string;
if (lo_val != NULL_TREE)
{
val_string = decode_constant_selective (lo_val, all_decls);
if (val_string->len)
APPEND (result, val_string->str);
FREE (val_string);
}
val_string = decode_constant_selective (hi_val, all_decls);
if (val_string->len)
{
MAYBE_NEWLINE (result);
APPEND (result, val_string->str);
}
FREE (val_string);
val = TREE_CHAIN (val);
if (val == NULL_TREE)
break;
}
}
}
return result;
case COMPONENT_REF:
{
mode_string = decode_constant_selective (TREE_OPERAND (init, 0), all_decls);
if (mode_string->len)
APPEND (result, mode_string->str);
FREE (mode_string);
return result;
}
fail:
error ("decode_constant_selective: mode and value mismatch");
break;
default:
error ("decode_constant_selective: cannot decode this mode");
break;
}
return result;
}
/* Assuming DECL is an ALIAS_DECL, return its prefix rename clause. */
static MYSTRING *
decode_prefix_rename (decl)
tree decl;
{
MYSTRING *result = newstring ("");
if (DECL_OLD_PREFIX (decl) || DECL_NEW_PREFIX (decl))
{
APPEND (result, "(");
if (DECL_OLD_PREFIX (decl))
APPEND (result, IDENTIFIER_POINTER (DECL_OLD_PREFIX (decl)));
APPEND (result, "->");
if (DECL_NEW_PREFIX (decl))
APPEND (result, IDENTIFIER_POINTER (DECL_NEW_PREFIX (decl)));
APPEND (result, ")!");
}
if (DECL_POSTFIX_ALL (decl))
APPEND (result, "ALL");
else
APPEND (result, IDENTIFIER_POINTER (DECL_POSTFIX (decl)));
return result;
}
static MYSTRING *
decode_decl (decl)
tree decl;
{
MYSTRING *result = newstring ("");
MYSTRING *mode_string;
tree type;
switch ((enum chill_tree_code)TREE_CODE (decl))
{
case VAR_DECL:
case BASED_DECL:
APPEND (result, "DCL ");
APPEND (result, IDENTIFIER_POINTER (DECL_NAME (decl)));
APPEND (result, " ");
mode_string = get_type (TREE_TYPE (decl));
APPEND (result, mode_string->str);
FREE (mode_string);
if ((enum chill_tree_code)TREE_CODE (decl) == BASED_DECL)
{
APPEND (result, " BASED (");
APPEND (result, IDENTIFIER_POINTER (DECL_ABSTRACT_ORIGIN (decl)));
APPEND (result, ")");
}
break;
case TYPE_DECL:
if (CH_DECL_SIGNAL (decl))
{
/* this is really a signal */
tree fields = TYPE_FIELDS (TREE_TYPE (decl));
tree signame = DECL_NAME (decl);
tree sigdest;
APPEND (result, "SIGNAL ");
APPEND (result, IDENTIFIER_POINTER (signame));
if (IDENTIFIER_SIGNAL_DATA (signame))
{
APPEND (result, " = (");
for ( ; fields != NULL_TREE;
fields = TREE_CHAIN (fields))
{
MYSTRING *mode_string;
mode_string = get_type (TREE_TYPE (fields));
APPEND (result, mode_string->str);
FREE (mode_string);
if (TREE_CHAIN (fields) != NULL_TREE)
APPEND (result, ", ");
}
APPEND (result, ")");
}
sigdest = IDENTIFIER_SIGNAL_DEST (signame);
if (sigdest != NULL_TREE)
{
APPEND (result, " TO ");
APPEND (result, IDENTIFIER_POINTER (DECL_NAME (sigdest)));
}
}
else
{
/* avoid defining a mode as itself */
if (CH_NOVELTY (TREE_TYPE (decl)) == decl)
APPEND (result, "NEWMODE ");
else
APPEND (result, "SYNMODE ");
APPEND (result, IDENTIFIER_POINTER (DECL_NAME (decl)));
APPEND (result, " = ");
mode_string = decode_mode (TREE_TYPE (decl));
APPEND (result, mode_string->str);
FREE (mode_string);
}
break;
case FUNCTION_DECL:
{
tree args;
type = TREE_TYPE (decl);
args = TYPE_ARG_TYPES (type);
APPEND (result, IDENTIFIER_POINTER (DECL_NAME (decl)));
if (CH_DECL_PROCESS (decl))
APPEND (result, ": PROCESS (");
else
APPEND (result, ": PROC (");
args = TYPE_ARG_TYPES (type);
mode_string = print_proc_tail (type, args, 1);
APPEND (result, mode_string->str);
FREE (mode_string);
/* generality */
if (CH_DECL_GENERAL (decl))
APPEND (result, " GENERAL");
if (CH_DECL_SIMPLE (decl))
APPEND (result, " SIMPLE");
if (DECL_INLINE (decl))
APPEND (result, " INLINE");
if (CH_DECL_RECURSIVE (decl))
APPEND (result, " RECURSIVE");
APPEND (result, " END");
}
break;
case FIELD_DECL:
APPEND (result, IDENTIFIER_POINTER (DECL_NAME (decl)));
APPEND (result, " ");
mode_string = get_type (TREE_TYPE (decl));
APPEND (result, mode_string->str);
FREE (mode_string);
if (DECL_INITIAL (decl) != NULL_TREE)
{
mode_string = decode_layout (DECL_INITIAL (decl));
APPEND (result, mode_string->str);
FREE (mode_string);
}
#if 0
if (is_forbidden (DECL_NAME (decl), forbid))
APPEND (result, " FORBID");
#endif
break;
case CONST_DECL:
if (DECL_INITIAL (decl) == NULL_TREE
|| TREE_CODE (DECL_INITIAL (decl)) == ERROR_MARK)
break;
APPEND (result, "SYN ");
APPEND (result, IDENTIFIER_POINTER (DECL_NAME (decl)));
APPEND (result, " ");
mode_string = get_type (TREE_TYPE (decl));
APPEND (result, mode_string->str);
FREE (mode_string);
APPEND (result, " = ");
mode_string = decode_constant (DECL_INITIAL (decl));
APPEND (result, mode_string->str);
FREE (mode_string);
break;
case ALIAS_DECL:
/* If CH_DECL_GRANTED, decl was granted into this scope, and
so wasn't in the source code. */
if (!CH_DECL_GRANTED (decl))
{
static int restricted = 0;
if (DECL_SEIZEFILE (decl) != use_seizefile_name
&& DECL_SEIZEFILE (decl))
{
use_seizefile_name = DECL_SEIZEFILE (decl);
restricted = use_seizefile_name == NULL_TREE ? 0 : CH_USE_SEIZEFILE_RESTRICTED (use_seizefile_name);
if (! restricted)
grant_use_seizefile (IDENTIFIER_POINTER (use_seizefile_name));
mark_use_seizefile_written (use_seizefile_name);
}
if (! restricted)
{
APPEND (result, "SEIZE ");
mode_string = decode_prefix_rename (decl);
APPEND (result, mode_string->str);
FREE (mode_string);
}
}
break;
default:
APPEND (result, "----- not implemented ------");
break;
}
return (result);
}
static MYSTRING *
decode_decl_selective (decl, all_decls)
tree decl;
tree all_decls;
{
MYSTRING *result = newstring ("");
MYSTRING *mode_string;
tree type;
if (CH_ALREADY_GRANTED (decl))
/* do nothing */
return result;
CH_ALREADY_GRANTED (decl) = 1;
switch ((int)TREE_CODE (decl))
{
case VAR_DECL:
case BASED_DECL:
mode_string = get_type_selective (TREE_TYPE (decl), all_decls);
if (mode_string->len)
APPEND (result, mode_string->str);
FREE (mode_string);
if ((enum chill_tree_code)TREE_CODE (decl) == BASED_DECL)
{
mode_string = decode_mode_selective (DECL_ABSTRACT_ORIGIN (decl), all_decls);
if (mode_string->len)
PREPEND (result, mode_string->str);
FREE (mode_string);
}
break;
case TYPE_DECL:
if (CH_DECL_SIGNAL (decl))
{
/* this is really a signal */
tree fields = TYPE_FIELDS (TREE_TYPE (decl));
tree signame = DECL_NAME (decl);
tree sigdest;
if (IDENTIFIER_SIGNAL_DATA (signame))
{
for ( ; fields != NULL_TREE;
fields = TREE_CHAIN (fields))
{
MYSTRING *mode_string;
mode_string = get_type_selective (TREE_TYPE (fields),
all_decls);
if (mode_string->len)
APPEND (result, mode_string->str);
FREE (mode_string);
}
}
sigdest = IDENTIFIER_SIGNAL_DEST (signame);
if (sigdest != NULL_TREE)
{
mode_string = decode_mode_selective (DECL_NAME (sigdest), all_decls);
if (mode_string->len)
{
MAYBE_NEWLINE (result);
APPEND (result, mode_string->str);
}
FREE (mode_string);
}
}
else
{
/* avoid defining a mode as itself */
mode_string = decode_mode_selective (TREE_TYPE (decl), all_decls);
APPEND (result, mode_string->str);
FREE (mode_string);
}
break;
case FUNCTION_DECL:
{
tree args;
type = TREE_TYPE (decl);
args = TYPE_ARG_TYPES (type);
args = TYPE_ARG_TYPES (type);
mode_string = print_proc_tail_selective (type, args, all_decls);
if (mode_string->len)
APPEND (result, mode_string->str);
FREE (mode_string);
}
break;
case FIELD_DECL:
mode_string = get_type_selective (TREE_TYPE (decl), all_decls);
if (mode_string->len)
APPEND (result, mode_string->str);
FREE (mode_string);
break;
case CONST_DECL:
if (DECL_INITIAL (decl) == NULL_TREE
|| TREE_CODE (DECL_INITIAL (decl)) == ERROR_MARK)
break;
mode_string = get_type_selective (TREE_TYPE (decl), all_decls);
if (mode_string->len)
APPEND (result, mode_string->str);
FREE (mode_string);
mode_string = decode_constant_selective (DECL_INITIAL (decl), all_decls);
if (mode_string->len)
{
MAYBE_NEWLINE (result);
APPEND (result, mode_string->str);
}
FREE (mode_string);
break;
}
MAYBE_NEWLINE (result);
return (result);
}
static void
globalize_decl (decl)
tree decl;
{
if (!TREE_PUBLIC (decl) && DECL_NAME (decl) &&
(TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL))
{
extern FILE *asm_out_file;
extern char *first_global_object_name;
char *name = XSTR (XEXP (DECL_RTL (decl), 0), 0);
if (!first_global_object_name)
first_global_object_name = name + (name[0] == '*');
ASM_GLOBALIZE_LABEL (asm_out_file, name);
}
}
static void
grant_one_decl (decl)
tree decl;
{
MYSTRING *result;
if (DECL_SOURCE_LINE (decl) == 0)
return;
result = decode_decl (decl);
if (result->len)
{
APPEND (result, ";\n");
APPEND (gstring, result->str);
}
FREE (result);
}
static void
grant_one_decl_selective (decl, all_decls)
tree decl;
tree all_decls;
{
MYSTRING *result;
MYSTRING *fixups;
tree d = DECL_ABSTRACT_ORIGIN (decl);
if (CH_ALREADY_GRANTED (d))
/* already done */
return;
result = decode_decl (d);
if (!result->len)
{
/* nothing to do */
FREE (result);
return;
}
APPEND (result, ";\n");
/* now process all undefined items in the decl */
fixups = decode_decl_selective (d, all_decls);
if (fixups->len)
{
PREPEND (result, fixups->str);
}
FREE (fixups);
/* we have finished a decl */
APPEND (selective_gstring, result->str);
FREE (result);
}
static int
compare_memory_file (fname, buf)
char *fname;
char *buf;
{
FILE *fb;
int c;
/* check if we have something to write */
if (!buf || !strlen (buf))
return (0);
if ((fb = fopen (fname, "r")) == NULL)
return (1);
while ((c = getc (fb)) != EOF)
{
if (c != *buf++)
{
fclose (fb);
return (1);
}
}
fclose (fb);
return (*buf ? 1 : 0);
}
void
write_grant_file ()
{
FILE *fb;
/* We only write out the grant file if it has changed,
to avoid changing its time-stamp and triggering an
unnecessary 'make' action. Return if no change. */
if (gstring == NULL || !spec_module_generated ||
!compare_memory_file (grant_file_name, gstring->str))
return;
fb = fopen (grant_file_name, "w");
if (fb == NULL)
pfatal_with_name (grant_file_name);
/* write file. Due to problems with record sizes on VAX/VMS
write string to '\n' */
#ifdef VMS
/* do it this way for VMS, cause of problems with
record sizes */
p = gstring->str;
while (*p)
{
p1 = strchr (p, '\n');
c = *++p1;
*p1 = '\0';
fprintf (fb, "%s", p);
*p1 = c;
p = p1;
}
#else
/* faster way to write */
if (write (fileno (fb), gstring->str, gstring->len) < 0)
{
int save_errno = errno;
unlink (grant_file_name);
errno = save_errno;
pfatal_with_name (grant_file_name);
}
#endif
fclose (fb);
}
/* handle grant statement */
void
set_default_grant_file ()
{
char *p, *tmp, *fname;
if (dump_base_name)
fname = dump_base_name; /* Probably invoked via gcc */
else
{ /* Probably invoked directly (not via gcc) */
fname = asm_file_name;
if (!fname)
fname = main_input_filename ? main_input_filename : input_filename;
if (!fname)
return;
}
p = strrchr (fname, '.');
if (!p)
{
tmp = (char *) alloca (strlen (fname) + 10);
strcpy (tmp, fname);
}
else
{
int i = p - fname;
tmp = (char *) alloca (i + 10);
strncpy (tmp, fname, i);
tmp[i] = '\0';
}
strcat (tmp, ".grt");
default_grant_file = build_string (strlen (tmp), tmp);
grant_file_name = TREE_STRING_POINTER (default_grant_file);
if (gstring == NULL)
gstring = newstring ("");
if (selective_gstring == NULL)
selective_gstring = newstring ("");
}
/* Make DECL visible under the name NAME in the (fake) outermost scope. */
void
push_granted (name, decl)
tree name ATTRIBUTE_UNUSED, decl ATTRIBUTE_UNUSED;
{
#if 0
IDENTIFIER_GRANTED_VALUE (name) = decl;
granted_decls = tree_cons (name, decl, granted_decls);
#endif
}
void
chill_grant (old_prefix, new_prefix, postfix, forbid)
tree old_prefix;
tree new_prefix;
tree postfix;
tree forbid;
{
if (pass == 1)
{
#if 0
tree old_name = old_prefix == NULL_TREE ? postfix
: get_identifier3 (IDENTIFIER_POINTER (old_prefix),
"!", IDENTIFIER_POINTER (postfix));
tree new_name = new_prefix == NULL_TREE ? postfix
: get_identifier3 (IDENTIFIER_POINTER (new_prefix),
"!", IDENTIFIER_POINTER (postfix));
#endif
tree alias = build_alias_decl (old_prefix, new_prefix, postfix);
CH_DECL_GRANTED (alias) = 1;
DECL_SEIZEFILE (alias) = current_seizefile_name;
TREE_CHAIN (alias) = current_module->granted_decls;
current_module->granted_decls = alias;
if (forbid)
warning ("FORBID is not yet implemented"); /* FIXME */
}
}
/* flag GRANT ALL only once. Avoids search in case of GRANT ALL. */
static int grant_all_seen = 0;
/* check if a decl is in the list of granted decls. */
static int
search_in_list (name, granted_decls)
tree name;
tree granted_decls;
{
tree vars;
for (vars = granted_decls; vars != NULL_TREE; vars = TREE_CHAIN (vars))
if (DECL_SOURCE_LINE (vars))
{
if (DECL_POSTFIX_ALL (vars))
{
grant_all_seen = 1;
return 1;
}
else if (name == DECL_NAME (vars))
return 1;
}
/* not found */
return 0;
}
static int
really_grant_this (decl, granted_decls)
tree decl;
tree granted_decls;
{
/* we never grant labels at module level */
if ((enum chill_tree_code)TREE_CODE (decl) == LABEL_DECL)
return 0;
if (grant_all_seen)
return 1;
switch ((enum chill_tree_code)TREE_CODE (decl))
{
case VAR_DECL:
case BASED_DECL:
case FUNCTION_DECL:
return search_in_list (DECL_NAME (decl), granted_decls);
case ALIAS_DECL:
case CONST_DECL:
return 1;
case TYPE_DECL:
if (CH_DECL_SIGNAL (decl))
return search_in_list (DECL_NAME (decl), granted_decls);
else
return 1;
default:
break;
}
/* this nerver should happen */
error_with_decl (decl, "function \"really_grant_this\" called for `%s'.");
return 1;
}
/* Write a SPEC MODULE using the declarations in the list DECLS. */
static int header_written = 0;
static char *header_template =
"--\n-- WARNING: this file was generated by\n\
-- GNUCHILL version %s\n-- based on gcc version %s\n--\n";
void
write_spec_module (decls, granted_decls)
tree decls;
tree granted_decls;
{
tree vars;
char *hdr;
if (granted_decls == NULL_TREE)
return;
use_seizefile_name = NULL_TREE;
if (!header_written)
{
hdr = (char*) alloca (strlen (gnuchill_version)
+ strlen (version_string)
+ strlen (header_template) + 1);
sprintf (hdr, header_template, gnuchill_version, version_string);
APPEND (gstring, hdr);
header_written = 1;
}
APPEND (gstring, IDENTIFIER_POINTER (current_module->name));
APPEND (gstring, ": SPEC MODULE\n");
/* first of all we look for GRANT ALL specified */
search_in_list (NULL_TREE, granted_decls);
if (grant_all_seen != 0)
{
/* write all identifiers to grant file */
for (vars = decls; vars != NULL_TREE; vars = TREE_CHAIN (vars))
{
if (DECL_SOURCE_LINE (vars))
{
if (DECL_NAME (vars))
{
if ((TREE_CODE (vars) != CONST_DECL || !CH_DECL_ENUM (vars)) &&
really_grant_this (vars, granted_decls))
grant_one_decl (vars);
}
else if (DECL_POSTFIX_ALL (vars))
{
static int restricted = 0;
if (DECL_SEIZEFILE (vars) != use_seizefile_name
&& DECL_SEIZEFILE (vars))
{
use_seizefile_name = DECL_SEIZEFILE (vars);
restricted = use_seizefile_name == NULL_TREE ? 0 : CH_USE_SEIZEFILE_RESTRICTED (use_seizefile_name);
if (! restricted)
grant_use_seizefile (IDENTIFIER_POINTER (use_seizefile_name));
mark_use_seizefile_written (use_seizefile_name);
}
if (! restricted)
{
APPEND (gstring, "SEIZE ALL;\n");
}
}
}
}
}
else
{
seizefile_list *wrk, *x;
/* do a selective write to the grantfile. This will reduce the
size of a grantfile and speed up compilation of
modules depending on this grant file */
if (selective_gstring == 0)
selective_gstring = newstring ("");
/* first of all process all SEIZE ALL's */
for (vars = decls; vars != NULL_TREE; vars = TREE_CHAIN (vars))
{
if (DECL_SOURCE_LINE (vars)
&& DECL_POSTFIX_ALL (vars))
grant_seized_identifier (vars);
}
/* now walk through granted decls */
granted_decls = nreverse (granted_decls);
for (vars = granted_decls; vars != NULL_TREE; vars = TREE_CHAIN (vars))
{
grant_one_decl_selective (vars, decls);
}
granted_decls = nreverse (granted_decls);
/* append all SEIZES */
wrk = selective_seizes;
while (wrk != 0)
{
x = wrk->next;
APPEND (gstring, wrk->seizes->str);
FREE (wrk->seizes);
free (wrk);
wrk = x;
}
selective_seizes = 0;
/* append generated string to grant file */
APPEND (gstring, selective_gstring->str);
FREE (selective_gstring);
selective_gstring = NULL;
}
for (vars = granted_decls; vars != NULL_TREE; vars = TREE_CHAIN (vars))
if (DECL_SOURCE_LINE (vars))
{
MYSTRING *mode_string = decode_prefix_rename (vars);
APPEND (gstring, "GRANT ");
APPEND (gstring, mode_string->str);
FREE (mode_string);
APPEND (gstring, ";\n");
}
APPEND (gstring, "END;\n");
spec_module_generated = 1;
/* initialize this for next spec module */
grant_all_seen = 0;
}
/*
* after the dark comes, after all of the modules are at rest,
* we tuck the compilation unit to bed... A story in pass 1
* and a hug-and-a-kiss goodnight in pass 2.
*/
void
chill_finish_compile ()
{
tree global_list;
tree chill_init_function;
tasking_setup ();
build_enum_tables ();
/* We only need an initializer function for the source file if
a) there's module-level code to be called, or
b) tasking-related stuff to be initialized. */
if (module_init_list != NULL_TREE || tasking_list != NULL_TREE)
{
extern tree initializer_type;
static tree chill_init_name;
/* declare the global initializer list */
global_list = do_decl (get_identifier ("_ch_init_list"),
build_chill_pointer_type (initializer_type), 1, 0,
NULL_TREE, 1);
/* Now, we're building the function which is the *real*
constructor - if there's any module-level code in this
source file, the compiler puts the file's initializer entry
onto the global initializer list, so each module's body code
will eventually get called, after all of the processes have
been started up. */
/* This is better done in pass 2 (when first_global_object_name
may have been set), but that is too late.
Perhaps rewrite this so nothing is done in pass 1. */
if (pass == 1)
{
extern char *first_global_object_name;
/* If we don't do this spoof, we get the name of the first
tasking_code variable, and not the file name. */
char *tmp = first_global_object_name;
first_global_object_name = NULL;
chill_init_name = get_file_function_name ('I');
first_global_object_name = tmp;
/* strip off the file's extension, if any. */
tmp = strrchr (IDENTIFIER_POINTER (chill_init_name), '.');
if (tmp)
*tmp = '\0';
}
start_chill_function (chill_init_name, void_type_node, NULL_TREE,
NULL_TREE, NULL_TREE);
TREE_PUBLIC (current_function_decl) = 1;
chill_init_function = current_function_decl;
/* For each module that we've compiled, that had module-level
code to be called, add its entry to the global initializer
list. */
if (pass == 2)
{
tree module_init;
for (module_init = module_init_list;
module_init != NULL_TREE;
module_init = TREE_CHAIN (module_init))
{
tree init_entry = TREE_VALUE (module_init);
/* assign module_entry.next := _ch_init_list; */
expand_expr_stmt (
build_chill_modify_expr (
build_component_ref (init_entry,
get_identifier ("__INIT_NEXT")),
global_list));
/* assign _ch_init_list := &module_entry; */
expand_expr_stmt (
build_chill_modify_expr (global_list,
build1 (ADDR_EXPR, ptr_type_node, init_entry)));
}
}
tasking_registry ();
make_decl_rtl (current_function_decl, NULL, 1);
finish_chill_function ();
if (pass == 2)
{
assemble_constructor (IDENTIFIER_POINTER (chill_init_name));
globalize_decl (chill_init_function);
}
/* ready now to link decls onto this list in pass 2. */
module_init_list = NULL_TREE;
tasking_list = NULL_TREE;
}
}