| /* 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)); |
| } |
| |
| } |