blob: 21d1cb9dce73bae6e8f6a6c56b0ec2b8dd9be74e [file] [log] [blame]
/* m2pp.c pretty print trees, output in Modula-2 where possible.
Copyright (C) 2007-2023 Free Software Foundation, Inc.
Contributed by Gaius Mulley <gaius@glam.ac.uk>.
This file is part of GNU Modula-2.
GNU Modula-2 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 3, or (at your option)
any later version.
GNU Modula-2 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 Modula-2; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
#if defined(GM2)
#include "gm2-gcc/gcc-consolidation.h"
#include "m2-tree.h"
#include "gm2-lang.h"
#include "gm2-gcc/m2tree.h"
#include "gm2-gcc/m2expr.h"
#include "gm2-gcc/m2type.h"
#include "gm2-gcc/m2decl.h"
#else
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "cp/cp-tree.h"
#include "stringpool.h"
#include "gm2-gcc/gcc-consolidation.h"
#include "../cp/cp-tree.h"
#endif
#define M2PP_C
#include "m2/m2pp.h"
namespace modula2 {
#undef DEBUGGING
typedef struct pretty_t
{
int needs_space;
int needs_indent;
int curpos;
int indent;
int issued_begin;
int in_vars;
int in_types;
tree block;
int bits;
} pretty;
typedef struct m2stack_t
{
tree value;
struct m2stack_t *next;
} stack;
/* Prototypes. */
static pretty *initPretty (int bits);
static pretty *dupPretty (pretty *s);
static int getindent (pretty *s);
static void setindent (pretty *s, int n);
static int getcurpos (pretty *s);
static void m2pp_identifier (pretty *s, tree t);
static void m2pp_needspace (pretty *s);
static void m2pp_function (pretty *s, tree t);
static void m2pp_function_header (pretty *s, tree t);
static void m2pp_function_vars (pretty *s, tree t);
static void m2pp_statement_sequence (pretty *s, tree t);
static void m2pp_print (pretty *s, const char *p);
static void m2pp_print_char (pretty *s, char ch);
static void m2pp_parameter (pretty *s, tree t);
static void m2pp_type (pretty *s, tree t);
static void m2pp_ident_pointer (pretty *s, tree t);
static void m2pp_set_type (pretty *s, tree t);
static void m2pp_enum (pretty *s, tree t);
static void m2pp_array (pretty *s, tree t);
static void m2pp_subrange (pretty *s, tree t);
static void m2pp_gimpified (pretty *s, tree t);
static void m2pp_pointer_type (pretty *s, tree t);
static void m2pp_record_type (pretty *s, tree t);
static void m2pp_union_type (pretty *s, tree t);
static void m2pp_simple_type (pretty *s, tree t);
static void m2pp_expression (pretty *s, tree t);
static void m2pp_relop (pretty *s, tree t, const char *p);
static void m2pp_simple_expression (pretty *s, tree t);
static void m2pp_statement_sequence (pretty *s, tree t);
static void m2pp_unknown (pretty *s, const char *s1, const char *s2);
static void m2pp_statement (pretty *s, tree t);
static void m2pp_assignment (pretty *s, tree t);
static void m2pp_designator (pretty *s, tree t);
static void m2pp_conditional (pretty *s, tree t);
static void m2pp_label_expr (pretty *s, tree t);
static void m2pp_label_decl (pretty *s, tree t);
static void m2pp_goto (pretty *s, tree t);
static void m2pp_list (pretty *s, tree t);
static void m2pp_offset (pretty *s, tree t);
static void m2pp_indirect_ref (pretty *s, tree t);
static void m2pp_integer_cst (pretty *s, tree t);
static void m2pp_real_cst (pretty *s, tree t);
static void m2pp_string_cst (pretty *s, tree t);
static void m2pp_integer (pretty *s, tree t);
static void m2pp_addr_expr (pretty *s, tree t);
static void m2pp_nop (pretty *s, tree t);
static void m2pp_convert (pretty *s, tree t);
static void m2pp_var_decl (pretty *s, tree t);
static void m2pp_binary (pretty *s, tree t, const char *p);
static void m2pp_unary (pretty *s, tree t, const char *p);
static void m2pp_call_expr (pretty *s, tree t);
static void m2pp_procedure_call (pretty *s, tree t);
static void m2pp_ssa (pretty *s, tree t);
static void m2pp_block (pretty *s, tree t);
static void m2pp_block_list (pretty *s, tree t);
static void m2pp_var_list (pretty *s, tree t);
static void m2pp_bind_expr (pretty *s, tree t);
static void m2pp_return_expr (pretty *s, tree t);
static void m2pp_result_decl (pretty *s, tree t);
static void m2pp_try_block (pretty *s, tree t);
static void m2pp_cleanup_point_expr (pretty *s, tree t);
static void m2pp_handler (pretty *s, tree t);
static void m2pp_component_ref (pretty *s, tree t);
static void m2pp_array_ref (pretty *s, tree t);
static void m2pp_begin (pretty *s);
static void m2pp_var (pretty *s);
static void m2pp_types (pretty *s);
static void m2pp_decl_expr (pretty *s, tree t);
static void m2pp_var_type_decl (pretty *s, tree t);
static void m2pp_non_lvalue_expr (pretty *s, tree t);
static void m2pp_procedure_type (pretty *s, tree t);
static void m2pp_param_type (pretty *s, tree t);
static void m2pp_type_lowlevel (pretty *s, tree t);
static void m2pp_try_catch_expr (pretty *s, tree t);
static void m2pp_throw (pretty *s, tree t);
static void m2pp_catch_expr (pretty *s, tree t);
static void m2pp_try_finally_expr (pretty *s, tree t);
static void m2pp_complex (pretty *s, tree t);
static void killPretty (pretty *s);
static void m2pp_compound_expression (pretty *s, tree t);
static void m2pp_target_expression (pretty *s, tree t);
static void m2pp_constructor (pretty *s, tree t);
static void m2pp_translation (pretty *s, tree t);
static void m2pp_module_block (pretty *s, tree t);
static void push (tree t);
static void pop (void);
static int begin_printed (tree t);
static void m2pp_decl_list (pretty *s, tree t);
static void m2pp_loc (pretty *s, tree t);
void pet (tree t);
void m2pp_integer (pretty *s, tree t);
extern void stop (void);
static stack *stackPtr = NULL;
/* do_pf helper function for pf. */
void
do_pf (tree t, int bits)
{
pretty *state = initPretty (bits);
if (TREE_CODE (t) == TRANSLATION_UNIT_DECL)
m2pp_translation (state, t);
else if (TREE_CODE (t) == BLOCK)
m2pp_module_block (state, t);
else if (TREE_CODE (t) == FUNCTION_DECL)
m2pp_function (state, t);
else
m2pp_statement_sequence (state, t);
killPretty (state);
}
/* pf print function. Expected to be printed interactively from
the debugger: print pf(func), or to be called from code. */
void
pf (tree t)
{
do_pf (t, FALSE);
}
/* pe print expression. Expected to be printed interactively from
the debugger: print pe(expr), or to be called from code. */
void
pe (tree t)
{
pretty *state = initPretty (FALSE);
m2pp_expression (state, t);
m2pp_needspace (state);
m2pp_print (state, ";\n");
killPretty (state);
}
/* pet print expression and its type. Expected to be printed
interactively from the debugger: print pet(expr), or to be called
from code. */
void
pet (tree t)
{
pretty *state = initPretty (FALSE);
m2pp_expression (state, t);
m2pp_needspace (state);
m2pp_print (state, ":");
m2pp_type (state, TREE_TYPE (t));
m2pp_print (state, ";\n");
killPretty (state);
}
/* pt print type. Expected to be printed interactively from the
debugger: print pt(expr), or to be called from code. */
void
pt (tree t)
{
pretty *state = initPretty (FALSE);
m2pp_type (state, t);
m2pp_needspace (state);
m2pp_print (state, ";\n");
killPretty (state);
}
/* ptl print type low level. Expected to be printed interactively
from the debugger: print ptl(type), or to be called from code. */
void
ptl (tree t)
{
pretty *state = initPretty (FALSE);
m2pp_type_lowlevel (state, t);
m2pp_needspace (state);
m2pp_print (state, ";\n");
killPretty (state);
}
/* ptcl print TREE_CHAINed list. */
void
ptcl (tree t)
{
pretty *state = initPretty (FALSE);
m2pp_decl_list (state, t);
m2pp_print (state, "\n");
killPretty (state);
}
/* loc if tree has a location then display it within a comment. */
static void
m2pp_loc (pretty *s, tree t)
{
if (CAN_HAVE_LOCATION_P (t))
{
if (EXPR_HAS_LOCATION (t))
{
if (EXPR_LOCATION (t) == UNKNOWN_LOCATION)
m2pp_print (s, "(* missing location1 *)\n");
else
{
expanded_location l = expand_location (EXPR_LOCATION (t));
m2pp_print (s, "(* ");
m2pp_print (s, l.file);
m2pp_print (s, ":");
printf ("%d", l.line);
m2pp_print (s, " *)");
m2pp_print (s, "\n");
}
}
else
{
m2pp_print (s, "(* missing location2 *)\n");
}
}
}
/* m2pp_decl_list prints a TREE_CHAINed list for a decl node. */
static void
m2pp_decl_list (pretty *s, tree t)
{
tree u = t;
m2pp_print (s, "(");
m2pp_needspace (s);
while (t != NULL_TREE)
{
m2pp_identifier (s, t);
t = TREE_CHAIN (t);
if (t == u || t == NULL_TREE)
break;
m2pp_print (s, ",");
m2pp_needspace (s);
}
m2pp_needspace (s);
m2pp_print (s, ")");
}
static void
m2pp_decl_bool (pretty *s, tree t)
{
if (TREE_STATIC (t))
m2pp_print (s, "static, ");
if (DECL_EXTERNAL (t))
m2pp_print (s, "external, ");
if (DECL_SEEN_IN_BIND_EXPR_P (t))
m2pp_print (s, "in bind expr, ");
}
void
pv (tree t)
{
if (t)
{
enum tree_code code = TREE_CODE (t);
if (code == PARM_DECL)
{
pretty *state = initPretty (FALSE);
m2pp_identifier (state, t);
m2pp_needspace (state);
m2pp_print (state, "<parm_decl context = ");
m2pp_identifier (state, DECL_CONTEXT (t));
if (DECL_ABSTRACT_ORIGIN (t) == t)
m2pp_print (state, ">\n");
else
{
m2pp_print (state, ", abstract origin = ");
m2pp_identifier (state, DECL_ABSTRACT_ORIGIN (t));
m2pp_print (state, ">\n");
modula2::pv (DECL_ABSTRACT_ORIGIN (t));
}
killPretty (state);
}
if (code == VAR_DECL)
{
pretty *state = initPretty (FALSE);
m2pp_identifier (state, t);
m2pp_needspace (state);
m2pp_print (state, "(* <var_decl context = ");
m2pp_identifier (state, DECL_CONTEXT (t));
m2pp_decl_bool (state, t);
if (DECL_ABSTRACT_ORIGIN (t) == t)
m2pp_print (state, "> *)\n");
else
{
m2pp_print (state, ", abstract origin = ");
m2pp_identifier (state, DECL_ABSTRACT_ORIGIN (t));
m2pp_print (state, "> *)\n");
modula2::pv (DECL_ABSTRACT_ORIGIN (t));
}
killPretty (state);
}
}
}
#if defined(GM2_MAINTAINER)
/* remember an internal debugging hook. */
static tree rememberF = NULL;
static void
remember (tree t)
{
rememberF = t;
printf ("type: watch *((tree *) %p) != %p\n", (void *)&DECL_SAVED_TREE (t),
(void *)DECL_SAVED_TREE (t));
}
#endif
/* push pushes tree t onto stack. */
static void
push (tree t)
{
stack *s = (stack *)xmalloc (sizeof (stack));
s->value = t;
s->next = stackPtr;
stackPtr = s;
}
/* pop pops a tree, from the stack. */
static void
pop (void)
{
stack *s = stackPtr;
stackPtr = stackPtr->next;
free (s);
}
/* being_printed returns TRUE if t is held on the stack. */
static int
begin_printed (tree t)
{
stack *s = stackPtr;
while (s != NULL)
{
if (s->value == t)
return TRUE;
else
s = s->next;
}
return FALSE;
}
/* dupPretty duplicate and return a copy of state s. */
static pretty *
dupPretty (pretty *s)
{
pretty *p = initPretty (s->bits);
*p = *s;
return p;
}
/* initPretty initialise the state of the pretty printer. */
static pretty *
initPretty (int bits)
{
pretty *state = (pretty *)xmalloc (sizeof (pretty));
state->needs_space = FALSE;
state->needs_indent = FALSE;
state->curpos = 0;
state->indent = 0;
state->issued_begin = FALSE;
state->in_vars = FALSE;
state->in_types = FALSE;
state->block = NULL_TREE;
state->bits = bits;
return state;
}
/* killPretty cleans up the state. */
static void
killPretty (pretty *s)
{
free (s);
fflush (stdout);
}
/* getindent returns the current indent value. */
static int
getindent (pretty *s)
{
return s->indent;
}
/* setindent sets the current indent to, n. */
static void
setindent (pretty *s, int n)
{
s->indent = n;
}
/* getcurpos returns the current cursor position. */
static int
getcurpos (pretty *s)
{
if (s->needs_space)
return s->curpos + 1;
else
return s->curpos;
}
/* m2pp_type_lowlevel prints out the low level details of a
fundamental type. */
static void
m2pp_type_lowlevel (pretty *s, tree t)
{
if (TREE_CODE (t) == INTEGER_TYPE)
{
m2pp_print (s, "min");
m2pp_needspace (s);
m2pp_integer_cst (s, TYPE_MIN_VALUE (t));
m2pp_print (s, ", max");
m2pp_needspace (s);
m2pp_integer_cst (s, TYPE_MAX_VALUE (t));
m2pp_print (s, ", type size unit");
m2pp_needspace (s);
m2pp_integer_cst (s, TYPE_SIZE_UNIT (t));
m2pp_print (s, ", type size");
m2pp_needspace (s);
m2pp_integer_cst (s, TYPE_SIZE (t));
printf (", precision %d, mode %d, align %d, user align %d",
TYPE_PRECISION (t), TYPE_MODE (t), TYPE_ALIGN (t),
TYPE_USER_ALIGN (t));
m2pp_needspace (s);
if (TYPE_UNSIGNED (t))
m2pp_print (s, "unsigned\n");
else
m2pp_print (s, "signed\n");
}
}
/* m2pp_var emit a VAR if necessary. */
static void
m2pp_var (pretty *s)
{
if (!s->in_vars)
{
s->in_vars = TRUE;
m2pp_print (s, "VAR\n");
setindent (s, getindent (s) + 3);
}
}
/* m2pp_types emit a TYPE if necessary. */
static void
m2pp_types (pretty *s)
{
if (!s->in_types)
{
s->in_types = TRUE;
m2pp_print (s, "TYPE\n");
setindent (s, getindent (s) + 3);
}
}
#ifdef DEBUGGING
/* hextree displays the critical fields for function, block and
bind_expr trees in raw hex. */
static void
hextree (tree t)
{
if (t == NULL_TREE)
return;
if (TREE_CODE (t) == BLOCK)
{
printf ("(* BLOCK %p *)\n", (void *)t);
printf ("BLOCK_VARS (t) = %p\n", (void *)BLOCK_VARS (t));
printf ("BLOCK_SUPERCONTEXT (t) = %p\n",
(void *)BLOCK_SUPERCONTEXT (t));
}
if (TREE_CODE (t) == BIND_EXPR)
{
printf ("(* BIND_EXPR %p *)\n", (void *)t);
printf ("BIND_EXPR_VARS (t) = %p\n", (void *)BIND_EXPR_VARS (t));
printf ("BIND_EXPR_BLOCK (t) = %p\n", (void *)BIND_EXPR_BLOCK (t));
printf ("BIND_EXPR_BODY (t) = %p\n", (void *)BIND_EXPR_BODY (t));
}
if (TREE_CODE (t) == FUNCTION_DECL)
{
printf ("(* FUNCTION_DECL %p *)\n", (void *)t);
printf ("DECL_INITIAL (t) = %p\n", (void *)DECL_INITIAL (t));
printf ("DECL_SAVED_TREE (t) = %p\n", (void *)DECL_SAVED_TREE (t));
hextree (DECL_INITIAL (t));
hextree (DECL_SAVED_TREE (t));
}
if (TREE_CODE (t) == VAR_DECL)
{
pretty *state = initPretty (FALSE);
printf ("(* VAR_DECL %p <", (void *)t);
if (DECL_SEEN_IN_BIND_EXPR_P (t))
printf ("b");
if (DECL_EXTERNAL (t))
printf ("e");
if (TREE_STATIC (t))
printf ("s");
printf ("> context = %p*)\n", (void *)decl_function_context (t));
m2pp_type (state, TREE_TYPE (t));
m2pp_needspace (state);
m2pp_print (state, ";\n");
killPretty (state);
}
if (TREE_CODE (t) == PARM_DECL)
{
pretty *state = initPretty (FALSE);
printf ("(* PARM_DECL %p <", (void *)t);
printf ("> context = %p*)\n", (void *)decl_function_context (t));
m2pp_type (state, TREE_TYPE (t));
m2pp_needspace (state);
m2pp_print (state, ";\n");
killPretty (state);
}
}
#endif
/* translation produce a pseudo implementation module from the tree t. */
static void
m2pp_translation (pretty *s, tree t)
{
tree block = DECL_INITIAL (t);
m2pp_print (s, "IMPLEMENTATION MODULE ");
m2pp_identifier (s, t);
m2pp_print (s, "\n\n");
if (block != NULL)
{
m2pp_module_block (s, block);
m2pp_print (s, "\n");
}
m2pp_print (s, "\n");
m2pp_print (s, "END ");
m2pp_identifier (s, t);
m2pp_print (s, ".\n");
}
static void
m2pp_module_block (pretty *s, tree t)
{
t = BLOCK_VARS (t);
if (t != NULL_TREE)
for (; t != NULL_TREE; t = TREE_CHAIN (t))
{
switch (TREE_CODE (t))
{
case FUNCTION_DECL:
if (!DECL_EXTERNAL (t))
{
pretty *p = dupPretty (s);
printf ("\n");
p->in_vars = FALSE;
p->in_types = FALSE;
m2pp_function (p, t);
killPretty (p);
printf ("\n");
s->in_vars = FALSE;
s->in_types = FALSE;
}
break;
case TYPE_DECL:
{
int o = getindent (s);
int p;
m2pp_print (s, "\n");
m2pp_types (s);
setindent (s, o + 3);
m2pp_identifier (s, t);
m2pp_print (s, " = ");
p = getcurpos (s);
setindent (s, p);
m2pp_type (s, TREE_TYPE (t));
setindent (s, o);
m2pp_needspace (s);
m2pp_print (s, ";\n");
s->in_vars = FALSE;
}
break;
case VAR_DECL:
m2pp_var (s);
m2pp_identifier (s, t);
m2pp_needspace (s);
m2pp_print (s, ":");
m2pp_needspace (s);
m2pp_type (s, TREE_TYPE (t));
m2pp_needspace (s);
m2pp_print (s, ";\n");
s->in_types = FALSE;
break;
case DECL_EXPR:
printf ("is this node legal here? \n");
m2pp_decl_expr (s, t);
break;
default:
m2pp_unknown (s, __FUNCTION__, get_tree_code_name (TREE_CODE (t)));
}
}
}
/* m2pp_begin emit a BEGIN if necessary. */
static void
m2pp_begin (pretty *s)
{
if (!s->issued_begin)
{
if (s->in_vars || s->in_types)
{
setindent (s, getindent (s) - 3);
m2pp_print (s, "BEGIN\n");
setindent (s, getindent (s) + 3);
}
else
{
m2pp_print (s, "BEGIN\n");
setindent (s, getindent (s) + 3);
}
s->issued_begin = TRUE;
s->in_vars = FALSE;
s->in_types = FALSE;
}
}
/* m2pp_function walk over the function. */
static void
m2pp_function (pretty *s, tree t)
{
m2pp_function_header (s, t);
m2pp_function_vars (s, t);
m2pp_statement_sequence (s, DECL_SAVED_TREE (t));
if (TREE_CODE (t) == FUNCTION_DECL)
{
m2pp_begin (s);
setindent (s, getindent (s) - 3);
m2pp_print (s, "END");
m2pp_needspace (s);
m2pp_identifier (s, t);
m2pp_needspace (s);
m2pp_print (s, ";\n");
}
}
/* m2pp_bind_expr displays the bind expr tree node. */
static void
m2pp_bind_expr (pretty *s, tree t)
{
if (TREE_CODE (t) == BIND_EXPR)
{
if (BIND_EXPR_VARS (t))
{
m2pp_print (s, "(* variables in bind_expr *)\n");
m2pp_var (s);
m2pp_var_list (s, BIND_EXPR_VARS (t));
}
if (BIND_EXPR_BLOCK (t))
{
m2pp_print (s, "(* bind_expr_block *)\n");
m2pp_statement_sequence (s, BIND_EXPR_BLOCK (t));
m2pp_needspace (s);
m2pp_print (s, "; \n");
}
m2pp_statement_sequence (s, BIND_EXPR_BODY (t));
}
}
/* m2pp_block_list iterates over the list of blocks. */
static void
m2pp_block_list (pretty *s, tree t)
{
for (; t; t = BLOCK_CHAIN (t))
m2pp_block (s, t);
}
/* m2pp_block prints the VARiables and the TYPEs inside a block. */
static void
m2pp_block (pretty *s, tree t)
{
if ((BLOCK_VARS (t) != NULL_TREE) && (s->block != BLOCK_VARS (t)))
{
s->block = BLOCK_VARS (t);
m2pp_print (s, "(* block variables *)\n");
m2pp_var (s);
m2pp_var_list (s, BLOCK_VARS (t));
}
}
/* m2pp_var_type_decl displays the variable and type declaration. */
static void
m2pp_var_type_decl (pretty *s, tree t)
{
m2pp_identifier (s, t);
m2pp_needspace (s);
m2pp_print (s, ":");
m2pp_needspace (s);
m2pp_type (s, TREE_TYPE (t));
m2pp_needspace (s);
m2pp_print (s, ";\n");
}
/* m2pp_var_list print a variable list. */
static void
m2pp_var_list (pretty *s, tree t)
{
if (t != NULL_TREE)
for (; t; t = TREE_CHAIN (t))
{
if (TREE_CODE (t) == FUNCTION_DECL)
{
pretty *p = dupPretty (s);
printf ("\n");
p->in_vars = FALSE;
p->in_types = FALSE;
m2pp_function (p, t);
killPretty (p);
printf ("\n");
}
else if (TREE_CODE (t) == TYPE_DECL)
m2pp_identifier (s, t);
else if (TREE_CODE (t) == DECL_EXPR)
{
printf ("is this node legal here? \n");
// is it legal to have a DECL_EXPR here ?
m2pp_var_type_decl (s, DECL_EXPR_DECL (t));
}
else
m2pp_var_type_decl (s, t);
}
}
#if 0
/* m2pp_type_list print a variable list. */
static void
m2pp_type_list (pretty *s, tree t)
{
if (t != NULL_TREE)
for (; t; t = TREE_CHAIN (t))
{
m2pp_identifier (s, t);
m2pp_needspace (s);
m2pp_print (s, "=");
m2pp_needspace (s);
m2pp_type (s, TREE_TYPE (t));
m2pp_needspace (s);
m2pp_print (s, ";\n");
}
}
#endif
/* m2pp_needspace sets appropriate flag to TRUE. */
static void
m2pp_needspace (pretty *s)
{
s->needs_space = TRUE;
}
/* m2pp_identifer prints an identifier. */
static void
m2pp_identifier (pretty *s, tree t)
{
if (t)
{
if (TREE_CODE (t) == COMPONENT_REF)
m2pp_component_ref (s, t);
else if (DECL_NAME (t) && IDENTIFIER_POINTER (DECL_NAME (t)))
m2pp_ident_pointer (s, DECL_NAME (t));
else
{
char name[100];
if (TREE_CODE (t) == CONST_DECL)
snprintf (name, 100, "C_%u", DECL_UID (t));
else
snprintf (name, 100, "D_%u", DECL_UID (t));
m2pp_print (s, name);
}
}
}
/* m2pp_ident_pointer displays an ident pointer. */
static void
m2pp_ident_pointer (pretty *s, tree t)
{
if (t)
m2pp_print (s, IDENTIFIER_POINTER (t));
}
/* m2pp_parameter prints out a param decl tree. */
static void
m2pp_parameter (pretty *s, tree t)
{
if (TREE_CODE (t) == PARM_DECL)
{
if (TREE_TYPE (t) && (TREE_CODE (TREE_TYPE (t)) == REFERENCE_TYPE))
{
m2pp_print (s, "VAR");
m2pp_needspace (s);
m2pp_identifier (s, t);
m2pp_print (s, ":");
m2pp_needspace (s);
m2pp_simple_type (s, TREE_TYPE (TREE_TYPE (t)));
}
else
{
m2pp_identifier (s, t);
m2pp_print (s, ":");
m2pp_needspace (s);
m2pp_simple_type (s, TREE_TYPE (t));
}
}
}
/* m2pp_param_type prints out the type of parameter. */
static void
m2pp_param_type (pretty *s, tree t)
{
if (t && (TREE_CODE (t) == REFERENCE_TYPE))
{
m2pp_print (s, "VAR");
m2pp_needspace (s);
m2pp_simple_type (s, TREE_TYPE (t));
}
else
m2pp_simple_type (s, t);
}
/* m2pp_procedure_type displays a procedure type. */
static void
m2pp_procedure_type (pretty *s, tree t)
{
push (t);
if (TREE_CODE (t) == FUNCTION_TYPE)
{
tree i = TYPE_ARG_TYPES (t);
tree returnType = TREE_TYPE (TREE_TYPE (t));
m2pp_needspace (s);
m2pp_print (s, "PROCEDURE");
m2pp_needspace (s);
if (i != NULL_TREE)
{
int o = getindent (s);
int p;
int first = TRUE;
m2pp_print (s, "(");
p = getcurpos (s);
setindent (s, p);
while (i != NULL_TREE)
{
if (TREE_CHAIN (i) == NULL_TREE)
{
if (TREE_VALUE (i) == void_type_node)
/* Ignore void_type_node at the end. */
;
else
{
m2pp_param_type (s, TREE_VALUE (i));
m2pp_print (s, ", ...");
}
break;
}
else
{
if (!first)
{
m2pp_print (s, ",");
m2pp_needspace (s);
}
m2pp_param_type (s, TREE_VALUE (i));
}
i = TREE_CHAIN (i);
first = FALSE;
}
m2pp_print (s, ")");
setindent (s, o);
}
else if (returnType != NULL_TREE)
{
m2pp_needspace (s);
m2pp_print (s, "()");
}
if (returnType != NULL_TREE)
{
m2pp_needspace (s);
m2pp_print (s, ": ");
m2pp_simple_type (s, returnType);
}
}
pop ();
}
/* m2pp_comment_header displays a simple header with some critical
tree info. */
static void
m2pp_comment_header (pretty *s, tree t)
{
int o = getindent (s);
m2pp_print (s, "(*\n");
setindent (s, o + 3);
m2pp_identifier (s, t);
m2pp_needspace (s);
m2pp_print (s, "-");
m2pp_needspace (s);
if (TREE_PUBLIC (t))
{
m2pp_needspace (s);
m2pp_print (s, "public,");
}
if (TREE_STATIC (t))
{
m2pp_needspace (s);
m2pp_print (s, "static,");
}
if (DECL_EXTERNAL (t))
{
m2pp_needspace (s);
m2pp_print (s, "extern");
}
m2pp_print (s, "\n");
setindent (s, o);
m2pp_print (s, "*)\n\n");
}
/* m2pp_function_header displays the function header. */
static void
m2pp_function_header (pretty *s, tree t)
{
push (t);
if (TREE_CODE (t) == FUNCTION_DECL)
{
tree i = DECL_ARGUMENTS (t);
tree returnType = TREE_TYPE (TREE_TYPE (t));
m2pp_comment_header (s, t);
m2pp_print (s, "PROCEDURE ");
m2pp_identifier (s, t);
m2pp_needspace (s);
if (i != NULL_TREE)
{
int o = getindent (s);
int p;
m2pp_print (s, "(");
p = getcurpos (s);
setindent (s, p);
while (i != NULL_TREE)
{
m2pp_parameter (s, i);
i = TREE_CHAIN (i);
if (i != NULL_TREE)
m2pp_print (s, ";\n");
}
m2pp_print (s, ")");
m2pp_needspace (s);
setindent (s, o);
}
else if (returnType != void_type_node)
{
m2pp_print (s, "()");
m2pp_needspace (s);
}
if (returnType != void_type_node)
{
m2pp_print (s, ": ");
m2pp_simple_type (s, returnType);
m2pp_needspace (s);
}
m2pp_print (s, "; ");
m2pp_loc (s, t);
m2pp_print (s, "\n");
}
pop ();
}
/* m2pp_add_var adds a variable into a list as defined by, data. */
static tree
m2pp_add_var (tree *tp, int *walk_subtrees, void *data)
{
tree t = *tp;
pretty *s = (pretty *)data;
enum tree_code code = TREE_CODE (t);
if (code == VAR_DECL)
{
m2pp_var (s);
m2pp_identifier (s, t);
m2pp_needspace (s);
m2pp_print (s, ":");
m2pp_needspace (s);
m2pp_type (s, TREE_TYPE (t));
m2pp_needspace (s);
m2pp_print (s, ";\n");
}
if (code == SSA_NAME)
{
m2pp_var (s);
m2pp_ssa (s, t);
m2pp_identifier (s, SSA_NAME_VAR (t));
m2pp_needspace (s);
m2pp_print (s, ":");
m2pp_needspace (s);
m2pp_type (s, TREE_TYPE (t));
m2pp_needspace (s);
m2pp_print (s, ";\n");
}
*walk_subtrees = 1;
return NULL_TREE;
}
/* m2pp_function_vars displays variables as defined by the function
tree. */
static void
m2pp_function_vars (pretty *s, tree t)
{
walk_tree_without_duplicates (&t, m2pp_add_var, s);
if (TREE_CODE (t) == FUNCTION_DECL && DECL_INITIAL (t))
{
m2pp_print (s, "(* variables in function_decl (decl_initial) *)\n");
m2pp_var (s);
m2pp_statement_sequence (s, DECL_INITIAL (t));
}
}
/* m2pp_print print out a string p interpreting '\n' and
adjusting the fields within state s. */
static void
m2pp_print (pretty *s, const char *p)
{
if (p)
{
int l = strlen (p);
int i = 0;
if (s->needs_space)
{
printf (" ");
s->needs_space = FALSE;
s->curpos++;
}
while (i < l)
{
if (p[i] == '\n')
{
s->needs_indent = TRUE;
s->curpos = 0;
printf ("\n");
}
else
{
if (s->needs_indent)
{
if (s->indent > 0)
printf ("%*c", s->indent, ' ');
s->needs_indent = FALSE;
s->curpos += s->indent;
}
s->curpos++;
putchar (p[i]);
}
i++;
}
}
}
/* m2pp_print_char prints out a character ch obeying needs_space
and needs_indent. */
static void
m2pp_print_char (pretty *s, char ch)
{
if (s->needs_space)
{
printf (" ");
s->needs_space = FALSE;
s->curpos++;
}
if (s->needs_indent)
{
if (s->indent > 0)
printf ("%*c", s->indent, ' ');
s->needs_indent = FALSE;
s->curpos += s->indent;
}
if (ch == '\n')
{
s->curpos++;
putchar ('\\');
putchar ('n');
}
else
putchar (ch);
s->curpos++;
}
/* m2pp_integer display the appropriate integer type. */
#if defined(GM2)
void
m2pp_integer (pretty *s, tree t)
{
if (t == m2type_GetM2ZType ())
m2pp_print (s, "M2ZTYPE");
else if (t == m2type_GetM2LongIntType ())
m2pp_print (s, "LONGINT");
else if (t == m2type_GetM2IntegerType ())
m2pp_print (s, "INTEGER");
else if (t == m2type_GetM2ShortIntType ())
m2pp_print (s, "SHORTINT");
else if (t == m2type_GetLongIntType ())
m2pp_print (s, "long int");
else if (t == m2type_GetIntegerType ())
m2pp_print (s, "int");
else if (t == m2type_GetShortIntType ())
m2pp_print (s, "short");
else if (t == m2type_GetM2LongCardType ())
m2pp_print (s, "LONGCARD");
else if (t == m2type_GetM2CardinalType ())
m2pp_print (s, "CARDINAL");
else if (t == m2type_GetM2ShortCardType ())
m2pp_print (s, "SHORTCARD");
else if (t == m2type_GetCardinalType ())
m2pp_print (s, "CARDINAL");
else if (t == m2type_GetPointerType ())
m2pp_print (s, "ADDRESS");
else if (t == m2type_GetByteType ())
m2pp_print (s, "BYTE");
else if (t == m2type_GetCharType ())
m2pp_print (s, "CHAR");
else if (t == m2type_GetBitsetType ())
m2pp_print (s, "BITSET");
else if (t == m2type_GetBitnumType ())
m2pp_print (s, "BITNUM");
else
{
if (TYPE_UNSIGNED (t))
m2pp_print (s, "CARDINAL");
else
m2pp_print (s, "INTEGER");
m2pp_integer_cst (s, TYPE_SIZE (t));
}
}
#else
void
m2pp_integer (pretty *s, tree t ATTRIBUTE_UNUSED)
{
m2pp_print (s, "INTEGER");
}
#endif
/* m2pp_complex display the actual complex type. */
#if defined(GM2)
static void
m2pp_complex (pretty *s, tree t)
{
if (t == m2type_GetM2ComplexType ())
m2pp_print (s, "COMPLEX");
else if (t == m2type_GetM2LongComplexType ())
m2pp_print (s, "LONGCOMPLEX");
else if (t == m2type_GetM2ShortComplexType ())
m2pp_print (s, "SHORTCOMPLEX");
else if (t == m2type_GetM2CType ())
m2pp_print (s, "C'omplex' type");
else if (t == m2type_GetM2Complex32 ())
m2pp_print (s, "COMPLEX32");
else if (t == m2type_GetM2Complex64 ())
m2pp_print (s, "COMPLEX64");
else if (t == m2type_GetM2Complex96 ())
m2pp_print (s, "COMPLEX96");
else if (t == m2type_GetM2Complex128 ())
m2pp_print (s, "COMPLEX128");
else
m2pp_print (s, "unknown COMPLEX type");
}
#else
static void
m2pp_complex (pretty *s, tree t ATTRIBUTE_UNUSED)
{
m2pp_print (s, "a COMPLEX type");
}
#endif
/* m2pp_type prints a full type. */
void
m2pp_type (pretty *s, tree t)
{
if (begin_printed (t))
{
m2pp_print (s, "<...>");
return;
}
if ((TREE_CODE (t) != FIELD_DECL) && (TREE_CODE (t) != TYPE_DECL))
m2pp_gimpified (s, t);
switch (TREE_CODE (t))
{
case INTEGER_TYPE:
m2pp_integer (s, t);
break;
case REAL_TYPE:
m2pp_print (s, "REAL");
break;
case ENUMERAL_TYPE:
m2pp_enum (s, t);
break;
case UNION_TYPE:
m2pp_union_type (s, t);
break;
case RECORD_TYPE:
m2pp_record_type (s, t);
break;
case ARRAY_TYPE:
m2pp_array (s, t);
break;
#if 0
case FUNCTION_TYPE:
m2pp_function_type (s, t);
break;
#endif
case TYPE_DECL:
m2pp_identifier (s, t);
break;
case POINTER_TYPE:
m2pp_pointer_type (s, t);
break;
#if defined(GM2)
case SET_TYPE:
m2pp_set_type (s, t);
break;
#endif
case VOID_TYPE:
m2pp_print (s, "ADDRESS");
break;
case COMPLEX_TYPE:
m2pp_complex (s, t);
break;
default:
m2pp_unknown (s, __FUNCTION__, get_tree_code_name (TREE_CODE (t)));
}
}
/* m2pp_set_type prints out the set type. */
static void
m2pp_set_type (pretty *s, tree t)
{
push (t);
m2pp_print (s, "SET OF");
m2pp_needspace (s);
m2pp_type (s, TREE_TYPE (t));
pop ();
}
/* m2pp_enum print out the enumeration type. */
static void
m2pp_enum (pretty *s, tree t)
{
tree chain_p = TYPE_VALUES (t);
push (t);
m2pp_print (s, "(");
while (chain_p)
{
m2pp_ident_pointer (s, TREE_PURPOSE (chain_p));
chain_p = TREE_CHAIN (chain_p);
if (chain_p)
m2pp_print (s, ", ");
}
m2pp_print (s, ")");
pop ();
}
/* m2pp_array prints out the array type. */
static void
m2pp_array (pretty *s, tree t)
{
push (t);
m2pp_print (s, "ARRAY");
m2pp_needspace (s);
m2pp_subrange (s, TYPE_DOMAIN (t));
m2pp_needspace (s);
m2pp_print (s, "OF");
m2pp_needspace (s);
m2pp_type (s, TREE_TYPE (t));
pop ();
}
/* m2pp_subrange prints out the subrange, but probably the lower
bound will always be zero. */
static void
m2pp_subrange (pretty *s, tree t)
{
tree min = TYPE_MIN_VALUE (t);
tree max = TYPE_MAX_VALUE (t);
m2pp_print (s, "[");
m2pp_expression (s, min);
m2pp_print (s, "..");
m2pp_expression (s, max);
m2pp_print (s, "]");
}
/* m2pp_gimplified print out a gimplified comment. */
static void
m2pp_gimpified (pretty *s, tree t)
{
if (!TYPE_SIZES_GIMPLIFIED (t))
{
m2pp_print (s, "(* <!g> *)");
m2pp_needspace (s);
}
}
/* m2pp_printer_type display the pointer type. */
static void
m2pp_pointer_type (pretty *s, tree t)
{
push (t);
if (TREE_CODE (t) == POINTER_TYPE)
{
if (TREE_CODE (TREE_TYPE (t)) == FUNCTION_TYPE)
m2pp_procedure_type (s, TREE_TYPE (t));
else if (t == ptr_type_node)
m2pp_print (s, "ADDRESS");
else
{
m2pp_print (s, "POINTER TO");
m2pp_needspace (s);
m2pp_type (s, TREE_TYPE (t));
}
}
pop ();
}
/* m2pp_record_alignment prints out whether this record is aligned
(packed). */
static void
m2pp_record_alignment (pretty *s, tree t)
{
if (TYPE_PACKED (t))
m2pp_print (s, "<* bytealignment (0) *>\n");
}
static unsigned int
m2pp_getaligned (tree t)
{
if (DECL_P (t))
{
if (DECL_USER_ALIGN (t))
return DECL_ALIGN (t);
}
else if (TYPE_P (t))
{
if (TYPE_USER_ALIGN (t))
return TYPE_ALIGN (t);
}
return 0;
}
static void
m2pp_recordfield_alignment (pretty *s, tree t)
{
unsigned int aligned = m2pp_getaligned (t);
if (aligned != 0)
{
int o = getindent (s);
int p = getcurpos (s);
m2pp_needspace (s);
m2pp_print (s, "<* bytealignment (");
setindent (s, p + 18);
printf ("%d", aligned / BITS_PER_UNIT);
m2pp_print (s, ")");
m2pp_needspace (s);
setindent (s, p);
m2pp_print (s, "*>");
setindent (s, o);
}
}
static void
m2pp_recordfield_bitfield (pretty *s, tree t)
{
if ((TREE_CODE (t) == FIELD_DECL) && DECL_PACKED (t))
{
m2pp_print (s, " (* packed");
if (DECL_NONADDRESSABLE_P (t))
m2pp_print (s, ", non-addressible");
if (DECL_BIT_FIELD (t))
m2pp_print (s, ", bit-field");
m2pp_print (s, ", offset: ");
m2pp_expression (s, DECL_FIELD_OFFSET (t));
m2pp_print (s, ", bit offset:");
m2pp_expression (s, DECL_FIELD_BIT_OFFSET (t));
m2pp_print (s, " *) ");
}
}
/* m2pp_record_type displays the record type. */
static void
m2pp_record_type (pretty *s, tree t)
{
push (t);
if (TREE_CODE (t) == RECORD_TYPE)
{
tree i;
int o = getindent (s);
int p = getcurpos (s);
m2pp_print (s, "RECORD\n");
setindent (s, p + 3);
m2pp_record_alignment (s, t);
for (i = TYPE_FIELDS (t); i != NULL_TREE; i = TREE_CHAIN (i))
{
m2pp_identifier (s, i);
m2pp_print (s, " : ");
m2pp_type (s, TREE_TYPE (i));
m2pp_recordfield_bitfield (s, i);
m2pp_recordfield_alignment (s, i);
m2pp_print (s, ";\n");
}
setindent (s, p);
m2pp_print (s, "END");
setindent (s, o);
}
pop ();
}
/* m2pp_record_type displays the record type. */
static void
m2pp_union_type (pretty *s, tree t)
{
push (t);
if (TREE_CODE (t) == UNION_TYPE)
{
tree i;
int o = getindent (s);
int p = getcurpos (s);
m2pp_print (s, "CASE .. OF\n");
setindent (s, p + 3);
m2pp_record_alignment (s, t);
for (i = TYPE_FIELDS (t); i != NULL_TREE; i = TREE_CHAIN (i))
{
m2pp_identifier (s, i);
m2pp_print (s, " : ");
m2pp_type (s, TREE_TYPE (i));
m2pp_recordfield_bitfield (s, i);
m2pp_print (s, ";\n");
}
setindent (s, p);
m2pp_print (s, "END");
setindent (s, o);
}
pop ();
}
/* m2pp_simple_type. */
static void
m2pp_simple_type (pretty *s, tree t)
{
if (begin_printed (t))
{
m2pp_print (s, "<...>");
return;
}
m2pp_gimpified (s, t);
switch (TREE_CODE (t))
{
case INTEGER_TYPE:
m2pp_integer (s, t);
break;
case REAL_TYPE:
m2pp_print (s, "REAL");
break;
case BOOLEAN_TYPE:
m2pp_print (s, "BOOLEAN");
break;
case VOID_TYPE:
m2pp_print (s, "ADDRESS");
break;
case TYPE_DECL:
m2pp_identifier (s, t);
break;
case POINTER_TYPE:
m2pp_pointer_type (s, t);
break;
case RECORD_TYPE:
m2pp_record_type (s, t);
break;
case UNION_TYPE:
m2pp_union_type (s, t);
break;
case ENUMERAL_TYPE:
m2pp_enum (s, t);
break;
case COMPLEX_TYPE:
m2pp_complex (s, t);
break;
default:
m2pp_unknown (s, __FUNCTION__, get_tree_code_name (TREE_CODE (t)));
}
}
/* m2pp_expression display an expression. */
static void
m2pp_expression (pretty *s, tree t)
{
enum tree_code code = TREE_CODE (t);
switch (code)
{
case EQ_EXPR:
m2pp_relop (s, t, "=");
break;
case NE_EXPR:
m2pp_relop (s, t, "#");
break;
case LE_EXPR:
m2pp_relop (s, t, "<=");
break;
case GE_EXPR:
m2pp_relop (s, t, ">=");
break;
case LT_EXPR:
m2pp_relop (s, t, "<");
break;
case GT_EXPR:
m2pp_relop (s, t, ">");
break;
default:
m2pp_simple_expression (s, t);
}
}
/* m2pp_relop displays the lhs relop rhs. */
static void
m2pp_relop (pretty *s, tree t, const char *p)
{
m2pp_expression (s, TREE_OPERAND (t, 0));
m2pp_needspace (s);
m2pp_print (s, p);
m2pp_needspace (s);
m2pp_expression (s, TREE_OPERAND (t, 1));
}
/* m2pp_compound_expression handle compound expression tree. */
static void
m2pp_compound_expression (pretty *s, tree t)
{
m2pp_print (s, "compound expression {");
m2pp_expression (s, TREE_OPERAND (t, 0));
m2pp_print (s, " (* result ignored *), ");
m2pp_expression (s, TREE_OPERAND (t, 1));
m2pp_print (s, "}");
m2pp_needspace (s);
}
/* m2pp_target_expression handle target expression tree. */
static void
m2pp_target_expression (pretty *s, tree t)
{
m2pp_print (s, "{");
m2pp_needspace (s);
if (TREE_OPERAND (t, 0) != NULL_TREE)
{
m2pp_print (s, "(* target *) ");
m2pp_expression (s, TREE_OPERAND (t, 0));
m2pp_print (s, ",");
m2pp_needspace (s);
}
if (TREE_OPERAND (t, 1) != NULL_TREE)
{
m2pp_print (s, "(* initializer *) ");
m2pp_expression (s, TREE_OPERAND (t, 1));
m2pp_print (s, ",");
m2pp_needspace (s);
}
if (TREE_OPERAND (t, 2) != NULL_TREE)
{
m2pp_print (s, "(* cleanup *) ");
m2pp_expression (s, TREE_OPERAND (t, 2));
m2pp_print (s, ",");
m2pp_needspace (s);
}
if (TREE_OPERAND (t, 3) != NULL_TREE)
{
m2pp_print (s, "(* saved initializer *) ");
m2pp_expression (s, TREE_OPERAND (t, 3));
m2pp_print (s, ",");
m2pp_needspace (s);
}
m2pp_print (s, "}");
m2pp_needspace (s);
}
/* m2pp_constructor print out a constructor. */
static void
m2pp_constructor (pretty *s, tree t)
{
tree purpose, value;
unsigned HOST_WIDE_INT ix;
m2pp_print (s, "{ ");
FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (t), ix, purpose, value)
{
m2pp_print (s, "(index: ");
m2pp_simple_expression (s, purpose);
m2pp_print (s, ") ");
m2pp_simple_expression (s, value);
m2pp_print (s, ", ");
}
m2pp_print (s, "}");
m2pp_print (s, "(* type: ");
setindent (s, getindent (s) + 8);
m2pp_type (s, TREE_TYPE (t));
setindent (s, getindent (s) - 8);
m2pp_print (s, " *)\n");
}
/* m2pp_complex_expr handle GCC complex_expr tree. */
static void
m2pp_complex_expr (pretty *s, tree t)
{
if (TREE_CODE (t) == COMPLEX_CST)
{
m2pp_print (s, "CMPLX(");
m2pp_needspace (s);
m2pp_expression (s, TREE_REALPART (t));
m2pp_print (s, ",");
m2pp_needspace (s);
m2pp_expression (s, TREE_IMAGPART (t));
m2pp_print (s, ")");
}
else
{
m2pp_print (s, "CMPLX(");
m2pp_needspace (s);
m2pp_expression (s, TREE_OPERAND (t, 0));
m2pp_print (s, ",");
m2pp_needspace (s);
m2pp_expression (s, TREE_OPERAND (t, 1));
m2pp_print (s, ")");
}
}
/* m2pp_imagpart_expr handle imagpart_expr tree. */
static void
m2pp_imagpart_expr (pretty *s, tree t)
{
m2pp_print (s, "IM(");
m2pp_needspace (s);
if (TREE_CODE (t) == IMAGPART_EXPR)
m2pp_expression (s, TREE_OPERAND (t, 0));
else if (TREE_CODE (t) == COMPLEX_CST)
m2pp_expression (s, TREE_IMAGPART (t));
m2pp_needspace (s);
m2pp_print (s, ")");
}
/* m2pp_realpart_expr handle imagpart_expr tree. */
static void
m2pp_realpart_expr (pretty *s, tree t)
{
m2pp_print (s, "RE(");
m2pp_needspace (s);
if (TREE_CODE (t) == REALPART_EXPR)
m2pp_expression (s, TREE_OPERAND (t, 0));
else if (TREE_CODE (t) == COMPLEX_CST)
m2pp_expression (s, TREE_REALPART (t));
m2pp_needspace (s);
m2pp_print (s, ")");
}
/* m2pp_bit_ior_expr generate a C style bit or. */
static void
m2pp_bit_ior_expr (pretty *s, tree t)
{
m2pp_binary (s, t, "|");
}
/* m2pp_truth_expr. */
static void
m2pp_truth_expr (pretty *s, tree t, const char *op)
{
m2pp_print (s, "(");
m2pp_expression (s, TREE_OPERAND (t, 0));
m2pp_print (s, ")");
m2pp_needspace (s);
m2pp_print (s, op);
m2pp_needspace (s);
m2pp_print (s, "(");
m2pp_expression (s, TREE_OPERAND (t, 1));
m2pp_print (s, ")");
}
/* m2pp_simple_expression handle GCC expression tree. */
static void
m2pp_simple_expression (pretty *s, tree t)
{
enum tree_code code = TREE_CODE (t);
switch (code)
{
case ERROR_MARK:
m2pp_print (s, "(* !!! ERROR NODE !!! *)");
break;
case CONSTRUCTOR:
m2pp_constructor (s, t);
break;
case IDENTIFIER_NODE:
m2pp_ident_pointer (s, t);
break;
case PARM_DECL:
m2pp_identifier (s, t);
break;
case FIELD_DECL:
m2pp_identifier (s, t);
break;
case TREE_LIST:
m2pp_list (s, t);
break;
case BLOCK:
m2pp_print (s, "(* BLOCK NODE *)");
break;
case OFFSET_TYPE:
m2pp_offset (s, t);
break;
case INTEGER_CST:
m2pp_integer_cst (s, t);
break;
case REAL_CST:
m2pp_real_cst (s, t);
break;
case STRING_CST:
m2pp_string_cst (s, t);
break;
case INDIRECT_REF:
m2pp_indirect_ref (s, t);
break;
case ADDR_EXPR:
m2pp_addr_expr (s, t);
break;
case NOP_EXPR:
m2pp_nop (s, t);
break;
case CONVERT_EXPR:
m2pp_convert (s, t);
break;
case VAR_DECL:
m2pp_var_decl (s, t);
break;
case RESULT_DECL:
m2pp_result_decl (s, t);
break;
case PLUS_EXPR:
m2pp_binary (s, t, "+");
break;
case MINUS_EXPR:
m2pp_binary (s, t, "-");
break;
case MULT_EXPR:
m2pp_binary (s, t, "*");
break;
case FLOOR_DIV_EXPR:
case CEIL_DIV_EXPR:
case TRUNC_DIV_EXPR:
case ROUND_DIV_EXPR:
m2pp_binary (s, t, "DIV");
break;
case FLOOR_MOD_EXPR:
case CEIL_MOD_EXPR:
case TRUNC_MOD_EXPR:
case ROUND_MOD_EXPR:
m2pp_binary (s, t, "MOD");
break;
case NEGATE_EXPR:
m2pp_unary (s, t, "-");
break;
case CALL_EXPR:
m2pp_call_expr (s, t);
break;
case SSA_NAME:
m2pp_ssa (s, t);
break;
case COMPONENT_REF:
m2pp_component_ref (s, t);
break;
case RETURN_EXPR:
m2pp_return_expr (s, t);
break;
case ARRAY_REF:
m2pp_array_ref (s, t);
break;
case NON_LVALUE_EXPR:
m2pp_non_lvalue_expr (s, t);
break;
case EXPR_STMT:
m2pp_expression (s, EXPR_STMT_EXPR (t));
break;
#if 0
case EXC_PTR_EXPR:
m2pp_print (s, "GCC_EXCEPTION_OBJECT");
break;
#endif
case INIT_EXPR:
case MODIFY_EXPR:
m2pp_assignment (s, t);
break;
case COMPOUND_EXPR:
m2pp_compound_expression (s, t);
break;
case TARGET_EXPR:
m2pp_target_expression (s, t);
break;
case THROW_EXPR:
m2pp_throw (s, t);
break;
case FUNCTION_DECL:
m2pp_identifier (s, t);
break;
case COMPLEX_EXPR:
m2pp_complex_expr (s, t);
break;
case REALPART_EXPR:
m2pp_realpart_expr (s, t);
break;
case IMAGPART_EXPR:
m2pp_imagpart_expr (s, t);
break;
case CONST_DECL:
m2pp_identifier (s, t);
break;
case POINTER_PLUS_EXPR:
m2pp_binary (s, t, "+");
break;
case CLEANUP_POINT_EXPR:
m2pp_cleanup_point_expr (s, t);
break;
case BIT_IOR_EXPR:
m2pp_bit_ior_expr (s, t);
break;
case TRUTH_ANDIF_EXPR:
m2pp_truth_expr (s, t, "AND");
break;
case TRUTH_ORIF_EXPR:
m2pp_truth_expr (s, t, "OR");
break;
default:
m2pp_unknown (s, __FUNCTION__, get_tree_code_name (code));
}
}
/* non_lvalue_expr indicates that operand 0 is not an lvalue. */
static void
m2pp_non_lvalue_expr (pretty *s, tree t)
{
m2pp_needspace (s);
m2pp_print (s, "assert_non_lvalue(");
m2pp_needspace (s);
m2pp_expression (s, TREE_OPERAND (t, 0));
m2pp_needspace (s);
m2pp_print (s, ")");
}
/* m2pp_array_ref prints out the array reference. */
static void
m2pp_array_ref (pretty *s, tree t)
{
m2pp_expression (s, TREE_OPERAND (t, 0));
m2pp_print (s, "[");
m2pp_expression (s, TREE_OPERAND (t, 1));
m2pp_print (s, "]");
}
/* m2pp_ssa prints out the ssa variable name. */
static void
m2pp_ssa (pretty *s, tree t)
{
m2pp_identifier (s, SSA_NAME_VAR (t));
}
/* m2pp_binary print the binary operator, p, and lhs, rhs. */
static void
m2pp_binary (pretty *s, tree t, const char *p)
{
tree left = TREE_OPERAND (t, 0);
tree right = TREE_OPERAND (t, 1);
m2pp_expression (s, left);
m2pp_needspace (s);
m2pp_print (s, p);
m2pp_needspace (s);
m2pp_expression (s, right);
}
/* m2pp_unary print the unary operator, p, and expression. */
static void
m2pp_unary (pretty *s, tree t, const char *p)
{
tree expr = TREE_OPERAND (t, 0);
m2pp_needspace (s);
m2pp_print (s, p);
m2pp_expression (s, expr);
}
/* m2pp_integer_cst displays the integer constant. */
static void
m2pp_integer_cst (pretty *s, tree t)
{
char val[100];
snprintf (val, 100, HOST_WIDE_INT_PRINT_UNSIGNED, TREE_INT_CST_LOW (t));
m2pp_print (s, val);
}
/* m2pp_real_cst displays the real constant. */
static void
m2pp_real_cst (pretty *s, tree t ATTRIBUTE_UNUSED)
{
m2pp_print (s, "<unknown real>");
}
/* m2pp_string_cst displays the real constant. */
static void
m2pp_string_cst (pretty *s, tree t)
{
const char *p = TREE_STRING_POINTER (t);
int i = 0;
m2pp_print (s, "\"");
while (p[i] != '\0')
{
m2pp_print_char (s, p[i]);
i++;
}
m2pp_print (s, "\"");
}
/* m2pp_statement_sequence iterates over a statement list
displaying each statement in turn. */
static void
m2pp_statement_sequence (pretty *s, tree t)
{
if (t != NULL_TREE)
{
if (TREE_CODE (t) == STATEMENT_LIST)
{
tree_stmt_iterator i;
m2pp_print (s, "(* statement list *)\n");
for (i = tsi_start (t); !tsi_end_p (i); tsi_next (&i))
m2pp_statement (s, *tsi_stmt_ptr (i));
}
else
m2pp_statement (s, t);
}
}
/* m2pp_unknown displays an error message. */
static void
m2pp_unknown (pretty *s, const char *s1, const char *s2)
{
m2pp_begin (s);
m2pp_print (s, s1);
m2pp_needspace (s);
m2pp_print (s, s2);
m2pp_needspace (s);
}
/* m2pp_throw displays a throw statement. */
static void
m2pp_throw (pretty *s, tree t)
{
tree expr = TREE_OPERAND (t, 0);
m2pp_begin (s);
if (expr == NULL_TREE)
m2pp_print (s, "THROW ;\n");
else
{
m2pp_print (s, "THROW (");
m2pp_expression (s, TREE_OPERAND (t, 0));
m2pp_print (s, ")\n");
}
}
/* m2pp_catch_expr attempts to reconstruct a catch expr. */
static void
m2pp_catch_expr (pretty *s, tree t)
{
tree types = CATCH_TYPES (t);
tree body = CATCH_BODY (t);
m2pp_print (s, "(* CATCH expression ");
if (types != NULL_TREE)
{
m2pp_print (s, "(");
m2pp_expression (s, types);
m2pp_print (s, ")");
}
m2pp_print (s, "*)\n");
m2pp_print (s, "(* catch body *)\n");
m2pp_statement_sequence (s, body);
m2pp_print (s, "(* end catch body *)\n");
}
/* m2pp_try_finally_expr attemts to reconstruct a try finally expr. */
static void
m2pp_try_finally_expr (pretty *s, tree t)
{
m2pp_begin (s);
m2pp_print (s, "(* try_finally_expr *)\n");
setindent (s, getindent (s) + 3);
m2pp_statement_sequence (s, TREE_OPERAND (t, 0));
setindent (s, getindent (s) - 3);
m2pp_print (s,
"(* finally (cleanup which is executed after the above) *)\n");
setindent (s, getindent (s) + 3);
m2pp_statement_sequence (s, TREE_OPERAND (t, 1));
setindent (s, getindent (s) - 3);
m2pp_print (s, "(* end try_finally_expr *)\n");
}
#if !defined(GM2)
/* m2pp_if_stmt pretty print a C++ if_stmt. */
static void
m2pp_if_stmt (pretty *s, tree t)
{
m2pp_print (s, "(* only C++ uses if_stmt nodes *)\n");
m2pp_print (s, "IF ");
m2pp_expression (s, TREE_OPERAND (t, 0));
m2pp_print (s, "\n");
m2pp_print (s, "THEN\n");
setindent (s, getindent (s) + 3);
m2pp_statement_sequence (s, TREE_OPERAND (t, 1));
setindent (s, getindent (s) - 3);
m2pp_print (s, "ELSE\n");
setindent (s, getindent (s) + 3);
m2pp_statement_sequence (s, TREE_OPERAND (t, 2));
setindent (s, getindent (s) - 3);
m2pp_print (s, "END\n");
}
#endif
/* m2pp_statement attempts to reconstruct a statement. */
static void
m2pp_statement (pretty *s, tree t)
{
enum tree_code code = TREE_CODE (t);
m2pp_loc (s, t);
switch (code)
{
case COND_EXPR:
m2pp_conditional (s, t);
break;
case LABEL_EXPR:
m2pp_label_expr (s, t);
break;
case LABEL_DECL:
m2pp_label_decl (s, t);
break;
case GOTO_EXPR:
m2pp_goto (s, t);
break;
case INIT_EXPR:
case MODIFY_EXPR:
m2pp_assignment (s, t);
break;
case CALL_EXPR:
m2pp_procedure_call (s, t);
break;
case BLOCK:
m2pp_block_list (s, t);
break;
case BIND_EXPR:
m2pp_bind_expr (s, t);
break;
case RETURN_EXPR:
m2pp_return_expr (s, t);
break;
case DECL_EXPR:
m2pp_decl_expr (s, t);
break;
case TRY_BLOCK:
m2pp_try_block (s, t);
break;
case HANDLER:
m2pp_handler (s, t);
break;
case CLEANUP_POINT_EXPR:
m2pp_cleanup_point_expr (s, t);
break;
case THROW_EXPR:
m2pp_throw (s, t);
break;
case TRY_CATCH_EXPR:
m2pp_try_catch_expr (s, t);
break;
case TRY_FINALLY_EXPR:
m2pp_try_finally_expr (s, t);
break;
case CATCH_EXPR:
m2pp_catch_expr (s, t);
break;
#if defined(CPP)
case IF_STMT:
m2pp_if_stmt (s, t);
break;
#endif
case ERROR_MARK:
m2pp_print (s, "<ERROR CODE>\n");
break;
default:
m2pp_unknown (s, __FUNCTION__, get_tree_code_name (TREE_CODE (t)));
}
}
/* m2pp_try_catch_expr is used after gimplification. */
static void
m2pp_try_catch_expr (pretty *s, tree t)
{
m2pp_print (s, "(* try_catch_expr begins *)\n");
m2pp_statement_sequence (s, TREE_OPERAND (t, 0));
setindent (s, 0);
m2pp_print (s, "EXCEPT\n");
setindent (s, 3);
m2pp_statement_sequence (s, TREE_OPERAND (t, 1));
m2pp_print (s, "(* try_catch_expr ends *)\n");
}
/* m2pp_cleanup_point_expr emits a comment indicating a GCC
cleanup_point_expr is present. */
static void
m2pp_cleanup_point_expr (pretty *s, tree t)
{
m2pp_begin (s);
m2pp_print (s, "(* cleanup point begins *)\n");
m2pp_expression (s, TREE_OPERAND (t, 0));
m2pp_print (s, "(* cleanup point ends *)\n");
}
/* m2pp_decl_expr displays a local declaration. */
static void
m2pp_decl_expr (pretty *s, tree t)
{
m2pp_var (s);
m2pp_print (s, "(* variable in decl_expr *)\n");
m2pp_var_type_decl (s, DECL_EXPR_DECL (t));
}
/* m2pp_procedure_call print a call to a procedure. */
static void
m2pp_procedure_call (pretty *s, tree t)
{
m2pp_begin (s);
m2pp_call_expr (s, t);
m2pp_needspace (s);
m2pp_print (s, ";\n");
}
/* args displays each argument in an iter list by calling expression. */
static void
m2pp_args (pretty *s, tree e)
{
call_expr_arg_iterator iter;
tree arg;
m2pp_print (s, "(");
m2pp_needspace (s);
FOR_EACH_CALL_EXPR_ARG (arg, iter, e)
{
m2pp_expression (s, arg);
if (more_call_expr_args_p (&iter))
{
m2pp_print (s, ",");
m2pp_needspace (s);
}
}
m2pp_print (s, ")");
}
/* m2pp_call_expr print a call to a procedure or function. */
static void
m2pp_call_expr (pretty *s, tree t)
{
tree call = CALL_EXPR_FN (t);
tree args = TREE_OPERAND (t, 1);
tree type = TREE_TYPE (t);
int has_return_type = TRUE;
tree proc;
if (type && (TREE_CODE (type) == VOID_TYPE))
has_return_type = FALSE;
if (TREE_CODE (call) == ADDR_EXPR || TREE_CODE (call) == NON_LVALUE_EXPR)
proc = TREE_OPERAND (call, 0);
else
proc = call;
m2pp_expression (s, proc);
if (args || has_return_type)
m2pp_args (s, t);
}
/* m2pp_return_expr displays the return statement. */
static void
m2pp_return_expr (pretty *s, tree t)
{
tree e = TREE_OPERAND (t, 0);
m2pp_begin (s);
if (e == NULL_TREE)
{
m2pp_print (s, "RETURN");
}
else if (TREE_CODE (e) == MODIFY_EXPR || (TREE_CODE (e) == INIT_EXPR))
{
m2pp_assignment (s, e);
m2pp_print (s, "RETURN");
m2pp_needspace (s);
m2pp_expression (s, TREE_OPERAND (e, 0));
}
else
{
m2pp_print (s, "RETURN");
m2pp_needspace (s);
m2pp_expression (s, e);
}
m2pp_needspace (s);
m2pp_print (s, ";\n");
}
/* m2pp_try_block displays the try block. */
static void
m2pp_try_block (pretty *s, tree t)
{
tree stmts = TRY_STMTS (t);
tree handlers = TRY_HANDLERS (t);
m2pp_begin (s);
m2pp_print (s, "(* TRY *)\n");
m2pp_statement_sequence (s, stmts);
setindent (s, 0);
m2pp_print (s, "EXCEPT\n");
setindent (s, 3);
m2pp_statement_sequence (s, handlers);
m2pp_print (s, "(* END TRY *)\n");
}
/* m2pp_try_block displays the handler block. */
static void
m2pp_handler (pretty *s, tree t)
{
tree parms = HANDLER_PARMS (t);
tree body = HANDLER_BODY (t);
tree type = HANDLER_TYPE (t);
m2pp_print (s, "(* handler *)\n");
if (parms != NULL_TREE)
{
m2pp_print (s, "(* handler parameter has a type (should be NULL_TREE) "
"in Modula-2 *)\n");
m2pp_print (s, "CATCH (");
m2pp_expression (s, parms);
m2pp_print (s, ")\n");
}
if (type != NULL_TREE)
m2pp_print (s, "(* handler type (should be NULL_TREE) in Modula-2 *)\n");
m2pp_statement_sequence (s, body);
}
/* m2pp_assignment prints out the assignment statement. */
static void
m2pp_assignment (pretty *s, tree t)
{
int o;
m2pp_begin (s);
m2pp_designator (s, TREE_OPERAND (t, 0));
m2pp_needspace (s);
m2pp_print (s, ":=");
m2pp_needspace (s);
o = getindent (s);
setindent (s, getcurpos (s) + 1);
m2pp_expression (s, TREE_OPERAND (t, 1));
m2pp_needspace (s);
m2pp_print (s, ";\n");
setindent (s, o);
}
/* m2pp_designator displays the lhs of an assignment. */
static void
m2pp_designator (pretty *s, tree t)
{
m2pp_expression (s, t);
}
/* m2pp_indirect_ref displays the indirect operator. */
static void
m2pp_indirect_ref (pretty *s, tree t)
{
m2pp_print (s, "(");
m2pp_expression (s, TREE_OPERAND (t, 0));
m2pp_print (s, ")^");
}
/* m2pp_conditional builds an IF THEN ELSE END. With more work
this should be moved into statement sequence which could look for
repeat and while loops. */
static void
m2pp_conditional (pretty *s, tree t)
{
int o;
m2pp_begin (s);
m2pp_print (s, "IF");
m2pp_needspace (s);
m2pp_expression (s, TREE_OPERAND (t, 0));
m2pp_print (s, "\nTHEN\n");
o = getindent (s);
setindent (s, o + 3);
m2pp_statement_sequence (s, TREE_OPERAND (t, 1));
setindent (s, o);
if (TREE_OPERAND (t, 2) != NULL_TREE)
{
m2pp_print (s, "ELSE\n");
setindent (s, o + 3);
m2pp_statement_sequence (s, TREE_OPERAND (t, 2));
setindent (s, o);
}
m2pp_print (s, "END ;\n");
}
/* m2pp_label_decl displays a label. Again should be moved into
statement sequence to determine proper loop constructs. */
static void
m2pp_label_decl (pretty *s, tree t)
{
m2pp_begin (s);
m2pp_print (s, "(* label ");
m2pp_identifier (s, t);
m2pp_print (s, ": *)\n");
}
/* m2pp_label_expr skips the LABEL_EXPR to find the LABEL_DECL. */
static void
m2pp_label_expr (pretty *s, tree t)
{
m2pp_begin (s);
m2pp_statement (s, TREE_OPERAND (t, 0));
}
/* m2pp_goto displays a goto statement. Again should be moved into
statement sequence to determine proper loop constructs. */
static void
m2pp_goto (pretty *s, tree t)
{
m2pp_begin (s);
m2pp_print (s, "(* goto ");
m2pp_identifier (s, TREE_OPERAND (t, 0));
m2pp_print (s, " *)\n");
}
/* m2pp_list prints a TREE_CHAINed list. */
static void
m2pp_list (pretty *s, tree t)
{
tree u = t;
m2pp_print (s, "(");
m2pp_needspace (s);
while (t != NULL_TREE)
{
m2pp_expression (s, TREE_VALUE (t));
t = TREE_CHAIN (t);
if (t == u || t == NULL_TREE)
break;
m2pp_print (s, ",");
m2pp_needspace (s);
}
m2pp_needspace (s);
m2pp_print (s, ")");
}
/* m2pp_offset displays the offset operator. */
static void
m2pp_offset (pretty *s, tree t)
{
tree type = TREE_TYPE (t);
tree base = TYPE_OFFSET_BASETYPE (t);
m2pp_print (s, "OFFSET (");
m2pp_type (s, base);
m2pp_print (s, ".");
m2pp_type (s, type);
m2pp_print (s, ")");
}
/* m2pp_addr_expr create an ADR expression. */
static void
m2pp_addr_expr (pretty *s, tree t)
{
m2pp_needspace (s);
m2pp_print (s, "ADR (");
m2pp_expression (s, TREE_OPERAND (t, 0));
m2pp_print (s, ")");
}
/* m2pp_nop generate a CAST expression. */
static void
m2pp_nop (pretty *s, tree t)
{
m2pp_needspace (s);
m2pp_print (s, "CAST (");
m2pp_simple_type (s, TREE_TYPE (t));
m2pp_print (s, ", ");
m2pp_expression (s, TREE_OPERAND (t, 0));
m2pp_print (s, ")");
}
/* m2pp_convert generate a CONVERT expression. */
static void
m2pp_convert (pretty *s, tree t)
{
m2pp_needspace (s);
m2pp_print (s, "CONVERT (");
m2pp_simple_type (s, TREE_TYPE (t));
m2pp_print (s, ", ");
m2pp_expression (s, TREE_OPERAND (t, 0));
m2pp_print (s, ")");
}
/* m2pp_var_decl generate a variable. */
static void
m2pp_var_decl (pretty *s, tree t)
{
m2pp_identifier (s, t);
}
/* m2pp_result_decl generate a result declaration (variable). */
static void
m2pp_result_decl (pretty *s, tree t)
{
m2pp_identifier (s, t);
}
/* m2pp_component_ref generate a record field access. */
static void
m2pp_component_ref (pretty *s, tree t)
{
m2pp_simple_expression (s, TREE_OPERAND (t, 0));
m2pp_print (s, ".");
m2pp_simple_expression (s, TREE_OPERAND (t, 1));
}
}