Merge gcc-2.95.3 changes onto mainline. Update FreeBSD changes to converge
with changes made in the FSF tree.
This commit is contained in:
parent
a093aec887
commit
6830f79554
@ -75,6 +75,7 @@ extern void output_file_directive ();
|
||||
.ident string is patterned after the ones produced by native svr4
|
||||
C compilers. */
|
||||
|
||||
#undef IDENT_ASM_OP
|
||||
#define IDENT_ASM_OP ".ident"
|
||||
|
||||
#ifdef IDENTIFY_WITH_IDENT
|
||||
@ -103,6 +104,7 @@ do { \
|
||||
/* This is how to allocate empty space in some section. The .zero
|
||||
pseudo-op is used for this on most svr4 assemblers. */
|
||||
|
||||
#undef SKIP_ASM_OP
|
||||
#define SKIP_ASM_OP ".zero"
|
||||
|
||||
#undef ASM_OUTPUT_SKIP
|
||||
@ -117,6 +119,7 @@ do { \
|
||||
make sure that the location counter for the .rodata section gets pro-
|
||||
perly re-aligned prior to the actual beginning of the jump table. */
|
||||
|
||||
#undef ALIGN_ASM_OP
|
||||
#define ALIGN_ASM_OP ".align"
|
||||
|
||||
#ifndef ASM_OUTPUT_BEFORE_CASE_LABEL
|
||||
@ -144,6 +147,7 @@ do { \
|
||||
the linker seems to want the alignment of data objects
|
||||
to depend on their types. We do exactly that here. */
|
||||
|
||||
#undef COMMON_ASM_OP
|
||||
#define COMMON_ASM_OP ".comm"
|
||||
|
||||
#undef ASM_OUTPUT_ALIGNED_COMMON
|
||||
@ -217,6 +221,7 @@ do { \
|
||||
#undef USE_CONST_SECTION
|
||||
#define USE_CONST_SECTION 1
|
||||
|
||||
#undef CONST_SECTION_ASM_OP
|
||||
#define CONST_SECTION_ASM_OP ".section\t.rodata"
|
||||
|
||||
/* Define the pseudo-ops used to switch to the .ctors and .dtors sections.
|
||||
@ -234,7 +239,9 @@ do { \
|
||||
errors unless the .ctors and .dtors sections are marked as writable
|
||||
via the SHF_WRITE attribute.) */
|
||||
|
||||
#undef CTORS_SECTION_ASM_OP
|
||||
#define CTORS_SECTION_ASM_OP ".section\t.ctors,\"aw\""
|
||||
#undef DTORS_SECTION_ASM_OP
|
||||
#define DTORS_SECTION_ASM_OP ".section\t.dtors,\"aw\""
|
||||
|
||||
/* Handle the small data sections. */
|
||||
@ -248,7 +255,9 @@ do { \
|
||||
The definitions say how to change sections to the .init and .fini
|
||||
sections. This is the same for all known svr4 assemblers. */
|
||||
|
||||
#undef INIT_SECTION_ASM_OP
|
||||
#define INIT_SECTION_ASM_OP ".section\t.init"
|
||||
#undef FINI_SECTION_ASM_OP
|
||||
#define FINI_SECTION_ASM_OP ".section\t.fini"
|
||||
|
||||
/* A default list of other sections which we might be "in" at any given
|
||||
@ -383,7 +392,9 @@ void FN () \
|
||||
different pseudo-op names for these, they may be overridden in the
|
||||
file which includes this one. */
|
||||
|
||||
#undef TYPE_ASM_OP
|
||||
#define TYPE_ASM_OP ".type"
|
||||
#undef SIZE_ASM_OP
|
||||
#define SIZE_ASM_OP ".size"
|
||||
|
||||
/* This is how we tell the assembler that a symbol is weak. */
|
||||
@ -504,6 +515,7 @@ do { \
|
||||
should define this to zero. */
|
||||
|
||||
#define STRING_LIMIT ((unsigned) 256)
|
||||
#undef STRING_ASM_OP
|
||||
#define STRING_ASM_OP ".string"
|
||||
|
||||
/* GAS is the only Alpha/ELF assembler. */
|
||||
|
@ -1,26 +0,0 @@
|
||||
/* Definitions of target machine for GNU compiler, for DEC Alpha, using
|
||||
encapsulated stabs and OSF V1.2.
|
||||
Copyright (C) 1994 Free Software Foundation, Inc.
|
||||
Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
|
||||
|
||||
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 "alpha/osf12.h"
|
||||
|
||||
#undef PREFERRED_DEBUGGING_TYPE
|
||||
#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
|
@ -1,26 +0,0 @@
|
||||
/* Definitions of target machine for GNU compiler, for DEC Alpha, using
|
||||
encapsulated stabs.
|
||||
Copyright (C) 1992, 1993 Free Software Foundation, Inc.
|
||||
Contributed by Peter Schauer (pes@regent.e-technik.tu-muenchen.de).
|
||||
|
||||
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 "alpha/osf2.h"
|
||||
|
||||
#undef PREFERRED_DEBUGGING_TYPE
|
||||
#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
|
@ -1,32 +0,0 @@
|
||||
/* Definitions of target machine for GNU compiler, for DEC Alpha.
|
||||
Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc.
|
||||
Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
|
||||
|
||||
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 "alpha/alpha.h"
|
||||
|
||||
/* In OSF 2.0, the size of wchar_t was changed from short unsigned
|
||||
to unsigned int. */
|
||||
|
||||
#undef WCHAR_TYPE
|
||||
#define WCHAR_TYPE "unsigned int"
|
||||
|
||||
#undef WCHAR_TYPE_SIZE
|
||||
#define WCHAR_TYPE_SIZE 32
|
@ -1,9 +1,8 @@
|
||||
/* Definitions for Intel 386 running FreeBSD with either a.out or ELF format
|
||||
Copyright (C) 1996-2000 Free Software Foundation, Inc.
|
||||
/* Definitions for Intel 386 running FreeBSD with ELF format
|
||||
Copyright (C) 1996 Free Software Foundation, Inc.
|
||||
Contributed by Eric Youngdale.
|
||||
Modified for stabs-in-ELF by H.J. Lu.
|
||||
Adapted from GNU/Linux version by John Polstra.
|
||||
Added support for generating "old a.out gas" on the fly by Peter Wemm.
|
||||
Continued development by David O'Brien <obrien@freebsd.org>
|
||||
|
||||
This file is part of GNU CC.
|
||||
@ -23,548 +22,50 @@ 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. */
|
||||
|
||||
/* $FreeBSD$ */
|
||||
#undef TARGET_VERSION
|
||||
#define TARGET_VERSION fprintf (stderr, " (i386 FreeBSD/ELF)");
|
||||
|
||||
#undef CPP_PREDEFINES
|
||||
#define CPP_PREDEFINES \
|
||||
"-Di386 -Acpu(i386) -Amachine(i386)" \
|
||||
FBSD_CPP_PREDEFINES
|
||||
/* The svr4 ABI for the i386 says that records and unions are returned
|
||||
in memory. */
|
||||
/* On FreeBSD, we do not. */
|
||||
#undef DEFAULT_PCC_STRUCT_RETURN
|
||||
#define DEFAULT_PCC_STRUCT_RETURN 0
|
||||
|
||||
#undef CC1_SPEC
|
||||
#define CC1_SPEC "\
|
||||
%{gline:%{!g:%{!g0:%{!g1:%{!g2: -g1}}}}} \
|
||||
%{maout: %{!mno-underscores: %{!munderscores: -munderscores }}}"
|
||||
/* This gets defined in tm.h->linux.h->svr4.h, and keeps us from using
|
||||
libraries compiled with the native cc, so undef it. */
|
||||
#undef NO_DOLLAR_IN_LABEL
|
||||
|
||||
#undef ASM_SPEC
|
||||
#define ASM_SPEC "%{v*: -v} %{maout: %{fpic:-k} %{fPIC:-k}}"
|
||||
/* Use more efficient ``thunks'' to implement C++ vtables. */
|
||||
#undef DEFAULT_VTABLE_THUNKS
|
||||
#define DEFAULT_VTABLE_THUNKS 1
|
||||
|
||||
#undef ASM_FINAL_SPEC
|
||||
#define ASM_FINAL_SPEC "%|"
|
||||
/* Override the default comment-starter of "/". */
|
||||
#undef ASM_COMMENT_START
|
||||
#define ASM_COMMENT_START "#"
|
||||
|
||||
/* Provide a LINK_SPEC appropriate for FreeBSD. Here we provide support
|
||||
for the special GCC options -static and -shared, which allow us to
|
||||
link things in one of these three modes by applying the appropriate
|
||||
combinations of options at link-time. We like to support here for
|
||||
as many of the other GNU linker options as possible. But I don't
|
||||
have the time to search for those flags. I am sure how to add
|
||||
support for -soname shared_object_name. H.J.
|
||||
#undef ASM_APP_ON
|
||||
#define ASM_APP_ON "#APP\n"
|
||||
|
||||
I took out %{v:%{!V:-V}}. It is too much :-(. They can use
|
||||
-Wl,-V.
|
||||
#undef ASM_APP_OFF
|
||||
#define ASM_APP_OFF "#NO_APP\n"
|
||||
|
||||
When the -shared link option is used a final link is not being
|
||||
done. */
|
||||
|
||||
#undef LINK_SPEC
|
||||
#define LINK_SPEC "\
|
||||
%{p:%e`-p' not supported; use `-pg' and gprof(1)} \
|
||||
%{maout: %{shared:-Bshareable} \
|
||||
%{!shared:%{!nostdlib:%{!r:%{!e*:-e start}}} -dc -dp %{static:-Bstatic} \
|
||||
%{pg:-Bstatic} %{Z}} \
|
||||
%{assert*} %{R*}} \
|
||||
%{!maout: \
|
||||
-m elf_i386 \
|
||||
%{Wl,*:%*} \
|
||||
%{assert*} %{R*} %{rpath*} %{defsym*} \
|
||||
%{shared:-Bshareable %{h*} %{soname*}} \
|
||||
%{symbolic:-Bsymbolic} \
|
||||
%{!shared: \
|
||||
%{!static: \
|
||||
%{rdynamic: -export-dynamic} \
|
||||
%{!dynamic-linker: -dynamic-linker /usr/libexec/ld-elf.so.1}} \
|
||||
%{static:-Bstatic}}}"
|
||||
|
||||
#undef STARTFILE_SPEC
|
||||
#define STARTFILE_SPEC "\
|
||||
%{maout: %{shared:c++rt0.o%s} \
|
||||
%{!shared: \
|
||||
%{pg:gcrt0.o%s}%{!pg: \
|
||||
%{static:scrt0.o%s} \
|
||||
%{!static:crt0.o%s}}}} \
|
||||
%{!maout: \
|
||||
%{!shared: \
|
||||
%{pg:gcrt1.o%s} \
|
||||
%{!pg: \
|
||||
%{p:gcrt1.o%s} \
|
||||
%{!p:crt1.o%s}}} \
|
||||
crti.o%s %{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}}"
|
||||
|
||||
/* Provide an ENDFILE_SPEC appropriate for FreeBSD/i386. Here we tack on our
|
||||
own magical crtend.o file (compare w/crtstuff.c) which provides part of the
|
||||
support for getting C++ file-scope static object constructed before
|
||||
entering `main', followed by the normal "finalizer" file, `crtn.o'. */
|
||||
|
||||
#undef ENDFILE_SPEC
|
||||
#define ENDFILE_SPEC "\
|
||||
%{!maout: \
|
||||
%{!shared:crtend.o%s} \
|
||||
%{shared:crtendS.o%s} crtn.o%s}"
|
||||
|
||||
|
||||
/************************[ Target stuff ]***********************************/
|
||||
|
||||
/* Define the actual types of some ANSI-mandated types.
|
||||
Needs to agree with <machine/ansi.h>. GCC defaults come from c-decl.c,
|
||||
c-common.c, and config/<arch>/<arch>.h. */
|
||||
|
||||
#undef SIZE_TYPE
|
||||
#define SIZE_TYPE "unsigned int"
|
||||
|
||||
#undef PTRDIFF_TYPE
|
||||
#define PTRDIFF_TYPE "int"
|
||||
|
||||
/* This is the pseudo-op used to generate a 32-bit word of data with a
|
||||
specific value in some section. */
|
||||
|
||||
#undef INT_ASM_OP
|
||||
#define INT_ASM_OP ".long"
|
||||
|
||||
/* Biggest alignment supported by the object file format of this
|
||||
machine. Use this macro to limit the alignment which can be
|
||||
specified using the `__attribute__ ((aligned (N)))' construct. If
|
||||
not defined, the default value is `BIGGEST_ALIGNMENT'. */
|
||||
|
||||
#define MAX_OFILE_ALIGNMENT (32768*8)
|
||||
|
||||
#undef TARGET_VERSION
|
||||
#define TARGET_VERSION fprintf (stderr, " (i386 FreeBSD/ELF)");
|
||||
|
||||
#define MASK_PROFILER_EPILOGUE 010000000000
|
||||
#define MASK_AOUT 004000000000 /* a.out not elf */
|
||||
#define MASK_UNDERSCORES 002000000000 /* use leading _ */
|
||||
|
||||
#define TARGET_PROFILER_EPILOGUE (target_flags & MASK_PROFILER_EPILOGUE)
|
||||
#define TARGET_AOUT (target_flags & MASK_AOUT)
|
||||
#define TARGET_ELF ((target_flags & MASK_AOUT) == 0)
|
||||
#define TARGET_UNDERSCORES ((target_flags & MASK_UNDERSCORES) != 0)
|
||||
|
||||
#undef SUBTARGET_SWITCHES
|
||||
#define SUBTARGET_SWITCHES \
|
||||
{ "profiler-epilogue", MASK_PROFILER_EPILOGUE}, \
|
||||
{ "no-profiler-epilogue", -MASK_PROFILER_EPILOGUE}, \
|
||||
{ "aout", MASK_AOUT}, \
|
||||
{ "no-aout", -MASK_AOUT}, \
|
||||
{ "underscores", MASK_UNDERSCORES}, \
|
||||
{ "no-underscores", -MASK_UNDERSCORES},
|
||||
|
||||
/* This goes away when the math emulator is fixed. */
|
||||
#undef TARGET_DEFAULT
|
||||
#define TARGET_DEFAULT \
|
||||
(MASK_80387 | MASK_IEEE_FP | MASK_FLOAT_RETURNS | MASK_NO_FANCY_MATH_387)
|
||||
|
||||
/* Prefix for internally generated assembler labels. If we aren't using
|
||||
underscores, we are using prefix `.'s to identify labels that should
|
||||
be ignored, as in `i386/gas.h' --karl@cs.umb.edu */
|
||||
#undef LPREFIX
|
||||
#define LPREFIX ((TARGET_UNDERSCORES) ? "L" : ".L")
|
||||
|
||||
/* The a.out tools do not support "linkonce" sections. */
|
||||
#undef SUPPORTS_ONE_ONLY
|
||||
#define SUPPORTS_ONE_ONLY TARGET_ELF
|
||||
|
||||
/* Enable alias attribute support. */
|
||||
#undef SET_ASM_OP
|
||||
#define SET_ASM_OP ".set"
|
||||
|
||||
/* The a.out tools do not support "Lscope" .stabs symbols. */
|
||||
#undef NO_DBX_FUNCTION_END
|
||||
#define NO_DBX_FUNCTION_END TARGET_AOUT
|
||||
|
||||
/* In ELF, the function stabs come first, before the relative offsets. */
|
||||
#undef DBX_FUNCTION_FIRST
|
||||
#define DBX_CHECK_FUNCTION_FIRST TARGET_ELF
|
||||
|
||||
/* supply our own hook for calling __main() from main() */
|
||||
#undef INVOKE__main
|
||||
#define INVOKE__main
|
||||
#undef GEN_CALL__MAIN
|
||||
#define GEN_CALL__MAIN \
|
||||
do { \
|
||||
if (!(TARGET_ELF)) \
|
||||
emit_library_call (gen_rtx (SYMBOL_REF, Pmode, NAME__MAIN), 0, \
|
||||
VOIDmode, 0); \
|
||||
} while (0)
|
||||
|
||||
/* Indicate that jump tables go in the text section. This is
|
||||
necessary when compiling PIC code. */
|
||||
#undef JUMP_TABLES_IN_TEXT_SECTION
|
||||
#define JUMP_TABLES_IN_TEXT_SECTION (flag_pic)
|
||||
|
||||
/* override the exception table positioning */
|
||||
#undef EXCEPTION_SECTION
|
||||
#define EXCEPTION_SECTION() \
|
||||
do { \
|
||||
if (TARGET_ELF) \
|
||||
{ \
|
||||
named_section (NULL_TREE, ".gcc_except_table", 0); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
if (flag_pic) \
|
||||
data_section (); \
|
||||
else \
|
||||
readonly_data_section (); \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
/* Tell final.c that we don't need a label passed to mcount. */
|
||||
#undef NO_PROFILE_DATA
|
||||
#define NO_PROFILE_DATA
|
||||
|
||||
/* Output assembler code to FILE to begin profiling of the current function.
|
||||
LABELNO is an optional label. */
|
||||
|
||||
#undef FUNCTION_PROFILER
|
||||
#define FUNCTION_PROFILER(FILE, LABELNO) \
|
||||
do { \
|
||||
char *_name = TARGET_AOUT ? "mcount" : ".mcount"; \
|
||||
if (flag_pic) \
|
||||
fprintf ((FILE), "\tcall *%s@GOT(%%ebx)\n", _name); \
|
||||
else \
|
||||
fprintf ((FILE), "\tcall %s\n", _name); \
|
||||
} while (0)
|
||||
|
||||
/* Output assembler code to FILE to end profiling of the current function. */
|
||||
|
||||
#undef FUNCTION_PROFILER_EPILOGUE
|
||||
#define FUNCTION_PROFILER_EPILOGUE(FILE, DO_RTL) \
|
||||
do { \
|
||||
if (TARGET_PROFILER_EPILOGUE) \
|
||||
{ \
|
||||
if (DO_RTL) \
|
||||
{ \
|
||||
/* ".mexitcount" is specially handled in \
|
||||
ASM_HACK_SYMBOLREF () so that we don't need to handle \
|
||||
flag_pic or TARGET_AOUT here. */ \
|
||||
rtx xop; \
|
||||
xop = gen_rtx_MEM (FUNCTION_MODE, \
|
||||
gen_rtx_SYMBOL_REF (Pmode, ".mexitcount")); \
|
||||
emit_call_insn (gen_rtx (CALL, VOIDmode, xop, const0_rtx)); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
/* XXX this !DO_RTL case is broken but not actually used. */ \
|
||||
char *_name = TARGET_AOUT ? "mcount" : ".mcount"; \
|
||||
if (flag_pic) \
|
||||
fprintf (FILE, "\tcall *%s@GOT(%%ebx)\n", _name); \
|
||||
else \
|
||||
fprintf (FILE, "\tcall %s\n", _name); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
/************************[ Assembler stuff ]********************************/
|
||||
|
||||
#undef ASM_APP_ON
|
||||
#define ASM_APP_ON "#APP\n"
|
||||
|
||||
#undef ASM_APP_OFF
|
||||
#define ASM_APP_OFF "#NO_APP\n"
|
||||
|
||||
/* This is how to begin an assembly language file.
|
||||
The .file command should always begin the output.
|
||||
ELF also needs a .version. */
|
||||
|
||||
#undef ASM_FILE_START
|
||||
#define ASM_FILE_START(FILE) \
|
||||
do { \
|
||||
output_file_directive ((FILE), main_input_filename); \
|
||||
if (TARGET_ELF) \
|
||||
fprintf ((FILE), "\t.version\t\"01.01\"\n"); \
|
||||
} while (0)
|
||||
|
||||
/* This is how to store into the string BUF
|
||||
the symbol_ref name of an internal numbered label where
|
||||
PREFIX is the class of label and NUM is the number within the class.
|
||||
This is suitable for output with `assemble_name'. */
|
||||
#undef ASM_GENERATE_INTERNAL_LABEL
|
||||
#define ASM_GENERATE_INTERNAL_LABEL(BUF, PREFIX, NUMBER) \
|
||||
sprintf ((BUF), "*%s%s%d", (TARGET_UNDERSCORES) ? "" : ".", \
|
||||
(PREFIX), (NUMBER))
|
||||
|
||||
/* This is how to output an internal numbered label where
|
||||
PREFIX is the class of label and NUM is the number within the class.
|
||||
For most svr4/ELF systems, the convention is that any symbol which begins
|
||||
with a period is not put into the linker symbol table by the assembler. */
|
||||
#undef ASM_OUTPUT_INTERNAL_LABEL
|
||||
#define ASM_OUTPUT_INTERNAL_LABEL(FILE,PREFIX,NUM) \
|
||||
fprintf ((FILE), "%s%s%d:\n", (TARGET_UNDERSCORES) ? "" : ".", \
|
||||
(PREFIX), (NUM))
|
||||
|
||||
/* This is how to output a reference to a user-level label named NAME. */
|
||||
#undef ASM_OUTPUT_LABELREF
|
||||
#define ASM_OUTPUT_LABELREF(FILE, NAME) \
|
||||
do { \
|
||||
char *_name = (NAME); \
|
||||
/* Hack to avoid writing lots of rtl in \
|
||||
FUNCTION_PROFILER_EPILOGUE (). */ \
|
||||
if (*_name == '.' && strcmp(_name + 1, "mexitcount") == 0) \
|
||||
{ \
|
||||
if (TARGET_AOUT) \
|
||||
_name++; \
|
||||
if (flag_pic) \
|
||||
fprintf ((FILE), "*%s@GOT(%%ebx)", _name); \
|
||||
else \
|
||||
fprintf ((FILE), "%s", _name); \
|
||||
} \
|
||||
else \
|
||||
fprintf (FILE, "%s%s", TARGET_UNDERSCORES ? "_" : "", _name); \
|
||||
} while (0)
|
||||
|
||||
/* This is how to hack on the symbol code of certain relcalcitrant
|
||||
symbols to modify their output in output_pic_addr_const (). */
|
||||
|
||||
#undef ASM_HACK_SYMBOLREF_CODE
|
||||
#define ASM_HACK_SYMBOLREF_CODE(NAME, CODE) \
|
||||
do { \
|
||||
/* Part of hack to avoid writing lots of rtl in \
|
||||
FUNCTION_PROFILER_EPILOGUE (). */ \
|
||||
char *_name = (NAME); \
|
||||
if (*_name == '.' && strcmp(_name + 1, "mexitcount") == 0) \
|
||||
(CODE) = 'X'; \
|
||||
} while (0)
|
||||
#undef SET_ASM_OP
|
||||
#define SET_ASM_OP ".set"
|
||||
|
||||
/* This is how to output an element of a case-vector that is relative.
|
||||
This is only used for PIC code. See comments by the `casesi' insn in
|
||||
i386.md for an explanation of the expression this outputs. */
|
||||
#undef ASM_OUTPUT_ADDR_DIFF_ELT
|
||||
#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
|
||||
fprintf ((FILE), "\t.long _GLOBAL_OFFSET_TABLE_+[.-%s%d]\n", LPREFIX, (VALUE))
|
||||
#undef ASM_OUTPUT_ADDR_DIFF_ELT
|
||||
#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
|
||||
fprintf (FILE, "\t.long _GLOBAL_OFFSET_TABLE_+[.-%s%d]\n", LPREFIX, VALUE)
|
||||
|
||||
#undef ASM_OUTPUT_ALIGN
|
||||
#define ASM_OUTPUT_ALIGN(FILE, LOG) \
|
||||
if ((LOG)!=0) { \
|
||||
if (in_text_section()) \
|
||||
fprintf ((FILE), "\t.p2align %d,0x90\n", (LOG)); \
|
||||
else \
|
||||
fprintf ((FILE), "\t.p2align %d\n", (LOG)); \
|
||||
}
|
||||
/* Indicate that jump tables go in the text section. This is
|
||||
necessary when compiling PIC code. */
|
||||
#define JUMP_TABLES_IN_TEXT_SECTION (flag_pic)
|
||||
|
||||
#undef ASM_OUTPUT_SOURCE_LINE
|
||||
#define ASM_OUTPUT_SOURCE_LINE(FILE, LINE) \
|
||||
do { \
|
||||
static int sym_lineno = 1; \
|
||||
if (TARGET_ELF) \
|
||||
{ \
|
||||
fprintf ((FILE), ".stabn 68,0,%d,.LM%d-", (LINE), sym_lineno); \
|
||||
assemble_name ((FILE), \
|
||||
XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0)); \
|
||||
fprintf ((FILE), "\n.LM%d:\n", sym_lineno); \
|
||||
sym_lineno += 1; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
fprintf ((FILE), "\t%s %d,0,%d\n", ASM_STABD_OP, N_SLINE, \
|
||||
lineno); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* These macros generate the special .type and .size directives which
|
||||
are used to set the corresponding fields of the linker symbol table
|
||||
entries in an ELF object file under SVR4. These macros also output
|
||||
the starting labels for the relevant functions/objects. */
|
||||
|
||||
/* Write the extra assembler code needed to declare a function properly.
|
||||
Some svr4 assemblers need to also have something extra said about the
|
||||
function's return value. We allow for that here. */
|
||||
|
||||
#undef ASM_DECLARE_FUNCTION_NAME
|
||||
#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \
|
||||
do { \
|
||||
fprintf (FILE, "\t%s\t ", TYPE_ASM_OP); \
|
||||
assemble_name (FILE, NAME); \
|
||||
putc (',', FILE); \
|
||||
fprintf (FILE, TYPE_OPERAND_FMT, "function"); \
|
||||
putc ('\n', FILE); \
|
||||
ASM_DECLARE_RESULT (FILE, DECL_RESULT (DECL)); \
|
||||
ASM_OUTPUT_LABEL(FILE, NAME); \
|
||||
} while (0)
|
||||
|
||||
/* This is how to declare the size of a function. */
|
||||
|
||||
#undef ASM_DECLARE_FUNCTION_SIZE
|
||||
#define ASM_DECLARE_FUNCTION_SIZE(FILE, FNAME, DECL) \
|
||||
do { \
|
||||
if (!flag_inhibit_size_directive) \
|
||||
{ \
|
||||
char label[256]; \
|
||||
static int labelno; \
|
||||
labelno++; \
|
||||
ASM_GENERATE_INTERNAL_LABEL (label, "Lfe", labelno); \
|
||||
ASM_OUTPUT_INTERNAL_LABEL (FILE, "Lfe", labelno); \
|
||||
fprintf (FILE, "\t%s\t ", SIZE_ASM_OP); \
|
||||
assemble_name (FILE, (FNAME)); \
|
||||
fprintf (FILE, ","); \
|
||||
assemble_name (FILE, label); \
|
||||
fprintf (FILE, "-"); \
|
||||
assemble_name (FILE, (FNAME)); \
|
||||
putc ('\n', FILE); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
/* The routine used to output NUL terminated strings. We use a special
|
||||
version of this for most svr4 targets because doing so makes the
|
||||
generated assembly code more compact (and thus faster to assemble)
|
||||
as well as more readable, especially for targets like the i386
|
||||
(where the only alternative is to output character sequences as
|
||||
comma separated lists of numbers). */
|
||||
|
||||
#undef ASM_OUTPUT_LIMITED_STRING
|
||||
#define ASM_OUTPUT_LIMITED_STRING(FILE, STR) \
|
||||
do { \
|
||||
register unsigned char *_limited_str = (unsigned char *) (STR); \
|
||||
register unsigned ch; \
|
||||
fprintf ((FILE), "\t%s\t\"", STRING_ASM_OP); \
|
||||
for (; (ch = *_limited_str); _limited_str++) \
|
||||
{ \
|
||||
register int escape; \
|
||||
switch (escape = ESCAPES[ch]) \
|
||||
{ \
|
||||
case 0: \
|
||||
putc (ch, (FILE)); \
|
||||
break; \
|
||||
case 1: \
|
||||
fprintf ((FILE), "\\%03o", ch); \
|
||||
break; \
|
||||
default: \
|
||||
putc ('\\', (FILE)); \
|
||||
putc (escape, (FILE)); \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
fprintf ((FILE), "\"\n"); \
|
||||
} while (0)
|
||||
|
||||
/* Switch into a generic section.
|
||||
|
||||
We make the section read-only and executable for a function decl,
|
||||
read-only for a const data decl, and writable for a non-const data decl.
|
||||
|
||||
If the section has already been defined, we must not
|
||||
emit the attributes here. The SVR4 assembler does not
|
||||
recognize section redefinitions.
|
||||
If DECL is NULL, no attributes are emitted. */
|
||||
|
||||
#undef ASM_OUTPUT_SECTION_NAME
|
||||
#define ASM_OUTPUT_SECTION_NAME(FILE, DECL, NAME, RELOC) \
|
||||
do { \
|
||||
static struct section_info \
|
||||
{ \
|
||||
struct section_info *next; \
|
||||
char *name; \
|
||||
enum sect_enum {SECT_RW, SECT_RO, SECT_EXEC} type; \
|
||||
} *sections; \
|
||||
struct section_info *s; \
|
||||
char *mode; \
|
||||
enum sect_enum type; \
|
||||
\
|
||||
for (s = sections; s; s = s->next) \
|
||||
if (!strcmp (NAME, s->name)) \
|
||||
break; \
|
||||
\
|
||||
if (DECL && TREE_CODE (DECL) == FUNCTION_DECL) \
|
||||
type = SECT_EXEC, mode = "ax"; \
|
||||
else if (DECL && DECL_READONLY_SECTION (DECL, RELOC)) \
|
||||
type = SECT_RO, mode = "a"; \
|
||||
else \
|
||||
type = SECT_RW, mode = "aw"; \
|
||||
\
|
||||
if (s == 0) \
|
||||
{ \
|
||||
s = (struct section_info *) xmalloc (sizeof (struct section_info)); \
|
||||
s->name = xmalloc ((strlen (NAME) + 1) * sizeof (*NAME)); \
|
||||
strcpy (s->name, NAME); \
|
||||
s->type = type; \
|
||||
s->next = sections; \
|
||||
sections = s; \
|
||||
fprintf (FILE, ".section\t%s,\"%s\",@progbits\n", NAME, mode); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
if (DECL && s->type != type) \
|
||||
error_with_decl (DECL, "%s causes a section type conflict"); \
|
||||
\
|
||||
fprintf (FILE, ".section\t%s\n", NAME); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#undef MAKE_DECL_ONE_ONLY
|
||||
#define MAKE_DECL_ONE_ONLY(DECL) (DECL_WEAK (DECL) = 1)
|
||||
#undef UNIQUE_SECTION_P
|
||||
#define UNIQUE_SECTION_P(DECL) (DECL_ONE_ONLY (DECL))
|
||||
#undef UNIQUE_SECTION
|
||||
#define UNIQUE_SECTION(DECL,RELOC) \
|
||||
do { \
|
||||
int len; \
|
||||
char *name, *string, *prefix; \
|
||||
\
|
||||
name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (DECL)); \
|
||||
\
|
||||
if (! DECL_ONE_ONLY (DECL)) \
|
||||
{ \
|
||||
prefix = "."; \
|
||||
if (TREE_CODE (DECL) == FUNCTION_DECL) \
|
||||
prefix = ".text."; \
|
||||
else if (DECL_READONLY_SECTION (DECL, RELOC)) \
|
||||
prefix = ".rodata."; \
|
||||
else \
|
||||
prefix = ".data."; \
|
||||
} \
|
||||
else if (TREE_CODE (DECL) == FUNCTION_DECL) \
|
||||
prefix = ".gnu.linkonce.t."; \
|
||||
else if (DECL_READONLY_SECTION (DECL, RELOC)) \
|
||||
prefix = ".gnu.linkonce.r."; \
|
||||
else \
|
||||
prefix = ".gnu.linkonce.d."; \
|
||||
\
|
||||
len = strlen (name) + strlen (prefix); \
|
||||
string = alloca (len + 1); \
|
||||
sprintf (string, "%s%s", prefix, name); \
|
||||
\
|
||||
DECL_SECTION_NAME (DECL) = build_string (len, string); \
|
||||
} while (0)
|
||||
|
||||
/* A C statement or statements to switch to the appropriate
|
||||
section for output of DECL. DECL is either a `VAR_DECL' node
|
||||
or a constant of some sort. RELOC indicates whether forming
|
||||
the initial value of DECL requires link-time relocations. */
|
||||
|
||||
#undef SELECT_SECTION
|
||||
#define SELECT_SECTION(DECL,RELOC) \
|
||||
{ \
|
||||
if (flag_pic && RELOC) \
|
||||
data_section (); \
|
||||
else if (TREE_CODE (DECL) == STRING_CST) \
|
||||
{ \
|
||||
if (! flag_writable_strings) \
|
||||
const_section (); \
|
||||
else \
|
||||
data_section (); \
|
||||
} \
|
||||
else if (TREE_CODE (DECL) == VAR_DECL) \
|
||||
{ \
|
||||
if (! DECL_READONLY_SECTION (DECL, RELOC)) \
|
||||
data_section (); \
|
||||
else \
|
||||
const_section (); \
|
||||
} \
|
||||
else \
|
||||
const_section (); \
|
||||
}
|
||||
|
||||
/* Define macro used to output shift-double opcodes when the shift
|
||||
count is in %cl. Some assemblers require %cl as an argument;
|
||||
some don't.
|
||||
|
||||
*OLD* GAS requires the %cl argument, so override i386/unix.h. */
|
||||
|
||||
#undef AS3_SHIFT_DOUBLE
|
||||
#define AS3_SHIFT_DOUBLE(a,b,c,d) AS3 (a,b,c,d)
|
||||
|
||||
|
||||
/************************[ Debugger stuff ]*********************************/
|
||||
/* Use stabs instead of DWARF debug format. */
|
||||
#undef PREFERRED_DEBUGGING_TYPE
|
||||
#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
|
||||
|
||||
/* Copy this from the svr4 specifications... */
|
||||
/* Define the register numbers to be used in Dwarf debugging information.
|
||||
@ -621,8 +122,8 @@ Boston, MA 02111-1307, USA. */
|
||||
17 for %st(6) (gnu regno = 14)
|
||||
18 for %st(7) (gnu regno = 15)
|
||||
*/
|
||||
#undef DWARF_DBX_REGISTER_NUMBER
|
||||
#define DWARF_DBX_REGISTER_NUMBER(n) \
|
||||
#undef DBX_REGISTER_NUMBER
|
||||
#define DBX_REGISTER_NUMBER(n) \
|
||||
((n) == 0 ? 0 \
|
||||
: (n) == 1 ? 2 \
|
||||
: (n) == 2 ? 1 \
|
||||
@ -634,59 +135,123 @@ Boston, MA 02111-1307, USA. */
|
||||
: ((n) >= FIRST_STACK_REG && (n) <= LAST_STACK_REG) ? (n)+3 \
|
||||
: (-1))
|
||||
|
||||
/* Now what stabs expects in the register. */
|
||||
#undef STABS_DBX_REGISTER_NUMBER
|
||||
#define STABS_DBX_REGISTER_NUMBER(n) \
|
||||
((n) == 0 ? 0 : \
|
||||
(n) == 1 ? 2 : \
|
||||
(n) == 2 ? 1 : \
|
||||
(n) == 3 ? 3 : \
|
||||
(n) == 4 ? 6 : \
|
||||
(n) == 5 ? 7 : \
|
||||
(n) == 6 ? 4 : \
|
||||
(n) == 7 ? 5 : \
|
||||
(n) + 4)
|
||||
/* Tell final.c that we don't need a label passed to mcount. */
|
||||
|
||||
#undef DBX_REGISTER_NUMBER
|
||||
#define DBX_REGISTER_NUMBER(n) ((write_symbols == DWARF_DEBUG) \
|
||||
? DWARF_DBX_REGISTER_NUMBER(n) \
|
||||
: STABS_DBX_REGISTER_NUMBER(n))
|
||||
#undef FUNCTION_PROFILER
|
||||
#define FUNCTION_PROFILER(FILE, LABELNO) \
|
||||
{ \
|
||||
if (flag_pic) \
|
||||
fprintf (FILE, "\tcall *.mcount@GOT(%%ebx)\n"); \
|
||||
else \
|
||||
fprintf (FILE, "\tcall .mcount\n"); \
|
||||
}
|
||||
|
||||
/* tag end of file in elf mode */
|
||||
#undef DBX_OUTPUT_MAIN_SOURCE_FILE_END
|
||||
#define DBX_OUTPUT_MAIN_SOURCE_FILE_END(FILE, FILENAME) \
|
||||
do { \
|
||||
if (TARGET_ELF) { \
|
||||
fprintf ((FILE), "\t.text\n\t.stabs \"\",%d,0,0,.Letext\n.Letext:\n", \
|
||||
N_SO); \
|
||||
} \
|
||||
} while (0)
|
||||
#undef SIZE_TYPE
|
||||
#define SIZE_TYPE "unsigned int"
|
||||
|
||||
#undef PTRDIFF_TYPE
|
||||
#define PTRDIFF_TYPE "int"
|
||||
|
||||
#undef WCHAR_TYPE
|
||||
#define WCHAR_TYPE "int"
|
||||
|
||||
/* stabs-in-elf has offsets relative to function beginning */
|
||||
#undef DBX_OUTPUT_LBRAC
|
||||
#define DBX_OUTPUT_LBRAC(FILE, NAME) \
|
||||
do { \
|
||||
fprintf (asmfile, "%s %d,0,0,", ASM_STABN_OP, N_LBRAC); \
|
||||
assemble_name (asmfile, buf); \
|
||||
if (TARGET_ELF) \
|
||||
{ \
|
||||
fputc ('-', asmfile); \
|
||||
assemble_name (asmfile, \
|
||||
XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0)); \
|
||||
} \
|
||||
fprintf (asmfile, "\n"); \
|
||||
} while (0)
|
||||
#undef WCHAR_UNSIGNED
|
||||
#define WCHAR_UNSIGNED 0
|
||||
|
||||
#undef WCHAR_TYPE_SIZE
|
||||
#define WCHAR_TYPE_SIZE BITS_PER_WORD
|
||||
|
||||
#undef CPP_PREDEFINES
|
||||
#define CPP_PREDEFINES "-Di386 -Dunix -D__ELF__ -D__FreeBSD__ -Asystem(unix) -Asystem(FreeBSD) -Acpu(i386) -Amachine(i386)"
|
||||
|
||||
#undef DBX_OUTPUT_RBRAC
|
||||
#define DBX_OUTPUT_RBRAC(FILE, NAME) \
|
||||
do { \
|
||||
fprintf (asmfile, "%s %d,0,0,", ASM_STABN_OP, N_RBRAC); \
|
||||
assemble_name (asmfile, buf); \
|
||||
if (TARGET_ELF) \
|
||||
{ \
|
||||
fputc ('-', asmfile); \
|
||||
assemble_name (asmfile, \
|
||||
XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0)); \
|
||||
} \
|
||||
fprintf (asmfile, "\n"); \
|
||||
} while (0)
|
||||
#undef CPP_SPEC
|
||||
#define CPP_SPEC "%(cpp_cpu) %{fPIC:-D__PIC__ -D__pic__} %{fpic:-D__PIC__ -D__pic__} %{posix:-D_POSIX_SOURCE}"
|
||||
|
||||
/* This defines which switch letters take arguments. On FreeBSD, most of
|
||||
the normal cases (defined in gcc.c) apply, and we also have -h* and
|
||||
-z* options (for the linker) (comming from svr4).
|
||||
We also have -R (alias --rpath), no -z, --soname (-h), --assert etc. */
|
||||
|
||||
#undef SWITCH_TAKES_ARG
|
||||
#define SWITCH_TAKES_ARG(CHAR) \
|
||||
(DEFAULT_SWITCH_TAKES_ARG (CHAR) \
|
||||
|| (CHAR) == 'h' \
|
||||
|| (CHAR) == 'z' \
|
||||
|| (CHAR) == 'R')
|
||||
|
||||
/* Provide a STARTFILE_SPEC appropriate for FreeBSD. Here we add
|
||||
the magical crtbegin.o file (see crtstuff.c) which provides part
|
||||
of the support for getting C++ file-scope static object constructed
|
||||
before entering `main'. */
|
||||
|
||||
#undef STARTFILE_SPEC
|
||||
#define STARTFILE_SPEC \
|
||||
"%{!shared: \
|
||||
%{pg:gcrt1.o%s} %{!pg:%{p:gcrt1.o%s} \
|
||||
%{!p:%{profile:gcrt1.o%s} \
|
||||
%{!profile:crt1.o%s}}}} \
|
||||
crti.o%s %{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}"
|
||||
|
||||
/* Provide a ENDFILE_SPEC appropriate for FreeBSD. Here we tack on
|
||||
the magical crtend.o file (see crtstuff.c) which provides part of
|
||||
the support for getting C++ file-scope static object constructed
|
||||
before entering `main', followed by a normal "finalizer" file,
|
||||
`crtn.o'. */
|
||||
|
||||
#undef ENDFILE_SPEC
|
||||
#define ENDFILE_SPEC \
|
||||
"%{!shared:crtend.o%s} %{shared:crtendS.o%s} crtn.o%s"
|
||||
|
||||
/* Provide a LIB_SPEC appropriate for FreeBSD. Just select the appropriate
|
||||
libc, depending on whether we're doing profiling or need threads support.
|
||||
(simular to the default, except no -lg, and no -p. */
|
||||
|
||||
#undef LIB_SPEC
|
||||
#define LIB_SPEC "%{!shared: \
|
||||
%{!pg:%{!pthread:%{!kthread:-lc} \
|
||||
%{kthread:-lpthread -lc}} \
|
||||
%{pthread:-lc_r}} \
|
||||
%{pg:%{!pthread:%{!kthread:-lc_p} \
|
||||
%{kthread:-lpthread_p -lc_p}} \
|
||||
%{pthread:-lc_r_p}}}"
|
||||
|
||||
/* Provide a LINK_SPEC appropriate for FreeBSD. Here we provide support
|
||||
for the special GCC options -static and -shared, which allow us to
|
||||
link things in one of these three modes by applying the appropriate
|
||||
combinations of options at link-time. We like to support here for
|
||||
as many of the other GNU linker options as possible. But I don't
|
||||
have the time to search for those flags. I am sure how to add
|
||||
support for -soname shared_object_name. H.J.
|
||||
|
||||
I took out %{v:%{!V:-V}}. It is too much :-(. They can use
|
||||
-Wl,-V.
|
||||
|
||||
When the -shared link option is used a final link is not being
|
||||
done. */
|
||||
|
||||
#undef LINK_SPEC
|
||||
#define LINK_SPEC "-m elf_i386 \
|
||||
%{Wl,*:%*} \
|
||||
%{v:-V} \
|
||||
%{assert*} %{R*} %{rpath*} %{defsym*} \
|
||||
%{shared:-Bshareable %{h*} %{soname*}} \
|
||||
%{!shared: \
|
||||
%{!static: \
|
||||
%{rdynamic:-export-dynamic} \
|
||||
%{!dynamic-linker:-dynamic-linker /usr/libexec/ld-elf.so.1}} \
|
||||
%{static:-Bstatic}} \
|
||||
%{symbolic:-Bsymbolic}"
|
||||
|
||||
/* A C statement to output to the stdio stream FILE an assembler
|
||||
command to advance the location counter to a multiple of 1<<LOG
|
||||
bytes if it is within MAX_SKIP bytes.
|
||||
|
||||
This is used to align code labels according to Intel recommendations. */
|
||||
|
||||
#ifdef HAVE_GAS_MAX_SKIP_P2ALIGN
|
||||
#define ASM_OUTPUT_MAX_SKIP_ALIGN(FILE,LOG,MAX_SKIP) \
|
||||
if ((LOG) != 0) {\
|
||||
if ((MAX_SKIP) == 0) fprintf ((FILE), "\t.p2align %d\n", (LOG)); \
|
||||
else fprintf ((FILE), "\t.p2align %d,,%d\n", (LOG), (MAX_SKIP)); \
|
||||
}
|
||||
#endif
|
||||
|
@ -1,4 +0,0 @@
|
||||
# Don't run fixproto
|
||||
STMP_FIXPROTO =
|
||||
# Use only native include files
|
||||
USER_H =
|
@ -1,582 +0,0 @@
|
||||
/* G++ preliminary semantic processing for the compiler driver.
|
||||
Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
|
||||
Contributed by Brendan Kehoe (brendan@cygnus.com).
|
||||
|
||||
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. */
|
||||
|
||||
/* This program is a wrapper to the main `gcc' driver. For GNU C++,
|
||||
we need to do two special things: a) append `-lg++' in situations
|
||||
where it's appropriate, to link in libg++, and b) add `-xc++'..`-xnone'
|
||||
around file arguments named `foo.c' or `foo.i'. So, we do all of
|
||||
this semantic processing then just exec gcc with the new argument
|
||||
list.
|
||||
|
||||
We used to do all of this in a small shell script, but many users
|
||||
found the performance of this as a shell script to be unacceptable.
|
||||
In situations where your PATH has a lot of NFS-mounted directories,
|
||||
using a script that runs sed and other things would be a nasty
|
||||
performance hit. With this program, we never search the PATH at all. */
|
||||
|
||||
#include "config.h"
|
||||
#ifdef __STDC__
|
||||
#include <stdarg.h>
|
||||
#else
|
||||
#include <varargs.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#if !defined(_WIN32)
|
||||
#include <sys/file.h> /* May get R_OK, etc. on some systems. */
|
||||
#else
|
||||
#include <process.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
|
||||
/* Defined to the name of the compiler; if using a cross compiler, the
|
||||
Makefile should compile this file with the proper name
|
||||
(e.g., "i386-aout-gcc"). */
|
||||
#ifndef GCC_NAME
|
||||
#define GCC_NAME "gcc"
|
||||
#endif
|
||||
|
||||
/* This bit is set if we saw a `-xfoo' language specification. */
|
||||
#define LANGSPEC (1<<1)
|
||||
/* This bit is set if they did `-lm' or `-lmath'. */
|
||||
#define MATHLIB (1<<2)
|
||||
|
||||
#ifndef MATH_LIBRARY
|
||||
#define MATH_LIBRARY "-lm"
|
||||
#endif
|
||||
|
||||
/* On MSDOS, write temp files in current dir
|
||||
because there's no place else we can expect to use. */
|
||||
#ifdef __MSDOS__
|
||||
#ifndef P_tmpdir
|
||||
#define P_tmpdir "."
|
||||
#endif
|
||||
#ifndef R_OK
|
||||
#define R_OK 4
|
||||
#define W_OK 2
|
||||
#define X_OK 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef VPROTO
|
||||
#ifdef __STDC__
|
||||
#define PVPROTO(ARGS) ARGS
|
||||
#define VPROTO(ARGS) ARGS
|
||||
#define VA_START(va_list,var) va_start(va_list,var)
|
||||
#else
|
||||
#define PVPROTO(ARGS) ()
|
||||
#define VPROTO(ARGS) (va_alist) va_dcl
|
||||
#define VA_START(va_list,var) va_start(va_list)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef errno
|
||||
extern int errno;
|
||||
#endif
|
||||
|
||||
extern int sys_nerr;
|
||||
#ifndef HAVE_STRERROR
|
||||
#if defined(bsd4_4)
|
||||
extern const char *const sys_errlist[];
|
||||
#else
|
||||
extern char *sys_errlist[];
|
||||
#endif
|
||||
#else
|
||||
extern char *strerror();
|
||||
#endif
|
||||
|
||||
/* Name with which this program was invoked. */
|
||||
static char *programname;
|
||||
|
||||
char *
|
||||
my_strerror(e)
|
||||
int e;
|
||||
{
|
||||
|
||||
#ifdef HAVE_STRERROR
|
||||
return strerror(e);
|
||||
|
||||
#else
|
||||
|
||||
static char buffer[30];
|
||||
if (!e)
|
||||
return "";
|
||||
|
||||
if (e > 0 && e < sys_nerr)
|
||||
return sys_errlist[e];
|
||||
|
||||
sprintf (buffer, "Unknown error %d", e);
|
||||
return buffer;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef HAVE_VPRINTF
|
||||
/* Output an error message and exit */
|
||||
|
||||
static void
|
||||
fatal VPROTO((char *format, ...))
|
||||
{
|
||||
#ifndef __STDC__
|
||||
char *format;
|
||||
#endif
|
||||
va_list ap;
|
||||
|
||||
VA_START (ap, format);
|
||||
|
||||
#ifndef __STDC__
|
||||
format = va_arg (ap, char*);
|
||||
#endif
|
||||
|
||||
fprintf (stderr, "%s: ", programname);
|
||||
vfprintf (stderr, format, ap);
|
||||
va_end (ap);
|
||||
fprintf (stderr, "\n");
|
||||
#if 0
|
||||
/* XXX Not needed for g++ driver. */
|
||||
delete_temp_files ();
|
||||
#endif
|
||||
exit (1);
|
||||
}
|
||||
|
||||
static void
|
||||
error VPROTO((char *format, ...))
|
||||
{
|
||||
#ifndef __STDC__
|
||||
char *format;
|
||||
#endif
|
||||
va_list ap;
|
||||
|
||||
VA_START (ap, format);
|
||||
|
||||
#ifndef __STDC__
|
||||
format = va_arg (ap, char*);
|
||||
#endif
|
||||
|
||||
fprintf (stderr, "%s: ", programname);
|
||||
vfprintf (stderr, format, ap);
|
||||
va_end (ap);
|
||||
|
||||
fprintf (stderr, "\n");
|
||||
}
|
||||
|
||||
#else /* not HAVE_VPRINTF */
|
||||
|
||||
static void
|
||||
error (msg, arg1, arg2)
|
||||
char *msg, *arg1, *arg2;
|
||||
{
|
||||
fprintf (stderr, "%s: ", programname);
|
||||
fprintf (stderr, msg, arg1, arg2);
|
||||
fprintf (stderr, "\n");
|
||||
}
|
||||
|
||||
static void
|
||||
fatal (msg, arg1, arg2)
|
||||
char *msg, *arg1, *arg2;
|
||||
{
|
||||
error (msg, arg1, arg2);
|
||||
#if 0
|
||||
/* XXX Not needed for g++ driver. */
|
||||
delete_temp_files ();
|
||||
#endif
|
||||
exit (1);
|
||||
}
|
||||
|
||||
#endif /* not HAVE_VPRINTF */
|
||||
|
||||
/* More 'friendly' abort that prints the line and file.
|
||||
config.h can #define abort fancy_abort if you like that sort of thing. */
|
||||
|
||||
void
|
||||
fancy_abort ()
|
||||
{
|
||||
fatal ("Internal g++ abort.");
|
||||
}
|
||||
|
||||
char *
|
||||
xmalloc (size)
|
||||
unsigned size;
|
||||
{
|
||||
register char *value = (char *) malloc (size);
|
||||
if (value == 0)
|
||||
fatal ("virtual memory exhausted");
|
||||
return value;
|
||||
}
|
||||
|
||||
/* Return a newly-allocated string whose contents concatenate those
|
||||
of s1, s2, s3. */
|
||||
static char *
|
||||
concat (s1, s2, s3)
|
||||
char *s1, *s2, *s3;
|
||||
{
|
||||
int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3);
|
||||
char *result = xmalloc (len1 + len2 + len3 + 1);
|
||||
|
||||
strcpy (result, s1);
|
||||
strcpy (result + len1, s2);
|
||||
strcpy (result + len1 + len2, s3);
|
||||
*(result + len1 + len2 + len3) = 0;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
pfatal_with_name (name)
|
||||
char *name;
|
||||
{
|
||||
fatal (concat ("%s: ", my_strerror (errno), ""), name);
|
||||
}
|
||||
|
||||
#ifdef __MSDOS__
|
||||
/* This is the common prefix we use to make temp file names. */
|
||||
char *temp_filename;
|
||||
|
||||
/* Length of the prefix. */
|
||||
int temp_filename_length;
|
||||
|
||||
/* Compute a string to use as the base of all temporary file names. */
|
||||
static char *
|
||||
choose_temp_base_try (try, base)
|
||||
char *try;
|
||||
char *base;
|
||||
{
|
||||
char *rv;
|
||||
if (base)
|
||||
rv = base;
|
||||
else if (try == (char *)0)
|
||||
rv = 0;
|
||||
else if (access (try, R_OK | W_OK) != 0)
|
||||
rv = 0;
|
||||
else
|
||||
rv = try;
|
||||
return rv;
|
||||
}
|
||||
|
||||
static void
|
||||
choose_temp_base ()
|
||||
{
|
||||
char *base = 0;
|
||||
int len;
|
||||
|
||||
base = choose_temp_base_try (getenv ("TMPDIR"), base);
|
||||
base = choose_temp_base_try (getenv ("TMP"), base);
|
||||
base = choose_temp_base_try (getenv ("TEMP"), base);
|
||||
|
||||
#ifdef P_tmpdir
|
||||
base = choose_temp_base_try (P_tmpdir, base);
|
||||
#endif
|
||||
|
||||
base = choose_temp_base_try ("/usr/tmp", base);
|
||||
base = choose_temp_base_try ("/tmp", base);
|
||||
|
||||
/* If all else fails, use the current directory! */
|
||||
if (base == (char *)0)
|
||||
base = "./";
|
||||
|
||||
len = strlen (base);
|
||||
temp_filename = xmalloc (len + sizeof("/ccXXXXXX"));
|
||||
strcpy (temp_filename, base);
|
||||
if (len > 0 && temp_filename[len-1] != '/')
|
||||
temp_filename[len++] = '/';
|
||||
strcpy (temp_filename + len, "ccXXXXXX");
|
||||
|
||||
mktemp (temp_filename);
|
||||
temp_filename_length = strlen (temp_filename);
|
||||
if (temp_filename_length == 0)
|
||||
abort ();
|
||||
}
|
||||
|
||||
static void
|
||||
perror_exec (name)
|
||||
char *name;
|
||||
{
|
||||
char *s;
|
||||
|
||||
if (errno < sys_nerr)
|
||||
s = concat ("installation problem, cannot exec %s: ",
|
||||
my_strerror( errno ), "");
|
||||
else
|
||||
s = "installation problem, cannot exec %s";
|
||||
error (s, name);
|
||||
}
|
||||
|
||||
/* This is almost exactly what's in gcc.c:pexecute for MSDOS. */
|
||||
void
|
||||
run_dos (program, argv)
|
||||
char *program;
|
||||
char *argv[];
|
||||
{
|
||||
char *scmd, *rf;
|
||||
FILE *argfile;
|
||||
int i;
|
||||
|
||||
choose_temp_base (); /* not in gcc.c */
|
||||
|
||||
scmd = (char *) malloc (strlen (program) + strlen (temp_filename) + 10);
|
||||
rf = scmd + strlen (program) + 6;
|
||||
sprintf (scmd, "%s.exe @%s.gp", program, temp_filename);
|
||||
|
||||
argfile = fopen (rf, "w");
|
||||
if (argfile == 0)
|
||||
pfatal_with_name (rf);
|
||||
|
||||
for (i=1; argv[i]; i++)
|
||||
{
|
||||
char *cp;
|
||||
for (cp = argv[i]; *cp; cp++)
|
||||
{
|
||||
if (*cp == '"' || *cp == '\'' || *cp == '\\' || isspace (*cp))
|
||||
fputc ('\\', argfile);
|
||||
fputc (*cp, argfile);
|
||||
}
|
||||
fputc ('\n', argfile);
|
||||
}
|
||||
fclose (argfile);
|
||||
|
||||
i = system (scmd);
|
||||
|
||||
remove (rf);
|
||||
|
||||
if (i == -1)
|
||||
perror_exec (program);
|
||||
}
|
||||
#endif /* __MSDOS__ */
|
||||
|
||||
int
|
||||
main (argc, argv)
|
||||
int argc;
|
||||
char **argv;
|
||||
{
|
||||
register int i, j = 0;
|
||||
register char *p;
|
||||
int verbose = 0;
|
||||
|
||||
/* This will be 0 if we encounter a situation where we should not
|
||||
link in libstdc++, or 2 if we should link in libg++ as well. */
|
||||
int library = 1;
|
||||
|
||||
/* Used to track options that take arguments, so we don't go wrapping
|
||||
those with -xc++/-xnone. */
|
||||
char *quote = NULL;
|
||||
|
||||
/* The new argument list will be contained in this. */
|
||||
char **arglist;
|
||||
|
||||
/* The name of the compiler we will want to run---by default, it
|
||||
will be the definition of `GCC_NAME', e.g., `gcc'. */
|
||||
char *gcc = GCC_NAME;
|
||||
|
||||
/* Non-zero if we saw a `-xfoo' language specification on the
|
||||
command line. Used to avoid adding our own -xc++ if the user
|
||||
already gave a language for the file. */
|
||||
int saw_speclang = 0;
|
||||
|
||||
/* Non-zero if we saw `-lm' or `-lmath' on the command line. */
|
||||
char *saw_math = 0;
|
||||
|
||||
/* The number of arguments being added to what's in argv, other than
|
||||
libraries. We use this to track the number of times we've inserted
|
||||
-xc++/-xnone. */
|
||||
int added = 0;
|
||||
|
||||
/* An array used to flag each argument that needs a bit set for
|
||||
LANGSPEC or MATHLIB. */
|
||||
int *args;
|
||||
|
||||
p = argv[0] + strlen (argv[0]);
|
||||
|
||||
/* If we're called as g++ (or i386-aout-g++), link in libg++ as well. */
|
||||
|
||||
if (strcmp (p - 3, "g++") == 0)
|
||||
{
|
||||
library = 2;
|
||||
}
|
||||
|
||||
while (p != argv[0] && p[-1] != '/')
|
||||
--p;
|
||||
programname = p;
|
||||
|
||||
if (argc == 1)
|
||||
fatal ("No input files specified");
|
||||
|
||||
#ifndef __MSDOS__
|
||||
/* We do a little magic to find out where the main gcc executable
|
||||
is. If they ran us as /usr/local/bin/g++, then we will look
|
||||
for /usr/local/bin/gcc; similarly, if they just ran us as `g++',
|
||||
we'll just look for `gcc'. */
|
||||
if (p != argv[0])
|
||||
{
|
||||
*--p = '\0';
|
||||
gcc = (char *) malloc ((strlen (argv[0]) + 1 + strlen (GCC_NAME) + 1)
|
||||
* sizeof (char));
|
||||
sprintf (gcc, "%s/%s", argv[0], GCC_NAME);
|
||||
}
|
||||
#endif
|
||||
|
||||
args = (int *) malloc (argc * sizeof (int));
|
||||
bzero ((char *) args, argc * sizeof (int));
|
||||
|
||||
for (i = 1; i < argc; i++)
|
||||
{
|
||||
/* If the previous option took an argument, we swallow it here. */
|
||||
if (quote)
|
||||
{
|
||||
quote = NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (argv[i][0] == '\0' || argv[i][1] == '\0')
|
||||
continue;
|
||||
|
||||
if (argv[i][0] == '-')
|
||||
{
|
||||
if (library != 0 && strcmp (argv[i], "-nostdlib") == 0)
|
||||
{
|
||||
library = 0;
|
||||
}
|
||||
else if (strcmp (argv[i], "-lm") == 0
|
||||
|| strcmp (argv[i], "-lmath") == 0)
|
||||
args[i] |= MATHLIB;
|
||||
else if (strcmp (argv[i], "-v") == 0)
|
||||
{
|
||||
verbose = 1;
|
||||
if (argc == 2)
|
||||
{
|
||||
/* If they only gave us `-v', don't try to link
|
||||
in libg++. */
|
||||
library = 0;
|
||||
}
|
||||
}
|
||||
else if (strncmp (argv[i], "-x", 2) == 0)
|
||||
saw_speclang = 1;
|
||||
else if (((argv[i][2] == '\0'
|
||||
&& (char *)strchr ("bBVDUoeTuIYmLiA", argv[i][1]) != NULL)
|
||||
|| strcmp (argv[i], "-Tdata") == 0))
|
||||
quote = argv[i];
|
||||
else if (library != 0 && ((argv[i][2] == '\0'
|
||||
&& (char *) strchr ("cSEM", argv[i][1]) != NULL)
|
||||
|| strcmp (argv[i], "-MM") == 0))
|
||||
{
|
||||
/* Don't specify libraries if we won't link, since that would
|
||||
cause a warning. */
|
||||
library = 0;
|
||||
}
|
||||
else
|
||||
/* Pass other options through. */
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
int len;
|
||||
|
||||
if (saw_speclang)
|
||||
{
|
||||
saw_speclang = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If the filename ends in .c or .i, put options around it.
|
||||
But not if a specified -x option is currently active. */
|
||||
len = strlen (argv[i]);
|
||||
if (len > 2
|
||||
&& (argv[i][len - 1] == 'c' || argv[i][len - 1] == 'i')
|
||||
&& argv[i][len - 2] == '.')
|
||||
{
|
||||
args[i] |= LANGSPEC;
|
||||
added += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (quote)
|
||||
fatal ("argument to `%s' missing\n", quote);
|
||||
|
||||
if (added || library)
|
||||
{
|
||||
arglist = (char **) malloc ((argc + added + 4) * sizeof (char *));
|
||||
|
||||
for (i = 1, j = 1; i < argc; i++, j++)
|
||||
{
|
||||
arglist[j] = argv[i];
|
||||
|
||||
/* Make sure -lg++ is before the math library, since libg++
|
||||
itself uses those math routines. */
|
||||
if (!saw_math && (args[i] & MATHLIB) && library)
|
||||
{
|
||||
--j;
|
||||
saw_math = argv[i];
|
||||
}
|
||||
|
||||
/* Wrap foo.c and foo.i files in a language specification to
|
||||
force the gcc compiler driver to run cc1plus on them. */
|
||||
if (args[i] & LANGSPEC)
|
||||
{
|
||||
int len = strlen (argv[i]);
|
||||
if (argv[i][len - 1] == 'i')
|
||||
arglist[j++] = "-xc++-cpp-output";
|
||||
else
|
||||
arglist[j++] = "-xc++";
|
||||
arglist[j++] = argv[i];
|
||||
arglist[j] = "-xnone";
|
||||
}
|
||||
}
|
||||
|
||||
/* Add `-lg++' if we haven't already done so. */
|
||||
if (library == 2)
|
||||
arglist[j++] = "-lg++";
|
||||
if (library)
|
||||
arglist[j++] = "-lstdc++";
|
||||
if (saw_math)
|
||||
arglist[j++] = saw_math;
|
||||
else if (library)
|
||||
arglist[j++] = MATH_LIBRARY;
|
||||
|
||||
arglist[j] = NULL;
|
||||
}
|
||||
else
|
||||
/* No need to copy 'em all. */
|
||||
arglist = argv;
|
||||
|
||||
arglist[0] = gcc;
|
||||
|
||||
if (verbose)
|
||||
{
|
||||
if (j == 0)
|
||||
j = argc;
|
||||
|
||||
for (i = 0; i < j; i++)
|
||||
fprintf (stderr, " %s", arglist[i]);
|
||||
fprintf (stderr, "\n");
|
||||
}
|
||||
#if !defined(OS2) && !defined (_WIN32)
|
||||
#ifdef __MSDOS__
|
||||
run_dos (gcc, arglist);
|
||||
#else /* !__MSDOS__ */
|
||||
if (execvp (gcc, arglist) < 0)
|
||||
pfatal_with_name (gcc);
|
||||
#endif /* __MSDOS__ */
|
||||
#else /* OS2 or _WIN32 */
|
||||
if (spawnvp (1, gcc, arglist) < 0)
|
||||
pfatal_with_name (gcc);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,752 +0,0 @@
|
||||
\input texinfo @c -*- Texinfo -*-
|
||||
@setfilename reno-1.info
|
||||
|
||||
@ifinfo
|
||||
@format
|
||||
START-INFO-DIR-ENTRY
|
||||
* Reno 1: (reno). The GNU C++ Renovation Project, Phase 1.
|
||||
END-INFO-DIR-ENTRY
|
||||
@end format
|
||||
@end ifinfo
|
||||
|
||||
@ifinfo
|
||||
Copyright @copyright{} 1992, 1993, 1994 Free Software Foundation, Inc.
|
||||
|
||||
Permission is granted to make and distribute verbatim copies of
|
||||
this manual provided the copyright notice and this permission notice
|
||||
are preserved on all copies.
|
||||
|
||||
@ignore
|
||||
Permission is granted to process this file through TeX and print the
|
||||
results, provided the printed document carries a copying permission
|
||||
notice identical to this one except for the removal of this paragraph
|
||||
(this paragraph not being relevant to the printed manual).
|
||||
|
||||
@end ignore
|
||||
|
||||
Permission is granted to copy and distribute modified versions of this
|
||||
manual under the conditions for verbatim copying, provided also that
|
||||
the entire resulting derived work is distributed under the terms of a
|
||||
permission notice identical to this one.
|
||||
|
||||
Permission is granted to copy and distribute translations of this manual
|
||||
into another language, under the above conditions for modified versions.
|
||||
@end ifinfo
|
||||
|
||||
@setchapternewpage odd
|
||||
@settitle GNU C++ Renovation Project
|
||||
@c @smallbook
|
||||
|
||||
@titlepage
|
||||
@finalout
|
||||
@title GNU C++ Renovation Project
|
||||
@subtitle Phase 1.3
|
||||
@author Brendan Kehoe, Jason Merrill,
|
||||
@author Mike Stump, Michael Tiemann
|
||||
@page
|
||||
|
||||
Edited March, 1994 by Roland Pesch (@code{pesch@@cygnus.com})
|
||||
@vskip 0pt plus 1filll
|
||||
Copyright @copyright{} 1992, 1993, 1994 Free Software Foundation, Inc.
|
||||
|
||||
Permission is granted to make and distribute verbatim copies of
|
||||
this manual provided the copyright notice and this permission notice
|
||||
are preserved on all copies.
|
||||
|
||||
@ignore
|
||||
Permission is granted to process this file through Tex and print the
|
||||
results, provided the printed document carries copying permission
|
||||
notice identical to this one except for the removal of this paragraph
|
||||
(this paragraph not being relevant to the printed manual).
|
||||
@end ignore
|
||||
|
||||
Permission is granted to copy and distribute modified versions of this
|
||||
manual under the conditions for verbatim copying, provided also that
|
||||
the entire resulting derived work is distributed under the terms of a
|
||||
permission notice identical to this one.
|
||||
|
||||
Permission is granted to copy and distribute translations of this manual
|
||||
into another language, under the above conditions for modified versions.
|
||||
@end titlepage
|
||||
|
||||
@ifinfo
|
||||
@node Top
|
||||
@top @sc{gnu} C++ Renovation Project
|
||||
|
||||
This file describes the goals of the @sc{gnu} C++ Renovation Project,
|
||||
and its accomplishments to date (as of Phase 1.3).
|
||||
|
||||
It also discusses the remaining divergences from @sc{gnu} C++, and how the
|
||||
name encoding in @sc{gnu} C++ differs from the sample encoding in
|
||||
@cite{The Annotated C++ Reference Manual}.
|
||||
@c This is not a good place to introduce the acronym ARM because it's
|
||||
@c info-only.
|
||||
|
||||
@menu
|
||||
* Introduction:: What is the GNU C++ Renovation Project?
|
||||
* Changes:: Summary of changes since previous GNU C++ releases.
|
||||
* Plans:: Plans for Reno-2.
|
||||
* Templates:: The template implementation.
|
||||
* ANSI:: GNU C++ conformance to ANSI C++.
|
||||
* Encoding:: Name encoding in GNU C++.
|
||||
@end menu
|
||||
|
||||
@end ifinfo
|
||||
|
||||
@node Introduction
|
||||
@chapter Introduction
|
||||
|
||||
As you may remember, @sc{gnu} C++ was the first native-code C++
|
||||
compiler available under Unix (December 1987). In November 1988, it was
|
||||
judged superior to the AT&T compiler in a Unix World review. In 1990 it
|
||||
won a Sun Observer ``Best-Of'' award. But now, with new requirements
|
||||
coming out of the @sc{ansi} C++ committee and a growing backlog of bugs, it's
|
||||
clear that @sc{gnu} C++ needs an overhaul.
|
||||
|
||||
The C++ language has been under development since 1982. It has
|
||||
evolved significantly since its original incarnation (C with Classes),
|
||||
addressing many commercial needs and incorporating many lessons
|
||||
learned as more and more people started using ``object-oriented''
|
||||
programming techniques. In 1989, the first X3J16 committee meeting
|
||||
was held in Washington DC; in the interest of users, C++ was going to
|
||||
be standardized.
|
||||
|
||||
As C++ has become more popular, more demands have been placed on its
|
||||
compilers. Some compilers are up to the demands, others are not.
|
||||
@sc{gnu} C++ was used to prototype several features which have since
|
||||
been incorporated into the standard, most notably exception handling.
|
||||
While @sc{gnu} C++ has been an excellent experimental vehicle, it did
|
||||
not have the resources that AT&T, Borland, or Microsoft have at their
|
||||
disposal.
|
||||
|
||||
We believe that @sc{gnu} C++ is an important compiler, providing users with
|
||||
many of the features that have made @sc{gnu} C so popular: fast compilation,
|
||||
good error messages, innovative features, and full sources that may be
|
||||
freely redistributed. The purpose of this overhaul, dubbed the @var{@sc{gnu}
|
||||
C++ Renovation Project}, is to take advantage of the functionality that
|
||||
@sc{gnu} C++ offers today, to strengthen its base technology, and put it in a
|
||||
position to remain---as other @sc{gnu} software currently is---the technical
|
||||
leader in the field.
|
||||
|
||||
This release represents the latest phase of work in strengthening the
|
||||
compiler on a variety of points. It includes many months of
|
||||
work concentrated on fixing many of the more egregious bugs that
|
||||
presented themselves in the compiler recently.
|
||||
@ignore
|
||||
@c FIXME-- update?
|
||||
Nearly 85% of all bugs reported in the period of February to September
|
||||
of 1992 were fixed as part of the work in the first phase.
|
||||
@end ignore
|
||||
In the coming months, we hope to continue expanding and enhancing the
|
||||
quality and dependability of the industry's only freely redistributable
|
||||
C++ compiler.
|
||||
|
||||
@node Changes
|
||||
@chapter Changes in Behavior in @sc{gnu} C++
|
||||
|
||||
The @sc{gnu} C++ compiler continues to improve and change. A major goal
|
||||
of our work has been to continue to bring the compiler into compliance
|
||||
with the draft @sc{ansi} C++ standard, and with @cite{The Annotated C++
|
||||
Reference Manual} (the @sc{arm}). This section outlines most of the
|
||||
user-noticeable changes that might be encountered during the normal
|
||||
course of use.
|
||||
|
||||
@menu
|
||||
* Summary of Phase 1.3::
|
||||
* Major changes::
|
||||
* New features::
|
||||
* Enhancements and bug fixes::
|
||||
* Problems with debugging::
|
||||
@end menu
|
||||
|
||||
@node Summary of Phase 1.3
|
||||
@section Summary of Changes in Phase 1.3
|
||||
|
||||
The bulk of this note discusses the cumulative effects of the @sc{gnu} C++
|
||||
Renovation Project to date. The work during its most recent phase (1.3)
|
||||
had these major effects:
|
||||
|
||||
@itemize @bullet
|
||||
@item The standard compiler driver @code{g++} is now the faster compiled
|
||||
version, rather than a shell script.
|
||||
|
||||
@item Nested types work much better; notably, nesting is no longer
|
||||
restricted to nine levels.
|
||||
|
||||
@item Better @sc{arm} conformance on member access control.
|
||||
|
||||
@item The compiler now always generates default assignment operators
|
||||
(@samp{operator =}), copy constructors (@samp{X::X(X&)}), and default
|
||||
constructors (@samp{X::X()}) whenever they are required.
|
||||
|
||||
@item The new draft @sc{ansi} standard keyword @code{mutable} is supported.
|
||||
|
||||
@item @samp{-fansi-overloading} is the default, to comply better with
|
||||
the @sc{arm} (at some cost in compatibility to earlier versions of @sc{gnu} C++).
|
||||
|
||||
@item More informative error messages.
|
||||
|
||||
@item System include files are automatically treated as if they were
|
||||
wrapped in @samp{extern "C" @{ @}}.
|
||||
|
||||
@item The new option @samp{-falt-external-templates} provides alternate
|
||||
template instantiation semantics.
|
||||
|
||||
@item Operator declarations are now checked more strictly.
|
||||
|
||||
@item You can now use template type arguments in the template parameter list.
|
||||
|
||||
@item You can call the destructor for any type.
|
||||
|
||||
@item The compiler source code is better organized.
|
||||
|
||||
@item You can specify where to instantiate template definitions explicitly.
|
||||
@end itemize
|
||||
|
||||
Much of the work in Phase 1.3 went to elimination of known bugs, as well
|
||||
as the major items above.
|
||||
|
||||
During the span of Phase 1.3, there were also two changes associated
|
||||
with the compiler that, while not specifically part of the C++
|
||||
Renovation project, may be of interest:
|
||||
|
||||
@itemize @bullet
|
||||
@item @code{gcov}, a code coverage tool for @sc{gnu cc}, is now available
|
||||
from Cygnus Support. (@code{gcov} is free software, but the @sc{fsf} has not
|
||||
yet accepted it.) @xref{Gcov,, @code{gcov}: a Test Coverage Program,
|
||||
gcc.info, Using GNU CC}, for more information (in Cygnus releases of
|
||||
that manual).
|
||||
|
||||
@item @sc{gnu} C++ now supports @dfn{signatures}, a language extension to
|
||||
provide more flexibility in abstract type definitions. @xref{C++
|
||||
Signatures,, Type Abstraction using Signatures, gcc.info, Using GNU CC}.
|
||||
@end itemize
|
||||
|
||||
@node Major changes
|
||||
@section Major Changes
|
||||
|
||||
This release includes four wholesale rewrites of certain areas of
|
||||
compiler functionality:
|
||||
|
||||
@enumerate 1
|
||||
@item Argument matching. @sc{gnu} C++ is more compliant with the rules
|
||||
described in Chapter 13, ``Overloading'', of the @sc{arm}. This behavior is
|
||||
the default, though you can specify it explicitly with
|
||||
@samp{-fansi-overloading}. For compatibility with earlier releases of
|
||||
@sc{gnu} C++, specify @samp{-fno-ansi-overloading}; this makes the compiler
|
||||
behave as it used to with respect to argument matching and name overloading.
|
||||
|
||||
@item Default constructors/destructors. Section 12.8 of the @sc{arm}, ``Copying
|
||||
Class Objects'', and Section 12.1, ``Constructors'', state that a
|
||||
compiler must declare such default functions if the user does not
|
||||
specify them. @sc{gnu} C++ now declares, and generates when necessary,
|
||||
the defaults for constructors and destructors you might omit. In
|
||||
particular, assignment operators (@samp{operator =}) behave the same way
|
||||
whether you define them, or whether the compiler generates them by
|
||||
default; taking the address of the default @samp{operator =} is now
|
||||
guaranteed to work. Default copy constructors (@samp{X::X(X&)}) now
|
||||
function correctly, rather than calling the copy assignment operator for
|
||||
the base class. Finally, constructors (@samp{X::X()}), as well as
|
||||
assignment operators and copy constructors, are now available whenever
|
||||
they are required.
|
||||
|
||||
@c XXX This may be taken out eventually...
|
||||
@item Binary incompatibility. There are no new binary incompatibilities
|
||||
in Phase 1.3, but Phase 1.2 introduced two binary incompatibilities with
|
||||
earlier releases. First, the functionality of @samp{operator
|
||||
new} and @samp{operator delete} changed. Name encoding
|
||||
(``mangling'') of virtual table names changed as well. Libraries
|
||||
built with versions of the compiler earlier than Phase 1.2 must be
|
||||
compiled with the new compiler. (This includes the Cygnus Q2
|
||||
progressive release and the FSF 2.4.5 release.)
|
||||
|
||||
@item New @code{g++} driver.
|
||||
A new binary @code{g++} compiler driver replaces the shell script.
|
||||
The new driver executes faster.
|
||||
@end enumerate
|
||||
|
||||
@node New features
|
||||
@section New features
|
||||
|
||||
@itemize @bullet
|
||||
@item
|
||||
The compiler warns when a class contains only private constructors
|
||||
or destructors, and has no friends. At the request of some of our
|
||||
customers, we have added a new option, @samp{-Wctor-dtor-privacy} (on by
|
||||
default), and its negation, @samp{-Wno-ctor-dtor-privacy}, to control
|
||||
the emission of this warning. If, for example, you are working towards
|
||||
making your code compile warning-free, you can use @w{@samp{-Wall
|
||||
-Wno-ctor-dtor-privacy}} to find the most common warnings.
|
||||
|
||||
@item
|
||||
There is now a mechanism which controls exactly when templates are
|
||||
expanded, so that you can reduce memory usage and program size and also
|
||||
instantiate them exactly once. You can control this mechanism with the
|
||||
option @samp{-fexternal-templates} and its corresponding negation
|
||||
@samp{-fno-external-templates}. Without this feature, space consumed by
|
||||
template instantiations can grow unacceptably in large-scale projects
|
||||
with many different source files. The default is
|
||||
@samp{-fno-external-templates}.
|
||||
|
||||
You do not need to use the @samp{-fexternal-templates} option when
|
||||
compiling a file that does not define and instantiate templates used in
|
||||
other files, even if those files @emph{are} compiled with
|
||||
@samp{-fexternal-templates}. The only side effect is an increase in
|
||||
object size for each file that was compiled without
|
||||
@samp{-fexternal-templates}.
|
||||
|
||||
When your code is compiled with @samp{-fexternal-templates}, all
|
||||
template instantiations are external; this requires that the templates
|
||||
be under the control of @samp{#pragma interface} and @samp{#pragma
|
||||
implementation}. All instantiations that will be needed should be in
|
||||
the implementation file; you can do this with a @code{typedef} that
|
||||
references the instantiation needed. Conversely, when you compile using
|
||||
the option @samp{-fno-external-templates}, all template instantiations are
|
||||
explicitly internal.
|
||||
|
||||
@samp{-fexternal-templates} also allows you to finally separate class
|
||||
template function definitions from their declarations, thus speeding up
|
||||
compilation times for every file that includes the template declaration.
|
||||
Now you can have tens or even hundreds of lines in template
|
||||
declarations, and thousands or tens of thousands of lines in template
|
||||
definitions, with the definitions only going through the compiler once
|
||||
instead of once for each source file. It is important to note that you
|
||||
must remember to externally instantiate @emph{all} templates that are
|
||||
used from template declarations in interface files. If you forget to do
|
||||
this, unresolved externals will occur.
|
||||
|
||||
In the example below, the object file generated (@file{example.o}) will
|
||||
contain the global instantiation for @samp{Stack<int>}. If other types
|
||||
of @samp{Stack} are needed, they can be added to @file{example.cc} or
|
||||
placed in a new file, in the same spirit as @file{example.cc}.
|
||||
|
||||
@code{foo.h}:
|
||||
@smallexample
|
||||
@group
|
||||
#pragma interface "foo.h"
|
||||
template<class T>
|
||||
class Stack @{
|
||||
static int statc;
|
||||
static T statc2;
|
||||
Stack() @{ @}
|
||||
virtual ~Stack() @{ @}
|
||||
int bar();
|
||||
@};
|
||||
@end group
|
||||
@end smallexample
|
||||
|
||||
@code{example.cc}:
|
||||
@smallexample
|
||||
@group
|
||||
#pragma implementation "foo.h"
|
||||
#include "foo.h"
|
||||
|
||||
typedef Stack<int> t;
|
||||
int Stack<int>::statc;
|
||||
int Stack<int>::statc2;
|
||||
int Stack<int>::bar() @{ @}
|
||||
@end group
|
||||
@end smallexample
|
||||
|
||||
Note that using @samp{-fexternal-templates} does not reduce memory usage
|
||||
from completely different instantiations (@samp{Stack<Name>} vs.
|
||||
@samp{Stack<Net_Connection>}), but only collapses different occurrences
|
||||
of @samp{Stack<Name>} so that only one @samp{Stack<Name>} is generated.
|
||||
|
||||
@samp{-falt-external-templates} selects a slight variation in the
|
||||
semantics described above (incidentally, you need not specify both
|
||||
options; @samp{-falt-external-templates} implies
|
||||
@samp{-fexternal-templates}).
|
||||
|
||||
With @samp{-fexternal-templates}, the compiler emits a definition in the
|
||||
implementation file that includes the header definition, @emph{even if}
|
||||
instantiation is triggered from a @emph{different} implementation file
|
||||
(e.g. with a template that uses another template).
|
||||
|
||||
With @samp{-falt-external-templates}, the definition always goes in the
|
||||
implementation file that triggers instantiation.
|
||||
|
||||
For instance, with these two header files---
|
||||
|
||||
@example
|
||||
@exdent @file{a.h}:
|
||||
#pragma interface
|
||||
template <class T> class A @{ @dots{} @};
|
||||
|
||||
@exdent @file{b.h}:
|
||||
#pragma interface
|
||||
class B @{ @dots{} @};
|
||||
void f (A<B>);
|
||||
@end example
|
||||
|
||||
Under @samp{-fexternal-templates}, the definition of @samp{A<B>} ends up
|
||||
in the implementation file that includes @file{a.h}. Under
|
||||
@samp{-falt-external-templates}, the same definition ends up in the
|
||||
implementation file that includes @file{b.h}.
|
||||
|
||||
@item
|
||||
You can control explicitly where a template is instantiated, without
|
||||
having to @emph{use} the template to get an instantiation.
|
||||
|
||||
To instantiate a class template explicitly, write @samp{template
|
||||
class @var{name}<paramvals>}, where @var{paramvals} is a list of values
|
||||
for the template parameters. For example, you might write
|
||||
|
||||
@example
|
||||
template class A<int>
|
||||
@end example
|
||||
|
||||
Similarly, to instantiate a function template explicitly, write
|
||||
@samp{template @var{fnsign}} where @var{fnsign} is the particular
|
||||
function signature you need. For example, you might write
|
||||
|
||||
@example
|
||||
template void foo (int, int)
|
||||
@end example
|
||||
|
||||
This syntax for explicit template instantiation agrees with recent
|
||||
extensions to the draft @sc{ansi} standard.
|
||||
|
||||
@item
|
||||
The compiler's actions on @sc{ansi}-related warnings and errors have
|
||||
been further enhanced. The @samp{-pedantic-errors} option produces
|
||||
error messages in a number of new situations: using @code{return} in a
|
||||
non-@code{void} function (one returning a value); declaring a local
|
||||
variable that shadows a parameter (e.g., the function takes an argument
|
||||
@samp{a}, and has a local variable @samp{a}); and use of the @samp{asm}
|
||||
keyword. Finally, the compiler by default now issues a warning when
|
||||
converting from an @code{int} to an enumerated type. This is likely to
|
||||
cause many new warnings in code that hadn't triggered them before. For
|
||||
example, when you compile this code,
|
||||
|
||||
@smallexample
|
||||
@group
|
||||
enum boolean @{ false, true @};
|
||||
void
|
||||
f ()
|
||||
@{
|
||||
boolean x;
|
||||
|
||||
x = 1; //@i{assigning an @code{int} to an @code{enum} now triggers a warning}
|
||||
@}
|
||||
@end group
|
||||
@end smallexample
|
||||
|
||||
@noindent
|
||||
you should see the warning ``@code{anachronistic conversion from integer
|
||||
type to enumeral type `boolean'}''. Instead of assigning the value 1,
|
||||
assign the original enumerated value @samp{true}.
|
||||
@end itemize
|
||||
|
||||
@node Enhancements and bug fixes
|
||||
@section Enhancements and bug fixes
|
||||
|
||||
@itemize @bullet
|
||||
@cindex nested types in template parameters
|
||||
@item
|
||||
You can now use nested types in a template parameter list, even if the nested
|
||||
type is defined within the same class that attempts to use the template.
|
||||
For example, given a template @code{list}, the following now works:
|
||||
|
||||
@smallexample
|
||||
struct glyph @{
|
||||
@dots{}
|
||||
struct stroke @{ @dots{} @};
|
||||
list<stroke> l;
|
||||
@dots{}
|
||||
@}
|
||||
@end smallexample
|
||||
|
||||
@cindex function pointers vs template parameters
|
||||
@item
|
||||
Function pointers now work in template parameter lists. For
|
||||
example, you might want to instantiate a parameterized @code{list} class
|
||||
in terms of a pointer to a function like this:
|
||||
|
||||
@smallexample
|
||||
list<int (*)(int, void *)> fnlist;
|
||||
@end smallexample
|
||||
|
||||
@item
|
||||
@c FIXME! Really no limit? Jason said "deeper than 9" now OK...
|
||||
Nested types are now handled correctly. In particular, there is no
|
||||
longer a limit to how deeply you can nest type definitions.
|
||||
|
||||
@item
|
||||
@sc{gnu} C++ now conforms to the specifications in Chapter 11 of the
|
||||
@sc{arm}, ``Member Access Control''.
|
||||
|
||||
@item
|
||||
The @sc{ansi} C++ committee has introduced a new keyword @code{mutable}.
|
||||
@sc{gnu} C++ supports it. Use @code{mutable} to specify that some
|
||||
particular members of a @code{const} class are @emph{not} constant. For
|
||||
example, you can use this to include a cache in a data structure that
|
||||
otherwise represents a read-only database.
|
||||
|
||||
@item
|
||||
Error messages now explicitly specify the declaration, type, or
|
||||
expression that contains an error.
|
||||
|
||||
@item
|
||||
To avoid copying and editing all system include files during @sc{gnu}
|
||||
C++ installation, the compiler now automatically recognizes system
|
||||
include files as C language definitions, as if they were wrapped in
|
||||
@samp{extern "C" @{ @dots{} @}}.
|
||||
|
||||
@item
|
||||
The compiler checks operator declarations more strictly. For example,
|
||||
you may no longer declare an @samp{operator +} with three arguments.
|
||||
|
||||
@item
|
||||
You can now use template type arguments in the same template
|
||||
parameter list where the type argument is specified (as well as in the
|
||||
template body). For example, you may write
|
||||
|
||||
@example
|
||||
template <class T, T t> class A @{ @dots{} @};
|
||||
@end example
|
||||
|
||||
@item
|
||||
Destructors are now available for all types, even built-in ones; for
|
||||
example, you can call @samp{int::~int}. (Destructors for types like
|
||||
@code{int} do not actually do anything, but their existence provides a
|
||||
level of generality that permits smooth template expansion in more
|
||||
cases.)
|
||||
|
||||
@item
|
||||
Enumerated types declared inside a class are now handled correctly.
|
||||
|
||||
@item
|
||||
An argument list for a function may not use an initializer list for its default
|
||||
value. For example, @w{@samp{void foo ( T x = @{ 1, 2 @} )}} is not permitted.
|
||||
|
||||
@item
|
||||
A significant amount of work went into improving the ability of the
|
||||
compiler to act accurately on multiple inheritance and virtual
|
||||
functions. Virtual function dispatch has been enhanced as well.
|
||||
|
||||
@item
|
||||
The warning concerning a virtual inheritance environment with a
|
||||
non-virtual destructor has been disabled, since it is not clear that
|
||||
such a warning is warranted.
|
||||
|
||||
@item
|
||||
Until exception handling is fully implemented in the Reno-2 release, use
|
||||
of the identifiers @samp{catch}, @samp{throw}, or @samp{try} results
|
||||
in the warning:
|
||||
|
||||
@smallexample
|
||||
t.C:1: warning: `catch', `throw', and `try'
|
||||
are all C++ reserved words
|
||||
@end smallexample
|
||||
|
||||
@item
|
||||
When giving a warning or error concerning initialization of a member in a
|
||||
class, the compiler gives the name of the member if it has one.
|
||||
|
||||
@item
|
||||
Detecting friendship between classes is more accurately checked.
|
||||
|
||||
@item
|
||||
The syntaxes of @w{@samp{#pragma implementation "file.h"}} and
|
||||
@samp{#pragma interface} are now more strictly controlled. The compiler
|
||||
notices (and warns) when any text follows @file{file.h} in the
|
||||
implementation pragma, or follows the word @samp{interface}. Any such
|
||||
text is otherwise ignored.
|
||||
|
||||
@item
|
||||
Trying to declare a template on a variable or type is now considered an
|
||||
error, not an unimplemented feature.
|
||||
|
||||
@item
|
||||
When an error occurs involving a template, the compiler attempts to
|
||||
tell you at which point of instantiation the error occurred, in
|
||||
addition to noting the line in the template declaration which had the
|
||||
actual error.
|
||||
|
||||
@item
|
||||
The symbol names for function templates in the resulting assembly file
|
||||
are now encoded according to the arguments, rather than just being
|
||||
emitted as, for example, two definitions of a function @samp{foo}.
|
||||
|
||||
@item
|
||||
Template member functions that are declared @code{static} no longer
|
||||
receive a @code{this} pointer.
|
||||
|
||||
@item
|
||||
Case labels are no longer allowed to have commas to make up their
|
||||
expressions.
|
||||
|
||||
@item
|
||||
Warnings concerning the shift count of a left or right shift now tell
|
||||
you if it was a @samp{left} or @samp{right} shift.
|
||||
|
||||
@item
|
||||
The compiler now warns when a decimal constant is so large that it
|
||||
becomes @code{unsigned}.
|
||||
|
||||
@item
|
||||
Union initializers which are raw constructors are now handled properly.
|
||||
|
||||
@item
|
||||
The compiler no longer gives incorrect errors when initializing a
|
||||
union with an empty initializer list.
|
||||
|
||||
@item
|
||||
Anonymous unions are now correctly used when nested inside a class.
|
||||
|
||||
@item
|
||||
Anonymous unions declared as static class members are now handled
|
||||
properly.
|
||||
|
||||
@item
|
||||
The compiler now notices when a field in a class is declared both as
|
||||
a type and a non-type.
|
||||
|
||||
@item
|
||||
The compiler now warns when a user-defined function shadows a
|
||||
built-in function, rather than emitting an error.
|
||||
|
||||
@item
|
||||
A conflict between two function declarations now produces an error
|
||||
regardless of their language context.
|
||||
|
||||
@item
|
||||
Duplicate definitions of variables with @samp{extern "C"} linkage are no
|
||||
longer considered in error. (Note in C++ linkage---the default---you may
|
||||
not have more than one definition of a variable.)
|
||||
|
||||
@item
|
||||
Referencing a label that is not defined in any function is now an error.
|
||||
|
||||
@item
|
||||
The syntax for pointers to methods has been improved; there are still
|
||||
some minor bugs, but a number of cases should now be accepted by the
|
||||
compiler.
|
||||
|
||||
@item
|
||||
In error messages, arguments are now numbered starting at 1, instead of
|
||||
0. Therefore, in the function @samp{void foo (int a, int b)}, the
|
||||
argument @samp{a} is argument 1, and @samp{b} is argument 2. There is
|
||||
no longer an argument 0.
|
||||
|
||||
@item
|
||||
The tag for an enumerator, rather than its value, used as a default
|
||||
argument is now shown in all error messages. For example, @w{@samp{void
|
||||
foo (enum x (= true))}} is shown instead of @w{@samp{void foo (enum x (=
|
||||
1))}}.
|
||||
|
||||
@item
|
||||
The @samp{__asm__} keyword is now accepted by the C++ front-end.
|
||||
|
||||
@item
|
||||
Expressions of the form @samp{foo->~Class()} are now handled properly.
|
||||
|
||||
@item
|
||||
The compiler now gives better warnings for situations which result in
|
||||
integer overflows (e.g., in storage sizes, enumerators, unary
|
||||
expressions, etc).
|
||||
|
||||
@item
|
||||
@code{unsigned} bitfields are now promoted to @code{signed int} if the
|
||||
field isn't as wide as an @code{int}.
|
||||
|
||||
@item
|
||||
Declaration and usage of prefix and postfix @samp{operator ++} and
|
||||
@samp{operator --} are now handled correctly. For example,
|
||||
|
||||
@smallexample
|
||||
@group
|
||||
class foo
|
||||
@{
|
||||
public:
|
||||
operator ++ ();
|
||||
operator ++ (int);
|
||||
operator -- ();
|
||||
operator -- (int);
|
||||
@};
|
||||
|
||||
void
|
||||
f (foo *f)
|
||||
@{
|
||||
f++; // @i{call @code{f->operator++(int)}}
|
||||
++f; // @i{call @code{f->operator++()}}
|
||||
f--; // @i{call @code{f->operator++(int)}}
|
||||
--f; // @i{call @code{f->operator++()}}
|
||||
@}
|
||||
@end group
|
||||
@end smallexample
|
||||
|
||||
@item
|
||||
In accordance with @sc{arm} section 10.1.1, ambiguities and dominance are now
|
||||
handled properly. The rules described in section 10.1.1 are now fully
|
||||
implemented.
|
||||
|
||||
@end itemize
|
||||
|
||||
@node Problems with debugging
|
||||
@section Problems with debugging
|
||||
|
||||
Two problems remain with regard to debugging:
|
||||
|
||||
@itemize @bullet
|
||||
@item
|
||||
Debugging of anonymous structures on the IBM RS/6000 host is incorrect.
|
||||
|
||||
@item
|
||||
Symbol table size is overly large due to redundant symbol information;
|
||||
this can make @code{gdb} coredump under certain circumstances. This
|
||||
problem is not host-specific.
|
||||
@end itemize
|
||||
|
||||
@node Plans
|
||||
@chapter Plans for Reno-2
|
||||
|
||||
The overall goal for the second phase of the @sc{gnu} C++ Renovation
|
||||
Project is to bring @sc{gnu} C++ to a new level of reliability, quality,
|
||||
and competitiveness. As particular elements of this strategy, we intend
|
||||
to:
|
||||
|
||||
@enumerate 0
|
||||
@item
|
||||
Fully implement @sc{ansi} exception handling.
|
||||
|
||||
@item
|
||||
With the exception handling, add Runtime Type Identification
|
||||
(@sc{rtti}), if the @sc{ansi} committee adopts it into the standard.
|
||||
|
||||
@item
|
||||
Bring the compiler into closer compliance with the @sc{arm} and the draft
|
||||
@sc{ansi} standard, and document what points in the @sc{arm} we do not yet comply,
|
||||
or agree, with.
|
||||
|
||||
@item
|
||||
Add further support for the @sc{dwarf} debugging format.
|
||||
|
||||
@item
|
||||
Finish the work to make the compiler compliant with @sc{arm} Section 12.6.2,
|
||||
initializing base classes in declaration order, rather than in the order
|
||||
that you specify them in a @var{mem-initializer} list.
|
||||
|
||||
@item
|
||||
Perform a full coverage analysis on the compiler, and weed out unused
|
||||
code, for a gain in performance and a reduction in the size of the compiler.
|
||||
|
||||
@item
|
||||
Further improve the multiple inheritance implementation in the
|
||||
compiler to make it cleaner and more complete.
|
||||
@end enumerate
|
||||
|
||||
@noindent
|
||||
As always, we encourage you to make suggestions and ask questions about
|
||||
@sc{gnu} C++ as a whole, so we can be sure that the end of this project
|
||||
will bring a compiler that everyone will find essential for C++ and will
|
||||
meet the needs of the world's C++ community.
|
||||
|
||||
@include templates.texi
|
||||
|
||||
@include gpcompare.texi
|
||||
|
||||
@contents
|
||||
|
||||
@bye
|
@ -1706,9 +1706,9 @@ static void
|
||||
profile_function (file)
|
||||
FILE *file;
|
||||
{
|
||||
#ifndef NO_PROFILE_DATA
|
||||
#ifndef NO_PROFILE_COUNTERS
|
||||
int align = MIN (BIGGEST_ALIGNMENT, LONG_TYPE_SIZE);
|
||||
#endif /* not NO_PROFILE_DATA */
|
||||
#endif
|
||||
#if defined(ASM_OUTPUT_REG_PUSH)
|
||||
#if defined(STRUCT_VALUE_INCOMING_REGNUM) || defined(STRUCT_VALUE_REGNUM)
|
||||
int sval = current_function_returns_struct;
|
||||
@ -1718,12 +1718,12 @@ profile_function (file)
|
||||
#endif
|
||||
#endif /* ASM_OUTPUT_REG_PUSH */
|
||||
|
||||
#ifndef NO_PROFILE_DATA
|
||||
#ifndef NO_PROFILE_COUNTERS
|
||||
data_section ();
|
||||
ASM_OUTPUT_ALIGN (file, floor_log2 (align / BITS_PER_UNIT));
|
||||
ASM_OUTPUT_INTERNAL_LABEL (file, "LP", profile_label_no);
|
||||
assemble_integer (const0_rtx, LONG_TYPE_SIZE / BITS_PER_UNIT, 1);
|
||||
#endif /* not NO_PROFILE_DATA */
|
||||
#endif
|
||||
|
||||
function_section (current_function_decl);
|
||||
|
||||
@ -3115,7 +3115,7 @@ alter_subreg (x)
|
||||
PUT_CODE (x, MEM);
|
||||
MEM_COPY_ATTRIBUTES (x, y);
|
||||
MEM_ALIAS_SET (x) = MEM_ALIAS_SET (y);
|
||||
XEXP (x, 0) = plus_constant (XEXP (y, 0), offset);
|
||||
XEXP (x, 0) = plus_constant_for_output (XEXP (y, 0), offset);
|
||||
}
|
||||
|
||||
return x;
|
||||
|
@ -1,653 +0,0 @@
|
||||
/* GNU Objective C Runtime message lookup
|
||||
Copyright (C) 1993, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
|
||||
Contributed by Kresten Krab Thorup
|
||||
|
||||
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. */
|
||||
|
||||
/* As a special exception, if you link this library with files compiled with
|
||||
GCC to produce an executable, this does not cause the resulting executable
|
||||
to be covered by the GNU General Public License. This exception does not
|
||||
however invalidate any other reasons why the executable file might be
|
||||
covered by the GNU General Public License. */
|
||||
|
||||
/* $FreeBSD$ */
|
||||
|
||||
#include "../tconfig.h"
|
||||
#include "runtime.h"
|
||||
#include "sarray.h"
|
||||
#include "encoding.h"
|
||||
#include "runtime-info.h"
|
||||
|
||||
/* this is how we hack STRUCT_VALUE to be 1 or 0 */
|
||||
#define gen_rtx(args...) 1
|
||||
#define gen_rtx_MEM(args...) 1
|
||||
#define rtx int
|
||||
|
||||
#if !defined(STRUCT_VALUE) || STRUCT_VALUE == 0
|
||||
#define INVISIBLE_STRUCT_RETURN 1
|
||||
#else
|
||||
#define INVISIBLE_STRUCT_RETURN 0
|
||||
#endif
|
||||
|
||||
/* The uninstalled dispatch table */
|
||||
struct sarray* __objc_uninstalled_dtable = 0; /* !T:MUTEX */
|
||||
|
||||
/* Send +initialize to class */
|
||||
static void __objc_send_initialize(Class);
|
||||
|
||||
static void __objc_install_dispatch_table_for_class (Class);
|
||||
|
||||
/* Forward declare some functions */
|
||||
static void __objc_init_install_dtable(id, SEL);
|
||||
|
||||
/* Various forwarding functions that are used based upon the
|
||||
return type for the selector.
|
||||
__objc_block_forward for structures.
|
||||
__objc_double_forward for floats/doubles.
|
||||
__objc_word_forward for pointers or types that fit in registers.
|
||||
*/
|
||||
static double __objc_double_forward(id, SEL, ...);
|
||||
static id __objc_word_forward(id, SEL, ...);
|
||||
typedef struct { id many[8]; } __big;
|
||||
#if INVISIBLE_STRUCT_RETURN
|
||||
static __big
|
||||
#else
|
||||
static id
|
||||
#endif
|
||||
__objc_block_forward(id, SEL, ...);
|
||||
static Method_t search_for_method_in_hierarchy (Class class, SEL sel);
|
||||
Method_t search_for_method_in_list(MethodList_t list, SEL op);
|
||||
id nil_method(id, SEL, ...);
|
||||
|
||||
/* Given a selector, return the proper forwarding implementation. */
|
||||
__inline__
|
||||
IMP
|
||||
__objc_get_forward_imp (SEL sel)
|
||||
{
|
||||
const char *t = sel->sel_types;
|
||||
|
||||
if (t && (*t == '[' || *t == '(' || *t == '{')
|
||||
#ifdef OBJC_MAX_STRUCT_BY_VALUE
|
||||
&& objc_sizeof_type(t) > OBJC_MAX_STRUCT_BY_VALUE
|
||||
#endif
|
||||
)
|
||||
return (IMP)__objc_block_forward;
|
||||
else if (t && (*t == 'f' || *t == 'd'))
|
||||
return (IMP)__objc_double_forward;
|
||||
else
|
||||
return (IMP)__objc_word_forward;
|
||||
}
|
||||
|
||||
/* Given a class and selector, return the selector's implementation. */
|
||||
__inline__
|
||||
IMP
|
||||
get_imp (Class class, SEL sel)
|
||||
{
|
||||
void* res = sarray_get_safe (class->dtable, (size_t) sel->sel_id);
|
||||
if (res == 0)
|
||||
{
|
||||
/* Not a valid method */
|
||||
if(class->dtable == __objc_uninstalled_dtable)
|
||||
{
|
||||
/* The dispatch table needs to be installed. */
|
||||
objc_mutex_lock(__objc_runtime_mutex);
|
||||
__objc_install_dispatch_table_for_class (class);
|
||||
objc_mutex_unlock(__objc_runtime_mutex);
|
||||
/* Call ourselves with the installed dispatch table
|
||||
and get the real method */
|
||||
res = get_imp(class, sel);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The dispatch table has been installed so the
|
||||
method just doesn't exist for the class.
|
||||
Return the forwarding implementation. */
|
||||
res = __objc_get_forward_imp(sel);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Query if an object can respond to a selector, returns YES if the
|
||||
object implements the selector otherwise NO. Does not check if the
|
||||
method can be forwarded. */
|
||||
__inline__
|
||||
BOOL
|
||||
__objc_responds_to (id object, SEL sel)
|
||||
{
|
||||
void* res;
|
||||
|
||||
/* Install dispatch table if need be */
|
||||
if (object->class_pointer->dtable == __objc_uninstalled_dtable)
|
||||
{
|
||||
objc_mutex_lock(__objc_runtime_mutex);
|
||||
__objc_install_dispatch_table_for_class (object->class_pointer);
|
||||
objc_mutex_unlock(__objc_runtime_mutex);
|
||||
}
|
||||
|
||||
/* Get the method from the dispatch table */
|
||||
res = sarray_get_safe (object->class_pointer->dtable, (size_t) sel->sel_id);
|
||||
return (res != 0);
|
||||
}
|
||||
|
||||
/* This is the lookup function. All entries in the table are either a
|
||||
valid method *or* zero. If zero then either the dispatch table
|
||||
needs to be installed or it doesn't exist and forwarding is attempted. */
|
||||
__inline__
|
||||
IMP
|
||||
objc_msg_lookup(id receiver, SEL op)
|
||||
{
|
||||
IMP result;
|
||||
if(receiver)
|
||||
{
|
||||
result = sarray_get_safe (receiver->class_pointer->dtable,
|
||||
(sidx)op->sel_id);
|
||||
if (result == 0)
|
||||
{
|
||||
/* Not a valid method */
|
||||
if(receiver->class_pointer->dtable == __objc_uninstalled_dtable)
|
||||
{
|
||||
/* The dispatch table needs to be installed.
|
||||
This happens on the very first method call to the class. */
|
||||
__objc_init_install_dtable(receiver, op);
|
||||
|
||||
/* Get real method for this in newly installed dtable */
|
||||
result = get_imp(receiver->class_pointer, op);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The dispatch table has been installed so the
|
||||
method just doesn't exist for the class.
|
||||
Attempt to forward the method. */
|
||||
result = __objc_get_forward_imp(op);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
else
|
||||
return nil_method;
|
||||
}
|
||||
|
||||
IMP
|
||||
objc_msg_lookup_super (Super_t super, SEL sel)
|
||||
{
|
||||
if (super->self)
|
||||
return get_imp (super->class, sel);
|
||||
else
|
||||
return nil_method;
|
||||
}
|
||||
|
||||
int method_get_sizeof_arguments (Method*);
|
||||
|
||||
retval_t
|
||||
objc_msg_sendv(id object, SEL op, arglist_t arg_frame)
|
||||
{
|
||||
Method* m = class_get_instance_method(object->class_pointer, op);
|
||||
const char *type;
|
||||
*((id*)method_get_first_argument (m, arg_frame, &type)) = object;
|
||||
*((SEL*)method_get_next_argument (arg_frame, &type)) = op;
|
||||
return __builtin_apply((apply_t)m->method_imp,
|
||||
arg_frame,
|
||||
method_get_sizeof_arguments (m));
|
||||
}
|
||||
|
||||
void
|
||||
__objc_init_dispatch_tables()
|
||||
{
|
||||
__objc_uninstalled_dtable
|
||||
= sarray_new(200, 0);
|
||||
}
|
||||
|
||||
/* This function is called by objc_msg_lookup when the
|
||||
dispatch table needs to be installed; thus it is called once
|
||||
for each class, namely when the very first message is sent to it. */
|
||||
static void
|
||||
__objc_init_install_dtable(id receiver, SEL op)
|
||||
{
|
||||
/* This may happen, if the programmer has taken the address of a
|
||||
method before the dtable was initialized... too bad for him! */
|
||||
if(receiver->class_pointer->dtable != __objc_uninstalled_dtable)
|
||||
return;
|
||||
|
||||
objc_mutex_lock(__objc_runtime_mutex);
|
||||
|
||||
if(CLS_ISCLASS(receiver->class_pointer))
|
||||
{
|
||||
/* receiver is an ordinary object */
|
||||
assert(CLS_ISCLASS(receiver->class_pointer));
|
||||
|
||||
/* install instance methods table */
|
||||
__objc_install_dispatch_table_for_class (receiver->class_pointer);
|
||||
|
||||
/* call +initialize -- this will in turn install the factory
|
||||
dispatch table if not already done :-) */
|
||||
__objc_send_initialize(receiver->class_pointer);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* receiver is a class object */
|
||||
assert(CLS_ISCLASS((Class)receiver));
|
||||
assert(CLS_ISMETA(receiver->class_pointer));
|
||||
|
||||
/* Install real dtable for factory methods */
|
||||
__objc_install_dispatch_table_for_class (receiver->class_pointer);
|
||||
|
||||
if (strcmp (sel_get_name (op), "initialize"))
|
||||
__objc_send_initialize((Class)receiver);
|
||||
else
|
||||
CLS_SETINITIALIZED((Class)receiver);
|
||||
}
|
||||
objc_mutex_unlock(__objc_runtime_mutex);
|
||||
}
|
||||
|
||||
/* Install dummy table for class which causes the first message to
|
||||
that class (or instances hereof) to be initialized properly */
|
||||
void
|
||||
__objc_install_premature_dtable(Class class)
|
||||
{
|
||||
assert(__objc_uninstalled_dtable);
|
||||
class->dtable = __objc_uninstalled_dtable;
|
||||
}
|
||||
|
||||
/* Send +initialize to class if not already done */
|
||||
static void
|
||||
__objc_send_initialize(Class class)
|
||||
{
|
||||
/* This *must* be a class object */
|
||||
assert(CLS_ISCLASS(class));
|
||||
assert(!CLS_ISMETA(class));
|
||||
|
||||
if (!CLS_ISINITIALIZED(class))
|
||||
{
|
||||
CLS_SETINITIALIZED(class);
|
||||
CLS_SETINITIALIZED(class->class_pointer);
|
||||
|
||||
if(class->super_class)
|
||||
__objc_send_initialize(class->super_class);
|
||||
|
||||
{
|
||||
SEL op = sel_register_name ("initialize");
|
||||
Class tmpclass = class;
|
||||
IMP imp = 0;
|
||||
|
||||
while (!imp && tmpclass) {
|
||||
MethodList_t method_list = tmpclass->class_pointer->methods;
|
||||
|
||||
while(!imp && method_list) {
|
||||
int i;
|
||||
Method_t method;
|
||||
|
||||
for (i=0;i<method_list->method_count;i++) {
|
||||
method = &(method_list->method_list[i]);
|
||||
if (method->method_name
|
||||
&& method->method_name->sel_id == op->sel_id) {
|
||||
imp = method->method_imp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
method_list = method_list->method_next;
|
||||
|
||||
}
|
||||
|
||||
tmpclass = tmpclass->super_class;
|
||||
}
|
||||
if (imp)
|
||||
(*imp)((id)class, op);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Walk on the methods list of class and install the methods in the reverse
|
||||
order of the lists. Since methods added by categories are before the methods
|
||||
of class in the methods list, this allows categories to substitute methods
|
||||
declared in class. However if more than one category replaces the same
|
||||
method nothing is guaranteed about what method will be used.
|
||||
Assumes that __objc_runtime_mutex is locked down. */
|
||||
static void
|
||||
__objc_install_methods_in_dtable (Class class, MethodList_t method_list)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!method_list)
|
||||
return;
|
||||
|
||||
if (method_list->method_next)
|
||||
__objc_install_methods_in_dtable (class, method_list->method_next);
|
||||
|
||||
for (i = 0; i < method_list->method_count; i++)
|
||||
{
|
||||
Method_t method = &(method_list->method_list[i]);
|
||||
sarray_at_put_safe (class->dtable,
|
||||
(sidx) method->method_name->sel_id,
|
||||
method->method_imp);
|
||||
}
|
||||
}
|
||||
|
||||
/* Assumes that __objc_runtime_mutex is locked down. */
|
||||
static void
|
||||
__objc_install_dispatch_table_for_class (Class class)
|
||||
{
|
||||
Class super;
|
||||
|
||||
/* If the class has not yet had its class links resolved, we must
|
||||
re-compute all class links */
|
||||
if(!CLS_ISRESOLV(class))
|
||||
__objc_resolve_class_links();
|
||||
|
||||
super = class->super_class;
|
||||
|
||||
if (super != 0 && (super->dtable == __objc_uninstalled_dtable))
|
||||
__objc_install_dispatch_table_for_class (super);
|
||||
|
||||
/* Allocate dtable if necessary */
|
||||
if (super == 0)
|
||||
{
|
||||
objc_mutex_lock(__objc_runtime_mutex);
|
||||
class->dtable = sarray_new (__objc_selector_max_index, 0);
|
||||
objc_mutex_unlock(__objc_runtime_mutex);
|
||||
}
|
||||
else
|
||||
class->dtable = sarray_lazy_copy (super->dtable);
|
||||
|
||||
__objc_install_methods_in_dtable (class, class->methods);
|
||||
}
|
||||
|
||||
void
|
||||
__objc_update_dispatch_table_for_class (Class class)
|
||||
{
|
||||
Class next;
|
||||
struct sarray *arr;
|
||||
|
||||
/* not yet installed -- skip it */
|
||||
if (class->dtable == __objc_uninstalled_dtable)
|
||||
return;
|
||||
|
||||
objc_mutex_lock(__objc_runtime_mutex);
|
||||
|
||||
arr = class->dtable;
|
||||
__objc_install_premature_dtable (class); /* someone might require it... */
|
||||
sarray_free (arr); /* release memory */
|
||||
|
||||
/* could have been lazy... */
|
||||
__objc_install_dispatch_table_for_class (class);
|
||||
|
||||
if (class->subclass_list) /* Traverse subclasses */
|
||||
for (next = class->subclass_list; next; next = next->sibling_class)
|
||||
__objc_update_dispatch_table_for_class (next);
|
||||
|
||||
objc_mutex_unlock(__objc_runtime_mutex);
|
||||
}
|
||||
|
||||
|
||||
/* This function adds a method list to a class. This function is
|
||||
typically called by another function specific to the run-time. As
|
||||
such this function does not worry about thread safe issues.
|
||||
|
||||
This one is only called for categories. Class objects have their
|
||||
methods installed right away, and their selectors are made into
|
||||
SEL's by the function __objc_register_selectors_from_class. */
|
||||
void
|
||||
class_add_method_list (Class class, MethodList_t list)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Passing of a linked list is not allowed. Do multiple calls. */
|
||||
assert (!list->method_next);
|
||||
|
||||
/* Check for duplicates. */
|
||||
for (i = 0; i < list->method_count; ++i)
|
||||
{
|
||||
Method_t method = &list->method_list[i];
|
||||
|
||||
if (method->method_name) /* Sometimes these are NULL */
|
||||
{
|
||||
/* This is where selector names are transmogrified to SEL's */
|
||||
method->method_name =
|
||||
sel_register_typed_name ((const char*)method->method_name,
|
||||
method->method_types);
|
||||
}
|
||||
}
|
||||
|
||||
/* Add the methods to the class's method list. */
|
||||
list->method_next = class->methods;
|
||||
class->methods = list;
|
||||
|
||||
/* Update the dispatch table of class */
|
||||
__objc_update_dispatch_table_for_class (class);
|
||||
}
|
||||
|
||||
Method_t
|
||||
class_get_instance_method(Class class, SEL op)
|
||||
{
|
||||
return search_for_method_in_hierarchy(class, op);
|
||||
}
|
||||
|
||||
Method_t
|
||||
class_get_class_method(MetaClass class, SEL op)
|
||||
{
|
||||
return search_for_method_in_hierarchy(class, op);
|
||||
}
|
||||
|
||||
|
||||
/* Search for a method starting from the current class up its hierarchy.
|
||||
Return a pointer to the method's method structure if found. NULL
|
||||
otherwise. */
|
||||
|
||||
static Method_t
|
||||
search_for_method_in_hierarchy (Class cls, SEL sel)
|
||||
{
|
||||
Method_t method = NULL;
|
||||
Class class;
|
||||
|
||||
if (! sel_is_mapped (sel))
|
||||
return NULL;
|
||||
|
||||
/* Scan the method list of the class. If the method isn't found in the
|
||||
list then step to its super class. */
|
||||
for (class = cls; ((! method) && class); class = class->super_class)
|
||||
method = search_for_method_in_list (class->methods, sel);
|
||||
|
||||
return method;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Given a linked list of method and a method's name. Search for the named
|
||||
method's method structure. Return a pointer to the method's method
|
||||
structure if found. NULL otherwise. */
|
||||
Method_t
|
||||
search_for_method_in_list (MethodList_t list, SEL op)
|
||||
{
|
||||
MethodList_t method_list = list;
|
||||
|
||||
if (! sel_is_mapped (op))
|
||||
return NULL;
|
||||
|
||||
/* If not found then we'll search the list. */
|
||||
while (method_list)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Search the method list. */
|
||||
for (i = 0; i < method_list->method_count; ++i)
|
||||
{
|
||||
Method_t method = &method_list->method_list[i];
|
||||
|
||||
if (method->method_name)
|
||||
if (method->method_name->sel_id == op->sel_id)
|
||||
return method;
|
||||
}
|
||||
|
||||
/* The method wasn't found. Follow the link to the next list of
|
||||
methods. */
|
||||
method_list = method_list->method_next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static retval_t __objc_forward (id object, SEL sel, arglist_t args);
|
||||
|
||||
/* Forwarding pointers/integers through the normal registers */
|
||||
static id
|
||||
__objc_word_forward (id rcv, SEL op, ...)
|
||||
{
|
||||
void *args, *res;
|
||||
|
||||
args = __builtin_apply_args ();
|
||||
res = __objc_forward (rcv, op, args);
|
||||
if (res)
|
||||
__builtin_return (res);
|
||||
else
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Specific routine for forwarding floats/double because of
|
||||
architectural differences on some processors. i386s for
|
||||
example which uses a floating point stack versus general
|
||||
registers for floating point numbers. This forward routine
|
||||
makes sure that GCC restores the proper return values */
|
||||
static double
|
||||
__objc_double_forward (id rcv, SEL op, ...)
|
||||
{
|
||||
void *args, *res;
|
||||
|
||||
args = __builtin_apply_args ();
|
||||
res = __objc_forward (rcv, op, args);
|
||||
__builtin_return (res);
|
||||
}
|
||||
|
||||
#if INVISIBLE_STRUCT_RETURN
|
||||
static __big
|
||||
#else
|
||||
static id
|
||||
#endif
|
||||
__objc_block_forward (id rcv, SEL op, ...)
|
||||
{
|
||||
void *args, *res;
|
||||
|
||||
args = __builtin_apply_args ();
|
||||
res = __objc_forward (rcv, op, args);
|
||||
if (res)
|
||||
__builtin_return (res);
|
||||
else
|
||||
#if INVISIBLE_STRUCT_RETURN
|
||||
return (__big) {{0, 0, 0, 0, 0, 0, 0, 0}};
|
||||
#else
|
||||
return nil;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* This function is installed in the dispatch table for all methods which are
|
||||
not implemented. Thus, it is called when a selector is not recognized. */
|
||||
static retval_t
|
||||
__objc_forward (id object, SEL sel, arglist_t args)
|
||||
{
|
||||
IMP imp;
|
||||
static SEL frwd_sel = 0; /* !T:SAFE2 */
|
||||
SEL err_sel;
|
||||
|
||||
/* first try if the object understands forward:: */
|
||||
if (!frwd_sel)
|
||||
frwd_sel = sel_get_any_uid("forward::");
|
||||
|
||||
if (__objc_responds_to (object, frwd_sel))
|
||||
{
|
||||
imp = get_imp(object->class_pointer, frwd_sel);
|
||||
return (*imp)(object, frwd_sel, sel, args);
|
||||
}
|
||||
|
||||
/* If the object recognizes the doesNotRecognize: method then we're going
|
||||
to send it. */
|
||||
err_sel = sel_get_any_uid ("doesNotRecognize:");
|
||||
if (__objc_responds_to (object, err_sel))
|
||||
{
|
||||
imp = get_imp (object->class_pointer, err_sel);
|
||||
return (*imp) (object, err_sel, sel);
|
||||
}
|
||||
|
||||
/* The object doesn't recognize the method. Check for responding to
|
||||
error:. If it does then sent it. */
|
||||
{
|
||||
size_t strlen (const char*);
|
||||
char msg[256 + strlen ((const char*)sel_get_name (sel))
|
||||
+ strlen ((const char*)object->class_pointer->name)];
|
||||
|
||||
sprintf (msg, "(%s) %s does not recognize %s",
|
||||
(CLS_ISMETA(object->class_pointer)
|
||||
? "class"
|
||||
: "instance" ),
|
||||
object->class_pointer->name, sel_get_name (sel));
|
||||
|
||||
err_sel = sel_get_any_uid ("error:");
|
||||
if (__objc_responds_to (object, err_sel))
|
||||
{
|
||||
imp = get_imp (object->class_pointer, err_sel);
|
||||
return (*imp) (object, sel_get_any_uid ("error:"), msg);
|
||||
}
|
||||
|
||||
/* The object doesn't respond to doesNotRecognize: or error:; Therefore,
|
||||
a default action is taken. */
|
||||
objc_error (object, OBJC_ERR_UNIMPLEMENTED, "%s\n", msg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
__objc_print_dtable_stats()
|
||||
{
|
||||
int total = 0;
|
||||
|
||||
objc_mutex_lock(__objc_runtime_mutex);
|
||||
|
||||
printf("memory usage: (%s)\n",
|
||||
#ifdef OBJC_SPARSE2
|
||||
"2-level sparse arrays"
|
||||
#else
|
||||
"3-level sparse arrays"
|
||||
#endif
|
||||
);
|
||||
|
||||
printf("arrays: %d = %ld bytes\n", narrays,
|
||||
(long)narrays*sizeof(struct sarray));
|
||||
total += narrays*sizeof(struct sarray);
|
||||
printf("buckets: %d = %ld bytes\n", nbuckets,
|
||||
(long)nbuckets*sizeof(struct sbucket));
|
||||
total += nbuckets*sizeof(struct sbucket);
|
||||
|
||||
printf("idxtables: %d = %ld bytes\n", idxsize, (long)idxsize*sizeof(void*));
|
||||
total += idxsize*sizeof(void*);
|
||||
printf("-----------------------------------\n");
|
||||
printf("total: %d bytes\n", total);
|
||||
printf("===================================\n");
|
||||
|
||||
objc_mutex_unlock(__objc_runtime_mutex);
|
||||
}
|
||||
|
||||
/* Returns the uninstalled dispatch table indicator.
|
||||
If a class' dispatch table points to __objc_uninstalled_dtable
|
||||
then that means it needs its dispatch table to be installed. */
|
||||
__inline__
|
||||
struct sarray*
|
||||
objc_get_uninstalled_dtable()
|
||||
{
|
||||
return __objc_uninstalled_dtable;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user