diff options
Diffstat (limited to 'contrib/gcc/cp/edsel.c')
-rw-r--r-- | contrib/gcc/cp/edsel.c | 928 |
1 files changed, 928 insertions, 0 deletions
diff --git a/contrib/gcc/cp/edsel.c b/contrib/gcc/cp/edsel.c new file mode 100644 index 000000000000..35099d523f76 --- /dev/null +++ b/contrib/gcc/cp/edsel.c @@ -0,0 +1,928 @@ +/* Interface to LUCID Cadillac system for GNU compiler. + Copyright (C) 1988, 1992, 1993 Free Software Foundation, Inc. + +This file is part of GNU CC. + +GNU CC is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU CC is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with GNU CC; see the file COPYING. If not, write to +the Free Software Foundation, 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +#include "config.h" + +#include "tree.h" +#include "flags.h" +#include <stdio.h> +#include "cp-tree.h" +#include "obstack.h" + +#ifdef CADILLAC +#include <compilerreq.h> +#include <compilerconn.h> +#include <sys/time.h> +#include <sys/types.h> +#include <errno.h> +#include <sys/file.h> + +#define obstack_chunk_alloc xmalloc +#define obstack_chunk_free free + +void init_cadillac (); + +extern char *input_filename; +extern int lineno; + +/* Put random information we might want to get back from + Cadillac here. */ +typedef struct +{ + /* The connection to the Cadillac kernel. */ + Connection *conn; + + /* Input and output file descriptors for Cadillac. */ + short fd_input, fd_output; + + /* #include nesting of current file. */ + short depth; + + /* State variables for the connection. */ + char messages; + char conversion; + char emission; + char process_until; + + /* #if level of current file. */ + int iflevel; + + /* Line number that starts current source file. */ + int lineno; + + /* Name of current file. */ + char *filename; + + /* Where to stop processing (if process_until is set). */ + char *end_filename; + int end_position; + +} cadillac_struct; +static cadillac_struct cadillacObj; + +/* Nonzero if in the process of exiting. */ +static int exiting; + +void cadillac_note_source (); +static void CWriteLanguageDecl (); +static void CWriteLanguageType (); +static void CWriteTopLevel (); +static void cadillac_note_filepos (); +static void cadillac_process_request (), cadillac_process_requests (); +static void cadillac_switch_source (); +static void exit_cadillac (); + +/* Blocking test. */ +static int +readable_p (fd) + int fd; +{ + fd_set f; + + FD_ZERO (&f); + FD_SET (fd, &f); + + return select (32, &f, NULL, NULL, 0) == 1; +} + +static CObjectType *tree_to_cadillac_map; +struct obstack cadillac_obstack; + + +#include "stack.h" + +struct context_level +{ + struct stack_level base; + + tree context; +}; + +/* Stack for maintaining contexts (in case functions or types are nested). + When defining a struct type, the `context' field is the RECORD_TYPE. + When defining a function, the `context' field is the FUNCTION_DECL. */ + +static struct context_level *context_stack; + +static struct context_level * +push_context_level (stack, obstack) + struct stack_level *stack; + struct obstack *obstack; +{ + struct context_level tem; + + tem.base.prev = stack; + return (struct context_level *)push_stack_level (obstack, &tem, sizeof (tem)); +} + +/* Discard a level of search allocation. */ + +static struct context_level * +pop_context_level (stack) + struct context_level *stack; +{ + stack = (struct context_level *)pop_stack_level (stack); + return stack; +} + +void +init_cadillac () +{ + extern FILE *finput; + extern int errno; + CCompilerMessage* req; + cadillac_struct *cp = &cadillacObj; + int i; + + if (! flag_cadillac) + return; + + tree_to_cadillac_map = (CObjectType*) xmalloc (sizeof (CObjectType) * LAST_CPLUS_TREE_CODE); + for (i = 0; i < LAST_CPLUS_TREE_CODE; i++) + tree_to_cadillac_map[i] = MiscOType; + tree_to_cadillac_map[RECORD_TYPE] = StructOType; + tree_to_cadillac_map[UNION_TYPE] = UnionOType; + tree_to_cadillac_map[ENUMERAL_TYPE] = EnumTypeOType; + tree_to_cadillac_map[TYPE_DECL] = TypedefOType; + tree_to_cadillac_map[VAR_DECL] = VariableOType; + tree_to_cadillac_map[CONST_DECL] = EnumConstantOType; + tree_to_cadillac_map[FUNCTION_DECL] = FunctionOType; + tree_to_cadillac_map[FIELD_DECL] = FieldOType; + +#ifdef sun + on_exit (&exit_cadillac, 0); +#endif + + gcc_obstack_init (&cadillac_obstack); + + /* Yow! This is the way Cadillac was designed to deal with + Oregon C++ compiler! */ + cp->fd_input = flag_cadillac; + cp->fd_output = flag_cadillac; + + /* Start in "turned-on" state. */ + cp->messages = 1; + cp->conversion = 1; + cp->emission = 1; + + /* Establish a connection with Cadillac here. */ + cp->conn = NewConnection (cp, cp->fd_input, cp->fd_output); + + CWriteHeader (cp->conn, WaitingMType, 0); + CWriteRequestBuffer (cp->conn); + + if (!readable_p (cp->fd_input)) + ; + + req = CReadCompilerMessage (cp->conn); + + if (!req) + switch (errno) + { + case EWOULDBLOCK: + sleep (5); + return; + + case 0: + fatal ("init_cadillac: EOF on connection to kernel, exiting\n"); + break; + + default: + perror ("Editor to kernel connection"); + exit (0); + } +} + +static void +cadillac_process_requests (conn) + Connection *conn; +{ + CCompilerMessage *req; + while (req = (CCompilerMessage*) CPeekNextRequest (conn)) + { + req = CReadCompilerMessage (conn); + cadillac_process_request (&cadillacObj, req); + } +} + +static void +cadillac_process_request (cp, req) + cadillac_struct *cp; + CCompilerMessage *req; +{ + if (! req) + return; + + switch (req->reqType) + { + case ProcessUntilMType: + if (cp->process_until) + my_friendly_abort (23); + cp->process_until = 1; + /* This is not really right. */ + cp->end_position = ((CCompilerCommand*)req)->processuntil.position; +#if 0 + cp->end_filename = req->processuntil.filename; +#endif + break; + + case CommandMType: + switch (req->header.data) + { + case MessagesOnCType: + cp->messages = 1; + break; + case MessagesOffCType: + cp->messages = 0; + break; + case ConversionOnCType: + cp->conversion = 1; + break; + case ConversionOffCType: + cp->conversion = 0; + break; + case EmissionOnCType: + cp->emission = 1; + break; + case EmissionOffCType: + cp->emission = 0; + break; + + case FinishAnalysisCType: + return; + + case PuntAnalysisCType: + case ContinueAnalysisCType: + case GotoFileposCType: + case OpenSucceededCType: + case OpenFailedCType: + fprintf (stderr, "request type %d not implemented\n", req->reqType); + return; + + case DieCType: + if (! exiting) + my_friendly_abort (24); + return; + + } + break; + + default: + fatal ("unknown request type %d", req->reqType); + } +} + +void +cadillac_start () +{ + Connection *conn = cadillacObj.conn; + CCompilerMessage *req; + + /* Let Cadillac know that we start in C++ language scope. */ + CWriteHeader (conn, ForeignLinkageMType, LinkCPlus); + CWriteLength (conn); + CWriteRequestBuffer (conn); + + cadillac_process_requests (conn); +} + +static void +cadillac_printf (msg, name) +{ + if (cadillacObj.messages) + printf ("[%s,%4d] %s `%s'\n", input_filename, lineno, msg, name); +} + +void +cadillac_start_decl (decl) + tree decl; +{ + Connection *conn = cadillacObj.conn; + CObjectType object_type = tree_to_cadillac_map [TREE_CODE (decl)]; + + if (context_stack) + switch (TREE_CODE (context_stack->context)) + { + case FUNCTION_DECL: + /* Currently, cadillac only implements top-level forms. */ + return; + case RECORD_TYPE: + case UNION_TYPE: + cadillac_printf ("start class-level decl", IDENTIFIER_POINTER (DECL_NAME (decl))); + break; + default: + my_friendly_abort (25); + } + else + { + cadillac_printf ("start top-level decl", IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))); + CWriteTopLevel (conn, StartMType); + } + + CWriteLanguageDecl (conn, decl, tree_to_cadillac_map[TREE_CODE (decl)]); + CWriteRequestBuffer (conn); + cadillac_process_requests (conn); +} + +void +cadillac_finish_decl (decl) + tree decl; +{ + Connection *conn = cadillacObj.conn; + + if (context_stack) + switch (TREE_CODE (context_stack->context)) + { + case FUNCTION_DECL: + return; + case RECORD_TYPE: + case UNION_TYPE: + cadillac_printf ("end class-level decl", IDENTIFIER_POINTER (DECL_NAME (decl))); + CWriteHeader (conn, EndDefMType, 0); + CWriteLength (conn); + break; + default: + my_friendly_abort (26); + } + else + { + cadillac_printf ("end top-level decl", IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))); + CWriteHeader (conn, EndDefMType, 0); + CWriteLength (conn); + CWriteTopLevel (conn, StopMType); + } + + CWriteRequestBuffer (conn); + cadillac_process_requests (conn); +} + +void +cadillac_start_function (fndecl) + tree fndecl; +{ + Connection *conn = cadillacObj.conn; + + if (context_stack) + /* nested functions not yet handled. */ + my_friendly_abort (27); + + cadillac_printf ("start top-level function", lang_printable_name (fndecl)); + context_stack = push_context_level (context_stack, &cadillac_obstack); + context_stack->context = fndecl; + + CWriteTopLevel (conn, StartMType); + my_friendly_assert (TREE_CODE (fndecl) == FUNCTION_DECL, 202); + CWriteLanguageDecl (conn, fndecl, + (TREE_CODE (TREE_TYPE (fndecl)) == METHOD_TYPE + ? MemberFnOType : FunctionOType)); + CWriteRequestBuffer (conn); + cadillac_process_requests (conn); +} + +void +cadillac_finish_function (fndecl) + tree fndecl; +{ + Connection *conn = cadillacObj.conn; + + cadillac_printf ("end top-level function", lang_printable_name (fndecl)); + context_stack = pop_context_level (context_stack); + + if (context_stack) + /* nested functions not yet implemented. */ + my_friendly_abort (28); + + CWriteHeader (conn, EndDefMType, 0); + CWriteLength (conn); + CWriteTopLevel (conn, StopMType); + CWriteRequestBuffer (conn); + cadillac_process_requests (conn); +} + +void +cadillac_finish_anon_union (decl) + tree decl; +{ + Connection *conn = cadillacObj.conn; + + if (! global_bindings_p ()) + return; + cadillac_printf ("finish top-level anon union", ""); + CWriteHeader (conn, EndDefMType, 0); + CWriteLength (conn); + CWriteTopLevel (conn, StopMType); + CWriteRequestBuffer (conn); + cadillac_process_requests (conn); +} + +void +cadillac_start_enum (type) + tree type; +{ + Connection *conn = cadillacObj.conn; + + tree name = TYPE_NAME (type); + + if (TREE_CODE (name) == TYPE_DECL) + name = DECL_NAME (name); + + if (context_stack) + switch (TREE_CODE (context_stack->context)) + { + case FUNCTION_DECL: + return; + case RECORD_TYPE: + case UNION_TYPE: + break; + default: + my_friendly_abort (29); + } + else + { + cadillac_printf ("start top-level enum", IDENTIFIER_POINTER (name)); + CWriteTopLevel (conn, StartMType); + } + + CWriteLanguageType (conn, type, tree_to_cadillac_map[ENUMERAL_TYPE]); +} + +void +cadillac_finish_enum (type) + tree type; +{ + Connection *conn = cadillacObj.conn; + tree name = TYPE_NAME (type); + + if (TREE_CODE (name) == TYPE_DECL) + name = DECL_NAME (name); + + if (context_stack) + switch (TREE_CODE (context_stack->context)) + { + case FUNCTION_DECL: + return; + case RECORD_TYPE: + case UNION_TYPE: + CWriteHeader (conn, EndDefMType, 0); + CWriteLength (conn); + break; + default: + my_friendly_abort (30); + } + else + { + CWriteHeader (conn, EndDefMType, 0); + CWriteLength (conn); + cadillac_printf ("finish top-level enum", IDENTIFIER_POINTER (name)); + CWriteTopLevel (conn, StopMType); + } + + CWriteRequestBuffer (conn); + cadillac_process_requests (conn); +} + +void +cadillac_start_struct (type) + tree type; +{ + Connection *conn = cadillacObj.conn; + tree name = TYPE_NAME (type); + + if (TREE_CODE (name) == TYPE_DECL) + name = DECL_NAME (name); + + if (context_stack) + switch (TREE_CODE (context_stack->context)) + { + case FUNCTION_DECL: + return; + case RECORD_TYPE: + case UNION_TYPE: + return; + default: + my_friendly_abort (31); + } + else + { + cadillac_printf ("start struct", IDENTIFIER_POINTER (name)); + CWriteTopLevel (conn, StartMType); + } + + context_stack = push_context_level (context_stack, &cadillac_obstack); + context_stack->context = type; + + CWriteLanguageType (conn, type, + TYPE_LANG_SPECIFIC (type) && CLASSTYPE_DECLARED_CLASS (type) ? ClassOType : tree_to_cadillac_map[TREE_CODE (type)]); +} + +void +cadillac_finish_struct (type) + tree type; +{ + Connection *conn = cadillacObj.conn; + tree name = TYPE_NAME (type); + + if (TREE_CODE (name) == TYPE_DECL) + name = DECL_NAME (name); + + context_stack = pop_context_level (context_stack); + if (context_stack) + return; + + cadillac_printf ("finish struct", IDENTIFIER_POINTER (name)); + CWriteHeader (conn, EndDefMType, 0); + CWriteLength (conn); + CWriteTopLevel (conn, StopMType); + CWriteRequestBuffer (conn); + cadillac_process_requests (conn); +} + +void +cadillac_finish_exception (type) + tree type; +{ + Connection *conn = cadillacObj.conn; + + fatal ("cadillac_finish_exception"); + CWriteHeader (conn, EndDefMType, 0); + CWriteLength (conn); + CWriteTopLevel (conn, StopMType); + CWriteRequestBuffer (conn); + cadillac_process_requests (conn); +} + +void +cadillac_push_class (type) + tree type; +{ +} + +void +cadillac_pop_class () +{ +} + +void +cadillac_push_lang (name) + tree name; +{ + Connection *conn = cadillacObj.conn; + CLinkLanguageType m; + + if (name == lang_name_cplusplus) + m = LinkCPlus; + else if (name == lang_name_c) + m = LinkC; + else + my_friendly_abort (32); + CWriteHeader (conn, ForeignLinkageMType, m); + CWriteRequestBuffer (conn); + cadillac_process_requests (conn); +} + +void +cadillac_pop_lang () +{ + Connection *conn = cadillacObj.conn; + + CWriteHeader (conn, ForeignLinkageMType, LinkPop); + CWriteRequestBuffer (conn); + cadillac_process_requests (conn); +} + +void +cadillac_finish_stmt () +{ +} + +void +cadillac_note_source () +{ + cadillacObj.lineno = lineno; + cadillacObj.filename = input_filename; +} + +static void +CWriteTopLevel (conn, m) + Connection *conn; + CMessageSubType m; +{ + static context_id = 0; + CWriteHeader (conn, TopLevelFormMType, m); + cadillac_note_filepos (); + + /* Eventually, this will point somewhere into the digest file. */ + context_id += 1; + CWriteSomething (conn, &context_id, sizeof (BITS32)); + + CWriteSomething (conn, &cadillacObj.iflevel, sizeof (BITS32)); + CWriteLength (conn); +} + +static void +cadillac_note_filepos () +{ + extern FILE *finput; + int pos = ftell (finput); + CWriteSomething (cadillacObj.conn, &pos, sizeof (BITS32)); +} + +void +cadillac_switch_source (startflag) + int startflag; +{ + Connection *conn = cadillacObj.conn; + /* Send out the name of the source file being compiled. */ + + CWriteHeader (conn, SourceFileMType, startflag ? StartMType : StopMType); + CWriteSomething (conn, &cadillacObj.depth, sizeof (BITS16)); + CWriteVstring0 (conn, input_filename); + CWriteLength (conn); + CWriteRequestBuffer (conn); + cadillac_process_requests (conn); +} + +void +cadillac_push_source () +{ + cadillacObj.depth += 1; + cadillac_switch_source (1); +} + +void +cadillac_pop_source () +{ + cadillacObj.depth -= 1; + cadillac_switch_source (0); +} + +struct cadillac_mdep +{ + short object_type; + char linkage; + char access; + short length; +}; + +static void +CWriteLanguageElem (conn, p, name) + Connection *conn; + struct cadillac_mdep *p; + char *name; +{ + CWriteSomething (conn, &p->object_type, sizeof (BITS16)); + CWriteSomething (conn, &p->linkage, sizeof (BITS8)); + CWriteSomething (conn, &p->access, sizeof (BITS8)); + CWriteSomething (conn, &p->length, sizeof (BITS16)); + CWriteVstring0 (conn, name); + +#if 0 + /* Don't write date_type. */ + CWriteVstring0 (conn, ""); +#endif + CWriteLength (conn); +} + +static void +CWriteLanguageDecl (conn, decl, object_type) + Connection *conn; + tree decl; + CObjectType object_type; +{ + struct cadillac_mdep foo; + tree name; + + CWriteHeader (conn, LanguageElementMType, StartDefineMType); + foo.object_type = object_type; + if (decl_type_context (decl)) + { + foo.linkage = ParentLinkage; + if (TREE_PRIVATE (decl)) + foo.access = PrivateAccess; + else if (TREE_PROTECTED (decl)) + foo.access = ProtectedAccess; + else + foo.access = PublicAccess; + } + else + { + if (TREE_PUBLIC (decl)) + foo.linkage = GlobalLinkage; + else + foo.linkage = FileLinkage; + foo.access = PublicAccess; + } + name = DECL_NAME (decl); + foo.length = IDENTIFIER_LENGTH (name); + + CWriteLanguageElem (conn, &foo, IDENTIFIER_POINTER (name)); + CWriteRequestBuffer (conn); + cadillac_process_requests (conn); +} + +static void +CWriteLanguageType (conn, type, object_type) + Connection *conn; + tree type; + CObjectType object_type; +{ + struct cadillac_mdep foo; + tree name = TYPE_NAME (type); + + CWriteHeader (conn, LanguageElementMType, StartDefineMType); + foo.object_type = object_type; + if (current_class_type) + { + foo.linkage = ParentLinkage; + if (TREE_PRIVATE (type)) + foo.access = PrivateAccess; + else if (TREE_PROTECTED (type)) + foo.access = ProtectedAccess; + else + foo.access = PublicAccess; + } + else + { + foo.linkage = NoLinkage; + foo.access = PublicAccess; + } + if (TREE_CODE (name) == TYPE_DECL) + name = DECL_NAME (name); + + foo.length = IDENTIFIER_LENGTH (name); + + CWriteLanguageElem (conn, &foo, IDENTIFIER_POINTER (name)); + CWriteRequestBuffer (conn); + cadillac_process_requests (conn); +} + +static void +CWriteUseObject (conn, type, object_type, use) + Connection *conn; + tree type; + CObjectType object_type; + CMessageSubType use; +{ + struct cadillac_mdep foo; + tree name = NULL_TREE; + + CWriteHeader (conn, LanguageElementMType, use); + foo.object_type = object_type; + if (current_class_type) + { + foo.linkage = ParentLinkage; + if (TREE_PRIVATE (type)) + foo.access = PrivateAccess; + else if (TREE_PROTECTED (type)) + foo.access = ProtectedAccess; + else + foo.access = PublicAccess; + } + else + { + foo.linkage = NoLinkage; + foo.access = PublicAccess; + } + switch (TREE_CODE (type)) + { + case VAR_DECL: + case FIELD_DECL: + case TYPE_DECL: + case CONST_DECL: + case FUNCTION_DECL: + name = DECL_NAME (type); + break; + + default: + my_friendly_abort (33); + } + + foo.length = IDENTIFIER_LENGTH (name); + + CWriteLanguageElem (conn, &foo, IDENTIFIER_POINTER (name)); + CWriteRequestBuffer (conn); + cadillac_process_requests (conn); +} + +/* Here's how we exit under cadillac. */ + +static void +exit_cadillac () +{ + extern int errorcount; + + Connection *conn = cadillacObj.conn; + + if (flag_cadillac) + { + CCompilerMessage *req; + + CWriteHeader (conn, FinishedMType, + errorcount ? 0 : CsObjectWritten | CsComplete); + /* Bye, bye! */ + CWriteRequestBuffer (conn); + + /* Block on read. */ + while (! readable_p (cadillacObj.fd_input)) + { + if (exiting) + my_friendly_abort (34); + exiting = 1; + } + exiting = 1; + + req = CReadCompilerMessage (conn); + cadillac_process_request (&cadillacObj, req); + } +} + +#else +/* Stubs. */ +void init_cadillac () {} +void cadillac_start () {} +void cadillac_start_decl (decl) + tree decl; +{} +void +cadillac_finish_decl (decl) + tree decl; +{} +void +cadillac_start_function (fndecl) + tree fndecl; +{} +void +cadillac_finish_function (fndecl) + tree fndecl; +{} +void +cadillac_finish_anon_union (decl) + tree decl; +{} +void +cadillac_start_enum (type) + tree type; +{} +void +cadillac_finish_enum (type) + tree type; +{} +void +cadillac_start_struct (type) + tree type; +{} +void +cadillac_finish_struct (type) + tree type; +{} +void +cadillac_finish_exception (type) + tree type; +{} +void +cadillac_push_class (type) + tree type; +{} +void +cadillac_pop_class () +{} +void +cadillac_push_lang (name) + tree name; +{} +void +cadillac_pop_lang () +{} +void +cadillac_note_source () +{} +void +cadillac_finish_stmt () +{} +void +cadillac_switch_source () +{} +void +cadillac_push_source () +{} +void +cadillac_pop_source () +{} +#endif |