⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tasking.c

📁 gcc-2.95.3 Linux下最常用的C编译器
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Implement tasking-related actions for CHILL.   Copyright (C) 1992, 93, 1994, 1998, 1999 Free Software Foundation, Inc.This file is part of GNU CC.GNU CC is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2, or (at your option)any later version.GNU CC is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with GNU CC; see the file COPYING.  If not, write tothe Free Software Foundation, 59 Temple Place - Suite 330,Boston, MA 02111-1307, USA.  */#include "config.h"#include "system.h"#include "tree.h"#include "rtl.h"#include "ch-tree.h"#include "flags.h"#include "input.h"#include "obstack.h"#include "assert.h"#include "tasking.h"#include "lex.h"#include "toplev.h"/* from ch-lex.l, from compiler directives */extern tree process_type;extern tree send_signal_prio;extern tree send_buffer_prio;tree tasking_message_type;tree instance_type_node;tree generic_signal_type_node;/* the type a tasking code variable has */tree chill_taskingcode_type_node;/* forward declarations */void validate_process_parameters PROTO((tree));tree make_process_struct         PROTO((tree, tree));/* list of this module's process, buffer, etc. decls. This is a list of TREE_VECs, chain by their TREE_CHAINs. */tree tasking_list = NULL_TREE;/* The parts of a tasking_list element. */#define TASK_INFO_PDECL(NODE) TREE_VEC_ELT(NODE,0)#define TASK_INFO_ENTRY(NODE) TREE_VEC_ELT(NODE,1)#define TASK_INFO_CODE_DECL(NODE) TREE_VEC_ELT(NODE,2)#define TASK_INFO_STUFF_NUM(NODE) TREE_VEC_ELT(NODE,3)#define TASK_INFO_STUFF_TYPE(NODE) TREE_VEC_ELT(NODE,4)/* name template for process argument type */static char * struct_name = "__tmp_%s_arg_type";/* name template for process arguments for debugging type */static char * struct_debug_name = "__tmp_%s_debug_type";#if 0/* name template for process argument variable */static char * data_name = "__tmp_%s_arg_variable";#endif/* name template for process wrapper */static char * wrapper_name = "__tmp_%s_wrapper";extern int ignoring;static tree void_ftype_void;static tree pointer_to_instance;static tree infinite_buffer_event_length_node;treeget_struct_type_name (name)     tree name;{  char *idp = IDENTIFIER_POINTER (name);        /* process name */  char *tmpname = xmalloc (strlen (idp) + strlen (struct_name) + 1);  sprintf (tmpname, struct_name, idp);  return get_identifier (tmpname);}treeget_struct_debug_type_name (name)     tree name;{  char *idp = IDENTIFIER_POINTER (name);        /* process name */  char *tmpname = xmalloc (strlen (idp) + strlen (struct_debug_name) + 1);  sprintf (tmpname, struct_debug_name, idp);  return get_identifier (tmpname);}treeget_tasking_code_name (name)     tree name;{  char *skelname = "__tmp_%s_code";  char *name_str = IDENTIFIER_POINTER (name);  char *tmpname  = (char *)alloca (IDENTIFIER_LENGTH (name) +				   strlen (skelname) + 1);  sprintf (tmpname, skelname, name_str);  return get_identifier (tmpname);}#if 0static treeget_struct_variable_name (name)     tree name;{  char *idp = IDENTIFIER_POINTER (name);        /* process name */  char *tmpname = xmalloc (strlen (idp) + strlen (data_name) + 1);  sprintf (tmpname, data_name, idp);  return get_identifier (tmpname);}#endifstatic treeget_process_wrapper_name (name)    tree name;{  char *idp = IDENTIFIER_POINTER (name);  char *tmpname = xmalloc (strlen (idp) + strlen (wrapper_name) + 1);      sprintf (tmpname, wrapper_name, idp);  return get_identifier (tmpname);}/* * If this is a quasi declaration - parsed within a SPEC MODULE, * QUASI_FLAG is TRUE, to indicate that the variable should not * be initialized.  The other module will do that. */treegenerate_tasking_code_variable (name, tasking_code_ptr, quasi_flag)     tree name, *tasking_code_ptr;     int  quasi_flag;{  tree decl;  tree tasking_code_name = get_tasking_code_name (name);    if (pass == 2 && ! quasi_flag && *tasking_code_ptr != NULL_TREE)    {      /* check for value should be assigned is out of range */      if (TREE_INT_CST_LOW (*tasking_code_ptr) >	  TREE_INT_CST_LOW (TYPE_MAX_VALUE (chill_taskingcode_type_node)))	  error ("Tasking code %ld out of range for `%s'.",		 (long) TREE_INT_CST_LOW (*tasking_code_ptr),		 IDENTIFIER_POINTER (name));    }  decl = do_decl (tasking_code_name, 		  chill_taskingcode_type_node, 1, 1,		  quasi_flag ? NULL_TREE : *tasking_code_ptr, 		  0);  /* prevent granting of this type */  DECL_SOURCE_LINE (decl) = 0;  if (pass == 2 && ! quasi_flag && *tasking_code_ptr != NULL_TREE)    *tasking_code_ptr = fold (build (PLUS_EXPR, chill_taskingcode_type_node,				     integer_one_node,				     *tasking_code_ptr));  return decl;}/* * If this is a quasi declaration - parsed within a SPEC MODULE, * QUASI_FLAG is TRUE, to indicate that the variable should not * be initialized.  The other module will do that.  This is just  * for BUFFERs and EVENTs. */treedecl_tasking_code_variable (name, tasking_code_ptr, quasi_flag)     tree name, *tasking_code_ptr;     int  quasi_flag;{  extern struct obstack permanent_obstack;  tree tasking_code_name = get_tasking_code_name (name);  tree decl;  /* guarantee that RTL for the code_variable resides in     the permanent obstack.  The BUFFER or EVENT may be     declared in a PROC, not at global scope... */  push_obstacks (&permanent_obstack, &permanent_obstack);  push_obstacks_nochange ();  if (pass == 2 && ! quasi_flag && *tasking_code_ptr != NULL_TREE)    {      /* check for value should be assigned is out of range */      if (TREE_INT_CST_LOW (*tasking_code_ptr) >	  TREE_INT_CST_LOW (TYPE_MAX_VALUE (chill_taskingcode_type_node)))	  error ("Tasking code %ld out of range for `%s'.",		 (long) TREE_INT_CST_LOW (*tasking_code_ptr),		 IDENTIFIER_POINTER (name));    }  decl = decl_temp1 (tasking_code_name, 		     chill_taskingcode_type_node, 1,		     quasi_flag ? NULL_TREE : *tasking_code_ptr, 		     0, 0);  /* prevent granting of this type */  DECL_SOURCE_LINE (decl) = 0;  /* Return to the ambient context.  */  pop_obstacks ();  if (pass == 2 && ! quasi_flag && *tasking_code_ptr != NULL_TREE)    *tasking_code_ptr = fold (build (PLUS_EXPR, chill_taskingcode_type_node,				     integer_one_node,				     *tasking_code_ptr));  return decl;}/* * Transmute a process parameter list into an argument structure  * TYPE_DECL for the start_process call to reference.  Create a  * proc_type variable for later.  Returns the new struct type. */treemake_process_struct (name, processparlist)     tree name, processparlist;{  tree temp;  tree a_parm;  tree field_decls = NULL_TREE;  if (name == NULL_TREE || TREE_CODE (name) == ERROR_MARK)    return error_mark_node;  if (processparlist == NULL_TREE)    return tree_cons (NULL_TREE, NULL_TREE, void_list_node);  if (TREE_CODE (processparlist) == ERROR_MARK)    return error_mark_node;  /* build list of field decls for build_chill_struct_type */  for (a_parm = processparlist; a_parm != NULL_TREE;        a_parm = TREE_CHAIN (a_parm))    {      tree parnamelist = TREE_VALUE (a_parm);      tree purpose     = TREE_PURPOSE (a_parm);      tree mode        = TREE_VALUE (purpose);      tree parm_attr   = TREE_PURPOSE (purpose);      tree field;      /* build a FIELD_DECL node */      if (parm_attr != NULL_TREE)	{	  if (parm_attr == ridpointers[(int)RID_LOC])	    mode = build_chill_reference_type (mode);	  else if (parm_attr == ridpointers[(int)RID_IN])	    ;	  else if (pass == 1)	    {	      for (field = parnamelist; field != NULL_TREE;		   field = TREE_CHAIN (field))	        error ("invalid attribute for argument `%s' (only IN or LOC allowed).",		       IDENTIFIER_POINTER (TREE_VALUE (field)));	    }	}      field = grok_chill_fixedfields (parnamelist, mode, NULL_TREE);      /* chain the fields in reverse */      if (field_decls == NULL_TREE)	field_decls = field;      else	chainon (field_decls, field);    }  temp = build_chill_struct_type (field_decls);  return temp;}/* Build a function for a PROCESS  and define some   types for the process arguments.   After the PROCESS a wrapper function will be    generated which gets the PROCESS arguments via a pointer   to a structure having the same layout as the arguments.   This wrapper function then will call the PROCESS.   The advantage in doing it this way is, that PROCESS   arguments may be displayed by gdb without any change   to gdb.*/treebuild_process_header (plabel, paramlist)     tree plabel, paramlist;{  tree struct_ptr_type = NULL_TREE;  tree new_param_list = NULL_TREE;  tree struct_decl = NULL_TREE;  tree process_struct = NULL_TREE;  tree struct_debug_type = NULL_TREE;  tree code_decl;      if (! global_bindings_p ())    {      error ("PROCESS may only be declared at module level");      return error_mark_node;    }  if (paramlist)    {      /* must make the structure OUTSIDE the parameter scope */      if (pass == 1)	{	  process_struct = make_process_struct (plabel, paramlist);	  struct_ptr_type = build_chill_pointer_type (process_struct);	}      else	{	  process_struct = NULL_TREE;	  struct_ptr_type = NULL_TREE;	}		                struct_decl = push_modedef (get_struct_type_name (plabel),				  struct_ptr_type, -1);      DECL_SOURCE_LINE (struct_decl) = 0;      struct_debug_type = push_modedef (get_struct_debug_type_name (plabel),					process_struct, -1);      DECL_SOURCE_LINE (struct_debug_type) = 0;      if (pass == 2)        {          /* build a list of PARM_DECL's */          tree  wrk = paramlist;          tree  tmp, list = NULL_TREE;                    while (wrk != NULL_TREE)            {              tree wrk1 = TREE_VALUE (wrk);                              while (wrk1 != NULL_TREE)                {                  tmp = make_node (PARM_DECL);                  DECL_ASSEMBLER_NAME (tmp) = DECL_NAME (tmp) = TREE_VALUE (wrk1);                  if (list == NULL_TREE)                    new_param_list = list = tmp;                  else                    {                      TREE_CHAIN (list) = tmp;                      list = tmp;                    }                  wrk1 = TREE_CHAIN (wrk1);                }              wrk = TREE_CHAIN (wrk);            }        }      else        {          /* build a list of modes */          tree  wrk = paramlist;                    while (wrk != NULL_TREE)            {              tree wrk1 = TREE_VALUE (wrk);                            while (wrk1 != NULL_TREE)                {                  new_param_list = tree_cons (TREE_PURPOSE (TREE_PURPOSE (wrk)),                                              TREE_VALUE (TREE_PURPOSE (wrk)),                                              new_param_list);                  wrk1 = TREE_CHAIN (wrk1);                }              wrk = TREE_CHAIN (wrk);            }          new_param_list = nreverse (new_param_list);        }    }  /* declare the code variable outside the process */  code_decl = generate_tasking_code_variable (plabel, 					      &process_type, 0);  /* start the parameter scope */  push_chill_function_context ();  if (! start_chill_function (plabel, void_type_node, 			      new_param_list, NULL_TREE, NULL_TREE))    return error_mark_node;  current_module->procedure_seen = 1;   CH_DECL_PROCESS (current_function_decl) = 1;  /* remember the code variable in the function decl */  DECL_TASKING_CODE_DECL (current_function_decl) =     (struct lang_decl *)code_decl;  if (paramlist == NULL_TREE)      /* do it here, cause we don't have a wrapper */    add_taskstuff_to_list (code_decl, "_TT_Process", process_type,			   current_function_decl, NULL_TREE);  return perm_tree_cons (code_decl, struct_decl, NULL_TREE);}/* Generate a function which gets a pointer   to an argument block and call the corresponding   PROCESS*/voidbuild_process_wrapper (plabel, processdata)    tree        plabel;    tree        processdata;{  tree  args = NULL_TREE;  tree  wrapper = NULL_TREE;  tree  parammode = TREE_VALUE (processdata);  tree  code_decl = TREE_PURPOSE (processdata);  tree  func = lookup_name (plabel);      /* check the mode. If it is an ERROR_MARK there was an error     in build_process_header, if it is a NULL_TREE the process     don't have parameters, so we must not generate a wrapper */  if (parammode == NULL_TREE ||      TREE_CODE (parammode) == ERROR_MARK)    return;      /* get the function name */  wrapper = get_process_wrapper_name (plabel);      /* build the argument */  if (pass == 2)    {      /* build a PARM_DECL */      args = make_node (PARM_DECL);      DECL_ASSEMBLER_NAME (args) = DECL_NAME (args) = get_identifier ("x");    }  else    {      /* build a tree list with the mode */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -